ExplodedGraph.h 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476
  1. //=-- ExplodedGraph.h - Local, Path-Sens. "Exploded Graph" -*- C++ -*-------==//
  2. //
  3. // The LLVM Compiler Infrastructure
  4. //
  5. // This file is distributed under the University of Illinois Open Source
  6. // License. See LICENSE.TXT for details.
  7. //
  8. //===----------------------------------------------------------------------===//
  9. //
  10. // This file defines the template classes ExplodedNode and ExplodedGraph,
  11. // which represent a path-sensitive, intra-procedural "exploded graph."
  12. // See "Precise interprocedural dataflow analysis via graph reachability"
  13. // by Reps, Horwitz, and Sagiv
  14. // (http://portal.acm.org/citation.cfm?id=199462) for the definition of an
  15. // exploded graph.
  16. //
  17. //===----------------------------------------------------------------------===//
  18. #ifndef LLVM_CLANG_GR_EXPLODEDGRAPH
  19. #define LLVM_CLANG_GR_EXPLODEDGRAPH
  20. #include "clang/Analysis/ProgramPoint.h"
  21. #include "clang/Analysis/AnalysisContext.h"
  22. #include "clang/AST/Decl.h"
  23. #include "llvm/ADT/SmallVector.h"
  24. #include "llvm/ADT/FoldingSet.h"
  25. #include "llvm/ADT/SmallPtrSet.h"
  26. #include "llvm/Support/Allocator.h"
  27. #include "llvm/ADT/OwningPtr.h"
  28. #include "llvm/ADT/GraphTraits.h"
  29. #include "llvm/ADT/DepthFirstIterator.h"
  30. #include "llvm/Support/Casting.h"
  31. #include "clang/Analysis/Support/BumpVector.h"
  32. #include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h"
  33. namespace clang {
  34. class CFG;
  35. namespace ento {
  36. class ExplodedGraph;
  37. //===----------------------------------------------------------------------===//
  38. // ExplodedGraph "implementation" classes. These classes are not typed to
  39. // contain a specific kind of state. Typed-specialized versions are defined
  40. // on top of these classes.
  41. //===----------------------------------------------------------------------===//
  42. // ExplodedNode is not constified all over the engine because we need to add
  43. // successors to it at any time after creating it.
  44. class ExplodedNode : public llvm::FoldingSetNode {
  45. friend class ExplodedGraph;
  46. friend class CoreEngine;
  47. friend class NodeBuilder;
  48. friend class BranchNodeBuilder;
  49. friend class IndirectGotoNodeBuilder;
  50. friend class SwitchNodeBuilder;
  51. friend class EndOfFunctionNodeBuilder;
  52. class NodeGroup {
  53. enum { Size1 = 0x0, SizeOther = 0x1, AuxFlag = 0x2, Mask = 0x3 };
  54. uintptr_t P;
  55. unsigned getKind() const {
  56. return P & 0x1;
  57. }
  58. void *getPtr() const {
  59. assert (!getFlag());
  60. return reinterpret_cast<void*>(P & ~Mask);
  61. }
  62. ExplodedNode *getNode() const {
  63. return reinterpret_cast<ExplodedNode*>(getPtr());
  64. }
  65. public:
  66. NodeGroup() : P(0) {}
  67. ExplodedNode **begin() const;
  68. ExplodedNode **end() const;
  69. unsigned size() const;
  70. bool empty() const { return (P & ~Mask) == 0; }
  71. void addNode(ExplodedNode *N, ExplodedGraph &G);
  72. void replaceNode(ExplodedNode *node);
  73. void setFlag() {
  74. assert(P == 0);
  75. P = AuxFlag;
  76. }
  77. bool getFlag() const {
  78. return P & AuxFlag ? true : false;
  79. }
  80. };
  81. /// Location - The program location (within a function body) associated
  82. /// with this node.
  83. const ProgramPoint Location;
  84. /// State - The state associated with this node.
  85. ProgramStateRef State;
  86. /// Preds - The predecessors of this node.
  87. NodeGroup Preds;
  88. /// Succs - The successors of this node.
  89. NodeGroup Succs;
  90. public:
  91. explicit ExplodedNode(const ProgramPoint &loc, ProgramStateRef state,
  92. bool IsSink)
  93. : Location(loc), State(state) {
  94. if (IsSink)
  95. Succs.setFlag();
  96. }
  97. ~ExplodedNode() {}
  98. /// getLocation - Returns the edge associated with the given node.
  99. ProgramPoint getLocation() const { return Location; }
  100. const LocationContext *getLocationContext() const {
  101. return getLocation().getLocationContext();
  102. }
  103. const Decl &getCodeDecl() const { return *getLocationContext()->getDecl(); }
  104. CFG &getCFG() const { return *getLocationContext()->getCFG(); }
  105. ParentMap &getParentMap() const {return getLocationContext()->getParentMap();}
  106. template <typename T>
  107. T &getAnalysis() const {
  108. return *getLocationContext()->getAnalysis<T>();
  109. }
  110. ProgramStateRef getState() const { return State; }
  111. template <typename T>
  112. const T* getLocationAs() const { return llvm::dyn_cast<T>(&Location); }
  113. static void Profile(llvm::FoldingSetNodeID &ID,
  114. const ProgramPoint &Loc,
  115. ProgramStateRef state,
  116. bool IsSink) {
  117. ID.Add(Loc);
  118. ID.AddPointer(state.getPtr());
  119. ID.AddBoolean(IsSink);
  120. }
  121. void Profile(llvm::FoldingSetNodeID& ID) const {
  122. Profile(ID, getLocation(), getState(), isSink());
  123. }
  124. /// addPredeccessor - Adds a predecessor to the current node, and
  125. /// in tandem add this node as a successor of the other node.
  126. void addPredecessor(ExplodedNode *V, ExplodedGraph &G);
  127. unsigned succ_size() const { return Succs.size(); }
  128. unsigned pred_size() const { return Preds.size(); }
  129. bool succ_empty() const { return Succs.empty(); }
  130. bool pred_empty() const { return Preds.empty(); }
  131. bool isSink() const { return Succs.getFlag(); }
  132. ExplodedNode *getFirstPred() {
  133. return pred_empty() ? NULL : *(pred_begin());
  134. }
  135. const ExplodedNode *getFirstPred() const {
  136. return const_cast<ExplodedNode*>(this)->getFirstPred();
  137. }
  138. // Iterators over successor and predecessor vertices.
  139. typedef ExplodedNode** succ_iterator;
  140. typedef const ExplodedNode* const * const_succ_iterator;
  141. typedef ExplodedNode** pred_iterator;
  142. typedef const ExplodedNode* const * const_pred_iterator;
  143. pred_iterator pred_begin() { return Preds.begin(); }
  144. pred_iterator pred_end() { return Preds.end(); }
  145. const_pred_iterator pred_begin() const {
  146. return const_cast<ExplodedNode*>(this)->pred_begin();
  147. }
  148. const_pred_iterator pred_end() const {
  149. return const_cast<ExplodedNode*>(this)->pred_end();
  150. }
  151. succ_iterator succ_begin() { return Succs.begin(); }
  152. succ_iterator succ_end() { return Succs.end(); }
  153. const_succ_iterator succ_begin() const {
  154. return const_cast<ExplodedNode*>(this)->succ_begin();
  155. }
  156. const_succ_iterator succ_end() const {
  157. return const_cast<ExplodedNode*>(this)->succ_end();
  158. }
  159. // For debugging.
  160. public:
  161. class Auditor {
  162. public:
  163. virtual ~Auditor();
  164. virtual void AddEdge(ExplodedNode *Src, ExplodedNode *Dst) = 0;
  165. };
  166. static void SetAuditor(Auditor* A);
  167. private:
  168. void replaceSuccessor(ExplodedNode *node) { Succs.replaceNode(node); }
  169. void replacePredecessor(ExplodedNode *node) { Preds.replaceNode(node); }
  170. };
  171. // FIXME: Is this class necessary?
  172. class InterExplodedGraphMap {
  173. virtual void anchor();
  174. llvm::DenseMap<const ExplodedNode*, ExplodedNode*> M;
  175. friend class ExplodedGraph;
  176. public:
  177. ExplodedNode *getMappedNode(const ExplodedNode *N) const;
  178. InterExplodedGraphMap() {}
  179. virtual ~InterExplodedGraphMap() {}
  180. };
  181. class ExplodedGraph {
  182. protected:
  183. friend class CoreEngine;
  184. // Type definitions.
  185. typedef SmallVector<ExplodedNode*,2> RootsTy;
  186. typedef SmallVector<ExplodedNode*,10> EndNodesTy;
  187. /// Roots - The roots of the simulation graph. Usually there will be only
  188. /// one, but clients are free to establish multiple subgraphs within a single
  189. /// SimulGraph. Moreover, these subgraphs can often merge when paths from
  190. /// different roots reach the same state at the same program location.
  191. RootsTy Roots;
  192. /// EndNodes - The nodes in the simulation graph which have been
  193. /// specially marked as the endpoint of an abstract simulation path.
  194. EndNodesTy EndNodes;
  195. /// Nodes - The nodes in the graph.
  196. llvm::FoldingSet<ExplodedNode> Nodes;
  197. /// BVC - Allocator and context for allocating nodes and their predecessor
  198. /// and successor groups.
  199. BumpVectorContext BVC;
  200. /// NumNodes - The number of nodes in the graph.
  201. unsigned NumNodes;
  202. /// A list of recently allocated nodes that can potentially be recycled.
  203. void *recentlyAllocatedNodes;
  204. /// A list of nodes that can be reused.
  205. void *freeNodes;
  206. /// A flag that indicates whether nodes should be recycled.
  207. bool reclaimNodes;
  208. /// Counter to determine when to reclaim nodes.
  209. unsigned reclaimCounter;
  210. public:
  211. /// \brief Retrieve the node associated with a (Location,State) pair,
  212. /// where the 'Location' is a ProgramPoint in the CFG. If no node for
  213. /// this pair exists, it is created. IsNew is set to true if
  214. /// the node was freshly created.
  215. ExplodedNode *getNode(const ProgramPoint &L, ProgramStateRef State,
  216. bool IsSink = false,
  217. bool* IsNew = 0);
  218. ExplodedGraph* MakeEmptyGraph() const {
  219. return new ExplodedGraph();
  220. }
  221. /// addRoot - Add an untyped node to the set of roots.
  222. ExplodedNode *addRoot(ExplodedNode *V) {
  223. Roots.push_back(V);
  224. return V;
  225. }
  226. /// addEndOfPath - Add an untyped node to the set of EOP nodes.
  227. ExplodedNode *addEndOfPath(ExplodedNode *V) {
  228. EndNodes.push_back(V);
  229. return V;
  230. }
  231. ExplodedGraph();
  232. ~ExplodedGraph();
  233. unsigned num_roots() const { return Roots.size(); }
  234. unsigned num_eops() const { return EndNodes.size(); }
  235. bool empty() const { return NumNodes == 0; }
  236. unsigned size() const { return NumNodes; }
  237. // Iterators.
  238. typedef ExplodedNode NodeTy;
  239. typedef llvm::FoldingSet<ExplodedNode> AllNodesTy;
  240. typedef NodeTy** roots_iterator;
  241. typedef NodeTy* const * const_roots_iterator;
  242. typedef NodeTy** eop_iterator;
  243. typedef NodeTy* const * const_eop_iterator;
  244. typedef AllNodesTy::iterator node_iterator;
  245. typedef AllNodesTy::const_iterator const_node_iterator;
  246. node_iterator nodes_begin() { return Nodes.begin(); }
  247. node_iterator nodes_end() { return Nodes.end(); }
  248. const_node_iterator nodes_begin() const { return Nodes.begin(); }
  249. const_node_iterator nodes_end() const { return Nodes.end(); }
  250. roots_iterator roots_begin() { return Roots.begin(); }
  251. roots_iterator roots_end() { return Roots.end(); }
  252. const_roots_iterator roots_begin() const { return Roots.begin(); }
  253. const_roots_iterator roots_end() const { return Roots.end(); }
  254. eop_iterator eop_begin() { return EndNodes.begin(); }
  255. eop_iterator eop_end() { return EndNodes.end(); }
  256. const_eop_iterator eop_begin() const { return EndNodes.begin(); }
  257. const_eop_iterator eop_end() const { return EndNodes.end(); }
  258. llvm::BumpPtrAllocator & getAllocator() { return BVC.getAllocator(); }
  259. BumpVectorContext &getNodeAllocator() { return BVC; }
  260. typedef llvm::DenseMap<const ExplodedNode*, ExplodedNode*> NodeMap;
  261. std::pair<ExplodedGraph*, InterExplodedGraphMap*>
  262. Trim(const NodeTy* const* NBeg, const NodeTy* const* NEnd,
  263. llvm::DenseMap<const void*, const void*> *InverseMap = 0) const;
  264. ExplodedGraph* TrimInternal(const ExplodedNode* const * NBeg,
  265. const ExplodedNode* const * NEnd,
  266. InterExplodedGraphMap *M,
  267. llvm::DenseMap<const void*, const void*> *InverseMap) const;
  268. /// Enable tracking of recently allocated nodes for potential reclamation
  269. /// when calling reclaimRecentlyAllocatedNodes().
  270. void enableNodeReclamation() { reclaimNodes = true; }
  271. /// Reclaim "uninteresting" nodes created since the last time this method
  272. /// was called.
  273. void reclaimRecentlyAllocatedNodes();
  274. private:
  275. bool shouldCollect(const ExplodedNode *node);
  276. void collectNode(ExplodedNode *node);
  277. };
  278. class ExplodedNodeSet {
  279. typedef llvm::SmallPtrSet<ExplodedNode*,5> ImplTy;
  280. ImplTy Impl;
  281. public:
  282. ExplodedNodeSet(ExplodedNode *N) {
  283. assert (N && !static_cast<ExplodedNode*>(N)->isSink());
  284. Impl.insert(N);
  285. }
  286. ExplodedNodeSet() {}
  287. inline void Add(ExplodedNode *N) {
  288. if (N && !static_cast<ExplodedNode*>(N)->isSink()) Impl.insert(N);
  289. }
  290. typedef ImplTy::iterator iterator;
  291. typedef ImplTy::const_iterator const_iterator;
  292. unsigned size() const { return Impl.size(); }
  293. bool empty() const { return Impl.empty(); }
  294. bool erase(ExplodedNode *N) { return Impl.erase(N); }
  295. void clear() { Impl.clear(); }
  296. void insert(const ExplodedNodeSet &S) {
  297. assert(&S != this);
  298. if (empty())
  299. Impl = S.Impl;
  300. else
  301. Impl.insert(S.begin(), S.end());
  302. }
  303. inline iterator begin() { return Impl.begin(); }
  304. inline iterator end() { return Impl.end(); }
  305. inline const_iterator begin() const { return Impl.begin(); }
  306. inline const_iterator end() const { return Impl.end(); }
  307. };
  308. } // end GR namespace
  309. } // end clang namespace
  310. // GraphTraits
  311. namespace llvm {
  312. template<> struct GraphTraits<clang::ento::ExplodedNode*> {
  313. typedef clang::ento::ExplodedNode NodeType;
  314. typedef NodeType::succ_iterator ChildIteratorType;
  315. typedef llvm::df_iterator<NodeType*> nodes_iterator;
  316. static inline NodeType* getEntryNode(NodeType* N) {
  317. return N;
  318. }
  319. static inline ChildIteratorType child_begin(NodeType* N) {
  320. return N->succ_begin();
  321. }
  322. static inline ChildIteratorType child_end(NodeType* N) {
  323. return N->succ_end();
  324. }
  325. static inline nodes_iterator nodes_begin(NodeType* N) {
  326. return df_begin(N);
  327. }
  328. static inline nodes_iterator nodes_end(NodeType* N) {
  329. return df_end(N);
  330. }
  331. };
  332. template<> struct GraphTraits<const clang::ento::ExplodedNode*> {
  333. typedef const clang::ento::ExplodedNode NodeType;
  334. typedef NodeType::const_succ_iterator ChildIteratorType;
  335. typedef llvm::df_iterator<NodeType*> nodes_iterator;
  336. static inline NodeType* getEntryNode(NodeType* N) {
  337. return N;
  338. }
  339. static inline ChildIteratorType child_begin(NodeType* N) {
  340. return N->succ_begin();
  341. }
  342. static inline ChildIteratorType child_end(NodeType* N) {
  343. return N->succ_end();
  344. }
  345. static inline nodes_iterator nodes_begin(NodeType* N) {
  346. return df_begin(N);
  347. }
  348. static inline nodes_iterator nodes_end(NodeType* N) {
  349. return df_end(N);
  350. }
  351. };
  352. } // end llvm namespace
  353. #endif