]> granicus.if.org Git - clang/commitdiff
Add new GRWorkList class that uses two queues:
authorTed Kremenek <kremenek@apple.com>
Tue, 16 Dec 2008 22:13:33 +0000 (22:13 +0000)
committerTed Kremenek <kremenek@apple.com>
Tue, 16 Dec 2008 22:13:33 +0000 (22:13 +0000)
- 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

include/clang/Analysis/PathSensitive/GRCoreEngine.h
include/clang/Analysis/PathSensitive/GRWorkList.h
lib/Analysis/GRCoreEngine.cpp

index e3a723fd637e5554aeb2e96de4f44cbc5c0231e5..d656bc7cfca0acf4d13625d669a5e58690d09975 100644 (file)
@@ -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
index 69178fb9cce3d737b29d1b454f8368d780ef23aa..de7ea5ebd6fbc935c23f29e0c42db7d455dd8775 100644 (file)
@@ -69,6 +69,7 @@ public:
   GRBlockCounter getBlockCounter() const { return CurrentCounter; }
   
   static GRWorkList* MakeDFS(); 
+  static GRWorkList* MakeBFSBlockDFSContents();
 };
 } // end clang namespace  
 #endif
index 44c9b4871f3446575481f151f14a9868d07850f4..42ea41382eb29bab24594775f7121be6efe03a0a 100644 (file)
 #include "llvm/Support/Casting.h"
 #include "llvm/ADT/DenseMap.h"
 #include <vector>
+#include <queue>
 
 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<GRWorkListUnit,20> Stack;
@@ -50,6 +55,48 @@ GRWorkList::~GRWorkList() {}
 
 GRWorkList* GRWorkList::MakeDFS() { return new DFS(); }
 
+namespace {
+  class VISIBILITY_HIDDEN BFSBlockDFSContents : public GRWorkList {
+    std::queue<GRWorkListUnit> Queue;
+    llvm::SmallVector<GRWorkListUnit,20> Stack;
+  public:
+    virtual bool hasWork() const {
+      return !Queue.empty() || !Stack.empty();
+    }
+    
+    virtual void Enqueue(const GRWorkListUnit& U) {
+      if (isa<BlockEntrance>(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<BlockEdge>(Node->getLocation()));
+      case ProgramPoint::BlockEdgeKind:
         HandleBlockEdge(cast<BlockEdge>(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<PostStmt>(Node->getLocation()));
         HandlePostStmt(cast<PostStmt>(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);