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_STATICANALYZER_CORE_PATHSENSITIVE_EXPLODEDGRAPH_H
00020 #define LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_EXPLODEDGRAPH_H
00021 
00022 #include "clang/AST/Decl.h"
00023 #include "clang/Analysis/AnalysisContext.h"
00024 #include "clang/Analysis/ProgramPoint.h"
00025 #include "clang/Analysis/Support/BumpVector.h"
00026 #include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h"
00027 #include "llvm/ADT/DepthFirstIterator.h"
00028 #include "llvm/ADT/FoldingSet.h"
00029 #include "llvm/ADT/GraphTraits.h"
00030 #include "llvm/ADT/SmallPtrSet.h"
00031 #include "llvm/ADT/SmallVector.h"
00032 #include "llvm/Support/Allocator.h"
00033 #include "llvm/Support/Casting.h"
00034 #include <memory>
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   /// Efficiently stores a list of ExplodedNodes, or an optional flag.
00064   ///
00065   /// NodeGroup provides opaque storage for a list of ExplodedNodes, optimizing
00066   /// for the case when there is only one node in the group. This is a fairly
00067   /// common case in an ExplodedGraph, where most nodes have only one
00068   /// predecessor and many have only one successor. It can also be used to
00069   /// store a flag rather than a node list, which ExplodedNode uses to mark
00070   /// whether a node is a sink. If the flag is set, the group is implicitly
00071   /// empty and no nodes may be added.
00072   class NodeGroup {
00073     // Conceptually a discriminated union. If the low bit is set, the node is
00074     // a sink. If the low bit is not set, the pointer refers to the storage
00075     // for the nodes in the group.
00076     // This is not a PointerIntPair in order to keep the storage type opaque.
00077     uintptr_t P;
00078     
00079   public:
00080     NodeGroup(bool Flag = false) : P(Flag) {
00081       assert(getFlag() == Flag);
00082     }
00083 
00084     ExplodedNode * const *begin() const;
00085 
00086     ExplodedNode * const *end() const;
00087 
00088     unsigned size() const;
00089 
00090     bool empty() const { return P == 0 || getFlag() != 0; }
00091 
00092     /// Adds a node to the list.
00093     ///
00094     /// The group must not have been created with its flag set.
00095     void addNode(ExplodedNode *N, ExplodedGraph &G);
00096 
00097     /// Replaces the single node in this group with a new node.
00098     ///
00099     /// Note that this should only be used when you know the group was not
00100     /// created with its flag set, and that the group is empty or contains
00101     /// only a single node.
00102     void replaceNode(ExplodedNode *node);
00103 
00104     /// Returns whether this group was created with its flag set.
00105     bool getFlag() const {
00106       return (P & 1);
00107     }
00108   };
00109 
00110   /// Location - The program location (within a function body) associated
00111   ///  with this node.
00112   const ProgramPoint Location;
00113 
00114   /// State - The state associated with this node.
00115   ProgramStateRef State;
00116 
00117   /// Preds - The predecessors of this node.
00118   NodeGroup Preds;
00119 
00120   /// Succs - The successors of this node.
00121   NodeGroup Succs;
00122 
00123 public:
00124 
00125   explicit ExplodedNode(const ProgramPoint &loc, ProgramStateRef state,
00126                         bool IsSink)
00127     : Location(loc), State(state), Succs(IsSink) {
00128     assert(isSink() == IsSink);
00129   }
00130   
00131   ~ExplodedNode() {}
00132 
00133   /// getLocation - Returns the edge associated with the given node.
00134   ProgramPoint getLocation() const { return Location; }
00135 
00136   const LocationContext *getLocationContext() const {
00137     return getLocation().getLocationContext();
00138   }
00139 
00140   const StackFrameContext *getStackFrame() const {
00141     return getLocationContext()->getCurrentStackFrame();
00142   }
00143 
00144   const Decl &getCodeDecl() const { return *getLocationContext()->getDecl(); }
00145 
00146   CFG &getCFG() const { return *getLocationContext()->getCFG(); }
00147 
00148   ParentMap &getParentMap() const {return getLocationContext()->getParentMap();}
00149 
00150   template <typename T>
00151   T &getAnalysis() const {
00152     return *getLocationContext()->getAnalysis<T>();
00153   }
00154 
00155   const ProgramStateRef &getState() const { return State; }
00156 
00157   template <typename T>
00158   Optional<T> getLocationAs() const LLVM_LVALUE_FUNCTION {
00159     return Location.getAs<T>();
00160   }
00161 
00162   static void Profile(llvm::FoldingSetNodeID &ID,
00163                       const ProgramPoint &Loc,
00164                       const ProgramStateRef &state,
00165                       bool IsSink) {
00166     ID.Add(Loc);
00167     ID.AddPointer(state.get());
00168     ID.AddBoolean(IsSink);
00169   }
00170 
00171   void Profile(llvm::FoldingSetNodeID& ID) const {
00172     // We avoid copy constructors by not using accessors.
00173     Profile(ID, Location, State, isSink());
00174   }
00175 
00176   /// addPredeccessor - Adds a predecessor to the current node, and
00177   ///  in tandem add this node as a successor of the other node.
00178   void addPredecessor(ExplodedNode *V, ExplodedGraph &G);
00179 
00180   unsigned succ_size() const { return Succs.size(); }
00181   unsigned pred_size() const { return Preds.size(); }
00182   bool succ_empty() const { return Succs.empty(); }
00183   bool pred_empty() const { return Preds.empty(); }
00184 
00185   bool isSink() const { return Succs.getFlag(); }
00186 
00187   bool hasSinglePred() const {
00188     return (pred_size() == 1);
00189   }
00190 
00191   ExplodedNode *getFirstPred() {
00192     return pred_empty() ? nullptr : *(pred_begin());
00193   }
00194 
00195   const ExplodedNode *getFirstPred() const {
00196     return const_cast<ExplodedNode*>(this)->getFirstPred();
00197   }
00198 
00199   const ExplodedNode *getFirstSucc() const {
00200     return succ_empty() ? nullptr : *(succ_begin());
00201   }
00202 
00203   // Iterators over successor and predecessor vertices.
00204   typedef ExplodedNode*       const *       succ_iterator;
00205   typedef const ExplodedNode* const * const_succ_iterator;
00206   typedef ExplodedNode*       const *       pred_iterator;
00207   typedef const ExplodedNode* const * const_pred_iterator;
00208 
00209   pred_iterator pred_begin() { return Preds.begin(); }
00210   pred_iterator pred_end() { return Preds.end(); }
00211 
00212   const_pred_iterator pred_begin() const {
00213     return const_cast<ExplodedNode*>(this)->pred_begin();
00214   }
00215   const_pred_iterator pred_end() const {
00216     return const_cast<ExplodedNode*>(this)->pred_end();
00217   }
00218 
00219   succ_iterator succ_begin() { return Succs.begin(); }
00220   succ_iterator succ_end() { return Succs.end(); }
00221 
00222   const_succ_iterator succ_begin() const {
00223     return const_cast<ExplodedNode*>(this)->succ_begin();
00224   }
00225   const_succ_iterator succ_end() const {
00226     return const_cast<ExplodedNode*>(this)->succ_end();
00227   }
00228 
00229   // For debugging.
00230 
00231 public:
00232 
00233   class Auditor {
00234   public:
00235     virtual ~Auditor();
00236     virtual void AddEdge(ExplodedNode *Src, ExplodedNode *Dst) = 0;
00237   };
00238 
00239   static void SetAuditor(Auditor* A);
00240   
00241 private:
00242   void replaceSuccessor(ExplodedNode *node) { Succs.replaceNode(node); }
00243   void replacePredecessor(ExplodedNode *node) { Preds.replaceNode(node); }
00244 };
00245 
00246 typedef llvm::DenseMap<const ExplodedNode *, const ExplodedNode *>
00247         InterExplodedGraphMap;
00248 
00249 class ExplodedGraph {
00250 protected:
00251   friend class CoreEngine;
00252 
00253   // Type definitions.
00254   typedef std::vector<ExplodedNode *> NodeVector;
00255 
00256   /// The roots of the simulation graph. Usually there will be only
00257   /// one, but clients are free to establish multiple subgraphs within a single
00258   /// SimulGraph. Moreover, these subgraphs can often merge when paths from
00259   /// different roots reach the same state at the same program location.
00260   NodeVector Roots;
00261 
00262   /// The nodes in the simulation graph which have been
00263   /// specially marked as the endpoint of an abstract simulation path.
00264   NodeVector EndNodes;
00265 
00266   /// Nodes - The nodes in the graph.
00267   llvm::FoldingSet<ExplodedNode> Nodes;
00268 
00269   /// BVC - Allocator and context for allocating nodes and their predecessor
00270   /// and successor groups.
00271   BumpVectorContext BVC;
00272 
00273   /// NumNodes - The number of nodes in the graph.
00274   unsigned NumNodes;
00275   
00276   /// A list of recently allocated nodes that can potentially be recycled.
00277   NodeVector ChangedNodes;
00278   
00279   /// A list of nodes that can be reused.
00280   NodeVector FreeNodes;
00281   
00282   /// Determines how often nodes are reclaimed.
00283   ///
00284   /// If this is 0, nodes will never be reclaimed.
00285   unsigned ReclaimNodeInterval;
00286   
00287   /// Counter to determine when to reclaim nodes.
00288   unsigned ReclaimCounter;
00289 
00290 public:
00291 
00292   /// \brief Retrieve the node associated with a (Location,State) pair,
00293   ///  where the 'Location' is a ProgramPoint in the CFG.  If no node for
00294   ///  this pair exists, it is created. IsNew is set to true if
00295   ///  the node was freshly created.
00296   ExplodedNode *getNode(const ProgramPoint &L, ProgramStateRef State,
00297                         bool IsSink = false,
00298                         bool* IsNew = nullptr);
00299 
00300   std::unique_ptr<ExplodedGraph> MakeEmptyGraph() const {
00301     return llvm::make_unique<ExplodedGraph>();
00302   }
00303 
00304   /// addRoot - Add an untyped node to the set of roots.
00305   ExplodedNode *addRoot(ExplodedNode *V) {
00306     Roots.push_back(V);
00307     return V;
00308   }
00309 
00310   /// addEndOfPath - Add an untyped node to the set of EOP nodes.
00311   ExplodedNode *addEndOfPath(ExplodedNode *V) {
00312     EndNodes.push_back(V);
00313     return V;
00314   }
00315 
00316   ExplodedGraph();
00317 
00318   ~ExplodedGraph();
00319   
00320   unsigned num_roots() const { return Roots.size(); }
00321   unsigned num_eops() const { return EndNodes.size(); }
00322 
00323   bool empty() const { return NumNodes == 0; }
00324   unsigned size() const { return NumNodes; }
00325 
00326   // Iterators.
00327   typedef ExplodedNode                        NodeTy;
00328   typedef llvm::FoldingSet<ExplodedNode>      AllNodesTy;
00329   typedef NodeVector::iterator                roots_iterator;
00330   typedef NodeVector::const_iterator          const_roots_iterator;
00331   typedef NodeVector::iterator                eop_iterator;
00332   typedef NodeVector::const_iterator          const_eop_iterator;
00333   typedef AllNodesTy::iterator                node_iterator;
00334   typedef AllNodesTy::const_iterator          const_node_iterator;
00335 
00336   node_iterator nodes_begin() { return Nodes.begin(); }
00337 
00338   node_iterator nodes_end() { return Nodes.end(); }
00339 
00340   const_node_iterator nodes_begin() const { return Nodes.begin(); }
00341 
00342   const_node_iterator nodes_end() const { return Nodes.end(); }
00343 
00344   roots_iterator roots_begin() { return Roots.begin(); }
00345 
00346   roots_iterator roots_end() { return Roots.end(); }
00347 
00348   const_roots_iterator roots_begin() const { return Roots.begin(); }
00349 
00350   const_roots_iterator roots_end() const { return Roots.end(); }
00351 
00352   eop_iterator eop_begin() { return EndNodes.begin(); }
00353 
00354   eop_iterator eop_end() { return EndNodes.end(); }
00355 
00356   const_eop_iterator eop_begin() const { return EndNodes.begin(); }
00357 
00358   const_eop_iterator eop_end() const { return EndNodes.end(); }
00359 
00360   llvm::BumpPtrAllocator & getAllocator() { return BVC.getAllocator(); }
00361   BumpVectorContext &getNodeAllocator() { return BVC; }
00362 
00363   typedef llvm::DenseMap<const ExplodedNode*, ExplodedNode*> NodeMap;
00364 
00365   /// Creates a trimmed version of the graph that only contains paths leading
00366   /// to the given nodes.
00367   ///
00368   /// \param Nodes The nodes which must appear in the final graph. Presumably
00369   ///              these are end-of-path nodes (i.e. they have no successors).
00370   /// \param[out] ForwardMap A optional map from nodes in this graph to nodes in
00371   ///                        the returned graph.
00372   /// \param[out] InverseMap An optional map from nodes in the returned graph to
00373   ///                        nodes in this graph.
00374   /// \returns The trimmed graph
00375   std::unique_ptr<ExplodedGraph>
00376   trim(ArrayRef<const NodeTy *> Nodes,
00377        InterExplodedGraphMap *ForwardMap = nullptr,
00378        InterExplodedGraphMap *InverseMap = nullptr) const;
00379 
00380   /// Enable tracking of recently allocated nodes for potential reclamation
00381   /// when calling reclaimRecentlyAllocatedNodes().
00382   void enableNodeReclamation(unsigned Interval) {
00383     ReclaimCounter = ReclaimNodeInterval = Interval;
00384   }
00385 
00386   /// Reclaim "uninteresting" nodes created since the last time this method
00387   /// was called.
00388   void reclaimRecentlyAllocatedNodes();
00389 
00390   /// \brief Returns true if nodes for the given expression kind are always
00391   ///        kept around.
00392   static bool isInterestingLValueExpr(const Expr *Ex);
00393 
00394 private:
00395   bool shouldCollect(const ExplodedNode *node);
00396   void collectNode(ExplodedNode *node);
00397 };
00398 
00399 class ExplodedNodeSet {
00400   typedef llvm::SmallPtrSet<ExplodedNode*,5> ImplTy;
00401   ImplTy Impl;
00402 
00403 public:
00404   ExplodedNodeSet(ExplodedNode *N) {
00405     assert (N && !static_cast<ExplodedNode*>(N)->isSink());
00406     Impl.insert(N);
00407   }
00408 
00409   ExplodedNodeSet() {}
00410 
00411   inline void Add(ExplodedNode *N) {
00412     if (N && !static_cast<ExplodedNode*>(N)->isSink()) Impl.insert(N);
00413   }
00414 
00415   typedef ImplTy::iterator       iterator;
00416   typedef ImplTy::const_iterator const_iterator;
00417 
00418   unsigned size() const { return Impl.size();  }
00419   bool empty()    const { return Impl.empty(); }
00420   bool erase(ExplodedNode *N) { return Impl.erase(N); }
00421 
00422   void clear() { Impl.clear(); }
00423   void insert(const ExplodedNodeSet &S) {
00424     assert(&S != this);
00425     if (empty())
00426       Impl = S.Impl;
00427     else
00428       Impl.insert(S.begin(), S.end());
00429   }
00430 
00431   inline iterator begin() { return Impl.begin(); }
00432   inline iterator end()   { return Impl.end();   }
00433 
00434   inline const_iterator begin() const { return Impl.begin(); }
00435   inline const_iterator end()   const { return Impl.end();   }
00436 };
00437 
00438 } // end GR namespace
00439 
00440 } // end clang namespace
00441 
00442 // GraphTraits
00443 
00444 namespace llvm {
00445   template<> struct GraphTraits<clang::ento::ExplodedNode*> {
00446     typedef clang::ento::ExplodedNode NodeType;
00447     typedef NodeType::succ_iterator  ChildIteratorType;
00448     typedef llvm::df_iterator<NodeType*>      nodes_iterator;
00449 
00450     static inline NodeType* getEntryNode(NodeType* N) {
00451       return N;
00452     }
00453 
00454     static inline ChildIteratorType child_begin(NodeType* N) {
00455       return N->succ_begin();
00456     }
00457 
00458     static inline ChildIteratorType child_end(NodeType* N) {
00459       return N->succ_end();
00460     }
00461 
00462     static inline nodes_iterator nodes_begin(NodeType* N) {
00463       return df_begin(N);
00464     }
00465 
00466     static inline nodes_iterator nodes_end(NodeType* N) {
00467       return df_end(N);
00468     }
00469   };
00470 
00471   template<> struct GraphTraits<const clang::ento::ExplodedNode*> {
00472     typedef const clang::ento::ExplodedNode NodeType;
00473     typedef NodeType::const_succ_iterator   ChildIteratorType;
00474     typedef llvm::df_iterator<NodeType*>       nodes_iterator;
00475 
00476     static inline NodeType* getEntryNode(NodeType* N) {
00477       return N;
00478     }
00479 
00480     static inline ChildIteratorType child_begin(NodeType* N) {
00481       return N->succ_begin();
00482     }
00483 
00484     static inline ChildIteratorType child_end(NodeType* N) {
00485       return N->succ_end();
00486     }
00487 
00488     static inline nodes_iterator nodes_begin(NodeType* N) {
00489       return df_begin(N);
00490     }
00491 
00492     static inline nodes_iterator nodes_end(NodeType* N) {
00493       return df_end(N);
00494     }
00495   };
00496 
00497 } // end llvm namespace
00498 
00499 #endif