[cfe-commits] r137273 - in /cfe/trunk: include/clang/StaticAnalyzer/Core/PathSensitive/GRState.h lib/StaticAnalyzer/Core/ExprEngine.cpp lib/StaticAnalyzer/Core/GRState.cpp
Anna Zaks
ganna at apple.com
Wed Aug 10 16:14:54 PDT 2011
Author: zaks
Date: Wed Aug 10 18:14:54 2011
New Revision: 137273
URL: http://llvm.org/viewvc/llvm-project?rev=137273&view=rev
Log:
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.
Modified:
cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/GRState.h
cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp
cfe/trunk/lib/StaticAnalyzer/Core/GRState.cpp
Modified: cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/GRState.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/GRState.h?rev=137273&r1=137272&r2=137273&view=diff
==============================================================================
--- cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/GRState.h (original)
+++ cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/GRState.h Wed Aug 10 18:14:54 2011
@@ -540,7 +540,17 @@
}
const GRState* getPersistentState(GRState& Impl);
-
+ const GRState* getPersistentStateWithGDM(const GRState *FromState,
+ const GRState *GDMState);
+
+ bool haveEqualEnvironments(const GRState * S1, const GRState * S2) {
+ return S1->Env == S2->Env;
+ }
+
+ bool haveEqualStores(const GRState * S1, const GRState * S2) {
+ return S1->store == S2->store;
+ }
+
/// Periodically called by ExprEngine to recycle GRStates that were
/// created but never used for creating an ExplodedNode.
void recycleUnusedStates();
@@ -690,7 +700,7 @@
inline SVal GRState::getSVal(const Stmt* Ex, bool useOnlyDirectBindings) const{
return Env.getSVal(Ex, *getStateManager().svalBuilder,
- useOnlyDirectBindings);
+ useOnlyDirectBindings);
}
inline SVal GRState::getSValAsScalarOrLoc(const Stmt *S) const {
Modified: cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp?rev=137273&r1=137272&r2=137273&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp Wed Aug 10 18:14:54 2011
@@ -229,6 +229,9 @@
}
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 @@
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();
+
+ // The constraint manager has not been cleaned up yet, so clean up now.
+ CheckerState = getConstraintManager().removeDeadBindings(CheckerState,
+ SymReaper);
+
+ 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.");
+
+ // 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);
+ }
}
- bool HasAutoGenerated = false;
-
for (ExplodedNodeSet::iterator I=Tmp.begin(), E=Tmp.end(); I!=E; ++I) {
+ // TODO: Remove Dest set, it's no longer needed.
ExplodedNodeSet Dst;
-
- // Set the cleaned state.
- Builder->SetCleanedState(*I == EntryNode ? CleanedState : GetState(*I));
-
// 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;
}
Modified: cfe/trunk/lib/StaticAnalyzer/Core/GRState.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/GRState.cpp?rev=137273&r1=137272&r2=137273&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Core/GRState.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Core/GRState.cpp Wed Aug 10 18:14:54 2011
@@ -81,8 +81,7 @@
NewState.setStore(newStore);
SymReaper.setReapedStore(newStore);
- state = getPersistentState(NewState);
- return ConstraintMgr->removeDeadBindings(state, SymReaper);
+ return getPersistentState(NewState);
}
const GRState *GRStateManager::MarshalState(const GRState *state,
@@ -338,6 +337,14 @@
recentlyAllocatedStates.clear();
}
+const GRState* GRStateManager::getPersistentStateWithGDM(
+ const GRState *FromState,
+ const GRState *GDMState) {
+ GRState NewState = *FromState;
+ NewState.GDM = GDMState->GDM;
+ return getPersistentState(NewState);
+}
+
const GRState* GRStateManager::getPersistentState(GRState& State) {
llvm::FoldingSetNodeID ID;
More information about the cfe-commits
mailing list