This revision was automatically updated to reflect the committed changes. Closed by commit rC338314: [analyzer] Bugfix for autorelease + main run loop leak checker (authored by george.karpenkov, committed by ). Herald added a subscriber: cfe-commits.
Changed prior to commit: https://reviews.llvm.org/D49921?vs=157708&id=158100#toc Repository: rC Clang https://reviews.llvm.org/D49921 Files: lib/StaticAnalyzer/Checkers/RunLoopAutoreleaseLeakChecker.cpp test/Analysis/Checkers/RunLoopAutoreleaseLeakChecker.m Index: lib/StaticAnalyzer/Checkers/RunLoopAutoreleaseLeakChecker.cpp =================================================================== --- lib/StaticAnalyzer/Checkers/RunLoopAutoreleaseLeakChecker.cpp +++ lib/StaticAnalyzer/Checkers/RunLoopAutoreleaseLeakChecker.cpp @@ -45,6 +45,7 @@ const char * RunLoopRunBind = "RunLoopRunM"; const char * OtherMsgBind = "OtherMessageSentM"; const char * AutoreleasePoolBind = "AutoreleasePoolM"; +const char * OtherStmtAutoreleasePoolBind = "OtherAutoreleasePoolM"; class RunLoopAutoreleaseLeakChecker : public Checker<check::ASTCodeBody> { @@ -111,17 +112,20 @@ const auto *AP = Match.getNodeAs<ObjCAutoreleasePoolStmt>(AutoreleasePoolBind); + const auto *OAP = + Match.getNodeAs<ObjCAutoreleasePoolStmt>(OtherStmtAutoreleasePoolBind); bool HasAutoreleasePool = (AP != nullptr); const auto *RL = Match.getNodeAs<ObjCMessageExpr>(RunLoopBind); const auto *RLR = Match.getNodeAs<Stmt>(RunLoopRunBind); assert(RLR && "Run loop launch not found"); - assert(ME != RLR); - if (HasAutoreleasePool && seenBefore(AP, RLR, ME)) + + // Launch of run loop occurs before the message-sent expression is seen. + if (seenBefore(DeclBody, RLR, ME)) return; - if (!HasAutoreleasePool && seenBefore(DeclBody, RLR, ME)) + if (HasAutoreleasePool && (OAP != AP)) return; PathDiagnosticLocation Location = PathDiagnosticLocation::createBegin( @@ -170,7 +174,8 @@ checkTempObjectsInSamePool(const Decl *D, AnalysisManager &AM, BugReporter &BR, const RunLoopAutoreleaseLeakChecker *Chkr) { StatementMatcher RunLoopRunM = getRunLoopRunM(); - StatementMatcher OtherMessageSentM = getOtherMessageSentM(); + StatementMatcher OtherMessageSentM = getOtherMessageSentM( + hasAncestor(autoreleasePoolStmt().bind(OtherStmtAutoreleasePoolBind))); StatementMatcher RunLoopInAutorelease = autoreleasePoolStmt( Index: test/Analysis/Checkers/RunLoopAutoreleaseLeakChecker.m =================================================================== --- test/Analysis/Checkers/RunLoopAutoreleaseLeakChecker.m +++ test/Analysis/Checkers/RunLoopAutoreleaseLeakChecker.m @@ -29,6 +29,17 @@ } } +void runloop_init_before_separate_pool() { // No warning: separate autorelease pool. + @autoreleasepool { + NSObject *object; + @autoreleasepool { + object = [[NSObject alloc] init]; // no-warning + } + (void) object; + [[NSRunLoop mainRunLoop] run]; + } +} + void xpcmain_init_before() { // Warning: object created before the loop. @autoreleasepool { NSObject *object = [[NSObject alloc] init]; // expected-warning{{Temporary objects allocated in the autorelease pool followed by the launch of xpc_main may never get released; consider moving them to a separate autorelease pool}}
Index: lib/StaticAnalyzer/Checkers/RunLoopAutoreleaseLeakChecker.cpp =================================================================== --- lib/StaticAnalyzer/Checkers/RunLoopAutoreleaseLeakChecker.cpp +++ lib/StaticAnalyzer/Checkers/RunLoopAutoreleaseLeakChecker.cpp @@ -45,6 +45,7 @@ const char * RunLoopRunBind = "RunLoopRunM"; const char * OtherMsgBind = "OtherMessageSentM"; const char * AutoreleasePoolBind = "AutoreleasePoolM"; +const char * OtherStmtAutoreleasePoolBind = "OtherAutoreleasePoolM"; class RunLoopAutoreleaseLeakChecker : public Checker<check::ASTCodeBody> { @@ -111,17 +112,20 @@ const auto *AP = Match.getNodeAs<ObjCAutoreleasePoolStmt>(AutoreleasePoolBind); + const auto *OAP = + Match.getNodeAs<ObjCAutoreleasePoolStmt>(OtherStmtAutoreleasePoolBind); bool HasAutoreleasePool = (AP != nullptr); const auto *RL = Match.getNodeAs<ObjCMessageExpr>(RunLoopBind); const auto *RLR = Match.getNodeAs<Stmt>(RunLoopRunBind); assert(RLR && "Run loop launch not found"); - assert(ME != RLR); - if (HasAutoreleasePool && seenBefore(AP, RLR, ME)) + + // Launch of run loop occurs before the message-sent expression is seen. + if (seenBefore(DeclBody, RLR, ME)) return; - if (!HasAutoreleasePool && seenBefore(DeclBody, RLR, ME)) + if (HasAutoreleasePool && (OAP != AP)) return; PathDiagnosticLocation Location = PathDiagnosticLocation::createBegin( @@ -170,7 +174,8 @@ checkTempObjectsInSamePool(const Decl *D, AnalysisManager &AM, BugReporter &BR, const RunLoopAutoreleaseLeakChecker *Chkr) { StatementMatcher RunLoopRunM = getRunLoopRunM(); - StatementMatcher OtherMessageSentM = getOtherMessageSentM(); + StatementMatcher OtherMessageSentM = getOtherMessageSentM( + hasAncestor(autoreleasePoolStmt().bind(OtherStmtAutoreleasePoolBind))); StatementMatcher RunLoopInAutorelease = autoreleasePoolStmt( Index: test/Analysis/Checkers/RunLoopAutoreleaseLeakChecker.m =================================================================== --- test/Analysis/Checkers/RunLoopAutoreleaseLeakChecker.m +++ test/Analysis/Checkers/RunLoopAutoreleaseLeakChecker.m @@ -29,6 +29,17 @@ } } +void runloop_init_before_separate_pool() { // No warning: separate autorelease pool. + @autoreleasepool { + NSObject *object; + @autoreleasepool { + object = [[NSObject alloc] init]; // no-warning + } + (void) object; + [[NSRunLoop mainRunLoop] run]; + } +} + void xpcmain_init_before() { // Warning: object created before the loop. @autoreleasepool { NSObject *object = [[NSObject alloc] init]; // expected-warning{{Temporary objects allocated in the autorelease pool followed by the launch of xpc_main may never get released; consider moving them to a separate autorelease pool}}
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits