10b57cec5SDimitry Andric //===- CallGraph.cpp - AST-based Call graph -------------------------------===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric // 90b57cec5SDimitry Andric // This file defines the AST-based CallGraph. 100b57cec5SDimitry Andric // 110b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 120b57cec5SDimitry Andric 130b57cec5SDimitry Andric #include "clang/Analysis/CallGraph.h" 140b57cec5SDimitry Andric #include "clang/AST/Decl.h" 150b57cec5SDimitry Andric #include "clang/AST/DeclBase.h" 160b57cec5SDimitry Andric #include "clang/AST/DeclObjC.h" 170b57cec5SDimitry Andric #include "clang/AST/Expr.h" 180b57cec5SDimitry Andric #include "clang/AST/ExprObjC.h" 190b57cec5SDimitry Andric #include "clang/AST/Stmt.h" 200b57cec5SDimitry Andric #include "clang/AST/StmtVisitor.h" 210b57cec5SDimitry Andric #include "clang/Basic/IdentifierTable.h" 220b57cec5SDimitry Andric #include "clang/Basic/LLVM.h" 230b57cec5SDimitry Andric #include "llvm/ADT/PostOrderIterator.h" 240b57cec5SDimitry Andric #include "llvm/ADT/STLExtras.h" 250b57cec5SDimitry Andric #include "llvm/ADT/Statistic.h" 260b57cec5SDimitry Andric #include "llvm/Support/Casting.h" 270b57cec5SDimitry Andric #include "llvm/Support/Compiler.h" 280b57cec5SDimitry Andric #include "llvm/Support/DOTGraphTraits.h" 290b57cec5SDimitry Andric #include "llvm/Support/GraphWriter.h" 300b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h" 310b57cec5SDimitry Andric #include <cassert> 320b57cec5SDimitry Andric #include <memory> 330b57cec5SDimitry Andric #include <string> 340b57cec5SDimitry Andric 350b57cec5SDimitry Andric using namespace clang; 360b57cec5SDimitry Andric 370b57cec5SDimitry Andric #define DEBUG_TYPE "CallGraph" 380b57cec5SDimitry Andric 390b57cec5SDimitry Andric STATISTIC(NumObjCCallEdges, "Number of Objective-C method call edges"); 400b57cec5SDimitry Andric STATISTIC(NumBlockCallEdges, "Number of block call edges"); 410b57cec5SDimitry Andric 420b57cec5SDimitry Andric namespace { 430b57cec5SDimitry Andric 440b57cec5SDimitry Andric /// A helper class, which walks the AST and locates all the call sites in the 450b57cec5SDimitry Andric /// given function body. 460b57cec5SDimitry Andric class CGBuilder : public StmtVisitor<CGBuilder> { 470b57cec5SDimitry Andric CallGraph *G; 480b57cec5SDimitry Andric CallGraphNode *CallerNode; 490b57cec5SDimitry Andric 500b57cec5SDimitry Andric public: 510b57cec5SDimitry Andric CGBuilder(CallGraph *g, CallGraphNode *N) : G(g), CallerNode(N) {} 520b57cec5SDimitry Andric 530b57cec5SDimitry Andric void VisitStmt(Stmt *S) { VisitChildren(S); } 540b57cec5SDimitry Andric 550b57cec5SDimitry Andric Decl *getDeclFromCall(CallExpr *CE) { 560b57cec5SDimitry Andric if (FunctionDecl *CalleeDecl = CE->getDirectCallee()) 570b57cec5SDimitry Andric return CalleeDecl; 580b57cec5SDimitry Andric 590b57cec5SDimitry Andric // Simple detection of a call through a block. 600b57cec5SDimitry Andric Expr *CEE = CE->getCallee()->IgnoreParenImpCasts(); 610b57cec5SDimitry Andric if (BlockExpr *Block = dyn_cast<BlockExpr>(CEE)) { 620b57cec5SDimitry Andric NumBlockCallEdges++; 630b57cec5SDimitry Andric return Block->getBlockDecl(); 640b57cec5SDimitry Andric } 650b57cec5SDimitry Andric 660b57cec5SDimitry Andric return nullptr; 670b57cec5SDimitry Andric } 680b57cec5SDimitry Andric 695ffd83dbSDimitry Andric void addCalledDecl(Decl *D, Expr *CallExpr) { 705ffd83dbSDimitry Andric if (G->includeCalleeInGraph(D)) { 710b57cec5SDimitry Andric CallGraphNode *CalleeNode = G->getOrInsertNode(D); 725ffd83dbSDimitry Andric CallerNode->addCallee({CalleeNode, CallExpr}); 730b57cec5SDimitry Andric } 740b57cec5SDimitry Andric } 750b57cec5SDimitry Andric 760b57cec5SDimitry Andric void VisitCallExpr(CallExpr *CE) { 770b57cec5SDimitry Andric if (Decl *D = getDeclFromCall(CE)) 785ffd83dbSDimitry Andric addCalledDecl(D, CE); 790b57cec5SDimitry Andric VisitChildren(CE); 800b57cec5SDimitry Andric } 810b57cec5SDimitry Andric 82a7dea167SDimitry Andric void VisitLambdaExpr(LambdaExpr *LE) { 83a7dea167SDimitry Andric if (FunctionTemplateDecl *FTD = LE->getDependentCallOperator()) 84a7dea167SDimitry Andric for (FunctionDecl *FD : FTD->specializations()) 85a7dea167SDimitry Andric G->VisitFunctionDecl(FD); 86a7dea167SDimitry Andric else if (CXXMethodDecl *MD = LE->getCallOperator()) 87a7dea167SDimitry Andric G->VisitFunctionDecl(MD); 88a7dea167SDimitry Andric } 89a7dea167SDimitry Andric 90a7dea167SDimitry Andric void VisitCXXNewExpr(CXXNewExpr *E) { 91a7dea167SDimitry Andric if (FunctionDecl *FD = E->getOperatorNew()) 925ffd83dbSDimitry Andric addCalledDecl(FD, E); 93a7dea167SDimitry Andric VisitChildren(E); 94a7dea167SDimitry Andric } 95a7dea167SDimitry Andric 96a7dea167SDimitry Andric void VisitCXXConstructExpr(CXXConstructExpr *E) { 97a7dea167SDimitry Andric CXXConstructorDecl *Ctor = E->getConstructor(); 98a7dea167SDimitry Andric if (FunctionDecl *Def = Ctor->getDefinition()) 995ffd83dbSDimitry Andric addCalledDecl(Def, E); 100a7dea167SDimitry Andric VisitChildren(E); 101a7dea167SDimitry Andric } 102a7dea167SDimitry Andric 103a7dea167SDimitry Andric // Include the evaluation of the default argument. 104a7dea167SDimitry Andric void VisitCXXDefaultArgExpr(CXXDefaultArgExpr *E) { 105a7dea167SDimitry Andric Visit(E->getExpr()); 106a7dea167SDimitry Andric } 107a7dea167SDimitry Andric 108a7dea167SDimitry Andric // Include the evaluation of the default initializers in a class. 109a7dea167SDimitry Andric void VisitCXXDefaultInitExpr(CXXDefaultInitExpr *E) { 110a7dea167SDimitry Andric Visit(E->getExpr()); 111a7dea167SDimitry Andric } 112a7dea167SDimitry Andric 1130b57cec5SDimitry Andric // Adds may-call edges for the ObjC message sends. 1140b57cec5SDimitry Andric void VisitObjCMessageExpr(ObjCMessageExpr *ME) { 1150b57cec5SDimitry Andric if (ObjCInterfaceDecl *IDecl = ME->getReceiverInterface()) { 1160b57cec5SDimitry Andric Selector Sel = ME->getSelector(); 1170b57cec5SDimitry Andric 1180b57cec5SDimitry Andric // Find the callee definition within the same translation unit. 1190b57cec5SDimitry Andric Decl *D = nullptr; 1200b57cec5SDimitry Andric if (ME->isInstanceMessage()) 1210b57cec5SDimitry Andric D = IDecl->lookupPrivateMethod(Sel); 1220b57cec5SDimitry Andric else 1230b57cec5SDimitry Andric D = IDecl->lookupPrivateClassMethod(Sel); 1240b57cec5SDimitry Andric if (D) { 1255ffd83dbSDimitry Andric addCalledDecl(D, ME); 1260b57cec5SDimitry Andric NumObjCCallEdges++; 1270b57cec5SDimitry Andric } 1280b57cec5SDimitry Andric } 1290b57cec5SDimitry Andric } 1300b57cec5SDimitry Andric 1310b57cec5SDimitry Andric void VisitChildren(Stmt *S) { 1320b57cec5SDimitry Andric for (Stmt *SubStmt : S->children()) 1330b57cec5SDimitry Andric if (SubStmt) 1340b57cec5SDimitry Andric this->Visit(SubStmt); 1350b57cec5SDimitry Andric } 1360b57cec5SDimitry Andric }; 1370b57cec5SDimitry Andric 1380b57cec5SDimitry Andric } // namespace 1390b57cec5SDimitry Andric 1400b57cec5SDimitry Andric void CallGraph::addNodesForBlocks(DeclContext *D) { 1410b57cec5SDimitry Andric if (BlockDecl *BD = dyn_cast<BlockDecl>(D)) 1420b57cec5SDimitry Andric addNodeForDecl(BD, true); 1430b57cec5SDimitry Andric 1440b57cec5SDimitry Andric for (auto *I : D->decls()) 1450b57cec5SDimitry Andric if (auto *DC = dyn_cast<DeclContext>(I)) 1460b57cec5SDimitry Andric addNodesForBlocks(DC); 1470b57cec5SDimitry Andric } 1480b57cec5SDimitry Andric 1490b57cec5SDimitry Andric CallGraph::CallGraph() { 1500b57cec5SDimitry Andric Root = getOrInsertNode(nullptr); 1510b57cec5SDimitry Andric } 1520b57cec5SDimitry Andric 1530b57cec5SDimitry Andric CallGraph::~CallGraph() = default; 1540b57cec5SDimitry Andric 1550b57cec5SDimitry Andric bool CallGraph::includeInGraph(const Decl *D) { 1560b57cec5SDimitry Andric assert(D); 1570b57cec5SDimitry Andric if (!D->hasBody()) 1580b57cec5SDimitry Andric return false; 1590b57cec5SDimitry Andric 1605ffd83dbSDimitry Andric return includeCalleeInGraph(D); 1615ffd83dbSDimitry Andric } 1625ffd83dbSDimitry Andric 1635ffd83dbSDimitry Andric bool CallGraph::includeCalleeInGraph(const Decl *D) { 1640b57cec5SDimitry Andric if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) { 1650b57cec5SDimitry Andric // We skip function template definitions, as their semantics is 1660b57cec5SDimitry Andric // only determined when they are instantiated. 1670b57cec5SDimitry Andric if (FD->isDependentContext()) 1680b57cec5SDimitry Andric return false; 1690b57cec5SDimitry Andric 1700b57cec5SDimitry Andric IdentifierInfo *II = FD->getIdentifier(); 171*5f757f3fSDimitry Andric if (II && II->getName().starts_with("__inline")) 1720b57cec5SDimitry Andric return false; 1730b57cec5SDimitry Andric } 1740b57cec5SDimitry Andric 1750b57cec5SDimitry Andric return true; 1760b57cec5SDimitry Andric } 1770b57cec5SDimitry Andric 1780b57cec5SDimitry Andric void CallGraph::addNodeForDecl(Decl* D, bool IsGlobal) { 1790b57cec5SDimitry Andric assert(D); 1800b57cec5SDimitry Andric 181a7dea167SDimitry Andric // Allocate a new node, mark it as root, and process its calls. 1820b57cec5SDimitry Andric CallGraphNode *Node = getOrInsertNode(D); 1830b57cec5SDimitry Andric 1840b57cec5SDimitry Andric // Process all the calls by this function as well. 1850b57cec5SDimitry Andric CGBuilder builder(this, Node); 1860b57cec5SDimitry Andric if (Stmt *Body = D->getBody()) 1870b57cec5SDimitry Andric builder.Visit(Body); 188a7dea167SDimitry Andric 189a7dea167SDimitry Andric // Include C++ constructor member initializers. 190a7dea167SDimitry Andric if (auto constructor = dyn_cast<CXXConstructorDecl>(D)) { 191a7dea167SDimitry Andric for (CXXCtorInitializer *init : constructor->inits()) { 192a7dea167SDimitry Andric builder.Visit(init->getInit()); 193a7dea167SDimitry Andric } 194a7dea167SDimitry Andric } 1950b57cec5SDimitry Andric } 1960b57cec5SDimitry Andric 1970b57cec5SDimitry Andric CallGraphNode *CallGraph::getNode(const Decl *F) const { 1980b57cec5SDimitry Andric FunctionMapTy::const_iterator I = FunctionMap.find(F); 1990b57cec5SDimitry Andric if (I == FunctionMap.end()) return nullptr; 2000b57cec5SDimitry Andric return I->second.get(); 2010b57cec5SDimitry Andric } 2020b57cec5SDimitry Andric 2030b57cec5SDimitry Andric CallGraphNode *CallGraph::getOrInsertNode(Decl *F) { 2040b57cec5SDimitry Andric if (F && !isa<ObjCMethodDecl>(F)) 2050b57cec5SDimitry Andric F = F->getCanonicalDecl(); 2060b57cec5SDimitry Andric 2070b57cec5SDimitry Andric std::unique_ptr<CallGraphNode> &Node = FunctionMap[F]; 2080b57cec5SDimitry Andric if (Node) 2090b57cec5SDimitry Andric return Node.get(); 2100b57cec5SDimitry Andric 211a7dea167SDimitry Andric Node = std::make_unique<CallGraphNode>(F); 2120b57cec5SDimitry Andric // Make Root node a parent of all functions to make sure all are reachable. 2130b57cec5SDimitry Andric if (F) 2145ffd83dbSDimitry Andric Root->addCallee({Node.get(), /*Call=*/nullptr}); 2150b57cec5SDimitry Andric return Node.get(); 2160b57cec5SDimitry Andric } 2170b57cec5SDimitry Andric 2180b57cec5SDimitry Andric void CallGraph::print(raw_ostream &OS) const { 2190b57cec5SDimitry Andric OS << " --- Call graph Dump --- \n"; 2200b57cec5SDimitry Andric 2210b57cec5SDimitry Andric // We are going to print the graph in reverse post order, partially, to make 2220b57cec5SDimitry Andric // sure the output is deterministic. 2230b57cec5SDimitry Andric llvm::ReversePostOrderTraversal<const CallGraph *> RPOT(this); 2240b57cec5SDimitry Andric for (llvm::ReversePostOrderTraversal<const CallGraph *>::rpo_iterator 2250b57cec5SDimitry Andric I = RPOT.begin(), E = RPOT.end(); I != E; ++I) { 2260b57cec5SDimitry Andric const CallGraphNode *N = *I; 2270b57cec5SDimitry Andric 2280b57cec5SDimitry Andric OS << " Function: "; 2290b57cec5SDimitry Andric if (N == Root) 2300b57cec5SDimitry Andric OS << "< root >"; 2310b57cec5SDimitry Andric else 2320b57cec5SDimitry Andric N->print(OS); 2330b57cec5SDimitry Andric 2340b57cec5SDimitry Andric OS << " calls: "; 2350b57cec5SDimitry Andric for (CallGraphNode::const_iterator CI = N->begin(), 2360b57cec5SDimitry Andric CE = N->end(); CI != CE; ++CI) { 2375ffd83dbSDimitry Andric assert(CI->Callee != Root && "No one can call the root node."); 2385ffd83dbSDimitry Andric CI->Callee->print(OS); 2390b57cec5SDimitry Andric OS << " "; 2400b57cec5SDimitry Andric } 2410b57cec5SDimitry Andric OS << '\n'; 2420b57cec5SDimitry Andric } 2430b57cec5SDimitry Andric OS.flush(); 2440b57cec5SDimitry Andric } 2450b57cec5SDimitry Andric 2460b57cec5SDimitry Andric LLVM_DUMP_METHOD void CallGraph::dump() const { 2470b57cec5SDimitry Andric print(llvm::errs()); 2480b57cec5SDimitry Andric } 2490b57cec5SDimitry Andric 2500b57cec5SDimitry Andric void CallGraph::viewGraph() const { 2510b57cec5SDimitry Andric llvm::ViewGraph(this, "CallGraph"); 2520b57cec5SDimitry Andric } 2530b57cec5SDimitry Andric 2540b57cec5SDimitry Andric void CallGraphNode::print(raw_ostream &os) const { 2550b57cec5SDimitry Andric if (const NamedDecl *ND = dyn_cast_or_null<NamedDecl>(FD)) 2560b57cec5SDimitry Andric return ND->printQualifiedName(os); 2570b57cec5SDimitry Andric os << "< >"; 2580b57cec5SDimitry Andric } 2590b57cec5SDimitry Andric 2600b57cec5SDimitry Andric LLVM_DUMP_METHOD void CallGraphNode::dump() const { 2610b57cec5SDimitry Andric print(llvm::errs()); 2620b57cec5SDimitry Andric } 2630b57cec5SDimitry Andric 2640b57cec5SDimitry Andric namespace llvm { 2650b57cec5SDimitry Andric 2660b57cec5SDimitry Andric template <> 2670b57cec5SDimitry Andric struct DOTGraphTraits<const CallGraph*> : public DefaultDOTGraphTraits { 2680b57cec5SDimitry Andric DOTGraphTraits (bool isSimple = false) : DefaultDOTGraphTraits(isSimple) {} 2690b57cec5SDimitry Andric 2700b57cec5SDimitry Andric static std::string getNodeLabel(const CallGraphNode *Node, 2710b57cec5SDimitry Andric const CallGraph *CG) { 2720b57cec5SDimitry Andric if (CG->getRoot() == Node) { 2730b57cec5SDimitry Andric return "< root >"; 2740b57cec5SDimitry Andric } 2750b57cec5SDimitry Andric if (const NamedDecl *ND = dyn_cast_or_null<NamedDecl>(Node->getDecl())) 2760b57cec5SDimitry Andric return ND->getNameAsString(); 2770b57cec5SDimitry Andric else 2780b57cec5SDimitry Andric return "< >"; 2790b57cec5SDimitry Andric } 2800b57cec5SDimitry Andric }; 2810b57cec5SDimitry Andric 2820b57cec5SDimitry Andric } // namespace llvm 283