blob: 424e5c795e26d768f8eaab677ac6803dc87f9329 [file] [log] [blame]
Anna Zaks196b8cf2012-03-08 00:42:23 +00001//== CallGraph.cpp - 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 defines the AST-based CallGraph.
11//
12//===----------------------------------------------------------------------===//
Anna Zaks4f858df2012-12-21 01:19:15 +000013#define DEBUG_TYPE "CallGraph"
14
Anna Zaks196b8cf2012-03-08 00:42:23 +000015#include "clang/Analysis/CallGraph.h"
Anna Zaks196b8cf2012-03-08 00:42:23 +000016#include "clang/AST/ASTContext.h"
17#include "clang/AST/Decl.h"
18#include "clang/AST/StmtVisitor.h"
Anna Zaks4f858df2012-12-21 01:19:15 +000019#include "llvm/ADT/Statistic.h"
Anna Zaks196b8cf2012-03-08 00:42:23 +000020#include "llvm/Support/GraphWriter.h"
21
22using namespace clang;
23
Anna Zaks4f858df2012-12-21 01:19:15 +000024STATISTIC(NumObjCCallEdges, "Number of objective C call edges");
25STATISTIC(NumBlockCallEdges, "Number of block call edges");
26
Anna Zaks6a860822012-04-12 22:36:48 +000027namespace {
28/// A helper class, which walks the AST and locates all the call sites in the
29/// given function body.
30class CGBuilder : public StmtVisitor<CGBuilder> {
31 CallGraph *G;
Anna Zaks6a860822012-04-12 22:36:48 +000032 CallGraphNode *CallerNode;
33
34public:
Benjamin Kramerfacde172012-06-06 17:32:50 +000035 CGBuilder(CallGraph *g, CallGraphNode *N)
36 : G(g), CallerNode(N) {}
Anna Zaks6a860822012-04-12 22:36:48 +000037
38 void VisitStmt(Stmt *S) { VisitChildren(S); }
39
Anna Zaks4f858df2012-12-21 01:19:15 +000040 Decl *getDeclFromCall(CallExpr *CE) {
Anna Zaks6a860822012-04-12 22:36:48 +000041 if (FunctionDecl *CalleeDecl = CE->getDirectCallee())
Anna Zaks4f858df2012-12-21 01:19:15 +000042 return CalleeDecl;
43
44 // Simple detection of a call through a block.
45 Expr *CEE = CE->getCallee()->IgnoreParenImpCasts();
46 if (BlockExpr *Block = dyn_cast<BlockExpr>(CEE)) {
47 NumBlockCallEdges++;
48 return Block->getBlockDecl();
49 }
50
51 return 0;
52 }
53
54 void addCalledDecl(Decl *D) {
55 if (G->includeInGraph(D)) {
56 CallGraphNode *CalleeNode = G->getOrInsertNode(D);
57 CallerNode->addCallee(CalleeNode, G);
58 }
59 }
60
61 void VisitCallExpr(CallExpr *CE) {
62 if (Decl *D = getDeclFromCall(CE))
63 addCalledDecl(D);
64 }
65
66 // Adds may-call edges for the ObjC message sends.
67 void VisitObjCMessageExpr(ObjCMessageExpr *ME) {
68 if (ObjCInterfaceDecl *IDecl = ME->getReceiverInterface()) {
69 Selector Sel = ME->getSelector();
70
71 // Fild the callee definition within the same translation unit.
72 Decl *D = 0;
73 if (ME->isInstanceMessage())
74 D = IDecl->lookupPrivateMethod(Sel);
75 else
76 D = IDecl->lookupPrivateClassMethod(Sel);
77 if (D) {
78 addCalledDecl(D);
79 NumObjCCallEdges++;
Anna Zaks6a860822012-04-12 22:36:48 +000080 }
Anna Zaks4f858df2012-12-21 01:19:15 +000081 }
Anna Zaks6a860822012-04-12 22:36:48 +000082 }
83
84 void VisitChildren(Stmt *S) {
85 for (Stmt::child_range I = S->children(); I; ++I)
86 if (*I)
87 static_cast<CGBuilder*>(this)->Visit(*I);
88 }
89};
90
91} // end anonymous namespace
92
Anna Zaks4f858df2012-12-21 01:19:15 +000093void CallGraph::addNodesForBlocks(DeclContext *D) {
94 if (BlockDecl *BD = dyn_cast<BlockDecl>(D))
95 addNodeForDecl(BD, true);
96
97 for (DeclContext::decl_iterator I = D->decls_begin(), E = D->decls_end();
98 I!=E; ++I)
99 if (DeclContext *DC = dyn_cast<DeclContext>(*I))
100 addNodesForBlocks(DC);
101}
102
Anna Zaks6a860822012-04-12 22:36:48 +0000103CallGraph::CallGraph() {
104 Root = getOrInsertNode(0);
105}
106
107CallGraph::~CallGraph() {
108 if (!FunctionMap.empty()) {
109 for (FunctionMapTy::iterator I = FunctionMap.begin(), E = FunctionMap.end();
110 I != E; ++I)
111 delete I->second;
112 FunctionMap.clear();
113 }
114}
115
116bool CallGraph::includeInGraph(const Decl *D) {
Anna Zaks4f858df2012-12-21 01:19:15 +0000117 assert(D);
118 if (!D->getBody())
119 return false;
120
Anna Zaks196b8cf2012-03-08 00:42:23 +0000121 if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
122 // We skip function template definitions, as their semantics is
123 // only determined when they are instantiated.
124 if (!FD->isThisDeclarationADefinition() ||
125 FD->isDependentContext())
126 return false;
127
128 IdentifierInfo *II = FD->getIdentifier();
129 if (II && II->getName().startswith("__inline"))
130 return false;
131 }
132
133 if (const ObjCMethodDecl *ID = dyn_cast<ObjCMethodDecl>(D)) {
134 if (!ID->isThisDeclarationADefinition())
135 return false;
136 }
137
138 return true;
139}
140
Anna Zaks6a860822012-04-12 22:36:48 +0000141void CallGraph::addNodeForDecl(Decl* D, bool IsGlobal) {
Anna Zaksd2776612012-03-08 23:16:26 +0000142 assert(D);
Anna Zaks196b8cf2012-03-08 00:42:23 +0000143
Anna Zaks6a860822012-04-12 22:36:48 +0000144 // Do nothing if the node already exists.
145 if (FunctionMap.find(D) != FunctionMap.end())
146 return;
147
148 // Allocate a new node, mark it as root, and process it's calls.
149 CallGraphNode *Node = getOrInsertNode(D);
Anna Zaks196b8cf2012-03-08 00:42:23 +0000150 if (IsGlobal)
151 Root->addCallee(Node, this);
152
153 // Process all the calls by this function as well.
Benjamin Kramerfacde172012-06-06 17:32:50 +0000154 CGBuilder builder(this, Node);
Ted Kremenekbb3d20f2012-04-05 04:03:23 +0000155 if (Stmt *Body = D->getBody())
156 builder.Visit(Body);
Anna Zaks196b8cf2012-03-08 00:42:23 +0000157}
158
Anna Zaksa5d531f2012-03-09 21:13:53 +0000159CallGraphNode *CallGraph::getNode(const Decl *F) const {
Matt Beaumont-Gayd53e8772012-03-14 20:21:25 +0000160 FunctionMapTy::const_iterator I = FunctionMap.find(F);
161 if (I == FunctionMap.end()) return 0;
162 return I->second;
Anna Zaksa5d531f2012-03-09 21:13:53 +0000163}
164
Anna Zaks6a860822012-04-12 22:36:48 +0000165CallGraphNode *CallGraph::getOrInsertNode(Decl *F) {
Anna Zaks196b8cf2012-03-08 00:42:23 +0000166 CallGraphNode *&Node = FunctionMap[F];
167 if (Node)
168 return Node;
169
170 Node = new CallGraphNode(F);
Anna Zaksd2776612012-03-08 23:16:26 +0000171 // If not root, add to the parentless list.
172 if (F != 0)
173 ParentlessNodes.insert(Node);
Anna Zaks196b8cf2012-03-08 00:42:23 +0000174 return Node;
175}
176
177void CallGraph::print(raw_ostream &OS) const {
178 OS << " --- Call graph Dump --- \n";
179 for (const_iterator I = begin(), E = end(); I != E; ++I) {
180 OS << " Function: ";
181 if (I->second == Root)
182 OS << "< root >";
183 else
184 I->second->print(OS);
185 OS << " calls: ";
186 for (CallGraphNode::iterator CI = I->second->begin(),
187 CE = I->second->end(); CI != CE; ++CI) {
188 assert(*CI != Root && "No one can call the root node.");
189 (*CI)->print(OS);
190 OS << " ";
191 }
192 OS << '\n';
193 }
194 OS.flush();
195}
196
197void CallGraph::dump() const {
198 print(llvm::errs());
199}
200
201void CallGraph::viewGraph() const {
202 llvm::ViewGraph(this, "CallGraph");
203}
204
Anna Zaks196b8cf2012-03-08 00:42:23 +0000205void CallGraphNode::print(raw_ostream &os) const {
Anna Zaks4f858df2012-12-21 01:19:15 +0000206 if (const NamedDecl *ND = dyn_cast_or_null<NamedDecl>(FD))
207 return ND->printName(os);
208 os << "< >";
Anna Zaks196b8cf2012-03-08 00:42:23 +0000209}
210
211void CallGraphNode::dump() const {
212 print(llvm::errs());
213}
214
215namespace llvm {
216
217template <>
218struct DOTGraphTraits<const CallGraph*> : public DefaultDOTGraphTraits {
219
220 DOTGraphTraits (bool isSimple=false) : DefaultDOTGraphTraits(isSimple) {}
221
222 static std::string getNodeLabel(const CallGraphNode *Node,
223 const CallGraph *CG) {
224 if (CG->getRoot() == Node) {
225 return "< root >";
226 }
Anna Zaks4f858df2012-12-21 01:19:15 +0000227 if (const NamedDecl *ND = dyn_cast_or_null<NamedDecl>(Node->getDecl()))
228 return ND->getNameAsString();
229 else
230 return "< >";
Anna Zaks196b8cf2012-03-08 00:42:23 +0000231 }
232
233};
234}