/// SymMgr - Object that manages the symbol information.
SymbolManager& SymMgr;
- /// StmtEntryNode - The immediate predecessor node.
- NodeTy* StmtEntryNode;
-
- /// CleanedState - The state for StmtEntryNode "cleaned" of all dead
+ /// EntryNode - The immediate predecessor node.
+ NodeTy* EntryNode;
+
+ /// CleanedState - The state for EntryNode "cleaned" of all dead
/// variables and symbols (as determined by a liveness analysis).
- ValueState* CleanedState;
+ ValueState* CleanedState;
/// CurrentStmt - The current block-level statement.
Stmt* CurrentStmt;
protected:
ValueState* GetState(NodeTy* N) {
- return N == StmtEntryNode ? CleanedState : N->getState();
+ return N == EntryNode ? CleanedState : N->getState();
}
ValueState* SetRVal(ValueState* St, Expr* Ex, RVal V);
ValueState* St, RVal TargetLV, RVal Val);
- // End-of-path.
+ // End-of-path and dead symbol notification.
virtual void EvalEndPath(GRExprEngine& Engine,
GREndPathNodeBuilder<ValueState>& Builder) {}
+
+ virtual void EvalDeadSymbols(ExplodedNodeSet<ValueState>& Dst,
+ GRExprEngine& Engine,
+ GRStmtNodeBuilder<ValueState>& Builder,
+ ProgramPoint P, ExplodedNode<ValueState>* Pred,
+ ValueState* St,
+ const ValueStateManager::DeadSymbolsTy& Dead) {}
+
// Return statements.
virtual void EvalReturn(ExplodedNodeSet<ValueState>& Dst,
BasicVals(StateMgr.getBasicValueFactory()),
TF(NULL), // FIXME
SymMgr(StateMgr.getSymbolManager()),
- StmtEntryNode(NULL), CleanedState(NULL), CurrentStmt(NULL) {
+ CurrentStmt(NULL) {
// Compute liveness information.
Liveness.runOnCFG(G.getCFG());
void GRExprEngine::ProcessStmt(Stmt* S, StmtNodeBuilder& builder) {
Builder = &builder;
- StmtEntryNode = builder.getLastNode();
+ EntryNode = builder.getLastNode();
CurrentStmt = S;
- NodeSet Dst;
// Set up our simple checks.
// Create the cleaned state.
- CleanedState = StateMgr.RemoveDeadBindings(StmtEntryNode->getState(),
- CurrentStmt, Liveness,
- DeadSymbols);
+ CleanedState = StateMgr.RemoveDeadBindings(EntryNode->getState(), CurrentStmt,
+ Liveness, DeadSymbols);
// Process any special transfer function for dead symbols.
NodeSet Tmp;
if (DeadSymbols.empty())
- Tmp.Add(StmtEntryNode);
+ Tmp.Add(EntryNode);
else {
SaveAndRestore<bool> OldSink(Builder->BuildSinks);
-/*
- FIXME: Will hook this up next.
-
- TF->EvalDeadSymbols(Tmp, *this, *Builder, StmtEntryNode->getLocation(), Pred,
- CleanedState, DeadSymbols);
-*/
- if (!Builder->BuildSinks && Tmp.empty() && !Builder->HasGeneratedNode)
- Tmp.Add(StmtEntryNode);
+ SaveOr OldHasGen(Builder->HasGeneratedNode);
+
+ TF->EvalDeadSymbols(Tmp, *this, *Builder, EntryNode->getLocation(),
+ EntryNode, CleanedState, DeadSymbols);
+
+ if (!Builder->BuildSinks && !Builder->HasGeneratedNode)
+ Tmp.Add(EntryNode);
}
-
+
+ bool HasAutoGenerated = false;
+
for (NodeSet::iterator I=Tmp.begin(), E=Tmp.end(); I!=E; ++I) {
+
+ NodeSet Dst;
+
// Set the cleaned state.
- Builder->SetCleanedState(*I == StmtEntryNode ? CleanedState : (*I)->getState());
-
+ Builder->SetCleanedState(*I == EntryNode ? CleanedState : GetState(*I));
+
// Visit the statement.
- Visit(S, StmtEntryNode, Dst);
+ Visit(S, *I, Dst);
+
+ // Do we need to auto-generate a node? We only need to do this to generate
+ // a node with a "cleaned" state; GRCoreEngine will actually handle
+ // auto-transitions for other cases.
+ if (Dst.size() == 1 && *Dst.begin() == EntryNode
+ && !Builder->HasGeneratedNode && !HasAutoGenerated) {
+ HasAutoGenerated = true;
+ builder.generateNode(S, GetState(EntryNode), *I);
+ }
}
- // If no nodes were generated, generate a new node that has all the
- // dead mappings removed.
-
- if (Dst.size() == 1 && *Dst.begin() == StmtEntryNode &&
- !Builder->HasGeneratedNode)
- builder.generateNode(S, GetState(StmtEntryNode), StmtEntryNode);
-
// NULL out these variables to cleanup.
-
+ CleanedState = NULL;
+ EntryNode = NULL;
CurrentStmt = NULL;
- StmtEntryNode = NULL;
Builder = NULL;
- CleanedState = NULL;
}
void GRExprEngine::Visit(Stmt* S, NodeTy* Pred, NodeSet& Dst) {