diff options
author | Jordan Rose <jordan_rose@apple.com> | 2012-11-15 19:11:27 +0000 |
---|---|---|
committer | Jordan Rose <jordan_rose@apple.com> | 2012-11-15 19:11:27 +0000 |
commit | 84c484545c5906ba55143e212b4a5275ab55889f (patch) | |
tree | 497cdfa32650b81a2db739e4f8a0b138324bf133 /lib/StaticAnalyzer/Core/ExprEngine.cpp | |
parent | 3d145f660a23d5bdabdd1ead83c51f3df1489b09 (diff) |
[analyzer] Mark symbol values as dead in the environment.
This allows us to properly remove dead bindings at the end of the top-level
stack frame, using the ReturnStmt, if there is one, to keep the return value
live. This in turn removes the need for a check::EndPath callback in leak
checkers.
This does cause some changes in the path notes for leak checkers. Previously,
a leak would be reported at the location of the closing brace in a function.
Now, it gets reported at the last statement. This matches the way leaks are
currently reported for inlined functions, but is less than ideal for both.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@168066 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/StaticAnalyzer/Core/ExprEngine.cpp')
-rw-r--r-- | lib/StaticAnalyzer/Core/ExprEngine.cpp | 28 |
1 files changed, 22 insertions, 6 deletions
diff --git a/lib/StaticAnalyzer/Core/ExprEngine.cpp b/lib/StaticAnalyzer/Core/ExprEngine.cpp index 045591c907..42bfe144db 100644 --- a/lib/StaticAnalyzer/Core/ExprEngine.cpp +++ b/lib/StaticAnalyzer/Core/ExprEngine.cpp @@ -268,22 +268,39 @@ static bool shouldRemoveDeadBindings(AnalysisManager &AMgr, void ExprEngine::removeDead(ExplodedNode *Pred, ExplodedNodeSet &Out, const Stmt *ReferenceStmt, - const StackFrameContext *LC, + const LocationContext *LC, const Stmt *DiagnosticStmt, ProgramPoint::Kind K) { assert((K == ProgramPoint::PreStmtPurgeDeadSymbolsKind || - ReferenceStmt == 0) + ReferenceStmt == 0 || isa<ReturnStmt>(ReferenceStmt)) && "PostStmt is not generally supported by the SymbolReaper yet"); + assert(LC && "Must pass the current (or expiring) LocationContext"); + + if (!DiagnosticStmt) { + DiagnosticStmt = ReferenceStmt; + assert(DiagnosticStmt && "Required for clearing a LocationContext"); + } + NumRemoveDeadBindings++; CleanedState = Pred->getState(); - SymbolReaper SymReaper(LC, ReferenceStmt, SymMgr, getStoreManager()); + + // LC is the location context being destroyed, but SymbolReaper wants a + // location context that is still live. (If this is the top-level stack + // frame, this will be null.) + if (!ReferenceStmt) { + assert(K == ProgramPoint::PostStmtPurgeDeadSymbolsKind && + "Use PostStmtPurgeDeadSymbolsKind for clearing a LocationContext"); + LC = LC->getParent(); + } + + const StackFrameContext *SFC = LC ? LC->getCurrentStackFrame() : 0; + SymbolReaper SymReaper(SFC, ReferenceStmt, SymMgr, getStoreManager()); getCheckerManager().runCheckersForLiveSymbols(CleanedState, SymReaper); // Create a state in which dead bindings are removed from the environment // and the store. TODO: The function should just return new env and store, // not a new state. - const StackFrameContext *SFC = LC->getCurrentStackFrame(); CleanedState = StateMgr.removeDeadBindings(CleanedState, SFC, SymReaper); // Process any special transfer function for dead symbols. @@ -345,8 +362,7 @@ void ExprEngine::ProcessStmt(const CFGStmt S, EntryNode = Pred; ExplodedNodeSet CleanedStates; if (shouldRemoveDeadBindings(AMgr, S, Pred, EntryNode->getLocationContext())){ - removeDead(EntryNode, CleanedStates, currStmt, - Pred->getStackFrame(), currStmt); + removeDead(EntryNode, CleanedStates, currStmt, Pred->getLocationContext()); } else CleanedStates.Add(EntryNode); |