]> granicus.if.org Git - clang/commitdiff
[analyzer] GenericNodeBuilder -> NodeBuilder.
authorAnna Zaks <ganna@apple.com>
Wed, 26 Oct 2011 21:06:22 +0000 (21:06 +0000)
committerAnna Zaks <ganna@apple.com>
Wed, 26 Oct 2011 21:06:22 +0000 (21:06 +0000)
Remove GenericNodeBuilder and use a class inherited from NodeBuilder instead.

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

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

index 5fddb75d1f3a9e9c1bf2f594292ac8b57b1c7380..192e1e4bee1bc6923196eb6ecbcbb5d0c3c13922 100644 (file)
@@ -168,6 +168,7 @@ public:
   void enqueue(ExplodedNodeSet &NB);
 };
 
+// TODO: Turn into a calss.
 struct NodeBuilderContext {
   CoreEngine &Eng;
   const CFGBlock *Block;
@@ -175,6 +176,8 @@ struct NodeBuilderContext {
   NodeBuilderContext(CoreEngine &E, const CFGBlock *B, ExplodedNode *N)
     : Eng(E), Block(B), Pred(N) { assert(B); assert(!N->isSink()); }
 
+  ExplodedNode *getPred() const { return Pred; }
+
   /// \brief Return the CFGBlock associated with this builder.
   const CFGBlock *getBlock() const { return Block; }
 
@@ -288,6 +291,34 @@ public:
   void addNodes(ExplodedNode *N) { Frontier.Add(N); }
 };
 
+/// \class NodeBuilderWithSinks
+/// \brief This node builder keeps track of the generated sink nodes.
+class NodeBuilderWithSinks: public NodeBuilder {
+protected:
+  SmallVector<ExplodedNode*, 2> sinksGenerated;
+  ProgramPoint &Location;
+
+public:
+  NodeBuilderWithSinks(ExplodedNode *Pred, ExplodedNodeSet &DstSet,
+                       const NodeBuilderContext &Ctx, ProgramPoint &L)
+    : NodeBuilder(Pred, DstSet, Ctx), Location(L) {}
+  ExplodedNode *generateNode(const ProgramState *State,
+                             ExplodedNode *Pred,
+                             const ProgramPointTag *Tag = 0,
+                             bool MarkAsSink = false) {
+    ProgramPoint LocalLoc = (Tag ? Location.withTag(Tag): Location);
+
+    ExplodedNode *N = generateNodeImpl(LocalLoc, State, Pred, MarkAsSink);
+    if (N && N->isSink())
+      sinksGenerated.push_back(N);
+    return N;
+  }
+
+  const SmallVectorImpl<ExplodedNode*> &getSinks() const {
+    return sinksGenerated;
+  }
+};
+
 /// \class StmtNodeBuilder
 /// \brief This builder class is useful for generating nodes that resulted from
 /// visiting a statement. The main difference from it's parent NodeBuilder is
@@ -467,52 +498,6 @@ public:
   const ProgramState *getState() const { return Pred->State; }
 };
 
-class GenericNodeBuilderImpl {
-protected:
-  CoreEngine &engine;
-  ExplodedNode *pred;
-  ProgramPoint pp;
-  SmallVector<ExplodedNode*, 2> sinksGenerated;  
-
-  ExplodedNode *generateNodeImpl(const ProgramState *state,
-                                 ExplodedNode *pred,
-                                 ProgramPoint programPoint,
-                                 bool asSink);
-
-  GenericNodeBuilderImpl(CoreEngine &eng, ExplodedNode *pr, ProgramPoint p)
-    : engine(eng), pred(pr), pp(p), hasGeneratedNode(false) {}
-
-public:
-  bool hasGeneratedNode;
-  
-  WorkList &getWorkList() { return *engine.WList; }
-  
-  ExplodedNode *getPredecessor() const { return pred; }
-  
-  BlockCounter getBlockCounter() const {
-    return engine.WList->getBlockCounter();
-  }
-  
-  const SmallVectorImpl<ExplodedNode*> &sinks() const {
-    return sinksGenerated;
-  }
-};
-
-template <typename PP_T>
-class GenericNodeBuilder : public GenericNodeBuilderImpl {
-public:
-  GenericNodeBuilder(CoreEngine &eng, ExplodedNode *pr, const PP_T &p)
-    : GenericNodeBuilderImpl(eng, pr, p) {}
-
-  ExplodedNode *generateNode(const ProgramState *state, ExplodedNode *pred,
-                             const ProgramPointTag *tag, bool asSink) {
-    return generateNodeImpl(state, pred, cast<PP_T>(pp).withTag(tag),
-                            asSink);
-  }
-  
-  const PP_T &getProgramPoint() const { return cast<PP_T>(pp); }
-};
-
 class CallEnterNodeBuilder {
   CoreEngine &Eng;
 
index 325d824090d8739c628e121e631a1ad9ed654b3d..7409b19e4e468f2dc2b311a17c39ae12fc9e52ff 100644 (file)
@@ -161,8 +161,7 @@ public:
                             ExplodedNode *Pred, ExplodedNodeSet &Dst);
 
   /// Called by CoreEngine when processing the entrance of a CFGBlock.
-  virtual void processCFGBlockEntrance(ExplodedNodeSet &dstNodes,
-                                GenericNodeBuilder<BlockEntrance> &nodeBuilder);
+  virtual void processCFGBlockEntrance(NodeBuilderWithSinks &nodeBuilder);
   
   /// ProcessBranch - Called by CoreEngine.  Used to generate successor
   ///  nodes by processing the 'effects' of a branch condition.
index c35e6cca413c3f279140441f2a7fa5ff7aafd794..d258b2c8074522a66ee2b21ff4398491c5e127a2 100644 (file)
@@ -40,6 +40,7 @@ class SwitchNodeBuilder;
 class EndOfFunctionNodeBuilder;
 class CallEnterNodeBuilder;
 class CallExitNodeBuilder;
