clang API Documentation

CallGraph.h
Go to the documentation of this file.
00001 //== CallGraph.h - AST-based Call 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 declares the AST-based CallGraph.
00011 //
00012 //  A call graph for functions whose definitions/bodies are available in the
00013 //  current translation unit. The graph has a "virtual" root node that contains
00014 //  edges to all externally available functions.
00015 //===----------------------------------------------------------------------===//
00016 
00017 #ifndef LLVM_CLANG_ANALYSIS_CALLGRAPH_H
00018 #define LLVM_CLANG_ANALYSIS_CALLGRAPH_H
00019 
00020 #include "clang/AST/DeclBase.h"
00021 #include "clang/AST/RecursiveASTVisitor.h"
00022 #include "llvm/ADT/DenseMap.h"
00023 #include "llvm/ADT/GraphTraits.h"
00024 #include "llvm/ADT/SetVector.h"
00025 
00026 namespace clang {
00027 class CallGraphNode;
00028 
00029 /// \brief The AST-based call graph.
00030 ///
00031 /// The call graph extends itself with the given declarations by implementing
00032 /// the recursive AST visitor, which constructs the graph by visiting the given
00033 /// declarations.
00034 class CallGraph : public RecursiveASTVisitor<CallGraph> {
00035   friend class CallGraphNode;
00036 
00037   typedef llvm::DenseMap<const Decl *, CallGraphNode *> FunctionMapTy;
00038 
00039   /// FunctionMap owns all CallGraphNodes.
00040   FunctionMapTy FunctionMap;
00041 
00042   /// This is a virtual root node that has edges to all the functions.
00043   CallGraphNode *Root;
00044 
00045 public:
00046   CallGraph();
00047   ~CallGraph();
00048 
00049   /// \brief Populate the call graph with the functions in the given
00050   /// declaration.
00051   ///
00052   /// Recursively walks the declaration to find all the dependent Decls as well.
00053   void addToCallGraph(Decl *D) {
00054     TraverseDecl(D);
00055   }
00056 
00057   /// \brief Determine if a declaration should be included in the graph.
00058   static bool includeInGraph(const Decl *D);
00059 
00060   /// \brief Lookup the node for the given declaration.
00061   CallGraphNode *getNode(const Decl *) const;
00062 
00063   /// \brief Lookup the node for the given declaration. If none found, insert
00064   /// one into the graph.
00065   CallGraphNode *getOrInsertNode(Decl *);
00066 
00067   /// Iterators through all the elements in the graph. Note, this gives
00068   /// non-deterministic order.
00069   typedef FunctionMapTy::iterator iterator;
00070   typedef FunctionMapTy::const_iterator const_iterator;
00071   iterator begin() { return FunctionMap.begin(); }
00072   iterator end()   { return FunctionMap.end();   }
00073   const_iterator begin() const { return FunctionMap.begin(); }
00074   const_iterator end()   const { return FunctionMap.end();   }
00075 
00076   /// \brief Get the number of nodes in the graph.
00077   unsigned size() const { return FunctionMap.size(); }
00078 
00079   /// \ brief Get the virtual root of the graph, all the functions available
00080   /// externally are represented as callees of the node.
00081   CallGraphNode *getRoot() const { return Root; }
00082 
00083   /// Iterators through all the nodes of the graph that have no parent. These
00084   /// are the unreachable nodes, which are either unused or are due to us
00085   /// failing to add a call edge due to the analysis imprecision.
00086   typedef llvm::SetVector<CallGraphNode *>::iterator nodes_iterator;
00087   typedef llvm::SetVector<CallGraphNode *>::const_iterator const_nodes_iterator;
00088 
00089   void print(raw_ostream &os) const;
00090   void dump() const;
00091   void viewGraph() const;
00092 
00093   void addNodesForBlocks(DeclContext *D);
00094 
00095   /// Part of recursive declaration visitation. We recursively visit all the
00096   /// declarations to collect the root functions.
00097   bool VisitFunctionDecl(FunctionDecl *FD) {
00098     // We skip function template definitions, as their semantics is
00099     // only determined when they are instantiated.
00100     if (includeInGraph(FD)) {
00101       // Add all blocks declared inside this function to the graph.
00102       addNodesForBlocks(FD);
00103       // If this function has external linkage, anything could call it.
00104       // Note, we are not precise here. For example, the function could have
00105       // its address taken.
00106       addNodeForDecl(FD, FD->isGlobal());
00107     }
00108     return true;
00109   }
00110 
00111   /// Part of recursive declaration visitation.
00112   bool VisitObjCMethodDecl(ObjCMethodDecl *MD) {
00113     if (includeInGraph(MD)) {
00114       addNodesForBlocks(MD);
00115       addNodeForDecl(MD, true);
00116     }
00117     return true;
00118   }
00119 
00120   // We are only collecting the declarations, so do not step into the bodies.
00121   bool TraverseStmt(Stmt *S) { return true; }
00122 
00123   bool shouldWalkTypesOfTypeLocs() const { return false; }
00124 
00125 private:
00126   /// \brief Add the given declaration to the call graph.
00127   void addNodeForDecl(Decl *D, bool IsGlobal);
00128 
00129   /// \brief Allocate a new node in the graph.
00130   CallGraphNode *allocateNewNode(Decl *);
00131 };
00132 
00133 class CallGraphNode {
00134 public:
00135   typedef CallGraphNode* CallRecord;
00136 
00137 private:
00138   /// \brief The function/method declaration.
00139   Decl *FD;
00140 
00141   /// \brief The list of functions called from this node.
00142   SmallVector<CallRecord, 5> CalledFunctions;
00143 
00144 public:
00145   CallGraphNode(Decl *D) : FD(D) {}
00146 
00147   typedef SmallVectorImpl<CallRecord>::iterator iterator;
00148   typedef SmallVectorImpl<CallRecord>::const_iterator const_iterator;
00149 
00150   /// Iterators through all the callees/children of the node.
00151   inline iterator begin() { return CalledFunctions.begin(); }
00152   inline iterator end()   { return CalledFunctions.end(); }
00153   inline const_iterator begin() const { return CalledFunctions.begin(); }
00154   inline const_iterator end()   const { return CalledFunctions.end();   }
00155 
00156   inline bool empty() const {return CalledFunctions.empty(); }
00157   inline unsigned size() const {return CalledFunctions.size(); }
00158 
00159   void addCallee(CallGraphNode *N, CallGraph *CG) {
00160     CalledFunctions.push_back(N);
00161   }
00162 
00163   Decl *getDecl() const { return FD; }
00164 
00165   void print(raw_ostream &os) const;
00166   void dump() const;
00167 };
00168 
00169 } // end clang namespace
00170 
00171 // Graph traits for iteration, viewing.
00172 namespace llvm {
00173 template <> struct GraphTraits<clang::CallGraphNode*> {
00174   typedef clang::CallGraphNode NodeType;
00175   typedef clang::CallGraphNode::CallRecord CallRecordTy;
00176   typedef std::pointer_to_unary_function<CallRecordTy,
00177                                          clang::CallGraphNode*> CGNDerefFun;
00178   static NodeType *getEntryNode(clang::CallGraphNode *CGN) { return CGN; }
00179   typedef mapped_iterator<NodeType::iterator, CGNDerefFun> ChildIteratorType;
00180   static inline ChildIteratorType child_begin(NodeType *N) {
00181     return map_iterator(N->begin(), CGNDerefFun(CGNDeref));
00182   }
00183   static inline ChildIteratorType child_end  (NodeType *N) {
00184     return map_iterator(N->end(), CGNDerefFun(CGNDeref));
00185   }
00186   static clang::CallGraphNode *CGNDeref(CallRecordTy P) {
00187     return P;
00188   }
00189 };
00190 
00191 template <> struct GraphTraits<const clang::CallGraphNode*> {
00192   typedef const clang::CallGraphNode NodeType;
00193   typedef NodeType::const_iterator ChildIteratorType;
00194   static NodeType *getEntryNode(const clang::CallGraphNode *CGN) { return CGN; }
00195   static inline ChildIteratorType child_begin(NodeType *N) { return N->begin();}
00196   static inline ChildIteratorType child_end(NodeType *N) { return N->end(); }
00197 };
00198 
00199 template <> struct GraphTraits<clang::CallGraph*>
00200   : public GraphTraits<clang::CallGraphNode*> {
00201 
00202   static NodeType *getEntryNode(clang::CallGraph *CGN) {
00203     return CGN->getRoot();  // Start at the external node!
00204   }
00205   typedef std::pair<const clang::Decl*, clang::CallGraphNode*> PairTy;
00206   typedef std::pointer_to_unary_function<PairTy, clang::CallGraphNode&> DerefFun;
00207   // nodes_iterator/begin/end - Allow iteration over all nodes in the graph
00208   typedef mapped_iterator<clang::CallGraph::iterator, DerefFun> nodes_iterator;
00209 
00210   static nodes_iterator nodes_begin(clang::CallGraph *CG) {
00211     return map_iterator(CG->begin(), DerefFun(CGdereference));
00212   }
00213   static nodes_iterator nodes_end  (clang::CallGraph *CG) {
00214     return map_iterator(CG->end(), DerefFun(CGdereference));
00215   }
00216   static clang::CallGraphNode &CGdereference(PairTy P) {
00217     return *(P.second);
00218   }
00219 
00220   static unsigned size(clang::CallGraph *CG) {
00221     return CG->size();
00222   }
00223 };
00224 
00225 template <> struct GraphTraits<const clang::CallGraph*> :
00226   public GraphTraits<const clang::CallGraphNode*> {
00227   static NodeType *getEntryNode(const clang::CallGraph *CGN) {
00228     return CGN->getRoot();
00229   }
00230   typedef std::pair<const clang::Decl*, clang::CallGraphNode*> PairTy;
00231   typedef std::pointer_to_unary_function<PairTy, clang::CallGraphNode&> DerefFun;
00232   // nodes_iterator/begin/end - Allow iteration over all nodes in the graph
00233   typedef mapped_iterator<clang::CallGraph::const_iterator,
00234                           DerefFun> nodes_iterator;
00235 
00236   static nodes_iterator nodes_begin(const clang::CallGraph *CG) {
00237     return map_iterator(CG->begin(), DerefFun(CGdereference));
00238   }
00239   static nodes_iterator nodes_end(const clang::CallGraph *CG) {
00240     return map_iterator(CG->end(), DerefFun(CGdereference));
00241   }
00242   static clang::CallGraphNode &CGdereference(PairTy P) {
00243     return *(P.second);
00244   }
00245 
00246   static unsigned size(const clang::CallGraph *CG) {
00247     return CG->size();
00248   }
00249 };
00250 
00251 } // end llvm namespace
00252 
00253 #endif