Author: george.karpenkov Date: Thu Nov 29 18:19:16 2018 New Revision: 347950
URL: http://llvm.org/viewvc/llvm-project?rev=347950&view=rev Log: [analyzer] RetainCountChecker for OSObject model the "free" call The "free" call frees the object immediately, ignoring the reference count. Sadly, it is actually used in a few places, so we need to model it. Differential Revision: https://reviews.llvm.org/D55092 Modified: cfe/trunk/include/clang/StaticAnalyzer/Core/RetainSummaryManager.h cfe/trunk/lib/StaticAnalyzer/Core/RetainSummaryManager.cpp cfe/trunk/test/Analysis/osobject-retain-release.cpp Modified: cfe/trunk/include/clang/StaticAnalyzer/Core/RetainSummaryManager.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/StaticAnalyzer/Core/RetainSummaryManager.h?rev=347950&r1=347949&r2=347950&view=diff ============================================================================== --- cfe/trunk/include/clang/StaticAnalyzer/Core/RetainSummaryManager.h (original) +++ cfe/trunk/include/clang/StaticAnalyzer/Core/RetainSummaryManager.h Thu Nov 29 18:19:16 2018 @@ -530,6 +530,8 @@ class RetainSummaryManager { /// Decrement the reference count on OS object. const RetainSummary *getOSSummaryReleaseRule(const FunctionDecl *FD); + /// Free the OS object. + const RetainSummary *getOSSummaryFreeRule(const FunctionDecl *FD); enum UnaryFuncKind { cfretain, cfrelease, cfautorelease, cfmakecollectable }; Modified: cfe/trunk/lib/StaticAnalyzer/Core/RetainSummaryManager.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/RetainSummaryManager.cpp?rev=347950&r1=347949&r2=347950&view=diff ============================================================================== --- cfe/trunk/lib/StaticAnalyzer/Core/RetainSummaryManager.cpp (original) +++ cfe/trunk/lib/StaticAnalyzer/Core/RetainSummaryManager.cpp Thu Nov 29 18:19:16 2018 @@ -303,6 +303,9 @@ RetainSummaryManager::generateSummary(co if (FName == "retain") return getOSSummaryRetainRule(FD); + if (FName == "free") + return getOSSummaryFreeRule(FD); + if (MD->getOverloadedOperator() == OO_New) return getOSSummaryCreateRule(MD); } @@ -622,6 +625,14 @@ RetainSummaryManager::getOSSummaryReleas } const RetainSummary * +RetainSummaryManager::getOSSummaryFreeRule(const FunctionDecl *FD) { + return getPersistentSummary(RetEffect::MakeNoRet(), + /*ReceiverEff=*/DoNothing, + /*DefaultEff=*/DoNothing, + /*ThisEff=*/Dealloc); +} + +const RetainSummary * RetainSummaryManager::getOSSummaryCreateRule(const FunctionDecl *FD) { return getPersistentSummary(RetEffect::MakeOwned(RetEffect::OS)); } Modified: cfe/trunk/test/Analysis/osobject-retain-release.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/osobject-retain-release.cpp?rev=347950&r1=347949&r2=347950&view=diff ============================================================================== --- cfe/trunk/test/Analysis/osobject-retain-release.cpp (original) +++ cfe/trunk/test/Analysis/osobject-retain-release.cpp Thu Nov 29 18:19:16 2018 @@ -14,6 +14,7 @@ struct OSMetaClass; struct OSObject { virtual void retain(); virtual void release() {}; + virtual void free(); virtual ~OSObject(){} unsigned int foo() { return 42; } @@ -65,6 +66,22 @@ struct OSMetaClassBase { static OSObject *safeMetaCast(const OSObject *inst, const OSMetaClass *meta); }; +void check_free_no_error() { + OSArray *arr = OSArray::withCapacity(10); + arr->retain(); + arr->retain(); + arr->retain(); + arr->free(); +} + +void check_free_use_after_free() { + OSArray *arr = OSArray::withCapacity(10); // expected-note{{Call to function 'OSArray::withCapacity' returns an OSObject of type struct OSArray * with a +1 retain count}} + arr->retain(); // expected-note{{Reference count incremented. The object now has a +2 retain count}} + arr->free(); // expected-note{{Object released}} + arr->retain(); // expected-warning{{Reference-counted object is used after it is released}} + // expected-note@-1{{Reference-counted object is used after it is released}} +} + unsigned int check_leak_explicit_new() { OSArray *arr = new OSArray; // expected-note{{Operator new returns an OSObject of type struct OSArray * with a +1 retain count}} return arr->getCount(); // expected-note{{Object leaked: allocated object of type struct OSArray * is not referenced later in this execution path and has a retain count of +1}} _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits