]> granicus.if.org Git - clang/commitdiff
Added "GREndPathNodeBuilder", a new node builder that will be used for
authorTed Kremenek <kremenek@apple.com>
Fri, 11 Apr 2008 22:03:04 +0000 (22:03 +0000)
committerTed Kremenek <kremenek@apple.com>
Fri, 11 Apr 2008 22:03:04 +0000 (22:03 +0000)
evaluating transfer functions at the end-of-path.

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

include/clang/Analysis/PathSensitive/ExplodedGraph.h
include/clang/Analysis/PathSensitive/GRCoreEngine.h
include/clang/Analysis/PathSensitive/GRExprEngine.h
lib/Analysis/GRCoreEngine.cpp

index 8db069639b6f8a6522481f62a29599f273399809..0d8f31fb826e5ef1ac83ef5256a0a17596503e6e 100644 (file)
@@ -30,12 +30,14 @@ namespace clang {
 
 class GRCoreEngineImpl;
 class ExplodedNodeImpl;
+class CFG;
+class ASTContext;
+
 class GRStmtNodeBuilderImpl;
 class GRBranchNodeBuilderImpl;
 class GRIndirectGotoNodeBuilderImpl;
 class GRSwitchNodeBuilderImpl;
-class CFG;
-class ASTContext;
+class GREndPathNodebuilderImpl;  
 
 class ExplodedNodeImpl : public llvm::FoldingSetNode {
 protected:
@@ -45,6 +47,7 @@ protected:
   friend class GRBranchNodeBuilderImpl;
   friend class GRIndirectGotoNodeBuilderImpl;
   friend class GRSwitchNodeBuilderImpl;
+  friend class GREndPathNodeBuilderImpl;  
   
   class NodeGroup {
     enum { Size1 = 0x0, SizeOther = 0x1, AuxFlag = 0x2, Mask = 0x3 };
@@ -199,6 +202,7 @@ protected:
   friend class GRBranchNodeBuilderImpl;
   friend class GRIndirectGotoNodeBuilderImpl;
   friend class GRSwitchNodeBuilderImpl;
+  friend class GREndPathNodeBuilderImpl;
   
   // Type definitions.
   typedef llvm::SmallVector<ExplodedNodeImpl*,2>    RootsTy;
index 5b7aeb59754b3cf22aaef60d98f11c60eaa8c76b..ccb217ca0aa807a7f560b72c90b7fb9dc7931f7f 100644 (file)
@@ -28,6 +28,7 @@ class GRStmtNodeBuilderImpl;
 class GRBranchNodeBuilderImpl;
 class GRIndirectGotoNodeBuilderImpl;
 class GRSwitchNodeBuilderImpl;
+class GREndPathNodeBuilderImpl;
 class GRWorkList;
 
 //===----------------------------------------------------------------------===//
@@ -45,6 +46,7 @@ protected:
   friend class GRBranchNodeBuilderImpl;
   friend class GRIndirectGotoNodeBuilderImpl;
   friend class GRSwitchNodeBuilderImpl;
+  friend class GREndPathNodeBuilderImpl;
   
   typedef llvm::DenseMap<Stmt*,Stmt*> ParentMapTy;
     
@@ -86,7 +88,7 @@ protected:
   void HandleBranch(Expr* Cond, Stmt* Term, CFGBlock* B,
                     ExplodedNodeImpl* Pred);  
   
-  virtual void* ProcessEOP(CFGBlock* Blk, void* State) = 0;  
+  virtual void ProcessEndPath(GREndPathNodeBuilderImpl& Builder) = 0;  
   
   virtual bool ProcessBlockEntrance(CFGBlock* Blk, void* State,
                                     GRBlockCounter BC) = 0;
@@ -487,6 +489,65 @@ public:
     return static_cast<StateTy*>(NB.getState());
   }    
 };
+  
+
+class GREndPathNodeBuilderImpl {
+  GRCoreEngineImpl& Eng;
+  CFGBlock& B;
+  ExplodedNodeImpl* Pred;  
+  bool HasGeneratedNode;
+  
+public:
+  GREndPathNodeBuilderImpl(CFGBlock* b, ExplodedNodeImpl* N,
+                           GRCoreEngineImpl* e)
+    : Eng(*e), B(*b), Pred(N), HasGeneratedNode(false) {}      
+  
+  ~GREndPathNodeBuilderImpl();
+  
+  ExplodedNodeImpl* getPredecessor() const { return Pred; }
+    
+  GRBlockCounter getBlockCounter() const { return Eng.WList->getBlockCounter();}
+  
+  unsigned getCurrentBlockCount() const {
+    return getBlockCounter().getNumVisited(B.getBlockID());
+  }  
+  
+  ExplodedNodeImpl* generateNodeImpl(void* State);
+    
+  CFGBlock* getBlock() const { return &B; }
+};
+
+
+template<typename STATE>
+class GREndPathNodeBuilder  {
+  typedef STATE                   StateTy;
+  typedef ExplodedNode<StateTy>   NodeTy;
+  
+  GREndPathNodeBuilderImpl& NB;
+  
+public:
+  GREndPathNodeBuilder(GREndPathNodeBuilderImpl& nb) : NB(nb) {}
+  
+  NodeTy* getPredecessor() const {
+    return static_cast<NodeTy*>(NB.getPredecessor());
+  }
+  
+  GRBlockCounter getBlockCounter() const {
+    return NB.getBlockCounter();
+  }  
+  
+  unsigned getCurrentBlockCount() const {
+    return NB.getCurrentBlockCount();
+  }
+  
+  StateTy* getState() const {
+    return getPredecessor()->getState();
+  }
+  
+  NodeTy* MakeNode(StateTy* St) {  
+    return static_cast<NodeTy*>(NB.generateNodeImpl(St));
+  }
+};
 
   
 template<typename SUBENGINE>
@@ -504,9 +565,9 @@ protected:
     return SubEngine.getInitialState();
   }
   
