From 846d4e923bf11bcdc2816758aafa331795f29230 Mon Sep 17 00:00:00 2001 From: Ted Kremenek Date: Thu, 24 Apr 2008 23:35:58 +0000 Subject: [PATCH] More boilerplate for handling specialized-transfer function logic for dead symbols. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@50233 91177308-0d34-0410-b5e6-96231b3b80d8 --- .../Analysis/PathSensitive/GRExprEngine.h | 12 ++-- .../Analysis/PathSensitive/GRTransferFuncs.h | 10 ++- lib/Analysis/GRExprEngine.cpp | 61 ++++++++++--------- 3 files changed, 47 insertions(+), 36 deletions(-) diff --git a/include/clang/Analysis/PathSensitive/GRExprEngine.h b/include/clang/Analysis/PathSensitive/GRExprEngine.h index 819043edb4..de8807a201 100644 --- a/include/clang/Analysis/PathSensitive/GRExprEngine.h +++ b/include/clang/Analysis/PathSensitive/GRExprEngine.h @@ -78,12 +78,12 @@ protected: /// 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; @@ -392,7 +392,7 @@ public: 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); diff --git a/include/clang/Analysis/PathSensitive/GRTransferFuncs.h b/include/clang/Analysis/PathSensitive/GRTransferFuncs.h index 47f5d2a59d..769353039c 100644 --- a/include/clang/Analysis/PathSensitive/GRTransferFuncs.h +++ b/include/clang/Analysis/PathSensitive/GRTransferFuncs.h @@ -84,11 +84,19 @@ public: ValueState* St, RVal TargetLV, RVal Val); - // End-of-path. + // End-of-path and dead symbol notification. virtual void EvalEndPath(GRExprEngine& Engine, GREndPathNodeBuilder& Builder) {} + + virtual void EvalDeadSymbols(ExplodedNodeSet& Dst, + GRExprEngine& Engine, + GRStmtNodeBuilder& Builder, + ProgramPoint P, ExplodedNode* Pred, + ValueState* St, + const ValueStateManager::DeadSymbolsTy& Dead) {} + // Return statements. virtual void EvalReturn(ExplodedNodeSet& Dst, diff --git a/lib/Analysis/GRExprEngine.cpp b/lib/Analysis/GRExprEngine.cpp index a287e54298..0438059f6c 100644 --- a/lib/Analysis/GRExprEngine.cpp +++ b/lib/Analysis/GRExprEngine.cpp @@ -42,7 +42,7 @@ GRExprEngine::GRExprEngine(CFG& cfg, Decl& CD, ASTContext& Ctx) BasicVals(StateMgr.getBasicValueFactory()), TF(NULL), // FIXME SymMgr(StateMgr.getSymbolManager()), - StmtEntryNode(NULL), CleanedState(NULL), CurrentStmt(NULL) { + CurrentStmt(NULL) { // Compute liveness information. Liveness.runOnCFG(G.getCFG()); @@ -167,9 +167,8 @@ ValueState* GRExprEngine::SetRVal(ValueState* St, Expr* Ex, RVal V) { void GRExprEngine::ProcessStmt(Stmt* S, StmtNodeBuilder& builder) { Builder = &builder; - StmtEntryNode = builder.getLastNode(); + EntryNode = builder.getLastNode(); CurrentStmt = S; - NodeSet Dst; // Set up our simple checks. @@ -187,49 +186,53 @@ void GRExprEngine::ProcessStmt(Stmt* S, StmtNodeBuilder& builder) { // 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 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) { -- 2.40.0