+class NodeBuilderWithSinks;
 class MemRegion;
 
 class SubEngine {
@@ -60,8 +61,7 @@ public:
   /// Called by CoreEngine when it starts processing a CFGBlock.  The
   /// SubEngine is expected to populate dstNodes with new nodes representing
   /// updated analysis state, or generate no nodes at all if it doesn't.
-  virtual void processCFGBlockEntrance(ExplodedNodeSet &dstNodes,
-                            GenericNodeBuilder<BlockEntrance> &nodeBuilder) = 0;
+  virtual void processCFGBlockEntrance(NodeBuilderWithSinks &nodeBuilder) = 0;
 
   /// Called by CoreEngine.  Used to generate successor
   ///  nodes by processing the 'effects' of a branch condition.
index 6b8c7df224e86c7d602f296d5c6efa0009b804a0..f6939172427154bc0b91a814a1289685b61eefd2 100644 (file)
@@ -261,6 +261,7 @@ void CoreEngine::HandleCallExit(const CallExit &L, ExplodedNode *Pred) {
 void CoreEngine::HandleBlockEdge(const BlockEdge &L, ExplodedNode *Pred) {
 
   const CFGBlock *Blk = L.getDst();
+  NodeBuilderContext BuilderCtx(*this, Blk, Pred);
 
   // Check if we are entering the EXIT block.
   if (Blk == &(L.getLocationContext()->getCFG()->getExit())) {
@@ -269,35 +270,30 @@ void CoreEngine::HandleBlockEdge(const BlockEdge &L, ExplodedNode *Pred) {
             && "EXIT block cannot contain Stmts.");
 
     // Process the final state transition.
-    NodeBuilderContext BuilderCtx(*this, Blk, Pred);
     SubEng.processEndOfFunction(BuilderCtx);
 
     // This path is done. Don't enqueue any more nodes.
     return;
   }
 
-  // Call into the subengine to process entering the CFGBlock.
+  // Call into the SubEngine to process entering the CFGBlock.
   ExplodedNodeSet dstNodes;
   BlockEntrance BE(Blk, Pred->getLocationContext());
-  GenericNodeBuilder<BlockEntrance> nodeBuilder(*this, Pred, BE);
-  SubEng.processCFGBlockEntrance(dstNodes, nodeBuilder);
+  NodeBuilderWithSinks nodeBuilder(Pred, dstNodes, BuilderCtx, BE);
+  SubEng.processCFGBlockEntrance(nodeBuilder);
 
-  if (dstNodes.empty()) {
-    if (!nodeBuilder.hasGeneratedNode) {
-      // Auto-generate a node and enqueue it to the worklist.
-      generateNode(BE, Pred->State, Pred);    
-    }
-  }
-  else {
-    for (ExplodedNodeSet::iterator I = dstNodes.begin(), E = dstNodes.end();
-         I != E; ++I) {
-      WList->enqueue(*I);
-    }
+  // Auto-generate a node.
+  if (!nodeBuilder.hasGeneratedNodes()) {
+    nodeBuilder.generateNode(Pred->State, Pred);
   }
 
+  // Enqueue nodes onto the worklist.
+  enqueue(dstNodes);
+
+  // Make sink nodes as exhausted.
+  const SmallVectorImpl<ExplodedNode*> &Sinks =  nodeBuilder.getSinks();
   for (SmallVectorImpl<ExplodedNode*>::const_iterator
-       I = nodeBuilder.sinks().begin(), E = nodeBuilder.sinks().end();
-       I != E; ++I) {
+         I =Sinks.begin(), E = Sinks.end(); I != E; ++I) {
     blocksExhausted.push_back(std::make_pair(L, *I));
   }
 }
@@ -465,27 +461,6 @@ void CoreEngine::enqueue(ExplodedNodeSet &S) {
   }
 }
 
-ExplodedNode *
-GenericNodeBuilderImpl::generateNodeImpl(const ProgramState *state,
-                                         ExplodedNode *pred,
-                                         ProgramPoint programPoint,
-                                         bool asSink) {
-  
-  hasGeneratedNode = true;
-  bool isNew;
-  ExplodedNode *node = engine.getGraph().getNode(programPoint, state, &isNew);
-  if (pred)
-    node->addPredecessor(pred, engine.getGraph());
-  if (isNew) {
-    if (asSink) {
-      node->markAsSink();
-      sinksGenerated.push_back(node);
-    }
-    return node;
-  }
-  return 0;
-}
-
 ExplodedNode* NodeBuilder::generateNodeImpl(const ProgramPoint &Loc,
                                             const ProgramState *State,
                                             ExplodedNode *FromN,
index 0eacb31b282e9b8695369b3cbdef029ff7e89b81..24fa04bd564d53b2c511a71ab1dcd3662584febe 100644 (file)
@@ -909,20 +909,13 @@ void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred,
   }
 }
 
-//===----------------------------------------------------------------------===//
-// Block entrance.  (Update counters).
-//===----------------------------------------------------------------------===//
-
-void ExprEngine::processCFGBlockEntrance(ExplodedNodeSet &dstNodes,
-                               GenericNodeBuilder<BlockEntrance> &nodeBuilder){
+/// Block entrance.  (Update counters).
+void ExprEngine::processCFGBlockEntrance(NodeBuilderWithSinks &nodeBuilder) {
   
   // FIXME: Refactor this into a checker.
-  const CFGBlock *block = nodeBuilder.getProgramPoint().getBlock();
-  ExplodedNode *pred = nodeBuilder.getPredecessor();
+  ExplodedNode *pred = nodeBuilder.getContext().getPred();
   
-  if (nodeBuilder.getBlockCounter().getNumVisited(
-                       pred->getLocationContext()->getCurrentStackFrame(), 
-                       block->getBlockID()) >= AMgr.getMaxVisit()) {
+  if (nodeBuilder.getContext().getCurrentBlockCount() >= AMgr.getMaxVisit()) {
     static SimpleProgramPointTag tag("ExprEngine : Block count exceeded");
     nodeBuilder.generateNode(pred->getState(), pred, &tag, true);
   }