From b1d3d968725baf28a00b12aad760434036cbe704 Mon Sep 17 00:00:00 2001 From: Anna Zaks Date: Thu, 27 Oct 2011 00:59:23 +0000 Subject: [PATCH] [analyzer] Make CoreEngine responsible for enqueueing Stmt Nodes. Enqueue the nodes generated as the result of processing a statement inside the Core Engine. This makes sure ExpEngine does not access CoreEngine's private members and is more concise. llvm-svn: 143089 --- .../Core/PathSensitive/CoreEngine.h | 9 ++- clang/lib/StaticAnalyzer/Core/CoreEngine.cpp | 52 +++++++++++++- clang/lib/StaticAnalyzer/Core/ExprEngine.cpp | 72 +++---------------- 3 files changed, 68 insertions(+), 65 deletions(-) diff --git a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h index 0bc20662bfbc..ca98e637e055 100644 --- a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h +++ b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h @@ -100,6 +100,9 @@ private: CoreEngine(const CoreEngine&); // Do not implement. CoreEngine& operator=(const CoreEngine&); + void enqueueStmtNode(ExplodedNode *N, + const CFGBlock *Block, unsigned Idx); + public: /// Construct a CoreEngine object to analyze the provided CFG using /// a DFS exploration of the exploded graph. @@ -163,8 +166,12 @@ public: return blocksAborted.end(); } - /// Enqueue the results of the node builder onto the work list. + /// \brief Enqueue the given set of nodes onto the work list. void enqueue(ExplodedNodeSet &NB); + + /// \brief Enqueue nodes that were created as a result of processing + /// a statement onto the work list. + void enqueue(ExplodedNodeSet &Set, const CFGBlock *Block, unsigned Idx); }; // TODO: Turn into a calss. diff --git a/clang/lib/StaticAnalyzer/Core/CoreEngine.cpp b/clang/lib/StaticAnalyzer/Core/CoreEngine.cpp index f69391724271..e88a8f1963db 100644 --- a/clang/lib/StaticAnalyzer/Core/CoreEngine.cpp +++ b/clang/lib/StaticAnalyzer/Core/CoreEngine.cpp @@ -454,13 +454,59 @@ void CoreEngine::generateNode(const ProgramPoint &Loc, if (IsNew) WList->enqueue(Node); } -void CoreEngine::enqueue(ExplodedNodeSet &S) { - for (ExplodedNodeSet::iterator I = S.begin(), - E = S.end(); I != E; ++I) { +void CoreEngine::enqueueStmtNode(ExplodedNode *N, + const CFGBlock *Block, unsigned Idx) { + assert (!N->isSink()); + + // Check if this node entered a callee. + if (isa(N->getLocation())) { + // Still use the index of the CallExpr. It's needed to create the callee + // StackFrameContext. + WList->enqueue(N, Block, Idx); + return; + } + + // Do not create extra nodes. Move to the next CFG element. + if (isa(N->getLocation())) { + WList->enqueue(N, Block, Idx+1); + return; + } + + const CFGStmt *CS = (*Block)[Idx].getAs(); + const Stmt *St = CS ? CS->getStmt() : 0; + PostStmt Loc(St, N->getLocationContext()); + + if (Loc == N->getLocation()) { + // Note: 'N' should be a fresh node because otherwise it shouldn't be + // a member of Deferred. + WList->enqueue(N, Block, Idx+1); + return; + } + + bool IsNew; + ExplodedNode *Succ = G->getNode(Loc, N->getState(), &IsNew); + Succ->addPredecessor(N, *G); + + if (IsNew) + WList->enqueue(Succ, Block, Idx+1); +} + +void CoreEngine::enqueue(ExplodedNodeSet &Set) { + for (ExplodedNodeSet::iterator I = Set.begin(), + E = Set.end(); I != E; ++I) { WList->enqueue(*I); } } +void CoreEngine::enqueue(ExplodedNodeSet &Set, + const CFGBlock *Block, unsigned Idx) { + for (ExplodedNodeSet::iterator I = Set.begin(), + E = Set.end(); I != E; ++I) { + enqueueStmtNode(*I, Block, Idx); + } +} + + ExplodedNode* NodeBuilder::generateNodeImpl(const ProgramPoint &Loc, const ProgramState *State, ExplodedNode *FromN, diff --git a/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp b/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp index 24fa04bd564d..2c5379f66a72 100644 --- a/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp +++ b/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp @@ -220,50 +220,6 @@ void ExprEngine::processCFGElement(const CFGElement E, ExplodedNode *Pred, currentBuilderContext = 0; } -const Stmt *ExprEngine::getStmt() const { - const CFGStmt *CS = (*currentBuilderContext->getBlock())[currentStmtIdx] - .getAs(); - return CS ? CS->getStmt() : 0; -} - -// TODO: Adding nodes to the worklist shoudl be a function inside CoreEngine. -void ExprEngine::GenerateAutoTransition(ExplodedNode *N) { - assert (!N->isSink()); - const CFGBlock *Block = currentBuilderContext->getBlock(); - unsigned Idx = currentStmtIdx; - - // Check if this node entered a callee. - if (isa(N->getLocation())) { - // Still use the index of the CallExpr. It's needed to create the callee - // StackFrameContext. - Engine.WList->enqueue(N, Block, Idx); - return; - } - - // Do not create extra nodes. Move to the next CFG element. - if (isa(N->getLocation())) { - Engine.WList->enqueue(N, Block, Idx+1); - return; - } - - PostStmt Loc(getStmt(), N->getLocationContext()); - - if (Loc == N->getLocation()) { - // Note: 'N' should be a fresh node because otherwise it shouldn't be - // a member of Deferred. - Engine.WList->enqueue(N, Block, Idx+1); - return; - } - - bool IsNew; - ExplodedNode *Succ = Engine.G->getNode(Loc, N->getState(), &IsNew); - Succ->addPredecessor(N, *Engine.G); - - if (IsNew) - Engine.WList->enqueue(Succ, Block, Idx+1); -} - - void ExprEngine::ProcessStmt(const CFGStmt S, ExplodedNode *Pred) { // TODO: Use RAII to remove the unnecessary, tagged nodes. @@ -346,19 +302,16 @@ void ExprEngine::ProcessStmt(const CFGStmt S, } } - ExplodedNodeSet AllDst; + ExplodedNodeSet Dst; for (ExplodedNodeSet::iterator I=Tmp.begin(), E=Tmp.end(); I!=E; ++I) { - ExplodedNodeSet Dst; + ExplodedNodeSet DstI; // Visit the statement. - Visit(currentStmt, *I, Dst); - AllDst.insert(Dst); + Visit(currentStmt, *I, DstI); + Dst.insert(DstI); } - for (ExplodedNodeSet::iterator I = AllDst.begin(), - E = AllDst.end(); I != E; ++I) { - assert(!(*I)->isSink()); - GenerateAutoTransition(*I); - } + // Enqueue the new nodes onto the work list. + Engine.enqueue(Dst, currentBuilderContext->getBlock(), currentStmtIdx); // NULL out these variables to cleanup. CleanedState = NULL; @@ -418,10 +371,9 @@ void ExprEngine::ProcessInitializer(const CFGInitializer Init, VisitCXXConstructExpr(ctorExpr, baseReg, Pred, Dst); } - for (ExplodedNodeSet::iterator I = Dst.begin(), - E = Dst.end(); I != E; ++I) { - GenerateAutoTransition(*I); - } + + // Enqueue the new nodes onto the work list. + Engine.enqueue(Dst, currentBuilderContext->getBlock(), currentStmtIdx); } void ExprEngine::ProcessImplicitDtor(const CFGImplicitDtor D, @@ -444,10 +396,8 @@ void ExprEngine::ProcessImplicitDtor(const CFGImplicitDtor D, llvm_unreachable("Unexpected dtor kind."); } - for (ExplodedNodeSet::iterator I = Dst.begin(), - E = Dst.end(); I != E; ++I) { - GenerateAutoTransition(*I); - } + // Enqueue the new nodes onto the work list. + Engine.enqueue(Dst, currentBuilderContext->getBlock(), currentStmtIdx); } void ExprEngine::ProcessAutomaticObjDtor(const CFGAutomaticObjDtor Dtor,