Author: george.karpenkov Date: Wed May 16 15:47:05 2018 New Revision: 332546
URL: http://llvm.org/viewvc/llvm-project?rev=332546&view=rev Log: [analyzer] Extend ObjCAutoreleaseWriteChecker to catch block declarations with autoreleasing variables Differential Revision: https://reviews.llvm.org/D46984 Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/ObjCAutoreleaseWriteChecker.cpp cfe/trunk/test/Analysis/autoreleasewritechecker_test.m Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/ObjCAutoreleaseWriteChecker.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/ObjCAutoreleaseWriteChecker.cpp?rev=332546&r1=332545&r2=332546&view=diff ============================================================================== --- cfe/trunk/lib/StaticAnalyzer/Checkers/ObjCAutoreleaseWriteChecker.cpp (original) +++ cfe/trunk/lib/StaticAnalyzer/Checkers/ObjCAutoreleaseWriteChecker.cpp Wed May 16 15:47:05 2018 @@ -115,14 +115,16 @@ static void emitDiagnostics(BoundNodes & QualType Ty = PVD->getType(); if (Ty->getPointeeType().getObjCLifetime() != Qualifiers::OCL_Autoreleasing) return; - const char *WarningMsg = "Write to"; + const char *ActionMsg = "Write to"; const auto *MarkedStmt = Match.getNodeAs<Expr>(ProblematicWriteBind); + bool IsCapture = false; // Prefer to warn on write, but if not available, warn on capture. if (!MarkedStmt) { MarkedStmt = Match.getNodeAs<Expr>(CapturedBind); assert(MarkedStmt); - WarningMsg = "Capture of"; + ActionMsg = "Capture of"; + IsCapture = true; } SourceRange Range = MarkedStmt->getSourceRange(); @@ -130,12 +132,14 @@ static void emitDiagnostics(BoundNodes & MarkedStmt, BR.getSourceManager(), ADC); bool IsMethod = Match.getNodeAs<ObjCMethodDecl>(IsMethodBind) != nullptr; const char *Name = IsMethod ? "method" : "function"; + BR.EmitBasicReport( ADC->getDecl(), Checker, - /*Name=*/(llvm::Twine(WarningMsg) + /*Name=*/(llvm::Twine(ActionMsg) + " autoreleasing out parameter inside autorelease pool").str(), /*Category=*/"Memory", - (llvm::Twine(WarningMsg) + " autoreleasing out parameter inside " + + (llvm::Twine(ActionMsg) + " autoreleasing out parameter " + + (IsCapture ? "'" + PVD->getName() + "'" + " " : "") + "inside " + "autorelease pool that may exit before " + Name + " returns; consider " "writing first to a strong local variable declared outside of the block") .str(), @@ -153,7 +157,7 @@ void ObjCAutoreleaseWriteChecker::checkA .bind(ParamBind); auto ReferencedParamM = - declRefExpr(to(parmVarDecl(DoublePointerParamM))); + declRefExpr(to(parmVarDecl(DoublePointerParamM))).bind(CapturedBind); // Write into a binded object, e.g. *ParamBind = X. auto WritesIntoM = binaryOperator( @@ -169,7 +173,7 @@ void ObjCAutoreleaseWriteChecker::checkA ignoringParenImpCasts(ReferencedParamM)); auto CapturedInParamM = stmt(anyOf( callExpr(ArgumentCaptureM), - objcMessageExpr(ArgumentCaptureM))).bind(CapturedBind); + objcMessageExpr(ArgumentCaptureM))); // WritesIntoM happens inside a block passed as an argument. auto WritesOrCapturesInBlockM = hasAnyArgument(allOf( @@ -192,7 +196,8 @@ void ObjCAutoreleaseWriteChecker::checkA auto MatcherM = decl(anyOf( objcMethodDecl(HasParamAndWritesInMarkedFuncM).bind(IsMethodBind), - functionDecl(HasParamAndWritesInMarkedFuncM))); + functionDecl(HasParamAndWritesInMarkedFuncM), + blockDecl(HasParamAndWritesInMarkedFuncM))); auto Matches = match(MatcherM, *D, AM.getASTContext()); for (BoundNodes Match : Matches) Modified: cfe/trunk/test/Analysis/autoreleasewritechecker_test.m URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/autoreleasewritechecker_test.m?rev=332546&r1=332545&r2=332546&view=diff ============================================================================== --- cfe/trunk/test/Analysis/autoreleasewritechecker_test.m (original) +++ cfe/trunk/test/Analysis/autoreleasewritechecker_test.m Wed May 16 15:47:05 2018 @@ -265,5 +265,17 @@ void multipleErrors(NSError *__autorelea }]; } +typedef void (^errBlock)(NSError *__autoreleasing *error); + +extern void expectError(errBlock); + +void captureAutoreleasingVarFromBlock(NSDictionary *dict) { + expectError(^(NSError *__autoreleasing *err) { + [dict enumerateKeysAndObjectsUsingBlock:^{ + writeIntoError(err); // expected-warning{{Capture of autoreleasing out parameter 'err'}} + }]; + }); +} + #endif _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits