diff options
author | Anna Zaks <ganna@apple.com> | 2011-08-10 23:14:54 +0000 |
---|---|---|
committer | Anna Zaks <ganna@apple.com> | 2011-08-10 23:14:54 +0000 |
commit | 6bd528b9d703fdea51053719d9c53504a61a6bd7 (patch) | |
tree | b57118bbf7652d3f0cac93d8f6da3bb04a75af5d /lib/StaticAnalyzer/Core/ExprEngine.cpp | |
parent | 70979d4de873382d0ba13b5bd8fb3ee797384582 (diff) |
Analyzer Core: In checkDeadSymbols checker callback, provide the state in which the symbols are not yet deleted so that checkers could inspect them. Since we are now always creating a transition in ProcessStmt(), remove the logic for adding a transition when none was generated. TODO: the extra transitions will have to be removed; more cleanups; a checker that tests teh new fucntionality.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@137273 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/StaticAnalyzer/Core/ExprEngine.cpp')
-rw-r--r-- | lib/StaticAnalyzer/Core/ExprEngine.cpp | 85 |
1 files changed, 56 insertions, 29 deletions
diff --git a/lib/StaticAnalyzer/Core/ExprEngine.cpp b/lib/StaticAnalyzer/Core/ExprEngine.cpp index 765db99555..21aa25604f 100644 --- a/lib/StaticAnalyzer/Core/ExprEngine.cpp +++ b/lib/StaticAnalyzer/Core/ExprEngine.cpp @@ -229,6 +229,9 @@ void ExprEngine::processCFGElement(const CFGElement E, } void ExprEngine::ProcessStmt(const CFGStmt S, StmtNodeBuilder& builder) { + // TODO: Use RAII to remove the unnecessary, tagged nodes. + //RegisterCreatedNodes registerCreatedNodes(getGraph()); + // Reclaim any unnecessary nodes in the ExplodedGraph. G.reclaimRecentlyAllocatedNodes(); // Recycle any unused states in the GRStateManager. @@ -239,74 +242,98 @@ void ExprEngine::ProcessStmt(const CFGStmt S, StmtNodeBuilder& builder) { currentStmt->getLocStart(), "Error evaluating statement"); + // A tag to track convenience transitions, which can be removed at cleanup. + static unsigned tag; Builder = &builder; EntryNode = builder.getPredecessor(); + const GRState *EntryState = EntryNode->getState(); + CleanedState = EntryState; + ExplodedNode *CleanedNode = 0; + // Create the cleaned state. const LocationContext *LC = EntryNode->getLocationContext(); SymbolReaper SymReaper(LC, currentStmt, SymMgr, getStoreManager()); if (AMgr.shouldPurgeDead()) { - const GRState *St = EntryNode->getState(); - getCheckerManager().runCheckersForLiveSymbols(St, SymReaper); + getCheckerManager().runCheckersForLiveSymbols(CleanedState, SymReaper); const StackFrameContext *SFC = LC->getCurrentStackFrame(); - CleanedState = StateMgr.removeDeadBindings(St, SFC, SymReaper); - } else { - CleanedState = EntryNode->getState(); + + // 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. + CleanedState = StateMgr.removeDeadBindings(CleanedState, SFC, SymReaper); } // Process any special transfer function for dead symbols. ExplodedNodeSet Tmp; + if (!SymReaper.hasDeadSymbols()) { + // Generate a CleanedNode that has the environment and store cleaned + // up. Since no symbols are dead, we can optimize and not clean out + // the constraint manager. + CleanedNode = + Builder->generateNode(currentStmt, CleanedState, EntryNode, &tag); + Tmp.Add(CleanedNode); - if (!SymReaper.hasDeadSymbols()) - Tmp.Add(EntryNode); - else { + } else { SaveAndRestore<bool> OldSink(Builder->BuildSinks); SaveOr OldHasGen(Builder->hasGeneratedNode); SaveAndRestore<bool> OldPurgeDeadSymbols(Builder->PurgingDeadSymbols); Builder->PurgingDeadSymbols = true; + // Call checkers with the non-cleaned state so that they could query the + // values of the soon to be dead symbols. // FIXME: This should soon be removed. ExplodedNodeSet Tmp2; getTF().evalDeadSymbols(Tmp2, *this, *Builder, EntryNode, - CleanedState, SymReaper); + EntryState, SymReaper); - getCheckerManager().runCheckersForDeadSymbols(Tmp, Tmp2, + ExplodedNodeSet Tmp3; + getCheckerManager().runCheckersForDeadSymbols(Tmp3, Tmp2, SymReaper, currentStmt, *this); - if (!Builder->BuildSinks && !Builder->hasGeneratedNode) - Tmp.Add(EntryNode); - } + // For each node in Tmp3, generate CleanedNodes that have the environment, + // the store, and the constraints cleaned up but have the user supplied + // states as the predecessors. + for (ExplodedNodeSet::const_iterator I = Tmp3.begin(), E = Tmp3.end(); + I != E; ++I) { + const GRState *CheckerState = (*I)->getState(); - bool HasAutoGenerated = false; + // The constraint manager has not been cleaned up yet, so clean up now. + CheckerState = getConstraintManager().removeDeadBindings(CheckerState, + SymReaper); - for (ExplodedNodeSet::iterator I=Tmp.begin(), E=Tmp.end(); I!=E; ++I) { - ExplodedNodeSet Dst; + assert(StateMgr.haveEqualEnvironments(CheckerState, EntryState) && + "Checkers are not allowed to modify the Environment as a part of " + "checkDeadSymbols processing."); + assert(StateMgr.haveEqualStores(CheckerState, EntryState) && + "Checkers are not allowed to modify the Store as a part of " + "checkDeadSymbols processing."); - // Set the cleaned state. - Builder->SetCleanedState(*I == EntryNode ? CleanedState : GetState(*I)); + // Create a state based on CleanedState with CheckerState GDM and + // generate a transition to that state. + const GRState *CleanedCheckerSt = + StateMgr.getPersistentStateWithGDM(CleanedState, CheckerState); + ExplodedNode *CleanedNode = Builder->generateNode(currentStmt, + CleanedCheckerSt, *I, + &tag); + Tmp.Add(CleanedNode); + } + } + for (ExplodedNodeSet::iterator I=Tmp.begin(), E=Tmp.end(); I!=E; ++I) { + // TODO: Remove Dest set, it's no longer needed. + ExplodedNodeSet Dst; // Visit the statement. Visit(currentStmt, *I, Dst); - - // Do we need to auto-generate a node? We only need to do this to generate - // a node with a "cleaned" state; CoreEngine will actually handle - // auto-transitions for other cases. - if (Dst.size() == 1 && *Dst.begin() == EntryNode - && !Builder->hasGeneratedNode && !HasAutoGenerated) { - HasAutoGenerated = true; - builder.generateNode(currentStmt, GetState(EntryNode), *I); - } } // NULL out these variables to cleanup. CleanedState = NULL; EntryNode = NULL; - currentStmt = 0; - Builder = NULL; } |