]> granicus.if.org Git - clang/commitdiff
[analyzer] Make CoreEngine responsible for enqueueing Stmt Nodes.
authorAnna Zaks <ganna@apple.com>
Thu, 27 Oct 2011 00:59:23 +0000 (00:59 +0000)
committerAnna Zaks <ganna@apple.com>
Thu, 27 Oct 2011 00:59:23 +0000 (00:59 +0000)
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.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@143089 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h
lib/StaticAnalyzer/Core/CoreEngine.cpp
lib/StaticAnalyzer/Core/ExprEngine.cpp

index 0bc20662bfbca406948ad1210e431a7071e6ba43..ca98e637e0553fef3361f5c305cefcf3f097fdc2 100644 (file)
@@ -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.
index f6939172427154bc0b91a814a1289685b61eefd2..e88a8f1963db5ee7e503300f3fa746a5606dc12a 100644 (file)
@@ -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<CallEnter>(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<PostInitializer>(N->getLocation())) {
+    WList->enqueue(N, Block, Idx+1);
+    return;
+  }
+
+  const CFGStmt *CS = (*Block)[Idx].getAs<CFGStmt>();
+  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,
index 24fa04bd564d53b2c511a71ab1dcd3662584febe..2c5379f66a7266e7d3e44d9d8f01bf9569c73af4 100644 (file)
@@ -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<CFGStmt>();
-  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<CallEnter>(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<PostInitializer>(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,