xref: /freebsd/contrib/llvm-project/clang/lib/Analysis/CallGraph.cpp (revision 5f757f3ff9144b609b3c433dfd370cc6bdc191ad)
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