]> CyberLeo.Net >> Repos - FreeBSD/releng/9.1.git/blob - contrib/llvm/tools/clang/include/clang/Analysis/CallGraph.h
Copy stable/9 to releng/9.1 as part of the 9.1-RELEASE release process.
[FreeBSD/releng/9.1.git] / contrib / llvm / tools / clang / include / clang / Analysis / CallGraph.h
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 "clang/AST/RecursiveASTVisitor.h"
22 #include "llvm/ADT/DenseMap.h"
23 #include "llvm/ADT/GraphTraits.h"
24 #include "llvm/ADT/SetVector.h"
25
26 namespace clang {
27 class CallGraphNode;
28
29 /// \class The AST-based call graph.
30 ///
31 /// The call graph extends itself with the given declarations by implementing
32 /// the recursive AST visitor, which constructs the graph by visiting the given
33 /// declarations.
34 class CallGraph : public RecursiveASTVisitor<CallGraph> {
35   friend class CallGraphNode;
36
37   typedef llvm::DenseMap<const Decl *, CallGraphNode *> FunctionMapTy;
38
39   /// FunctionMap owns all CallGraphNodes.
40   FunctionMapTy FunctionMap;
41
42   /// This is a virtual root node that has edges to all the global functions -
43   /// 'main' or functions accessible from other translation units.
44   CallGraphNode *Root;
45
46   /// The list of nodes that have no parent. These are unreachable from Root.
47   /// Declarations can get to this list due to impressions in the graph, for
48   /// example, we do not track functions whose addresses were taken.
49   llvm::SetVector<CallGraphNode *> ParentlessNodes;
50
51 public:
52   CallGraph();
53   ~CallGraph();
54
55   /// \brief Populate the call graph with the functions in the given
56   /// declaration.
57   ///
58   /// Recursively walks the declaration to find all the dependent Decls as well.
59   void addToCallGraph(Decl *D) {
60     TraverseDecl(D);
61   }
62
63   /// \brief Determine if a declaration should be included in the graph.
64   static bool includeInGraph(const Decl *D);
65
66   /// \brief Lookup the node for the given declaration.
67   CallGraphNode *getNode(const Decl *) const;
68
69   /// \brief Lookup the node for the given declaration. If none found, insert
70   /// one into the graph.
71   CallGraphNode *getOrInsertNode(Decl *);
72
73   /// Iterators through all the elements in the graph. Note, this gives
74   /// non-deterministic order.
75   typedef FunctionMapTy::iterator iterator;
76   typedef FunctionMapTy::const_iterator const_iterator;
77   iterator begin() { return FunctionMap.begin(); }
78   iterator end()   { return FunctionMap.end();   }
79   const_iterator begin() const { return FunctionMap.begin(); }
80   const_iterator end()   const { return FunctionMap.end();   }
81
82   /// \brief Get the number of nodes in the graph.
83   unsigned size() const { return FunctionMap.size(); }
84
85   /// \ brief Get the virtual root of the graph, all the functions available
86   /// externally are represented as callees of the node.
87   CallGraphNode *getRoot() const { return Root; }
88
89   /// Iterators through all the nodes of the graph that have no parent. These
90   /// are the unreachable nodes, which are either unused or are due to us
91   /// failing to add a call edge due to the analysis imprecision.
92   typedef llvm::SetVector<CallGraphNode *>::iterator nodes_iterator;
93   typedef llvm::SetVector<CallGraphNode *>::const_iterator const_nodes_iterator;
94   nodes_iterator parentless_begin() { return ParentlessNodes.begin(); }
95   nodes_iterator parentless_end() { return ParentlessNodes.end(); }
96   const_nodes_iterator
97     parentless_begin() const { return ParentlessNodes.begin(); }
98   const_nodes_iterator
99     parentless_end() const { return ParentlessNodes.end(); }
100
101   void print(raw_ostream &os) const;
102   void dump() const;
103   void viewGraph() const;
104
105   /// Part of recursive declaration visitation.
106   bool VisitFunctionDecl(FunctionDecl *FD) {
107     // We skip function template definitions, as their semantics is
108     // only determined when they are instantiated.
109     if (includeInGraph(FD))
110       // If this function has external linkage, anything could call it.
111       // Note, we are not precise here. For example, the function could have
112       // its address taken.
113       addNodeForDecl(FD, FD->isGlobal());
114     return true;
115   }
116
117   /// Part of recursive declaration visitation.
118   bool VisitObjCMethodDecl(ObjCMethodDecl *MD) {
119     if (includeInGraph(MD))
120       addNodeForDecl(MD, true);
121     return true;
122   }
123
124 private:
125   /// \brief Add the given declaration to the call graph.
126   void addNodeForDecl(Decl *D, bool IsGlobal);
127
128   /// \brief Allocate a new node in the graph.
129   CallGraphNode *allocateNewNode(Decl *);
130 };
131
132 class CallGraphNode {
133 public:
134   typedef CallGraphNode* CallRecord;
135
136 private:
137   /// \brief The function/method declaration.
138   Decl *FD;
139
140   /// \brief The list of functions called from this node.
141   // Small vector might be more efficient since we are only tracking functions
142   // whose definition is in the current TU.
143   llvm::SmallVector<CallRecord, 5> CalledFunctions;
144
145 public:
146   CallGraphNode(Decl *D) : FD(D) {}
147
148   typedef llvm::SmallVector<CallRecord, 5>::iterator iterator;
149   typedef llvm::SmallVector<CallRecord, 5>::const_iterator const_iterator;
150
151   /// Iterators through all the callees/children of the node.
152   inline iterator begin() { return CalledFunctions.begin(); }
153   inline iterator end()   { return CalledFunctions.end(); }
154   inline const_iterator begin() const { return CalledFunctions.begin(); }
155   inline const_iterator end()   const { return CalledFunctions.end();   }
156
157   inline bool empty() const {return CalledFunctions.empty(); }
158   inline unsigned size() const {return CalledFunctions.size(); }
159
160   void addCallee(CallGraphNode *N, CallGraph *CG) {
161     CalledFunctions.push_back(N);
162     CG->ParentlessNodes.remove(N);
163   }
164
165   Decl *getDecl() const { return FD; }
166
167   StringRef getName() const;
168
169   void print(raw_ostream &os) const;
170   void dump() const;
171 };
172
173 } // end clang namespace
174
175 // Graph traits for iteration, viewing.
176 namespace llvm {
177 template <> struct GraphTraits<clang::CallGraphNode*> {
178   typedef clang::CallGraphNode NodeType;
179   typedef clang::CallGraphNode::CallRecord CallRecordTy;
180   typedef std::pointer_to_unary_function<CallRecordTy,
181                                          clang::CallGraphNode*> CGNDerefFun;
182   static NodeType *getEntryNode(clang::CallGraphNode *CGN) { return CGN; }
183   typedef mapped_iterator<NodeType::iterator, CGNDerefFun> ChildIteratorType;
184   static inline ChildIteratorType child_begin(NodeType *N) {
185     return map_iterator(N->begin(), CGNDerefFun(CGNDeref));
186   }
187   static inline ChildIteratorType child_end  (NodeType *N) {
188     return map_iterator(N->end(), CGNDerefFun(CGNDeref));
189   }
190   static clang::CallGraphNode *CGNDeref(CallRecordTy P) {
191     return P;
192   }
193 };
194
195 template <> struct GraphTraits<const clang::CallGraphNode*> {
196   typedef const clang::CallGraphNode NodeType;
197   typedef NodeType::const_iterator ChildIteratorType;
198   static NodeType *getEntryNode(const clang::CallGraphNode *CGN) { return CGN; }
199   static inline ChildIteratorType child_begin(NodeType *N) { return N->begin();}
200   static inline ChildIteratorType child_end  (NodeType *N) { return N->end(); }
201 };
202
203 template <> struct GraphTraits<clang::CallGraph*>
204   : public GraphTraits<clang::CallGraphNode*> {
205
206   static NodeType *getEntryNode(clang::CallGraph *CGN) {
207     return CGN->getRoot();  // Start at the external node!
208   }
209   typedef std::pair<const clang::Decl*, clang::CallGraphNode*> PairTy;
210   typedef std::pointer_to_unary_function<PairTy, clang::CallGraphNode&> DerefFun;
211   // nodes_iterator/begin/end - Allow iteration over all nodes in the graph
212   typedef mapped_iterator<clang::CallGraph::iterator, DerefFun> nodes_iterator;
213
214   static nodes_iterator nodes_begin(clang::CallGraph *CG) {
215     return map_iterator(CG->begin(), DerefFun(CGdereference));
216   }
217   static nodes_iterator nodes_end  (clang::CallGraph *CG) {
218     return map_iterator(CG->end(), DerefFun(CGdereference));
219   }
220   static clang::CallGraphNode &CGdereference(PairTy P) {
221     return *(P.second);
222   }
223
224   static unsigned size(clang::CallGraph *CG) {
225     return CG->size();
226   }
227 };
228
229 template <> struct GraphTraits<const clang::CallGraph*> :
230   public GraphTraits<const clang::CallGraphNode*> {
231   static NodeType *getEntryNode(const clang::CallGraph *CGN) {
232     return CGN->getRoot();
233   }
234   typedef std::pair<const clang::Decl*, clang::CallGraphNode*> PairTy;
235   typedef std::pointer_to_unary_function<PairTy, clang::CallGraphNode&> DerefFun;
236   // nodes_iterator/begin/end - Allow iteration over all nodes in the graph
237   typedef mapped_iterator<clang::CallGraph::const_iterator,
238                           DerefFun> nodes_iterator;
239
240   static nodes_iterator nodes_begin(const clang::CallGraph *CG) {
241     return map_iterator(CG->begin(), DerefFun(CGdereference));
242   }
243   static nodes_iterator nodes_end(const clang::CallGraph *CG) {
244     return map_iterator(CG->end(), DerefFun(CGdereference));
245   }
246   static clang::CallGraphNode &CGdereference(PairTy P) {
247     return *(P.second);
248   }
249
250   static unsigned size(const clang::CallGraph *CG) {
251     return CG->size();
252   }
253 };
254
255 } // end llvm namespace
256
257 #endif