-  virtual void* ProcessEOP(CFGBlock* Blk, void* State) {
-    // FIXME: Perform dispatch to adjust state.
-    return State;
+  virtual void ProcessEndPath(GREndPathNodeBuilderImpl& BuilderImpl) {
+    GREndPathNodeBuilder<StateTy> Builder(BuilderImpl);
+    SubEngine.ProcessEndPath(Builder);
   }
   
   virtual void ProcessStmt(Stmt* S, GRStmtNodeBuilderImpl& BuilderImpl) {
index 473b658b679d2741d9db30670319cf335ecdcaba..1c813dfd8999fb4408d1057c6646974ca94b68fe 100644 (file)
@@ -39,6 +39,7 @@ public:
   typedef GRBranchNodeBuilder<StateTy>        BranchNodeBuilder;
   typedef GRIndirectGotoNodeBuilder<StateTy>  IndirectGotoNodeBuilder;
   typedef GRSwitchNodeBuilder<StateTy>        SwitchNodeBuilder;
+  typedef GREndPathNodeBuilder<StateTy>       EndPathNodeBuilder;
   typedef ExplodedNodeSet<StateTy>            NodeSet;
   
     
@@ -364,6 +365,9 @@ public:
   ///  nodes by processing the 'effects' of a switch statement.
   void ProcessSwitch(SwitchNodeBuilder& builder);
   
+  /// ProcessEndPath - Called by GRCoreEngine.  Used to generate end-of-path
+  ///  nodes when the control reaches the end of a function.
+  void ProcessEndPath(EndPathNodeBuilder& builder) {}
   
   ValueStateManager& getStateManager() { return StateMgr; }
   const ValueStateManager& getStateManger() const { return StateMgr; }
index 53831ed06d59fb60893443ed74257d617b2a1d05..42c89270f9079944254f6c7783f9d85441546eaf 100644 (file)
@@ -124,16 +124,10 @@ void GRCoreEngineImpl::HandleBlockEdge(const BlockEdge& L,
     assert (getCFG().getExit().size() == 0 
             && "EXIT block cannot contain Stmts.");
 
-    // Process the final state transition.    
-    void* State = ProcessEOP(Blk, Pred->State);
+    // Process the final state transition.
+    GREndPathNodeBuilderImpl Builder(Blk, Pred, this);
+    ProcessEndPath(Builder);
 
-    bool IsNew;
-    ExplodedNodeImpl* Node = G->getNodeImpl(BlockEntrance(Blk), State, &IsNew);
-    Node->addPredecessor(Pred);
-    
-    // If the node was freshly created, mark it as an "End-Of-Path" node.
-    if (IsNew) G->addEndOfPath(Node); 
-    
     // This path is done. Don't enqueue any more nodes.
     return;
   }
@@ -442,3 +436,27 @@ GRSwitchNodeBuilderImpl::generateDefaultCaseNodeImpl(void* St, bool isSink) {
   
   return NULL;
 }
+
+GREndPathNodeBuilderImpl::~GREndPathNodeBuilderImpl() {
+  // Auto-generate an EOP node if one has not been generated.
+  if (!HasGeneratedNode) generateNodeImpl(Pred->State);
+}
+
+ExplodedNodeImpl* GREndPathNodeBuilderImpl::generateNodeImpl(void* State) {
+  HasGeneratedNode = true;
+    
+  bool IsNew;
+  
+  ExplodedNodeImpl* Node =
+    Eng.G->getNodeImpl(BlockEntrance(&B), Pred->State, &IsNew);
+  
+
+  Node->addPredecessor(Pred);
+  
+  if (IsNew) {
+    Node->markAsSink();
+    Eng.G->addEndOfPath(Node);
+  }
+  
+  return Node;
+}