diff options
Diffstat (limited to 'lib/StaticAnalyzer/Core/CoreEngine.cpp')
-rw-r--r-- | lib/StaticAnalyzer/Core/CoreEngine.cpp | 59 |
1 files changed, 32 insertions, 27 deletions
diff --git a/lib/StaticAnalyzer/Core/CoreEngine.cpp b/lib/StaticAnalyzer/Core/CoreEngine.cpp index b09b2c2..4623c35 100644 --- a/lib/StaticAnalyzer/Core/CoreEngine.cpp +++ b/lib/StaticAnalyzer/Core/CoreEngine.cpp @@ -12,8 +12,6 @@ // //===----------------------------------------------------------------------===// -#define DEBUG_TYPE "CoreEngine" - #include "clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h" #include "clang/AST/Expr.h" #include "clang/AST/StmtCXX.h" @@ -26,6 +24,8 @@ using namespace clang; using namespace ento; +#define DEBUG_TYPE "CoreEngine" + STATISTIC(NumSteps, "The # of steps executed."); STATISTIC(NumReachedMaxSteps, @@ -43,22 +43,22 @@ namespace { class DFS : public WorkList { SmallVector<WorkListUnit,20> Stack; public: - virtual bool hasWork() const { + bool hasWork() const override { return !Stack.empty(); } - virtual void enqueue(const WorkListUnit& U) { + void enqueue(const WorkListUnit& U) override { Stack.push_back(U); } - virtual WorkListUnit dequeue() { + WorkListUnit dequeue() override { assert (!Stack.empty()); const WorkListUnit& U = Stack.back(); Stack.pop_back(); // This technically "invalidates" U, but we are fine. return U; } - - virtual bool visitItemsInWorkList(Visitor &V) { + + bool visitItemsInWorkList(Visitor &V) override { for (SmallVectorImpl<WorkListUnit>::iterator I = Stack.begin(), E = Stack.end(); I != E; ++I) { if (V.visit(*I)) @@ -71,21 +71,21 @@ public: class BFS : public WorkList { std::deque<WorkListUnit> Queue; public: - virtual bool hasWork() const { + bool hasWork() const override { return !Queue.empty(); } - virtual void enqueue(const WorkListUnit& U) { + void enqueue(const WorkListUnit& U) override { Queue.push_back(U); } - virtual WorkListUnit dequeue() { + WorkListUnit dequeue() override { WorkListUnit U = Queue.front(); Queue.pop_front(); return U; } - - virtual bool visitItemsInWorkList(Visitor &V) { + + bool visitItemsInWorkList(Visitor &V) override { for (std::deque<WorkListUnit>::iterator I = Queue.begin(), E = Queue.end(); I != E; ++I) { if (V.visit(*I)) @@ -109,18 +109,18 @@ namespace { std::deque<WorkListUnit> Queue; SmallVector<WorkListUnit,20> Stack; public: - virtual bool hasWork() const { + bool hasWork() const override { return !Queue.empty() || !Stack.empty(); } - virtual void enqueue(const WorkListUnit& U) { + void enqueue(const WorkListUnit& U) override { if (U.getNode()->getLocation().getAs<BlockEntrance>()) Queue.push_front(U); else Stack.push_back(U); } - virtual WorkListUnit dequeue() { + WorkListUnit dequeue() override { // Process all basic blocks to completion. if (!Stack.empty()) { const WorkListUnit& U = Stack.back(); @@ -135,7 +135,7 @@ namespace { Queue.pop_front(); return U; } - virtual bool visitItemsInWorkList(Visitor &V) { + bool visitItemsInWorkList(Visitor &V) override { for (SmallVectorImpl<WorkListUnit>::iterator I = Stack.begin(), E = Stack.end(); I != E; ++I) { if (V.visit(*I)) @@ -192,9 +192,9 @@ bool CoreEngine::ExecuteWorkList(const LocationContext *L, unsigned Steps, if (!InitState) // Generate the root. - generateNode(StartLoc, SubEng.getInitialState(L), 0); + generateNode(StartLoc, SubEng.getInitialState(L), nullptr); else - generateNode(StartLoc, InitState, 0); + generateNode(StartLoc, InitState, nullptr); } // Check if we have a steps limit @@ -532,11 +532,16 @@ void CoreEngine::enqueueStmtNode(ExplodedNode *N, return; } + if ((*Block)[Idx].getKind() == CFGElement::NewAllocator) { + WList->enqueue(N, Block, Idx+1); + return; + } + // At this point, we know we're processing a normal statement. CFGStmt CS = (*Block)[Idx].castAs<CFGStmt>(); PostStmt Loc(CS.getStmt(), N->getLocationContext()); - if (Loc == N->getLocation()) { + if (Loc == N->getLocation().withTag(nullptr)) { // Note: 'N' should be a fresh node because otherwise it shouldn't be // a member of Deferred. WList->enqueue(N, Block, Idx+1); @@ -562,7 +567,7 @@ ExplodedNode *CoreEngine::generateCallExitBeginNode(ExplodedNode *N) { bool isNew; ExplodedNode *Node = G->getNode(Loc, N->getState(), false, &isNew); Node->addPredecessor(N, *G); - return isNew ? Node : 0; + return isNew ? Node : nullptr; } @@ -611,7 +616,7 @@ ExplodedNode* NodeBuilder::generateNodeImpl(const ProgramPoint &Loc, Frontier.erase(FromN); if (!IsNew) - return 0; + return nullptr; if (!MarkAsSink) Frontier.Add(N); @@ -635,7 +640,7 @@ ExplodedNode *BranchNodeBuilder::generateNode(ProgramStateRef State, ExplodedNode *NodePred) { // If the branch has been marked infeasible we should not generate a node. if (!isFeasible(branch)) - return NULL; + return nullptr; ProgramPoint Loc = BlockEdge(C.Block, branch ? DstT:DstF, NodePred->getLocationContext()); @@ -654,7 +659,7 @@ IndirectGotoNodeBuilder::generateNode(const iterator &I, Succ->addPredecessor(Pred, *Eng.G); if (!IsNew) - return 0; + return nullptr; if (!IsSink) Eng.WList->enqueue(Succ); @@ -673,7 +678,7 @@ SwitchNodeBuilder::generateCaseStmtNode(const iterator &I, false, &IsNew); Succ->addPredecessor(Pred, *Eng.G); if (!IsNew) - return 0; + return nullptr; Eng.WList->enqueue(Succ); return Succ; @@ -690,8 +695,8 @@ SwitchNodeBuilder::generateDefaultCaseNode(ProgramStateRef St, // Sanity check for default blocks that are unreachable and not caught // by earlier stages. if (!DefaultBlock) - return NULL; - + return nullptr; + bool IsNew; ExplodedNode *Succ = Eng.G->getNode(BlockEdge(Src, DefaultBlock, Pred->getLocationContext()), St, @@ -699,7 +704,7 @@ SwitchNodeBuilder::generateDefaultCaseNode(ProgramStateRef St, Succ->addPredecessor(Pred, *Eng.G); if (!IsNew) - return 0; + return nullptr; if (!IsSink) Eng.WList->enqueue(Succ); |