CallGraph.h revision a5d531f67de0cfeb56b843da15146f3b4cd75bd9
1//== CallGraph.h - AST-based Call 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 declares the AST-based CallGraph.
11//
12//  A call graph for functions whose definitions/bodies are available in the
13//  current translation unit. The graph has a "virtual" root node that contains
14//  edges to all externally available functions.
15//===----------------------------------------------------------------------===//
16
17#ifndef LLVM_CLANG_ANALYSIS_CALLGRAPH
18#define LLVM_CLANG_ANALYSIS_CALLGRAPH
19
20#include "clang/AST/DeclBase.h"
21#include "llvm/ADT/DenseMap.h"
22#include "llvm/ADT/GraphTraits.h"
23#include "llvm/ADT/SetVector.h"
24
25namespace clang {
26class CallGraphNode;
27
28class CallGraph {
29  friend class CallGraphNode;
30  typedef llvm::DenseMap<const Decl *, CallGraphNode *> FunctionMapTy;
31
32  /// FunctionMap owns all CallGraphNodes.
33  FunctionMapTy FunctionMap;
34
35  /// This is a virtual root node that has edges to all the global functions -
36  /// 'main' or functions accessible from other translation units.
37  CallGraphNode *Root;
38
39  /// The list of nodes that have no parent. These are unreachable from Root.
40  /// Declarations can get to this list due to impressions in the graph, for
41  /// example, we do not track functions whose addresses were taken.
42  llvm::SetVector<CallGraphNode *> ParentlessNodes;
43
44public:
45  CallGraph();
46  ~CallGraph();
47
48  /// \brief Add the given declaration to the call graph.
49  void addToCallGraph(Decl *D, bool IsGlobal);
50
51  /// \brief Populate the call graph with the functions in the given DeclContext.
52  void addToCallGraph(DeclContext *DC);
53
54  /// \brief Lookup the node for the given declaration.
55  CallGraphNode *getNode(const Decl *) const;
56
57  /// \brief Lookup the node for the given declaration. If none found, insert
58  /// one into the graph.
59  CallGraphNode *getOrInsertFunction(Decl *);
60
61  /// Iterators through all the elements in the graph. Note, this gives
62  /// non-deterministic order.
63  typedef FunctionMapTy::iterator iterator;
64  typedef FunctionMapTy::const_iterator const_iterator;
65  iterator begin() { return FunctionMap.begin(); }
66  iterator end()   { return FunctionMap.end();   }
67  const_iterator begin() const { return FunctionMap.begin(); }
68  const_iterator end()   const { return FunctionMap.end();   }
69
70  /// \brief Get the number of nodes in the graph.
71  unsigned size() const { return FunctionMap.size(); }
72
73  /// \ brief Get the virtual root of the graph, all the functions available
74  /// externally are represented as callees of the node.
75  CallGraphNode *getRoot() const { return Root; }
76
77  /// Iterators through all the nodes of the graph that have no parent. These
78  /// are the unreachable nodes, which are either unused or are due to us
79  /// failing to add a call edge due to the analysis imprecision.
80  typedef llvm::SetVector<CallGraphNode *>::iterator nodes_iterator;
81  typedef llvm::SetVector<CallGraphNode *>::const_iterator const_nodes_iterator;
82  nodes_iterator parentless_begin() { return ParentlessNodes.begin(); }
83  nodes_iterator parentless_end() { return ParentlessNodes.end(); }
84  const_nodes_iterator
85    parentless_begin() const { return ParentlessNodes.begin(); }
86  const_nodes_iterator
87    parentless_end() const { return ParentlessNodes.end(); }
88
89  void print(raw_ostream &os) const;
90  void dump() const;
91  void viewGraph() const;
92};
93
94class CallGraphNode {
95public:
96  typedef CallGraphNode* CallRecord;
97
98private:
99  /// \brief The function/method declaration.
100  Decl *FD;
101
102  /// \brief The list of functions called from this node.
103  // Small vector might be more efficient since we are only tracking functions
104  // whose definition is in the current TU.
105  llvm::SmallVector<CallRecord, 5> CalledFunctions;
106
107public:
108  CallGraphNode(Decl *D) : FD(D) {}
109
110  typedef llvm::SmallVector<CallRecord, 5>::iterator iterator;
111  typedef llvm::SmallVector<CallRecord, 5>::const_iterator const_iterator;
112
113  /// Iterators through all the callees/children of the node.
114  inline iterator begin() { return CalledFunctions.begin(); }
115  inline iterator end()   { return CalledFunctions.end(); }
116  inline const_iterator begin() const { return CalledFunctions.begin(); }
117  inline const_iterator end()   const { return CalledFunctions.end();   }
118
119  inline bool empty() const {return CalledFunctions.empty(); }
120  inline unsigned size() const {return CalledFunctions.size(); }
121
122  void addCallee(CallGraphNode *N, CallGraph *CG) {
123    CalledFunctions.push_back(N);
124    CG->ParentlessNodes.remove(N);
125  }
126
127  Decl *getDecl() const { return FD; }
128
129  StringRef getName() const;
130
131  void print(raw_ostream &os) const;
132  void dump() const;
133};
134
135} // end clang namespace
136
137// Graph traits for iteration, viewing.
138namespace llvm {
139template <> struct GraphTraits<clang::CallGraphNode*> {
140  typedef clang::CallGraphNode NodeType;
141  typedef clang::CallGraphNode::CallRecord CallRecordTy;
142  typedef std::pointer_to_unary_function<CallRecordTy,
143                                         clang::CallGraphNode*> CGNDerefFun;
144  static NodeType *getEntryNode(clang::CallGraphNode *CGN) { return CGN; }
145  typedef mapped_iterator<NodeType::iterator, CGNDerefFun> ChildIteratorType;
146  static inline ChildIteratorType child_begin(NodeType *N) {
147    return map_iterator(N->begin(), CGNDerefFun(CGNDeref));
148  }
149  static inline ChildIteratorType child_end  (NodeType *N) {
150    return map_iterator(N->end(), CGNDerefFun(CGNDeref));
151  }
152  static clang::CallGraphNode *CGNDeref(CallRecordTy P) {
153    return P;
154  }
155};
156
157template <> struct GraphTraits<const clang::CallGraphNode*> {
158  typedef const clang::CallGraphNode NodeType;
159  typedef NodeType::const_iterator ChildIteratorType;
160  static NodeType *getEntryNode(const clang::CallGraphNode *CGN) { return CGN; }
161  static inline ChildIteratorType child_begin(NodeType *N) { return N->begin();}
162  static inline ChildIteratorType child_end  (NodeType *N) { return N->end(); }
163};
164
165template <> struct GraphTraits<clang::CallGraph*>
166  : public GraphTraits<clang::CallGraphNode*> {
167
168  static NodeType *getEntryNode(clang::CallGraph *CGN) {
169    return CGN->getRoot();  // Start at the external node!
170  }
171  typedef std::pair<const clang::Decl*, clang::CallGraphNode*> PairTy;
172  typedef std::pointer_to_unary_function<PairTy, clang::CallGraphNode&> DerefFun;
173  // nodes_iterator/begin/end - Allow iteration over all nodes in the graph
174  typedef mapped_iterator<clang::CallGraph::iterator, DerefFun> nodes_iterator;
175
176  static nodes_iterator nodes_begin(clang::CallGraph *CG) {
177    return map_iterator(CG->begin(), DerefFun(CGdereference));
178  }
179  static nodes_iterator nodes_end  (clang::CallGraph *CG) {
180    return map_iterator(CG->end(), DerefFun(CGdereference));
181  }
182  static clang::CallGraphNode &CGdereference(PairTy P) {
183    return *(P.second);
184  }
185
186  static unsigned size(clang::CallGraph *CG) {
187    return CG->size();
188  }
189};
190
191template <> struct GraphTraits<const clang::CallGraph*> :
192  public GraphTraits<const clang::CallGraphNode*> {
193  static NodeType *getEntryNode(const clang::CallGraph *CGN) {
194    return CGN->getRoot();
195  }
196  typedef std::pair<const clang::Decl*, clang::CallGraphNode*> PairTy;
197  typedef std::pointer_to_unary_function<PairTy, clang::CallGraphNode&> DerefFun;
198  // nodes_iterator/begin/end - Allow iteration over all nodes in the graph
199  typedef mapped_iterator<clang::CallGraph::const_iterator,
200                          DerefFun> nodes_iterator;
201
202  static nodes_iterator nodes_begin(const clang::CallGraph *CG) {
203    return map_iterator(CG->begin(), DerefFun(CGdereference));
204  }
205  static nodes_iterator nodes_end(const clang::CallGraph *CG) {
206    return map_iterator(CG->end(), DerefFun(CGdereference));
207  }
208  static clang::CallGraphNode &CGdereference(PairTy P) {
209    return *(P.second);
210  }
211
212  static unsigned size(const clang::CallGraph *CG) {
213    return CG->size();
214  }
215};
216
217} // end llvm namespace
218
219#endif
220