blob: 6d9530bf0c68d5151dcb603d0fba04718619920e [file] [log] [blame]
Anna Zaksc000e7e2012-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//===----------------------------------------------------------------------===//
13#include "clang/Analysis/CallGraph.h"
Anna Zaksc000e7e2012-03-08 00:42:23 +000014#include "clang/AST/ASTContext.h"
15#include "clang/AST/Decl.h"
16#include "clang/AST/StmtVisitor.h"
Anna Zaks1ee76c12012-12-21 17:27:01 +000017#include "llvm/ADT/PostOrderIterator.h"
Anna Zaks5c32dfc2012-12-21 01:19:15 +000018#include "llvm/ADT/Statistic.h"
Anna Zaksc000e7e2012-03-08 00:42:23 +000019#include "llvm/Support/GraphWriter.h"
20
21using namespace clang;
22
Chandler Carruth10346662014-04-22 03:17:02 +000023#define DEBUG_TYPE "CallGraph"
24
Anna Zaks41277502012-12-21 17:27:04 +000025STATISTIC(NumObjCCallEdges, "Number of Objective-C method call edges");
Anna Zaks5c32dfc2012-12-21 01:19:15 +000026STATISTIC(NumBlockCallEdges, "Number of block call edges");
27
Anna Zaks8e078522012-04-12 22:36:48 +000028namespace {
29/// A helper class, which walks the AST and locates all the call sites in the
30/// given function body.
31class CGBuilder : public StmtVisitor<CGBuilder> {
32 CallGraph *G;
Anna Zaks8e078522012-04-12 22:36:48 +000033 CallGraphNode *CallerNode;
34
35public:
Benjamin Kramerd1d76b22012-06-06 17:32:50 +000036 CGBuilder(CallGraph *g, CallGraphNode *N)
37 : G(g), CallerNode(N) {}
Anna Zaks8e078522012-04-12 22:36:48 +000038
39 void VisitStmt(Stmt *S) { VisitChildren(S); }
40
Anna Zaks5c32dfc2012-12-21 01:19:15 +000041 Decl *getDeclFromCall(CallExpr *CE) {
Anna Zaks8e078522012-04-12 22:36:48 +000042 if (FunctionDecl *CalleeDecl = CE->getDirectCallee())
Anna Zaks5c32dfc2012-12-21 01:19:15 +000043 return CalleeDecl;
44
45 // Simple detection of a call through a block.
46 Expr *CEE = CE->getCallee()->IgnoreParenImpCasts();
47 if (BlockExpr *Block = dyn_cast<BlockExpr>(CEE)) {
48 NumBlockCallEdges++;
49 return Block->getBlockDecl();
50 }
51
Craig Topper25542942014-05-20 04:30:07 +000052 return nullptr;
Anna Zaks5c32dfc2012-12-21 01:19:15 +000053 }
54
55 void addCalledDecl(Decl *D) {
56 if (G->includeInGraph(D)) {
57 CallGraphNode *CalleeNode = G->getOrInsertNode(D);
Haojian Wu05349982016-12-12 14:12:10 +000058 CallerNode->addCallee(CalleeNode);
Anna Zaks5c32dfc2012-12-21 01:19:15 +000059 }
60 }
61
62 void VisitCallExpr(CallExpr *CE) {
63 if (Decl *D = getDeclFromCall(CE))
64 addCalledDecl(D);
Artem Dergachev12caf8e2017-01-27 12:14:56 +000065 VisitChildren(CE);
Anna Zaks5c32dfc2012-12-21 01:19:15 +000066 }
67
68 // Adds may-call edges for the ObjC message sends.
69 void VisitObjCMessageExpr(ObjCMessageExpr *ME) {
70 if (ObjCInterfaceDecl *IDecl = ME->getReceiverInterface()) {
71 Selector Sel = ME->getSelector();
72
Anna Zaks41277502012-12-21 17:27:04 +000073 // Find the callee definition within the same translation unit.
Craig Topper25542942014-05-20 04:30:07 +000074 Decl *D = nullptr;
Anna Zaks5c32dfc2012-12-21 01:19:15 +000075 if (ME->isInstanceMessage())
76 D = IDecl->lookupPrivateMethod(Sel);
77 else
78 D = IDecl->lookupPrivateClassMethod(Sel);
79 if (D) {
80 addCalledDecl(D);
81 NumObjCCallEdges++;
Anna Zaks8e078522012-04-12 22:36:48 +000082 }
Anna Zaks5c32dfc2012-12-21 01:19:15 +000083 }
Anna Zaks8e078522012-04-12 22:36:48 +000084 }
85
86 void VisitChildren(Stmt *S) {
Benjamin Kramer642f1732015-07-02 21:03:14 +000087 for (Stmt *SubStmt : S->children())
88 if (SubStmt)
89 this->Visit(SubStmt);
Anna Zaks8e078522012-04-12 22:36:48 +000090 }
91};
92
93} // end anonymous namespace
94
Anna Zaks5c32dfc2012-12-21 01:19:15 +000095void CallGraph::addNodesForBlocks(DeclContext *D) {
96 if (BlockDecl *BD = dyn_cast<BlockDecl>(D))
97 addNodeForDecl(BD, true);
98
Aaron Ballman629afae2014-03-07 19:56:05 +000099 for (auto *I : D->decls())
100 if (auto *DC = dyn_cast<DeclContext>(I))
Anna Zaks5c32dfc2012-12-21 01:19:15 +0000101 addNodesForBlocks(DC);
102}
103
Anna Zaks8e078522012-04-12 22:36:48 +0000104CallGraph::CallGraph() {
Craig Topper25542942014-05-20 04:30:07 +0000105 Root = getOrInsertNode(nullptr);
Anna Zaks8e078522012-04-12 22:36:48 +0000106}
107
Justin Lebar5f3d1dc2016-10-10 16:26:48 +0000108CallGraph::~CallGraph() {}
Anna Zaks8e078522012-04-12 22:36:48 +0000109
110bool CallGraph::includeInGraph(const Decl *D) {
Anna Zaks5c32dfc2012-12-21 01:19:15 +0000111 assert(D);
Anna Zaks87d404d2014-12-17 00:34:07 +0000112 if (!D->hasBody())
Anna Zaks5c32dfc2012-12-21 01:19:15 +0000113 return false;
114
Anna Zaksc000e7e2012-03-08 00:42:23 +0000115 if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
116 // We skip function template definitions, as their semantics is
117 // only determined when they are instantiated.
Anna Zaks87d404d2014-12-17 00:34:07 +0000118 if (FD->isDependentContext())
Anna Zaksc000e7e2012-03-08 00:42:23 +0000119 return false;
120
121 IdentifierInfo *II = FD->getIdentifier();
122 if (II && II->getName().startswith("__inline"))
123 return false;
124 }
125
Anna Zaksc000e7e2012-03-08 00:42:23 +0000126 return true;
127}
128
Anna Zaks8e078522012-04-12 22:36:48 +0000129void CallGraph::addNodeForDecl(Decl* D, bool IsGlobal) {
Anna Zaks9a008bb2012-03-08 23:16:26 +0000130 assert(D);
Anna Zaksc000e7e2012-03-08 00:42:23 +0000131
Anna Zaks8e078522012-04-12 22:36:48 +0000132 // Allocate a new node, mark it as root, and process it's calls.
133 CallGraphNode *Node = getOrInsertNode(D);
Anna Zaksc000e7e2012-03-08 00:42:23 +0000134
135 // Process all the calls by this function as well.
Benjamin Kramerd1d76b22012-06-06 17:32:50 +0000136 CGBuilder builder(this, Node);
Ted Kremenek504957f2012-04-05 04:03:23 +0000137 if (Stmt *Body = D->getBody())
138 builder.Visit(Body);
Anna Zaksc000e7e2012-03-08 00:42:23 +0000139}
140
Anna Zaksc2555772012-03-09 21:13:53 +0000141CallGraphNode *CallGraph::getNode(const Decl *F) const {
Matt Beaumont-Gaydcc425e2012-03-14 20:21:25 +0000142 FunctionMapTy::const_iterator I = FunctionMap.find(F);
Craig Topper25542942014-05-20 04:30:07 +0000143 if (I == FunctionMap.end()) return nullptr;
Justin Lebar5f3d1dc2016-10-10 16:26:48 +0000144 return I->second.get();
Anna Zaksc2555772012-03-09 21:13:53 +0000145}
146
Anna Zaks8e078522012-04-12 22:36:48 +0000147CallGraphNode *CallGraph::getOrInsertNode(Decl *F) {
Anna Zaks87d404d2014-12-17 00:34:07 +0000148 if (F && !isa<ObjCMethodDecl>(F))
149 F = F->getCanonicalDecl();
150
Justin Lebar5f3d1dc2016-10-10 16:26:48 +0000151 std::unique_ptr<CallGraphNode> &Node = FunctionMap[F];
Anna Zaksc000e7e2012-03-08 00:42:23 +0000152 if (Node)
Justin Lebar5f3d1dc2016-10-10 16:26:48 +0000153 return Node.get();
Anna Zaksc000e7e2012-03-08 00:42:23 +0000154
Justin Lebar5f3d1dc2016-10-10 16:26:48 +0000155 Node = llvm::make_unique<CallGraphNode>(F);
Anna Zaks1ee76c12012-12-21 17:27:01 +0000156 // Make Root node a parent of all functions to make sure all are reachable.
Craig Topper25542942014-05-20 04:30:07 +0000157 if (F)
Haojian Wu05349982016-12-12 14:12:10 +0000158 Root->addCallee(Node.get());
Justin Lebar5f3d1dc2016-10-10 16:26:48 +0000159 return Node.get();
Anna Zaksc000e7e2012-03-08 00:42:23 +0000160}
161
162void CallGraph::print(raw_ostream &OS) const {
163 OS << " --- Call graph Dump --- \n";
Anna Zaks1ee76c12012-12-21 17:27:01 +0000164
165 // We are going to print the graph in reverse post order, partially, to make
166 // sure the output is deterministic.
167 llvm::ReversePostOrderTraversal<const clang::CallGraph*> RPOT(this);
168 for (llvm::ReversePostOrderTraversal<const clang::CallGraph*>::rpo_iterator
169 I = RPOT.begin(), E = RPOT.end(); I != E; ++I) {
170 const CallGraphNode *N = *I;
171
Anna Zaksc000e7e2012-03-08 00:42:23 +0000172 OS << " Function: ";
Anna Zaks1ee76c12012-12-21 17:27:01 +0000173 if (N == Root)
Anna Zaksc000e7e2012-03-08 00:42:23 +0000174 OS << "< root >";
175 else
Anna Zaks1ee76c12012-12-21 17:27:01 +0000176 N->print(OS);
177
Anna Zaksc000e7e2012-03-08 00:42:23 +0000178 OS << " calls: ";
Anna Zaks1ee76c12012-12-21 17:27:01 +0000179 for (CallGraphNode::const_iterator CI = N->begin(),
180 CE = N->end(); CI != CE; ++CI) {
Anna Zaksc000e7e2012-03-08 00:42:23 +0000181 assert(*CI != Root && "No one can call the root node.");
182 (*CI)->print(OS);
183 OS << " ";
184 }
185 OS << '\n';
186 }
187 OS.flush();
188}
189
Yaron Kerencdae9412016-01-29 19:38:18 +0000190LLVM_DUMP_METHOD void CallGraph::dump() const {
Anna Zaksc000e7e2012-03-08 00:42:23 +0000191 print(llvm::errs());
192}
193
194void CallGraph::viewGraph() const {
195 llvm::ViewGraph(this, "CallGraph");
196}
197
Anna Zaksc000e7e2012-03-08 00:42:23 +0000198void CallGraphNode::print(raw_ostream &os) const {
Anna Zaks5c32dfc2012-12-21 01:19:15 +0000199 if (const NamedDecl *ND = dyn_cast_or_null<NamedDecl>(FD))
200 return ND->printName(os);
201 os << "< >";
Anna Zaksc000e7e2012-03-08 00:42:23 +0000202}
203
Yaron Kerencdae9412016-01-29 19:38:18 +0000204LLVM_DUMP_METHOD void CallGraphNode::dump() const {
Anna Zaksc000e7e2012-03-08 00:42:23 +0000205 print(llvm::errs());
206}
207
208namespace llvm {
209
210template <>
211struct DOTGraphTraits<const CallGraph*> : public DefaultDOTGraphTraits {
212
213 DOTGraphTraits (bool isSimple=false) : DefaultDOTGraphTraits(isSimple) {}
214
215 static std::string getNodeLabel(const CallGraphNode *Node,
216 const CallGraph *CG) {
217 if (CG->getRoot() == Node) {
218 return "< root >";
219 }
Anna Zaks5c32dfc2012-12-21 01:19:15 +0000220 if (const NamedDecl *ND = dyn_cast_or_null<NamedDecl>(Node->getDecl()))
221 return ND->getNameAsString();
222 else
223 return "< >";
Anna Zaksc000e7e2012-03-08 00:42:23 +0000224 }
225
226};
Alexander Kornienkoab9db512015-06-22 23:07:51 +0000227}