diff options
author | Anna Zaks <ganna@apple.com> | 2012-05-04 22:18:39 +0000 |
---|---|---|
committer | Anna Zaks <ganna@apple.com> | 2012-05-04 22:18:39 +0000 |
commit | 58822c403cc8855adeecba92248612ee08dc1f3a (patch) | |
tree | eefbb6252cdf286b4ed099f71ef6dff293268120 | |
parent | f132ba8e571298ceda306c4484e031f990b347da (diff) |
[analyzer] RetainCountChecker: Allow objects to escape through callbacks
Fixes radar://10973977.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@156215 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp | 28 | ||||
-rw-r--r-- | test/Analysis/retain-release.m | 26 |
2 files changed, 46 insertions, 8 deletions
diff --git a/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp b/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp index 3bd7ae4322..2cf9353771 100644 --- a/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp +++ b/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp @@ -739,7 +739,8 @@ public: InitializeMethodSummaries(); } - const RetainSummary *getSummary(const FunctionDecl *FD); + const RetainSummary *getSummary(const FunctionDecl *FD, + const CallOrObjCMessage *CME = 0); const RetainSummary *getMethodSummary(Selector S, IdentifierInfo *ClsName, const ObjCInterfaceDecl *ID, @@ -886,7 +887,9 @@ static bool isMakeCollectable(const FunctionDecl *FD, StringRef FName) { return FName.find("MakeCollectable") != StringRef::npos; } -const RetainSummary * RetainSummaryManager::getSummary(const FunctionDecl *FD) { +const RetainSummary * +RetainSummaryManager::getSummary(const FunctionDecl *FD, + const CallOrObjCMessage *CME) { // Look up a summary in our cache of FunctionDecls -> Summaries. FuncSummariesTy::iterator I = FuncSummaries.find(FD); if (I != FuncSummaries.end()) @@ -1001,6 +1004,11 @@ const RetainSummary * RetainSummaryManager::getSummary(const FunctionDecl *FD) { ScratchArgs = AF.add(ScratchArgs, 1, StopTracking); ScratchArgs = AF.add(ScratchArgs, 2, StopTracking); S = getPersistentSummary(RetEffect::MakeNoRet(), DoNothing, DoNothing); + } else if (CME && CME->hasNonZeroCallbackArg()) { + // Allow objects to escape throug callbacks. radar://10973977 + for (unsigned I = 0; I < CME->getNumArgs(); ++I) + ScratchArgs = AF.add(ScratchArgs, I, StopTracking); + S = getPersistentSummary(RetEffect::MakeNoRet(), DoNothing, DoNothing); } // Did we get a summary? @@ -2633,10 +2641,13 @@ void RetainCountChecker::checkPostStmt(const CallExpr *CE, if (dyn_cast_or_null<BlockDataRegion>(L.getAsRegion())) { Summ = Summaries.getPersistentStopSummary(); } else if (const FunctionDecl *FD = L.getAsFunctionDecl()) { - Summ = Summaries.getSummary(FD); + CallOrObjCMessage CME(CE, state, C.getLocationContext()); + Summ = Summaries.getSummary(FD, &CME); } else if (const CXXMemberCallExpr *me = dyn_cast<CXXMemberCallExpr>(CE)) { - if (const CXXMethodDecl *MD = me->getMethodDecl()) - Summ = Summaries.getSummary(MD); + if (const CXXMethodDecl *MD = me->getMethodDecl()) { + CallOrObjCMessage CME(CE, state, C.getLocationContext()); + Summ = Summaries.getSummary(MD, &CME); + } } if (!Summ) @@ -2652,13 +2663,14 @@ void RetainCountChecker::checkPostStmt(const CXXConstructExpr *CE, return; RetainSummaryManager &Summaries = getSummaryManager(C); - const RetainSummary *Summ = Summaries.getSummary(Ctor); + ProgramStateRef state = C.getState(); + CallOrObjCMessage CME(CE, state, C.getLocationContext()); + const RetainSummary *Summ = Summaries.getSummary(Ctor, &CME); // If we didn't get a summary, this constructor doesn't affect retain counts. if (!Summ) return; - ProgramStateRef state = C.getState(); checkSummary(*Summ, CallOrObjCMessage(CE, state, C.getLocationContext()), C); } @@ -3250,7 +3262,7 @@ void RetainCountChecker::checkPreStmt(const ReturnStmt *S, if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(CD)) { if (!isa<CXXMethodDecl>(FD)) - if (const RetainSummary *Summ = Summaries.getSummary(FD)) + if (const RetainSummary *Summ = Summaries.getSummary(FD, 0)) checkReturnWithRetEffect(S, C, Pred, Summ->getRetEffect(), X, Sym, state); } diff --git a/test/Analysis/retain-release.m b/test/Analysis/retain-release.m index 54af13d2a3..fb89cc8114 100644 --- a/test/Analysis/retain-release.m +++ b/test/Analysis/retain-release.m @@ -1686,6 +1686,32 @@ void rdar_10824732() { } } +// Stop tracking objects passed to functions, which take callbacks as parameters. +// radar://10973977 +typedef int (*CloseCallback) (void *); +void ReaderForIO(CloseCallback ioclose, void *ioctx); +int IOClose(void *context); + +@protocol SInS <NSObject> +@end + +@interface radar10973977 : NSObject +- (id<SInS>)inputS; +- (void)reader; +@end + +@implementation radar10973977 +- (void)reader +{ + id<SInS> inputS = [[self inputS] retain]; + ReaderForIO(IOClose, inputS); +} +- (id<SInS>)inputS +{ + return 0; +} +@end + //===----------------------------------------------------------------------===// // Test returning allocated memory in a struct. // |