1*67e74705SXin Li //== CallGraph.cpp - AST-based Call graph ----------------------*- C++ -*--==//
2*67e74705SXin Li //
3*67e74705SXin Li // The LLVM Compiler Infrastructure
4*67e74705SXin Li //
5*67e74705SXin Li // This file is distributed under the University of Illinois Open Source
6*67e74705SXin Li // License. See LICENSE.TXT for details.
7*67e74705SXin Li //
8*67e74705SXin Li //===----------------------------------------------------------------------===//
9*67e74705SXin Li //
10*67e74705SXin Li // This file defines the AST-based CallGraph.
11*67e74705SXin Li //
12*67e74705SXin Li //===----------------------------------------------------------------------===//
13*67e74705SXin Li #include "clang/Analysis/CallGraph.h"
14*67e74705SXin Li #include "clang/AST/ASTContext.h"
15*67e74705SXin Li #include "clang/AST/Decl.h"
16*67e74705SXin Li #include "clang/AST/StmtVisitor.h"
17*67e74705SXin Li #include "llvm/ADT/PostOrderIterator.h"
18*67e74705SXin Li #include "llvm/ADT/Statistic.h"
19*67e74705SXin Li #include "llvm/Support/GraphWriter.h"
20*67e74705SXin Li
21*67e74705SXin Li using namespace clang;
22*67e74705SXin Li
23*67e74705SXin Li #define DEBUG_TYPE "CallGraph"
24*67e74705SXin Li
25*67e74705SXin Li STATISTIC(NumObjCCallEdges, "Number of Objective-C method call edges");
26*67e74705SXin Li STATISTIC(NumBlockCallEdges, "Number of block call edges");
27*67e74705SXin Li
28*67e74705SXin Li namespace {
29*67e74705SXin Li /// A helper class, which walks the AST and locates all the call sites in the
30*67e74705SXin Li /// given function body.
31*67e74705SXin Li class CGBuilder : public StmtVisitor<CGBuilder> {
32*67e74705SXin Li CallGraph *G;
33*67e74705SXin Li CallGraphNode *CallerNode;
34*67e74705SXin Li
35*67e74705SXin Li public:
CGBuilder(CallGraph * g,CallGraphNode * N)36*67e74705SXin Li CGBuilder(CallGraph *g, CallGraphNode *N)
37*67e74705SXin Li : G(g), CallerNode(N) {}
38*67e74705SXin Li
VisitStmt(Stmt * S)39*67e74705SXin Li void VisitStmt(Stmt *S) { VisitChildren(S); }
40*67e74705SXin Li
getDeclFromCall(CallExpr * CE)41*67e74705SXin Li Decl *getDeclFromCall(CallExpr *CE) {
42*67e74705SXin Li if (FunctionDecl *CalleeDecl = CE->getDirectCallee())
43*67e74705SXin Li return CalleeDecl;
44*67e74705SXin Li
45*67e74705SXin Li // Simple detection of a call through a block.
46*67e74705SXin Li Expr *CEE = CE->getCallee()->IgnoreParenImpCasts();
47*67e74705SXin Li if (BlockExpr *Block = dyn_cast<BlockExpr>(CEE)) {
48*67e74705SXin Li NumBlockCallEdges++;
49*67e74705SXin Li return Block->getBlockDecl();
50*67e74705SXin Li }
51*67e74705SXin Li
52*67e74705SXin Li return nullptr;
53*67e74705SXin Li }
54*67e74705SXin Li
addCalledDecl(Decl * D)55*67e74705SXin Li void addCalledDecl(Decl *D) {
56*67e74705SXin Li if (G->includeInGraph(D)) {
57*67e74705SXin Li CallGraphNode *CalleeNode = G->getOrInsertNode(D);
58*67e74705SXin Li CallerNode->addCallee(CalleeNode, G);
59*67e74705SXin Li }
60*67e74705SXin Li }
61*67e74705SXin Li
VisitCallExpr(CallExpr * CE)62*67e74705SXin Li void VisitCallExpr(CallExpr *CE) {
63*67e74705SXin Li if (Decl *D = getDeclFromCall(CE))
64*67e74705SXin Li addCalledDecl(D);
65*67e74705SXin Li }
66*67e74705SXin Li
67*67e74705SXin Li // Adds may-call edges for the ObjC message sends.
VisitObjCMessageExpr(ObjCMessageExpr * ME)68*67e74705SXin Li void VisitObjCMessageExpr(ObjCMessageExpr *ME) {
69*67e74705SXin Li if (ObjCInterfaceDecl *IDecl = ME->getReceiverInterface()) {
70*67e74705SXin Li Selector Sel = ME->getSelector();
71*67e74705SXin Li
72*67e74705SXin Li // Find the callee definition within the same translation unit.
73*67e74705SXin Li Decl *D = nullptr;
74*67e74705SXin Li if (ME->isInstanceMessage())
75*67e74705SXin Li D = IDecl->lookupPrivateMethod(Sel);
76*67e74705SXin Li else
77*67e74705SXin Li D = IDecl->lookupPrivateClassMethod(Sel);
78*67e74705SXin Li if (D) {
79*67e74705SXin Li addCalledDecl(D);
80*67e74705SXin Li NumObjCCallEdges++;
81*67e74705SXin Li }
82*67e74705SXin Li }
83*67e74705SXin Li }
84*67e74705SXin Li
VisitChildren(Stmt * S)85*67e74705SXin Li void VisitChildren(Stmt *S) {
86*67e74705SXin Li for (Stmt *SubStmt : S->children())
87*67e74705SXin Li if (SubStmt)
88*67e74705SXin Li this->Visit(SubStmt);
89*67e74705SXin Li }
90*67e74705SXin Li };
91*67e74705SXin Li
92*67e74705SXin Li } // end anonymous namespace
93*67e74705SXin Li
addNodesForBlocks(DeclContext * D)94*67e74705SXin Li void CallGraph::addNodesForBlocks(DeclContext *D) {
95*67e74705SXin Li if (BlockDecl *BD = dyn_cast<BlockDecl>(D))
96*67e74705SXin Li addNodeForDecl(BD, true);
97*67e74705SXin Li
98*67e74705SXin Li for (auto *I : D->decls())
99*67e74705SXin Li if (auto *DC = dyn_cast<DeclContext>(I))
100*67e74705SXin Li addNodesForBlocks(DC);
101*67e74705SXin Li }
102*67e74705SXin Li
CallGraph()103*67e74705SXin Li CallGraph::CallGraph() {
104*67e74705SXin Li Root = getOrInsertNode(nullptr);
105*67e74705SXin Li }
106*67e74705SXin Li
~CallGraph()107*67e74705SXin Li CallGraph::~CallGraph() {
108*67e74705SXin Li llvm::DeleteContainerSeconds(FunctionMap);
109*67e74705SXin Li }
110*67e74705SXin Li
includeInGraph(const Decl * D)111*67e74705SXin Li bool CallGraph::includeInGraph(const Decl *D) {
112*67e74705SXin Li assert(D);
113*67e74705SXin Li if (!D->hasBody())
114*67e74705SXin Li return false;
115*67e74705SXin Li
116*67e74705SXin Li if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
117*67e74705SXin Li // We skip function template definitions, as their semantics is
118*67e74705SXin Li // only determined when they are instantiated.
119*67e74705SXin Li if (FD->isDependentContext())
120*67e74705SXin Li return false;
121*67e74705SXin Li
122*67e74705SXin Li IdentifierInfo *II = FD->getIdentifier();
123*67e74705SXin Li if (II && II->getName().startswith("__inline"))
124*67e74705SXin Li return false;
125*67e74705SXin Li }
126*67e74705SXin Li
127*67e74705SXin Li return true;
128*67e74705SXin Li }
129*67e74705SXin Li
addNodeForDecl(Decl * D,bool IsGlobal)130*67e74705SXin Li void CallGraph::addNodeForDecl(Decl* D, bool IsGlobal) {
131*67e74705SXin Li assert(D);
132*67e74705SXin Li
133*67e74705SXin Li // Allocate a new node, mark it as root, and process it's calls.
134*67e74705SXin Li CallGraphNode *Node = getOrInsertNode(D);
135*67e74705SXin Li
136*67e74705SXin Li // Process all the calls by this function as well.
137*67e74705SXin Li CGBuilder builder(this, Node);
138*67e74705SXin Li if (Stmt *Body = D->getBody())
139*67e74705SXin Li builder.Visit(Body);
140*67e74705SXin Li }
141*67e74705SXin Li
getNode(const Decl * F) const142*67e74705SXin Li CallGraphNode *CallGraph::getNode(const Decl *F) const {
143*67e74705SXin Li FunctionMapTy::const_iterator I = FunctionMap.find(F);
144*67e74705SXin Li if (I == FunctionMap.end()) return nullptr;
145*67e74705SXin Li return I->second;
146*67e74705SXin Li }
147*67e74705SXin Li
getOrInsertNode(Decl * F)148*67e74705SXin Li CallGraphNode *CallGraph::getOrInsertNode(Decl *F) {
149*67e74705SXin Li if (F && !isa<ObjCMethodDecl>(F))
150*67e74705SXin Li F = F->getCanonicalDecl();
151*67e74705SXin Li
152*67e74705SXin Li CallGraphNode *&Node = FunctionMap[F];
153*67e74705SXin Li if (Node)
154*67e74705SXin Li return Node;
155*67e74705SXin Li
156*67e74705SXin Li Node = new CallGraphNode(F);
157*67e74705SXin Li // Make Root node a parent of all functions to make sure all are reachable.
158*67e74705SXin Li if (F)
159*67e74705SXin Li Root->addCallee(Node, this);
160*67e74705SXin Li return Node;
161*67e74705SXin Li }
162*67e74705SXin Li
print(raw_ostream & OS) const163*67e74705SXin Li void CallGraph::print(raw_ostream &OS) const {
164*67e74705SXin Li OS << " --- Call graph Dump --- \n";
165*67e74705SXin Li
166*67e74705SXin Li // We are going to print the graph in reverse post order, partially, to make
167*67e74705SXin Li // sure the output is deterministic.
168*67e74705SXin Li llvm::ReversePostOrderTraversal<const clang::CallGraph*> RPOT(this);
169*67e74705SXin Li for (llvm::ReversePostOrderTraversal<const clang::CallGraph*>::rpo_iterator
170*67e74705SXin Li I = RPOT.begin(), E = RPOT.end(); I != E; ++I) {
171*67e74705SXin Li const CallGraphNode *N = *I;
172*67e74705SXin Li
173*67e74705SXin Li OS << " Function: ";
174*67e74705SXin Li if (N == Root)
175*67e74705SXin Li OS << "< root >";
176*67e74705SXin Li else
177*67e74705SXin Li N->print(OS);
178*67e74705SXin Li
179*67e74705SXin Li OS << " calls: ";
180*67e74705SXin Li for (CallGraphNode::const_iterator CI = N->begin(),
181*67e74705SXin Li CE = N->end(); CI != CE; ++CI) {
182*67e74705SXin Li assert(*CI != Root && "No one can call the root node.");
183*67e74705SXin Li (*CI)->print(OS);
184*67e74705SXin Li OS << " ";
185*67e74705SXin Li }
186*67e74705SXin Li OS << '\n';
187*67e74705SXin Li }
188*67e74705SXin Li OS.flush();
189*67e74705SXin Li }
190*67e74705SXin Li
dump() const191*67e74705SXin Li LLVM_DUMP_METHOD void CallGraph::dump() const {
192*67e74705SXin Li print(llvm::errs());
193*67e74705SXin Li }
194*67e74705SXin Li
viewGraph() const195*67e74705SXin Li void CallGraph::viewGraph() const {
196*67e74705SXin Li llvm::ViewGraph(this, "CallGraph");
197*67e74705SXin Li }
198*67e74705SXin Li
print(raw_ostream & os) const199*67e74705SXin Li void CallGraphNode::print(raw_ostream &os) const {
200*67e74705SXin Li if (const NamedDecl *ND = dyn_cast_or_null<NamedDecl>(FD))
201*67e74705SXin Li return ND->printName(os);
202*67e74705SXin Li os << "< >";
203*67e74705SXin Li }
204*67e74705SXin Li
dump() const205*67e74705SXin Li LLVM_DUMP_METHOD void CallGraphNode::dump() const {
206*67e74705SXin Li print(llvm::errs());
207*67e74705SXin Li }
208*67e74705SXin Li
209*67e74705SXin Li namespace llvm {
210*67e74705SXin Li
211*67e74705SXin Li template <>
212*67e74705SXin Li struct DOTGraphTraits<const CallGraph*> : public DefaultDOTGraphTraits {
213*67e74705SXin Li
DOTGraphTraitsllvm::DOTGraphTraits214*67e74705SXin Li DOTGraphTraits (bool isSimple=false) : DefaultDOTGraphTraits(isSimple) {}
215*67e74705SXin Li
getNodeLabelllvm::DOTGraphTraits216*67e74705SXin Li static std::string getNodeLabel(const CallGraphNode *Node,
217*67e74705SXin Li const CallGraph *CG) {
218*67e74705SXin Li if (CG->getRoot() == Node) {
219*67e74705SXin Li return "< root >";
220*67e74705SXin Li }
221*67e74705SXin Li if (const NamedDecl *ND = dyn_cast_or_null<NamedDecl>(Node->getDecl()))
222*67e74705SXin Li return ND->getNameAsString();
223*67e74705SXin Li else
224*67e74705SXin Li return "< >";
225*67e74705SXin Li }
226*67e74705SXin Li
227*67e74705SXin Li };
228*67e74705SXin Li }
229