[cfe-commits] r45922 - /cfe/trunk/include/clang/Analysis/PathSensitive/ExplodedGraph.h

Ted Kremenek kremenek at apple.com
Sat Jan 12 20:00:17 PST 2008


Author: kremenek
Date: Sat Jan 12 22:00:16 2008
New Revision: 45922

URL: http://llvm.org/viewvc/llvm-project?rev=45922&view=rev
Log:
Merged ExplodedNode.h into ExplodedGraph.h, since the ExplodedNode class will
only be used in the context of the ExplodedGraph class.

Modified:
    cfe/trunk/include/clang/Analysis/PathSensitive/ExplodedGraph.h

Modified: cfe/trunk/include/clang/Analysis/PathSensitive/ExplodedGraph.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Analysis/PathSensitive/ExplodedGraph.h?rev=45922&r1=45921&r2=45922&view=diff

==============================================================================
--- cfe/trunk/include/clang/Analysis/PathSensitive/ExplodedGraph.h (original)
+++ cfe/trunk/include/clang/Analysis/PathSensitive/ExplodedGraph.h Sat Jan 12 22:00:16 2008
@@ -15,23 +15,198 @@
 #ifndef LLVM_CLANG_ANALYSIS_EXPLODEDGRAPH
 #define LLVM_CLANG_ANALYSIS_EXPLODEDGRAPH
 
-#include "clang/Analysis/PathSensitive/ExplodedNode.h"
+#include "clang/Analysis/ProgramPoint.h"
 #include "llvm/ADT/SmallVector.h"
 #include "llvm/ADT/FoldingSet.h"
 #include "llvm/ADT/DenseMap.h"
 #include "llvm/Support/Allocator.h"
 #include "llvm/ADT/OwningPtr.h"
