xref: /aosp_15_r20/external/clang/lib/Analysis/CallGraph.cpp (revision 67e74705e28f6214e480b399dd47ea732279e315)
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