Index: clang/lib/StaticAnalyzer/Core/RetainSummaryManager.cpp =================================================================== --- clang/lib/StaticAnalyzer/Core/RetainSummaryManager.cpp +++ clang/lib/StaticAnalyzer/Core/RetainSummaryManager.cpp @@ -303,6 +303,9 @@ if (FName == "retain") return getOSSummaryRetainRule(FD); + if (FName == "free") + return getOSSummaryFreeRule(FD); + if (MD->getOverloadedOperator() == OO_New) return getOSSummaryCreateRule(MD); } @@ -621,6 +624,14 @@ /*ThisEff=*/DecRef); } +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)); Index: clang/test/Analysis/osobject-retain-release.cpp =================================================================== --- clang/test/Analysis/osobject-retain-release.cpp +++ clang/test/Analysis/osobject-retain-release.cpp @@ -14,6 +14,7 @@ struct OSObject { virtual void retain(); virtual void release() {}; + virtual void free(); virtual ~OSObject(){} unsigned int foo() { return 42; } @@ -65,6 +66,23 @@ 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); + arr->retain(); + arr->retain(); + arr->retain(); + arr->free(); + arr->retain(); // expected-warning{{}} +} + 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}}