From e1efd4de8685e0785daf9cab227f7a21cfc9c80b Mon Sep 17 00:00:00 2001 From: Ted Kremenek Date: Tue, 16 Dec 2008 22:13:33 +0000 Subject: [PATCH] Add new GRWorkList class that uses two queues: - one queue (FIFO) to queue up nodes at block entrances - another queue (LIFO) to queue up other nodes - The idea is to explore basic blocks to completion, but to do a BFS exploration of blocks. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@61106 91177308-0d34-0410-b5e6-96231b3b80d8 --- .../Analysis/PathSensitive/GRCoreEngine.h | 3 +- .../clang/Analysis/PathSensitive/GRWorkList.h | 1 + lib/Analysis/GRCoreEngine.cpp | 68 +++++++++++++++++-- 3 files changed, 66 insertions(+), 6 deletions(-) diff --git a/include/clang/Analysis/PathSensitive/GRCoreEngine.h b/include/clang/Analysis/PathSensitive/GRCoreEngine.h index e3a723fd63..d656bc7cfc 100644 --- a/include/clang/Analysis/PathSensitive/GRCoreEngine.h +++ b/include/clang/Analysis/PathSensitive/GRCoreEngine.h @@ -613,7 +613,8 @@ public: /// Construct a GRCoreEngine object to analyze the provided CFG using /// a DFS exploration of the exploded graph. GRCoreEngine(CFG& cfg, Decl& cd, ASTContext& ctx, SubEngineTy& subengine) - : GRCoreEngineImpl(new GraphTy(cfg, cd, ctx), GRWorkList::MakeDFS()), + : GRCoreEngineImpl(new GraphTy(cfg, cd, ctx), + GRWorkList::MakeBFSBlockDFSContents()), SubEngine(subengine) {} /// Construct a GRCoreEngine object to analyze the provided CFG and to diff --git a/include/clang/Analysis/PathSensitive/GRWorkList.h b/include/clang/Analysis/PathSensitive/GRWorkList.h index 69178fb9cc..de7ea5ebd6 100644 --- a/include/clang/Analysis/PathSensitive/GRWorkList.h +++ b/include/clang/Analysis/PathSensitive/GRWorkList.h @@ -69,6 +69,7 @@ public: GRBlockCounter getBlockCounter() const { return CurrentCounter; } static GRWorkList* MakeDFS(); + static GRWorkList* MakeBFSBlockDFSContents(); }; } // end clang namespace #endif diff --git a/lib/Analysis/GRCoreEngine.cpp b/lib/Analysis/GRCoreEngine.cpp index 44c9b4871f..42ea41382e 100644 --- a/lib/Analysis/GRCoreEngine.cpp +++ b/lib/Analysis/GRCoreEngine.cpp @@ -18,11 +18,16 @@ #include "llvm/Support/Casting.h" #include "llvm/ADT/DenseMap.h" #include +#include using llvm::cast; using llvm::isa; using namespace clang; +//===----------------------------------------------------------------------===// +// Worklist classes for exploration of reachable states. +//===----------------------------------------------------------------------===// + namespace { class VISIBILITY_HIDDEN DFS : public GRWorkList { llvm::SmallVector Stack; @@ -50,6 +55,48 @@ GRWorkList::~GRWorkList() {} GRWorkList* GRWorkList::MakeDFS() { return new DFS(); } +namespace { + class VISIBILITY_HIDDEN BFSBlockDFSContents : public GRWorkList { + std::queue Queue; + llvm::SmallVector Stack; + public: + virtual bool hasWork() const { + return !Queue.empty() || !Stack.empty(); + } + + virtual void Enqueue(const GRWorkListUnit& U) { + if (isa(U.getNode()->getLocation())) + Queue.push(U); + else + Stack.push_back(U); + } + + virtual GRWorkListUnit Dequeue() { + // Process all basic blocks to completion. + if (!Stack.empty()) { + const GRWorkListUnit& U = Stack.back(); + Stack.pop_back(); // This technically "invalidates" U, but we are fine. + return U; + } + + assert(!Queue.empty()); + // Don't use const reference. The subsequent pop_back() might make it + // unsafe. + GRWorkListUnit U = Queue.front(); + Queue.pop(); + return U; + } + }; +} // end anonymous namespace + +GRWorkList* GRWorkList::MakeBFSBlockDFSContents() { + return new BFSBlockDFSContents(); +} + +//===----------------------------------------------------------------------===// +// Core analysis engine. +//===----------------------------------------------------------------------===// + /// ExecuteWorkList - Run the worklist algorithm for a maximum number of steps. bool GRCoreEngineImpl::ExecuteWorkList(unsigned Steps) { @@ -90,8 +137,7 @@ bool GRCoreEngineImpl::ExecuteWorkList(unsigned Steps) { // Dispatch on the location type. switch (Node->getLocation().getKind()) { - default: - assert (isa(Node->getLocation())); + case ProgramPoint::BlockEdgeKind: HandleBlockEdge(cast(Node->getLocation()), Node); break; @@ -102,9 +148,9 @@ bool GRCoreEngineImpl::ExecuteWorkList(unsigned Steps) { case ProgramPoint::BlockExitKind: assert (false && "BlockExit location never occur in forward analysis."); break; - - case ProgramPoint::PostLoadKind: - case ProgramPoint::PostStmtKind: + + default: + assert(isa(Node->getLocation())); HandlePostStmt(cast(Node->getLocation()), WU.getBlock(), WU.getIndex(), Node); break; @@ -332,6 +378,18 @@ static inline ProgramPoint GetPostLoc(Stmt* S, ProgramPoint::Kind K) { case ProgramPoint::PostLoadKind: return PostLoad(S); + + case ProgramPoint::PostUndefLocationCheckFailedKind: + return PostUndefLocationCheckFailed(S); + + case ProgramPoint::PostLocationChecksSucceedKind: + return PostLocationChecksSucceed(S); + + case ProgramPoint::PostOutOfBoundsCheckFailedKind: + return PostOutOfBoundsCheckFailed(S); + + case ProgramPoint::PostNullCheckFailedKind: + return PostNullCheckFailed(S); case ProgramPoint::PostStoreKind: return PostStore(S);