diff options
author | Jordan Rose <jordan_rose@apple.com> | 2012-12-06 18:58:18 +0000 |
---|---|---|
committer | Jordan Rose <jordan_rose@apple.com> | 2012-12-06 18:58:18 +0000 |
commit | 4ee1c557c3ebddb8a9be8f6fb66605b971793820 (patch) | |
tree | 48c197751b7de2cd274494eccc89ad7e5a96ae70 /lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp | |
parent | 4ecca28e20410f5e2816c5ddff5cdeaf45fb74b5 (diff) |
[analyzer] Simplify RetainCountChecker's handling of dead symbols.
Previously we made three passes over the set of dead symbols, and removed
them from the state /twice/. Now we combine the autorelease pass and the
symbol death pass, and only have to remove the bindings for the symbols
that leaked.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@169527 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp')
-rw-r--r-- | lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp | 53 |
1 files changed, 24 insertions, 29 deletions
diff --git a/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp b/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp index 4cf47999c2..5ab9499a61 100644 --- a/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp +++ b/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp @@ -2545,7 +2545,7 @@ public: SymbolRef sid, RefVal V, SmallVectorImpl<SymbolRef> &Leaked) const; - std::pair<ExplodedNode *, ProgramStateRef > + ProgramStateRef handleAutoreleaseCounts(ProgramStateRef state, ExplodedNode *Pred, const ProgramPointTag *Tag, CheckerContext &Ctx, SymbolRef Sym, RefVal V) const; @@ -3260,11 +3260,10 @@ void RetainCountChecker::checkPreStmt(const ReturnStmt *S, // Update the autorelease counts. static SimpleProgramPointTag AutoreleaseTag("RetainCountChecker : Autorelease"); - llvm::tie(Pred, state) = handleAutoreleaseCounts(state, Pred, &AutoreleaseTag, - C, Sym, X); + state = handleAutoreleaseCounts(state, Pred, &AutoreleaseTag, C, Sym, X); // Did we cache out? - if (!Pred) + if (!state) return; // Get the updated binding. @@ -3473,8 +3472,8 @@ RetainCountChecker::checkRegionChanges(ProgramStateRef state, // Handle dead symbols and end-of-path. //===----------------------------------------------------------------------===// -std::pair<ExplodedNode *, ProgramStateRef > -RetainCountChecker::handleAutoreleaseCounts(ProgramStateRef state, +ProgramStateRef +RetainCountChecker::handleAutoreleaseCounts(ProgramStateRef state, ExplodedNode *Pred, const ProgramPointTag *Tag, CheckerContext &Ctx, @@ -3483,7 +3482,7 @@ RetainCountChecker::handleAutoreleaseCounts(ProgramStateRef state, // No autorelease counts? Nothing to be done. if (!ACnt) - return std::make_pair(Pred, state); + return state; assert(!Ctx.isObjCGCEnabled() && "Autorelease counts in GC mode?"); unsigned Cnt = V.getCount(); @@ -3504,11 +3503,7 @@ RetainCountChecker::handleAutoreleaseCounts(ProgramStateRef state, V.setCount(Cnt - ACnt); V.setAutoreleaseCount(0); } - state = setRefBinding(state, Sym, V); - ExplodedNode *N = Ctx.addTransition(state, Pred, Tag); - if (N == 0) - state = 0; - return std::make_pair(N, state); + return setRefBinding(state, Sym, V); } // Woah! More autorelease counts then retain counts left. @@ -3535,7 +3530,7 @@ RetainCountChecker::handleAutoreleaseCounts(ProgramStateRef state, Ctx.emitReport(report); } - return std::make_pair((ExplodedNode *)0, (ProgramStateRef )0); + return 0; } ProgramStateRef @@ -3560,9 +3555,6 @@ RetainCountChecker::processLeaks(ProgramStateRef state, SmallVectorImpl<SymbolRef> &Leaked, CheckerContext &Ctx, ExplodedNode *Pred) const { - if (Leaked.empty()) - return Pred; - // Generate an intermediate node representing the leak point. ExplodedNode *N = Ctx.addTransition(state, Pred); @@ -3591,8 +3583,8 @@ void RetainCountChecker::checkEndPath(CheckerContext &Ctx) const { ExplodedNode *Pred = Ctx.getPredecessor(); for (RefBindingsTy::iterator I = B.begin(), E = B.end(); I != E; ++I) { - llvm::tie(Pred, state) = handleAutoreleaseCounts(state, Pred, /*Tag=*/0, - Ctx, I->first, I->second); + state = handleAutoreleaseCounts(state, Pred, /*Tag=*/0, Ctx, + I->first, I->second); if (!state) return; } @@ -3632,6 +3624,7 @@ void RetainCountChecker::checkDeadSymbols(SymbolReaper &SymReaper, ProgramStateRef state = C.getState(); RefBindingsTy B = state->get<RefBindings>(); + SmallVector<SymbolRef, 10> Leaked; // Update counts from autorelease pools for (SymbolReaper::dead_iterator I = SymReaper.dead_begin(), @@ -3641,20 +3634,19 @@ void RetainCountChecker::checkDeadSymbols(SymbolReaper &SymReaper, // Use the symbol as the tag. // FIXME: This might not be as unique as we would like. const ProgramPointTag *Tag = getDeadSymbolTag(Sym); - llvm::tie(Pred, state) = handleAutoreleaseCounts(state, Pred, Tag, C, - Sym, *T); + state = handleAutoreleaseCounts(state, Pred, Tag, C, Sym, *T); if (!state) return; + + // Fetch the new reference count from the state, and use it to handle + // this symbol. + state = handleSymbolDeath(state, *I, *getRefBinding(state, Sym), Leaked); } } - B = state->get<RefBindings>(); - SmallVector<SymbolRef, 10> Leaked; - - for (SymbolReaper::dead_iterator I = SymReaper.dead_begin(), - E = SymReaper.dead_end(); I != E; ++I) { - if (const RefVal *T = B.lookup(*I)) - state = handleSymbolDeath(state, *I, *T, Leaked); + if (Leaked.empty()) { + C.addTransition(state); + return; } Pred = processLeaks(state, Leaked, C, Pred); @@ -3664,10 +3656,13 @@ void RetainCountChecker::checkDeadSymbols(SymbolReaper &SymReaper, return; // Now generate a new node that nukes the old bindings. + // The only bindings left at this point are the leaked symbols. RefBindingsTy::Factory &F = state->get_context<RefBindings>(); + B = state->get<RefBindings>(); - for (SymbolReaper::dead_iterator I = SymReaper.dead_begin(), - E = SymReaper.dead_end(); I != E; ++I) + for (SmallVectorImpl<SymbolRef>::iterator I = Leaked.begin(), + E = Leaked.end(); + I != E; ++I) B = F.remove(B, *I); state = state->set<RefBindings>(B); |