clang API Documentation

ExplodedGraph.h
Go to the documentation of this file.
00001 //=-- ExplodedGraph.h - Local, Path-Sens. "Exploded Graph" -*- C++ -*-------==//
00002 //
00003 //                     The LLVM Compiler Infrastructure
00004 //
00005 // This file is distributed under the University of Illinois Open Source
00006 // License. See LICENSE.TXT for details.
00007 //
00008 //===----------------------------------------------------------------------===//
00009 //
00010 //  This file defines the template classes ExplodedNode and ExplodedGraph,
00011 //  which represent a path-sensitive, intra-procedural "exploded graph."
00012 //  See "Precise interprocedural dataflow analysis via graph reachability"
00013 //  by Reps, Horwitz, and Sagiv
00014 //  (http://portal.acm.org/citation.cfm?id=199462) for the definition of an
00015 //  exploded graph.
00016 //
00017 //===----------------------------------------------------------------------===//
00018 
00019 #ifndef LLVM_CLANG_GR_EXPLODEDGRAPH
00020 #define LLVM_CLANG_GR_EXPLODEDGRAPH
00021 
00022 #include "clang/Analysis/ProgramPoint.h"
00023 #include "clang/Analysis/AnalysisContext.h"
00024 #include "clang/AST/Decl.h"
00025 #include "llvm/ADT/SmallVector.h"
00026 #include "llvm/ADT/FoldingSet.h"
00027 #include "llvm/ADT/SmallPtrSet.h"
00028 #include "llvm/Support/Allocator.h"
00029 #include "llvm/ADT/OwningPtr.h"
00030 #include "llvm/ADT/GraphTraits.h"
00031 #include "llvm/ADT/DepthFirstIterator.h"
00032 #include "llvm/Support/Casting.h"
00033 #include "clang/Analysis/Support/BumpVector.h"
00034 #include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h"
00035 #include <vector>
00036 
00037 namespace clang {
00038 
00039 class CFG;
00040 
00041 namespace ento {
00042 
00043 class ExplodedGraph;
00044 
00045 //===----------------------------------------------------------------------===//
00046 // ExplodedGraph "implementation" classes.  These classes are not typed to
00047 // contain a specific kind of state.  Typed-specialized versions are defined
00048 // on top of these classes.
00049 //===----------------------------------------------------------------------===//
00050 
00051 // ExplodedNode is not constified all over the engine because we need to add
00052 // successors to it at any time after creating it.
00053 
00054 class ExplodedNode : public llvm::FoldingSetNode {
00055   friend class ExplodedGraph;
00056   friend class CoreEngine;
00057   friend class NodeBuilder;
00058   friend class BranchNodeBuilder;
00059   friend class IndirectGotoNodeBuilder;
00060   friend class SwitchNodeBuilder;
00061   friend class EndOfFunctionNodeBuilder;
00062 
00063   class NodeGroup {
00064     enum { Size1 = 0x0, SizeOther = 0x1, AuxFlag = 0x2, Mask = 0x3 };
00065     uintptr_t P;
00066 
00067     unsigned getKind() const {
00068       return P & 0x1;
00069     }
00070 
00071     void *getPtr() const {
00072       assert (!getFlag());
00073       return reinterpret_cast<void*>(P & ~Mask);
00074     }
00075 
00076     ExplodedNode *getNode() const {
00077       return reinterpret_cast<ExplodedNode*>(getPtr());
00078     }
00079     
00080   public:
00081     NodeGroup() : P(0) {}
00082 
00083     ExplodedNode **begin() const;
00084 
00085     ExplodedNode **end() const;
00086 
00087     unsigned size() const;
00088 
00089     bool empty() const { return (P & ~Mask) == 0; }
00090 
00091     void addNode(ExplodedNode *N, ExplodedGraph &G);
00092 
00093     void replaceNode(ExplodedNode *node);
00094 
00095     void setFlag() {
00096       assert(P == 0);
00097       P = AuxFlag;
00098     }
00099 
00100     bool getFlag() const {
00101       return P & AuxFlag ? true : false;
00102     }
00103   };
00104 
00105   /// Location - The program location (within a function body) associated
00106   ///  with this node.
00107   const ProgramPoint Location;
00108 
00109   /// State - The state associated with this node.
00110   ProgramStateRef State;
00111 
00112   /// Preds - The predecessors of this node.
00113   NodeGroup Preds;
00114 
00115   /// Succs - The successors of this node.
00116   NodeGroup Succs;
00117 
00118 public:
00119 
00120   explicit ExplodedNode(const ProgramPoint &loc, ProgramStateRef state,
00121                         bool IsSink)
00122     : Location(loc), State(state) {
00123     if (IsSink)
00124       Succs.setFlag();
00125   }
00126   
00127   ~ExplodedNode() {}
00128 
00129   /// getLocation - Returns the edge associated with the given node.
00130   ProgramPoint getLocation() const { return Location; }
00131 
00132   const LocationContext *getLocationContext() const {
00133     return getLocation().getLocationContext();
00134   }
00135 
00136   const Decl &getCodeDecl() const { return *getLocationContext()->getDecl(); }
00137 
00138   CFG &getCFG() const { return *getLocationContext()->getCFG(); }
00139 
00140   ParentMap &getParentMap() const {return getLocationContext()->getParentMap();}
00141 
00142   template <typename T>
00143   T &getAnalysis() const {
00144     return *getLocationContext()->getAnalysis<T>();
00145   }
00146 
00147   ProgramStateRef getState() const { return State; }
00148 
00149   template <typename T>
00150   const T* getLocationAs() const { return llvm::dyn_cast<T>(&Location); }
00151 
00152   static void Profile(llvm::FoldingSetNodeID &ID,
00153                       const ProgramPoint &Loc,
00154                       ProgramStateRef state,
00155                       bool IsSink) {
00156     ID.Add(Loc);
00157     ID.AddPointer(state.getPtr());
00158     ID.AddBoolean(IsSink);
00159   }
00160 
00161   void Profile(llvm::FoldingSetNodeID& ID) const {
00162     Profile(ID, getLocation(), getState(), isSink());
00163   }
00164 
00165   /// addPredeccessor - Adds a predecessor to the current node, and
00166   ///  in tandem add this node as a successor of the other node.
00167   void addPredecessor(ExplodedNode *V, ExplodedGraph &G);
00168 
00169   unsigned succ_size() const { return Succs.size(); }
00170   unsigned pred_size() const { return Preds.size(); }
00171   bool succ_empty() const { return Succs.empty(); }
00172   bool pred_empty() const { return Preds.empty(); }
00173 
00174   bool isSink() const { return Succs.getFlag(); }
00175 
00176    bool hasSinglePred() const {
00177     return (pred_size() == 1);
00178   }
00179 
00180   ExplodedNode *getFirstPred() {
00181     return pred_empty() ? NULL : *(pred_begin());
00182   }
00183 
00184   const ExplodedNode *getFirstPred() const {
00185     return const_cast<ExplodedNode*>(this)->getFirstPred();
00186   }
00187 
00188   // Iterators over successor and predecessor vertices.
00189   typedef ExplodedNode**       succ_iterator;
00190   typedef const ExplodedNode* const * const_succ_iterator;
00191   typedef ExplodedNode**       pred_iterator;
00192   typedef const ExplodedNode* const * const_pred_iterator;
00193 
00194   pred_iterator pred_begin() { return Preds.begin(); }
00195   pred_iterator pred_end() { return Preds.end(); }
00196 
00197   const_pred_iterator pred_begin() const {
00198     return const_cast<ExplodedNode*>(this)->pred_begin();
00199   }
00200   const_pred_iterator pred_end() const {
00201     return const_cast<ExplodedNode*>(this)->pred_end();
00202   }
00203 
00204   succ_iterator succ_begin() { return Succs.begin(); }
00205   succ_iterator succ_end() { return Succs.end(); }
00206 
00207   const_succ_iterator succ_begin() const {
00208     return const_cast<ExplodedNode*>(this)->succ_begin();
00209   }
00210   const_succ_iterator succ_end() const {
00211     return const_cast<ExplodedNode*>(this)->succ_end();
00212   }
00213 
00214   // For debugging.
00215 
00216 public:
00217 
00218   class Auditor {
00219   public:
00220     virtual ~Auditor();
00221     virtual void AddEdge(ExplodedNode *Src, ExplodedNode *Dst) = 0;
00222   };
00223 
00224   static void SetAuditor(Auditor* A);
00225   
00226 private:
00227   void replaceSuccessor(ExplodedNode *node) { Succs.replaceNode(node); }
00228   void replacePredecessor(ExplodedNode *node) { Preds.replaceNode(node); }
00229 };
00230 
00231 // FIXME: Is this class necessary?
00232 class InterExplodedGraphMap {
00233   virtual void anchor();
00234   llvm::DenseMap<const ExplodedNode*, ExplodedNode*> M;
00235   friend class ExplodedGraph;
00236 
00237 public:
00238   ExplodedNode *getMappedNode(const ExplodedNode *N) const;
00239 
00240   InterExplodedGraphMap() {}
00241   virtual ~InterExplodedGraphMap() {}
00242 };
00243 
00244 class ExplodedGraph {
00245 protected:
00246   friend class CoreEngine;
00247 
00248   // Type definitions.
00249   typedef std::vector<ExplodedNode *> NodeVector;
00250 
00251   /// The roots of the simulation graph. Usually there will be only
00252   /// one, but clients are free to establish multiple subgraphs within a single
00253   /// SimulGraph. Moreover, these subgraphs can often merge when paths from
00254   /// different roots reach the same state at the same program location.
00255   NodeVector Roots;
00256 
00257   /// The nodes in the simulation graph which have been
00258   /// specially marked as the endpoint of an abstract simulation path.
00259   NodeVector EndNodes;
00260 
00261   /// Nodes - The nodes in the graph.
00262   llvm::FoldingSet<ExplodedNode> Nodes;
00263 
00264   /// BVC - Allocator and context for allocating nodes and their predecessor
00265   /// and successor groups.
00266   BumpVectorContext BVC;
00267 
00268   /// NumNodes - The number of nodes in the graph.
00269   unsigned NumNodes;
00270   
00271   /// A list of recently allocated nodes that can potentially be recycled.
00272   NodeVector ChangedNodes;
00273   
00274   /// A list of nodes that can be reused.
00275   NodeVector FreeNodes;
00276   
00277   /// A flag that indicates whether nodes should be recycled.
00278   bool reclaimNodes;
00279   
00280   /// Counter to determine when to reclaim nodes.
00281   unsigned reclaimCounter;
00282 
00283 public:
00284 
00285   /// \brief Retrieve the node associated with a (Location,State) pair,
00286   ///  where the 'Location' is a ProgramPoint in the CFG.  If no node for
00287   ///  this pair exists, it is created. IsNew is set to true if
00288   ///  the node was freshly created.
00289   ExplodedNode *getNode(const ProgramPoint &L, ProgramStateRef State,
00290                         bool IsSink = false,
00291                         bool* IsNew = 0);
00292 
00293   ExplodedGraph* MakeEmptyGraph() const {
00294     return new ExplodedGraph();
00295   }
00296 
00297   /// addRoot - Add an untyped node to the set of roots.
00298   ExplodedNode *addRoot(ExplodedNode *V) {
00299     Roots.push_back(V);
00300     return V;
00301   }
00302 
00303   /// addEndOfPath - Add an untyped node to the set of EOP nodes.
00304   ExplodedNode *addEndOfPath(ExplodedNode *V) {
00305     EndNodes.push_back(V);
00306     return V;
00307   }
00308 
00309   ExplodedGraph();
00310 
00311   ~ExplodedGraph();
00312   
00313   unsigned num_roots() const { return Roots.size(); }
00314   unsigned num_eops() const { return EndNodes.size(); }
00315 
00316   bool empty() const { return NumNodes == 0; }
00317   unsigned size() const { return NumNodes; }
00318 
00319   // Iterators.
00320   typedef ExplodedNode                        NodeTy;
00321   typedef llvm::FoldingSet<ExplodedNode>      AllNodesTy;
00322   typedef NodeVector::iterator                roots_iterator;
00323   typedef NodeVector::const_iterator          const_roots_iterator;
00324   typedef NodeVector::iterator                eop_iterator;
00325   typedef NodeVector::const_iterator          const_eop_iterator;
00326   typedef AllNodesTy::iterator                node_iterator;
00327   typedef AllNodesTy::const_iterator          const_node_iterator;
00328 
00329   node_iterator nodes_begin() { return Nodes.begin(); }
00330 
00331   node_iterator nodes_end() { return Nodes.end(); }
00332 
00333   const_node_iterator nodes_begin() const { return Nodes.begin(); }
00334 
00335   const_node_iterator nodes_end() const { return Nodes.end(); }
00336 
00337   roots_iterator roots_begin() { return Roots.begin(); }
00338 
00339   roots_iterator roots_end() { return Roots.end(); }
00340 
00341   const_roots_iterator roots_begin() const { return Roots.begin(); }
00342 
00343   const_roots_iterator roots_end() const { return Roots.end(); }
00344 
00345   eop_iterator eop_begin() { return EndNodes.begin(); }
00346 
00347   eop_iterator eop_end() { return EndNodes.end(); }
00348 
00349   const_eop_iterator eop_begin() const { return EndNodes.begin(); }
00350 
00351   const_eop_iterator eop_end() const { return EndNodes.end(); }
00352 
00353   llvm::BumpPtrAllocator & getAllocator() { return BVC.getAllocator(); }
00354   BumpVectorContext &getNodeAllocator() { return BVC; }
00355 
00356   typedef llvm::DenseMap<const ExplodedNode*, ExplodedNode*> NodeMap;
00357 
00358   std::pair<ExplodedGraph*, InterExplodedGraphMap*>
00359   Trim(const NodeTy* const* NBeg, const NodeTy* const* NEnd,
00360        llvm::DenseMap<const void*, const void*> *InverseMap = 0) const;
00361 
00362   ExplodedGraph* TrimInternal(const ExplodedNode* const * NBeg,
00363                               const ExplodedNode* const * NEnd,
00364                               InterExplodedGraphMap *M,
00365                     llvm::DenseMap<const void*, const void*> *InverseMap) const;
00366 
00367   /// Enable tracking of recently allocated nodes for potential reclamation
00368   /// when calling reclaimRecentlyAllocatedNodes().
00369   void enableNodeReclamation() { reclaimNodes = true; }
00370 
00371   /// Reclaim "uninteresting" nodes created since the last time this method
00372   /// was called.
00373   void reclaimRecentlyAllocatedNodes();
00374 
00375 private:
00376   bool shouldCollect(const ExplodedNode *node);
00377   void collectNode(ExplodedNode *node);
00378 };
00379 
00380 class ExplodedNodeSet {
00381   typedef llvm::SmallPtrSet<ExplodedNode*,5> ImplTy;
00382   ImplTy Impl;
00383 
00384 public:
00385   ExplodedNodeSet(ExplodedNode *N) {
00386     assert (N && !static_cast<ExplodedNode*>(N)->isSink());
00387     Impl.insert(N);
00388   }
00389 
00390   ExplodedNodeSet() {}
00391 
00392   inline void Add(ExplodedNode *N) {
00393     if (N && !static_cast<ExplodedNode*>(N)->isSink()) Impl.insert(N);
00394   }
00395 
00396   typedef ImplTy::iterator       iterator;
00397   typedef ImplTy::const_iterator const_iterator;
00398 
00399   unsigned size() const { return Impl.size();  }
00400   bool empty()    const { return Impl.empty(); }
00401   bool erase(ExplodedNode *N) { return Impl.erase(N); }
00402 
00403   void clear() { Impl.clear(); }
00404   void insert(const ExplodedNodeSet &S) {
00405     assert(&S != this);
00406     if (empty())
00407       Impl = S.Impl;
00408     else
00409       Impl.insert(S.begin(), S.end());
00410   }
00411 
00412   inline iterator begin() { return Impl.begin(); }
00413   inline iterator end()   { return Impl.end();   }
00414 
00415   inline const_iterator begin() const { return Impl.begin(); }
00416   inline const_iterator end()   const { return Impl.end();   }
00417 };
00418 
00419 } // end GR namespace
00420 
00421 } // end clang namespace
00422 
00423 // GraphTraits
00424 
00425 namespace llvm {
00426   template<> struct GraphTraits<clang::ento::ExplodedNode*> {
00427     typedef clang::ento::ExplodedNode NodeType;
00428     typedef NodeType::succ_iterator  ChildIteratorType;
00429     typedef llvm::df_iterator<NodeType*>      nodes_iterator;
00430 
00431     static inline NodeType* getEntryNode(NodeType* N) {
00432       return N;
00433     }
00434 
00435     static inline ChildIteratorType child_begin(NodeType* N) {
00436       return N->succ_begin();
00437     }
00438 
00439     static inline ChildIteratorType child_end(NodeType* N) {
00440       return N->succ_end();
00441     }
00442 
00443     static inline nodes_iterator nodes_begin(NodeType* N) {
00444       return df_begin(N);
00445     }
00446 
00447     static inline nodes_iterator nodes_end(NodeType* N) {
00448       return df_end(N);
00449     }
00450   };
00451 
00452   template<> struct GraphTraits<const clang::ento::ExplodedNode*> {
00453     typedef const clang::ento::ExplodedNode NodeType;
00454     typedef NodeType::const_succ_iterator   ChildIteratorType;
00455     typedef llvm::df_iterator<NodeType*>       nodes_iterator;
00456 
00457     static inline NodeType* getEntryNode(NodeType* N) {
00458       return N;
00459     }
00460 
00461     static inline ChildIteratorType child_begin(NodeType* N) {
00462       return N->succ_begin();
00463     }
00464 
00465     static inline ChildIteratorType child_end(NodeType* N) {
00466       return N->succ_end();
00467     }
00468 
00469     static inline nodes_iterator nodes_begin(NodeType* N) {
00470       return df_begin(N);
00471     }
00472 
00473     static inline nodes_iterator nodes_end(NodeType* N) {
00474       return df_end(N);
00475     }
00476   };
00477 
00478 } // end llvm namespace
00479 
00480 #endif