+#include "llvm/ADT/GraphTraits.h"
+#include "llvm/ADT/DepthFirstIterator.h"
+#include <vector>
 
 namespace clang {
-  
+
 class GREngineImpl;
+
+/// ExplodeNodeGroup - A utility class used to represent the set of successor
+///  and predecessor nodes of a node.  Most nodes will have only 1 successor
+///  and 1 predecessor, so class allows us to store such unit sets of nodes
+///  using a single pointer without allocating an entire vector.  For
+///  larger sets of nodes, we dynamically allocate a vector.  This class
+///  will likely be revised in the future to further improve performance and
+///  to reduce memory footprint.
+class ExplodedNodeGroup {
+  enum { Size1 = 0x0, SizeOther = 0x1, Flags = 0x1 };
+  uintptr_t P;
+  
+  unsigned getKind() const { return P & Flags; }
+  
+  std::vector<ExplodeNodeImpl*>& getVector() {
+    assert (getKind() == SizeOther);
+    return *reinterpret_cast<std::vector<ExplodeNodeImpl*>*>(P & ~Flags);
+  }
+  
+  ExplodeNodeImpl* getNode() {
+    assert (getKind() == Size1);
+    return reinterpret_cast<ExplodeNodeImpl*>(P);
+  }
+  
+public:
+  ExplodedNodeGroup() : P(0) {}
+  
+  ~ExplodedNodeGroup() { if (getKind() == SizeOther) delete &getVector(); }
+  
+  inline ExplodedNodeImpl** begin() const {
+    if (getKind() == Size1)
+      return (ExplodedNodeImpl**) &P;
+    else
+      return getVector().begin();
+  }
+  
+  inline ExplodedNodeImpl** end() const {
+    if (getKind() == Size1)
+      return ((ExplodedNodeImpl**) &P)+1;
+    else
+      return getVector().end();
+  }
+  
+  inline unsigned size() const {
+    if (getKind() == Size1)
+      return getNode() ? 1 : 0;
+    else
+      return getVector().size();
+  }
+  
+  inline bool empty() const {
+    if (getKind() == Size1)
+      return getNode() ? false : true;
+    else
+      return getVector().empty();
+  }
+  
+  inline void addNode(ExplodedNodeImpl* N) {
+    if (getKind() == Size1) {
+      if (ExplodedNodeImpl* NOld = getNode()) {
+        std::vector<ExplodeNodeImpl*>* V = new std::vector<ExplodeNodeImpl*>();
+        V->push_back(NOld);
+        V->push_back(N);
+        P = reinterpret_cast<uintptr_t>(V) & SizeOther;
+      }
+      else
+        P = reinterpret_cast<uintptr_t>(N);
+    }
+    else
+      getVector().push_back(N);
+  }
+};
+
+/// ExplodeNodeImpl - 
+class ExplodedNodeImpl : public llvm::FoldingSetNode {
+protected:
+  friend class ExplodedGraphImpl;
+  
+  /// Location - The program location (within a function body) associated
+  ///  with this node.
+  const ProgramPoint Location;
+  
+  /// State - The state associated with this node. Normally this value
+  ///  is immutable, but we anticipate there will be times when algorithms
+  ///  that directly manipulate the analysis graph will need to change it.
+  void* State;
+  
+  /// Preds - The predecessors of this node.
+  ExplodedNodeGroup Preds;
+  
+  /// Succs - The successors of this node.
+  ExplodedNodeGroup Succs;
+  
+  /// Construct a ExplodedNodeImpl with the provided location and state.
+  explicit ExplodedNodeImpl(const ProgramLocation& loc, void* state)
+  : Location(loc), State(state) {}
+  
+  /// addPredeccessor - Adds a predecessor to the current node, and 
+  ///  in tandem add this node as a successor of the other node.  This
+  ///  method is intended to be used only by ExplodedGraphImpl.
+  void addPredecessor(ExplodedNodeImpl* V) {
+    Preds.addNode(V);
+    V->Succs.addNode(this);
+  }
+  
+public:
+  /// getLocation - Returns the edge associated with the given node.
+  const ProgramPoint& getLocation() const { return Location; }
   
+  unsigned succ_size() const { return Succs.size(); }
+  unsigned pred_size() const { return Preds.size(); }
+  bool succ_empty() const { return Succs.empty(); }
+  bool pred_empty() const { return Preds.size(); }
+};
+
+
+template <typename StateTy>
+struct GRTrait {
+  static inline void* toPtr(StateTy S) {
+    return reinterpret_cast<void*>(S);
+  }  
+  static inline StateTy toState(void* P) {
+    return reinterpret_cast<StateTy>(P);
+  }
+};
+
+
+template <typename StateTy>
+class ExplodedNode : public ExplodedNodeImpl {
+public:
+  /// Construct a ExplodedNodeImpl with the given node ID, program edge,
+  ///  and state.
+  explicit ExplodedNode(unsigned ID, const ProgramEdge& loc, StateTy state)
+  : ExplodedNodeImpl(ID, loc, GRTrait<StateTy>::toPtr(state)) {}
+  
+  /// getState - Returns the state associated with the node.  
+  inline StateTy getState() const {
+    return GRTrait<StateTy>::toState(State);
+  }
+  
+  // Profiling (for FoldingSet).
+  inline void Profile(llvm::FoldingSetNodeID& ID) const {
+    StateTy::Profile(ID, getState());
+  }
+  
+  // Iterators over successor and predecessor vertices.
+  typedef ExplodedNode**       succ_iterator;
+  typedef const ExplodedNode** const_succ_iterator;
+  typedef ExplodedNode**       pred_iterator;
+  typedef const ExplodedNode** const_pred_pred_iterator;
+
+  pred_iterator pred_begin() { return (ExplodedNode**) Pred.begin(); }
+  pred_iterator pred_end() { return (ExplodedNode**) Pred.end(); }
+
+  const_pred_iterator pred_begin() const {
+    return const_cast<ExplodedNode*>(this)->pred_begin();
+  }  
+  const_pred_iterator pred_end() const {
+    return const_cast<ExplodedNode*>(this)->pred_end();
+  }
+
+  succ_iterator succ_begin() { return (ExplodedNode**) Succ.begin(); }
+  succ_iterator succ_end() { return (ExplodedNode**) Succ.end(); }
+
+  const_succ_iterator succ_begin() const {
+    return const_cast<ExplodedNode*>(this)->succ_begin();
+  }
+  const_succ_iterator succ_end() const {
+    return const_cast<ExplodedNode*>(this)->succ_end();
+  }
+};
+
+
 class ExplodedGraphImpl {
 protected:
   friend class GREngineImpl;
   
   // Type definitions.
-  typedef llvm::DenseMap<ProgramEdge,void*>         EdgeNodeSetMap;  
+  typedef llvm::DenseMap<ProgramEdge,void*>         EdgeNodeSetMap;
   typedef llvm::SmallVector<ExplodedNodeImpl*,2>    RootsTy;
   typedef llvm::SmallVector<ExplodedNodeImpl*,10>   EndNodesTy;
   
@@ -62,7 +237,7 @@
   ///  is intended to be used only by GREngineImpl.
   virtual ExplodedNodeImpl* getNodeImpl(const ProgramEdge& L, void* State,
                                         bool* IsNew) = 0;
-                                                            
+
   /// addRoot - Add an untyped node to the set of roots.
   ExplodedNodeImpl* addRoot(ExplodedNodeImpl* V) {
     Roots.push_back(V);
@@ -77,9 +252,9 @@
 
 public:
   virtual ~ExplodedGraphImpl() {};
-  
+
   unsigned num_roots() const { return Roots.size(); }
-  unsigned num_eops() const { return EndNodes.size(); }  
+  unsigned num_eops() const { return EndNodes.size(); }
   unsigned getCounter() const { return NodeCounter; }
 };
   
@@ -92,7 +267,7 @@
   
 protected:
   llvm::OwningPtr<CheckerTy> CheckerState;
-  
+
 protected:
   virtual ExplodedNodeImpl*
   getNodeImpl(const ProgramEdge& L, void* State, bool* IsNew) {
@@ -191,4 +366,63 @@
   
 } // end clang namespace
 
+// GraphTraits
+
+namespace llvm {
+  template<typename StateTy>
+  struct GraphTraits<clang::ExplodedNode<StateTy>*> {
+    typedef clang::ExplodedNode<StateTy>      NodeType;
+    typedef typename NodeType::succ_iterator  ChildIteratorType;
+    typedef llvm::df_iterator<NodeType*>      nodes_iterator;
+    
+    static inline NodeType* getEntryNode(NodeType* N) {
+      return N;
+    }
+    
+    static inline ChildIteratorType child_begin(NodeType* N) {
+      return N->succ_begin();
+    }
+    
+    static inline ChildIteratorType child_end(NodeType* N) {
+      return N->succ_end();
+    }
+    
+    static inline nodes_iterator nodes_begin(NodeType* N) {
+      return df_begin(N);
+    }
+    
+    static inline nodes_iterator nodes_end(NodeType* N) {
+      return df_end(N);
+    }
+  };
+  
+  template<typename StateTy>
+  struct GraphTraits<const clang::ExplodedNode<StateTy>*> {
+    typedef const clang::ExplodedNode<StateTy> NodeType;
+    typedef typename NodeType::succ_iterator   ChildIteratorType;
+    typedef llvm::df_iterator<NodeType*>       nodes_iterator;
+    
+    static inline NodeType* getEntryNode(NodeType* N) {
+      return N;
+    }
+    
+    static inline ChildIteratorType child_begin(NodeType* N) {
+      return N->succ_begin();
+    }
+    
+    static inline ChildIteratorType child_end(NodeType* N) {
+      return N->succ_end();
+    }
+    
+    static inline nodes_iterator nodes_begin(NodeType* N) {
+      return df_begin(N);
+    }
+    
+    static inline nodes_iterator nodes_end(NodeType* N) {
+      return df_end(N);
+    }
+  };
+  
+} // end llvm namespace
+
 #endif





More information about the cfe-commits mailing list