]> granicus.if.org Git - clang/commitdiff
[analyzer] Pass external Dst set to NodeBuilder
authorAnna Zaks <ganna@apple.com>
Mon, 24 Oct 2011 18:25:53 +0000 (18:25 +0000)
committerAnna Zaks <ganna@apple.com>
Mon, 24 Oct 2011 18:25:53 +0000 (18:25 +0000)
This moves the responsibility for storing the output node set from the
builder to the clients. The builder is just responsible for transforming
an input set into the output set: {SrcSet/SrcNode} -> {Frontier}.

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

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

index ad587ae928d445c1c850c51a757632b88ad2c8fd..522749c37c26bafde5a029faa5cc6817246a226a 100644 (file)
@@ -29,8 +29,6 @@ class CheckerContext {
   const ProgramPoint Location;
   const ProgramState *ST;
   const unsigned size;
-  // TODO: Use global context.
-  NodeBuilderContext Ctx;
   NodeBuilder &NB;
 public:
   bool *respondsToCallback;
@@ -48,7 +46,6 @@ public:
       Location(loc),
       ST(st),
       size(Dst.size()),
-      Ctx(builder.C.Eng, builder.getBlock(), pred),
       NB(builder),
       respondsToCallback(respondsToCB) {
     assert(!(ST && ST != Pred->getState()));
index b151dfef22884b2bff5fe2a11abacfe285818b45..934d15d8cc48b9cd51bf657c3bbbced2a1c60545 100644 (file)
@@ -165,7 +165,7 @@ public:
   }
 
   /// Enqueue the results of the node builder onto the work list.
-  void enqueue(NodeBuilder &NB);
+  void enqueue(ExplodedNodeSet &NB);
 };
 
 struct NodeBuilderContext {
@@ -181,12 +181,7 @@ class NodeBuilder {
 protected:
   friend class StmtNodeBuilder;
 
-  ExplodedNode *BuilderPred;
-
-// TODO: Context should become protected after refactoring is done.
-public:
   const NodeBuilderContext &C;
-protected:
 
   /// Specifies if the builder results have been finalized. For example, if it
   /// is set to false, autotransitions are yet to be generated.
@@ -196,8 +191,7 @@ protected:
 
   /// \brief The frontier set - a set of nodes which need to be propagated after
   /// the builder dies.
-  typedef llvm::SmallPtrSet<ExplodedNode*,5> DeferredTy;
-  DeferredTy Deferred;
+  ExplodedNodeSet &Frontier;
 
   BlockCounter getBlockCounter() const { return C.Eng.WList->getBlockCounter();}
 
@@ -205,9 +199,6 @@ protected:
   virtual bool checkResults() {
     if (!Finalized)
       return false;
-    for (DeferredTy::iterator I=Deferred.begin(), E=Deferred.end(); I!=E; ++I)
-      if ((*I)->isSink())
-        return false;
     return true;
   }
 
@@ -220,15 +211,16 @@ protected:
                                  bool MarkAsSink = false);
 
 public:
-  NodeBuilder(NodeBuilderContext &Ctx, bool F = true)
-    : C(Ctx), Finalized(F), HasGeneratedNodes(false) {
-    Deferred.insert(C.ContextPred);
+  NodeBuilder(ExplodedNode *SrcNode, ExplodedNodeSet &DstSet,
+              const NodeBuilderContext &Ctx, bool F = true)
+    : C(Ctx), Finalized(F), HasGeneratedNodes(false), Frontier(DstSet) {
+    Frontier.insert(SrcNode);
   }
 
-  /// Create a new builder using the parent builder's context.
-  NodeBuilder(const NodeBuilder &ParentBldr, bool F = true)
-    : C(ParentBldr.C), Finalized(F), HasGeneratedNodes(false) {
-    Deferred.insert(C.ContextPred);
+  NodeBuilder(const ExplodedNodeSet &SrcSet, ExplodedNodeSet &DstSet,
+              const NodeBuilderContext &Ctx, bool F = true)
+    : C(Ctx), Finalized(F), HasGeneratedNodes(false), Frontier(DstSet) {
+    Frontier.insert(SrcSet);
   }
 
   virtual ~NodeBuilder() {}
@@ -249,21 +241,29 @@ public:
     return HasGeneratedNodes;
   }
 
-  typedef DeferredTy::iterator iterator;
+  const ExplodedNodeSet &getResults() {
+    finalizeResults();
+    assert(checkResults());
+    return Frontier;
+  }
+
+  typedef ExplodedNodeSet::iterator iterator;
   /// \brief Iterators through the results frontier.
-  inline iterator results_begin() {
+  inline iterator begin() {
     finalizeResults();
     assert(checkResults());
-    return Deferred.begin();
+    return Frontier.begin();
   }
-  inline iterator results_end() {
+  inline iterator end() {
     finalizeResults();
-    return Deferred.end();
+    return Frontier.end();
   }
 
   /// \brief Return the CFGBlock associated with this builder.
   const CFGBlock *getBlock() const { return C.Block; }
 
+  const NodeBuilderContext &getContext() { return C; }
+
   /// \brief Returns the number of times the current basic block has been
   /// visited on the exploded graph path.
   unsigned getCurrentBlockCount() const {
@@ -297,7 +297,11 @@ public:
   void GenerateAutoTransition(ExplodedNode *N);
 
 public:
-  StmtNodeBuilder(ExplodedNode *N, unsigned idx, NodeBuilderContext &Ctx);
+  StmtNodeBuilder(ExplodedNode *SrcNode, ExplodedNodeSet &DstSet,
+                  unsigned idx, const NodeBuilderContext &Ctx)
+    : NodeBuilder(SrcNode, DstSet, Ctx), Idx(idx),
+      PurgingDeadSymbols(false), BuildSinks(false), hasGeneratedNode(false),
+      PointKind(ProgramPoint::PostStmtKind), Tag(0) {}
 
   ~StmtNodeBuilder();
   
@@ -364,8 +368,8 @@ public:
   void importNodesFromBuilder(const NodeBuilder &NB) {
     ExplodedNode *NBPred = const_cast<ExplodedNode*>(NB.C.ContextPred);
     if (NB.hasGeneratedNodes()) {
-      Deferred.erase(NBPred);
-      Deferred.insert(NB.Deferred.begin(), NB.Deferred.end());
+      Frontier.erase(NBPred);
+      Frontier.insert(NB.Frontier);
     }
   }
 };
@@ -378,15 +382,16 @@ class BranchNodeBuilder: public NodeBuilder {
   bool InFeasibleFalse;
 
 public:
-  BranchNodeBuilder(NodeBuilderContext &C,
+  BranchNodeBuilder(ExplodedNode *SrcNode, ExplodedNodeSet &DstSet,
+                    const NodeBuilderContext &C,
                     const CFGBlock *dstT, const CFGBlock *dstF)
-  : NodeBuilder(C), DstT(dstT), DstF(dstF),
+  : NodeBuilder(SrcNode, DstSet, C), DstT(dstT), DstF(dstF),
     InFeasibleTrue(!DstT), InFeasibleFalse(!DstF) {}
 
-  /// Create a new builder using the parent builder's context.
-  BranchNodeBuilder(BranchNodeBuilder &ParentBldr)
-  : NodeBuilder(ParentBldr), DstT(ParentBldr.DstT),
-    DstF(ParentBldr.DstF),
+  BranchNodeBuilder(const ExplodedNodeSet &SrcSet, ExplodedNodeSet &DstSet,
+                    const NodeBuilderContext &C,
+                    const CFGBlock *dstT, const CFGBlock *dstF)
+  : NodeBuilder(SrcSet, DstSet, C), DstT(dstT), DstF(dstF),
     InFeasibleTrue(!DstT), InFeasibleFalse(!DstF) {}
 
   ExplodedNode *generateNode(const ProgramState *State, bool branch,
index 43700f8f3f4cf267edeac575475a238ffb979ae2..258fbeb95249228017d02d44cf53aed6684040c5 100644 (file)
@@ -386,6 +386,7 @@ public:
 
   unsigned size() const { return Impl.size();  }
   bool empty()    const { return Impl.empty(); }
+  bool erase(ExplodedNode *N) { return Impl.erase(N); }
 
   void clear() { Impl.clear(); }
   void insert(const ExplodedNodeSet &S) {
index 07b2cedbd00703330159ec42a45ef08ff7924094..f18b04b8b8a6080a54a1db71bfe8f68878b22267 100644 (file)
@@ -117,6 +117,10 @@ public:
   BugReporter& getBugReporter() { return BR; }
 
   StmtNodeBuilder &getBuilder() { assert(Builder); return *Builder; }
+  const NodeBuilderContext &getBuilderContext() {
+    assert(Builder);
+    return Builder->getContext();
+  }
 
   bool isObjCGCEnabled() { return ObjCGCEnabled; }
 
@@ -163,6 +167,7 @@ public:
   void processBranch(const Stmt *Condition, const Stmt *Term, 
                      NodeBuilderContext& BuilderCtx,
                      ExplodedNode *Pred,
+                     ExplodedNodeSet &Dst,
                      const CFGBlock *DstT,
                      const CFGBlock *DstF);
 
index 8dfc1865bdb40a7e7ef25978d3bc96242cafc92d..e891e8fc423a06a29ea14b83b9944563f6a8b95b 100644 (file)
@@ -69,6 +69,7 @@ public:
   virtual void processBranch(const Stmt *Condition, const Stmt *Term,
                              NodeBuilderContext& BuilderCtx,
                              ExplodedNode *Pred,
+                             ExplodedNodeSet &Dst,
                              const CFGBlock *DstT,
                              const CFGBlock *DstF) = 0;
 
index 26479d055218ebe20695fcdac5b1bd777e3ecbcd..5f43b77ceb69a358c235478c302f2971a724ab47 100644 (file)
@@ -18,8 +18,8 @@ using namespace ento;
 
 CheckerContext::~CheckerContext() {
   // Copy the results into the Dst set.
-  for (NodeBuilder::iterator I = NB.results_begin(),
-                             E = NB.results_end(); I != E; ++I) {
+  for (NodeBuilder::iterator I = NB.begin(),
+                             E = NB.end(); I != E; ++I) {
     Dst.Add(*I);
   }
 }
index 525bd71111fc22fc2967f1de46b9db6c4e7931a3..b9ab7b4c744600dba01ef708f2837ea7a0922ffb 100644 (file)
@@ -315,7 +315,8 @@ void CoreEngine::HandleBlockEntrance(const BlockEntrance &L,
   // Process the entrance of the block.
   if (CFGElement E = L.getFirstElement()) {
     NodeBuilderContext Ctx(*this, L.getBlock(), Pred);
-    StmtNodeBuilder Builder(Pred, 0, Ctx);
+    ExplodedNodeSet Dst;
+    StmtNodeBuilder Builder(Pred, Dst, 0, Ctx);
     SubEng.processCFGElement(E, Builder, Pred);
   }
   else
@@ -419,8 +420,11 @@ void CoreEngine::HandleBranch(const Stmt *Cond, const Stmt *Term,
                                 const CFGBlock * B, ExplodedNode *Pred) {
   assert(B->succ_size() == 2);
   NodeBuilderContext Ctx(*this, B, Pred);
-  SubEng.processBranch(Cond, Term, Ctx, Pred,
+  ExplodedNodeSet Dst;
+  SubEng.processBranch(Cond, Term, Ctx, Pred, Dst,
                        *(B->succ_begin()), *(B->succ_begin()+1));
+  // Enqueue the new frontier onto the worklist.
+  enqueue(Dst);
 }
 
 void CoreEngine::HandlePostStmt(const CFGBlock *B, unsigned StmtIdx, 
@@ -432,7 +436,8 @@ void CoreEngine::HandlePostStmt(const CFGBlock *B, unsigned StmtIdx,
     HandleBlockExit(B, Pred);
   else {
     NodeBuilderContext Ctx(*this, B, Pred);
-    StmtNodeBuilder Builder(Pred, StmtIdx, Ctx);
+    ExplodedNodeSet Dst;
+    StmtNodeBuilder Builder(Pred, Dst, StmtIdx, Ctx);
     SubEng.processCFGElement((*B)[StmtIdx], Builder, Pred);
   }
 }
@@ -457,9 +462,9 @@ void CoreEngine::generateNode(const ProgramPoint &Loc,
   if (IsNew) WList->enqueue(Node);
 }
 
-void CoreEngine::enqueue(NodeBuilder &NB) {
-  for (NodeBuilder::iterator I = NB.results_begin(),
-                               E = NB.results_end(); I != E; ++I) {
+void CoreEngine::enqueue(ExplodedNodeSet &S) {
+  for (ExplodedNodeSet::iterator I = S.begin(),
+                                 E = S.end(); I != E; ++I) {
     WList->enqueue(*I);
   }
 }
@@ -494,28 +499,19 @@ ExplodedNode* NodeBuilder::generateNodeImpl(const ProgramPoint &Loc,
   bool IsNew;
   ExplodedNode *N = C.Eng.G->getNode(Loc, State, &IsNew);
   N->addPredecessor(FromN, *C.Eng.G);
-  Deferred.erase(FromN);
+  Frontier.erase(FromN);
 
   if (MarkAsSink)
     N->markAsSink();
-
-  if (IsNew && !N->isSink())
-    Deferred.insert(N);
+    
+  if (IsNew)
+    Frontier.Add(N);
 
   return (IsNew ? N : 0);
 }
 
-
-StmtNodeBuilder::StmtNodeBuilder(ExplodedNode *N, unsigned idx,
-                                 NodeBuilderContext &Ctx)
-  : NodeBuilder(Ctx), Idx(idx),
-    PurgingDeadSymbols(false), BuildSinks(false), hasGeneratedNode(false),
-    PointKind(ProgramPoint::PostStmtKind), Tag(0) {
-  Deferred.insert(N);
-}
-
 StmtNodeBuilder::~StmtNodeBuilder() {
-  for (DeferredTy::iterator I=Deferred.begin(), E=Deferred.end(); I!=E; ++I)
+  for (iterator I=Frontier.begin(), E=Frontier.end(); I!=E; ++I)
     if (!(*I)->isSink())
       GenerateAutoTransition(*I);
 }
@@ -554,14 +550,14 @@ void StmtNodeBuilder::GenerateAutoTransition(ExplodedNode *N) {
     C.Eng.WList->enqueue(Succ, C.Block, Idx+1);
 }
 
-ExplodedNode *StmtNodeBuilder::MakeNode(ExplodedNodeSet &Dst,
+ExplodedNode *StmtNodeBuilder::MakeNode(ExplodedNodeSet &DstSet,
                                         const Stmt *S, 
                                         ExplodedNode *Pred,
                                         const ProgramState *St,
                                         ProgramPoint::Kind K) {
   ExplodedNode *N = generateNode(S, St, Pred, K, 0, BuildSinks);
   if (N && !BuildSinks){
-      Dst.Add(N);
+      DstSet.Add(N);
   }
   return N;
 }
index 269d7c74ee5da711f8d5e97d9f90f7c98990ffec..5742266de2bbb17f8fcb3bbd2a214e4a088a6eb8 100644 (file)
@@ -945,15 +945,14 @@ static SVal RecoverCastedSymbol(ProgramStateManager& StateMgr,
 void ExprEngine::processBranch(const Stmt *Condition, const Stmt *Term,
                                NodeBuilderContext& BldCtx,
                                ExplodedNode *Pred,
+                               ExplodedNodeSet &Dst,
                                const CFGBlock *DstT,
                                const CFGBlock *DstF) {
-
   // Check for NULL conditions; e.g. "for(;;)"
   if (!Condition) {
-    BranchNodeBuilder NullCondBldr(BldCtx, DstT, DstF);
+    BranchNodeBuilder NullCondBldr(Pred, Dst, BldCtx, DstT, DstF);
     NullCondBldr.markInfeasible(false);
     NullCondBldr.generateNode(Pred->getState(), true, Pred);
-    Engine.enqueue(NullCondBldr);
     return;
   }
 
@@ -961,18 +960,19 @@ void ExprEngine::processBranch(const Stmt *Condition, const Stmt *Term,
                                 Condition->getLocStart(),
                                 "Error evaluating branch");
 
-  NodeBuilder CheckerBldr(BldCtx);
+  ExplodedNodeSet TmpCheckersOut;
+  NodeBuilder CheckerBldr(Pred, TmpCheckersOut, BldCtx);
   getCheckerManager().runCheckersForBranchCondition(Condition, CheckerBldr,
                                                     Pred, *this);
 
-  for (NodeBuilder::iterator I = CheckerBldr.results_begin(),
-                             E = CheckerBldr.results_end(); E != I; ++I) {
+  BranchNodeBuilder builder(CheckerBldr.getResults(), Dst, BldCtx, DstT, DstF);
+  for (NodeBuilder::iterator I = CheckerBldr.begin(),
+                             E = CheckerBldr.end(); E != I; ++I) {
     ExplodedNode *PredI = *I;
 
     if (PredI->isSink())
       continue;
 
-    BranchNodeBuilder builder(BldCtx, DstT, DstF);
     const ProgramState *PrevState = Pred->getState();
     SVal X = PrevState->getSVal(Condition);
 
@@ -998,8 +998,6 @@ void ExprEngine::processBranch(const Stmt *Condition, const Stmt *Term,
     if (X.isUnknownOrUndef()) {
       builder.generateNode(MarkBranch(PrevState, Term, true), true, PredI);
       builder.generateNode(MarkBranch(PrevState, Term, false), false, PredI);
-      // Enqueue the results into the work list.
-      Engine.enqueue(builder);
       continue;
     }
 
@@ -1020,9 +1018,6 @@ void ExprEngine::processBranch(const Stmt *Condition, const Stmt *Term,
       else
         builder.markInfeasible(false);
     }
-
-    // Enqueue the results into the work list.
-    Engine.enqueue(builder);
   }
 }