1196b8cfe9cfcc452eb2f83aa4ad330c2324f8c7dAnna Zaks//== CallGraph.cpp - AST-based Call graph ----------------------*- C++ -*--==// 2196b8cfe9cfcc452eb2f83aa4ad330c2324f8c7dAnna Zaks// 3196b8cfe9cfcc452eb2f83aa4ad330c2324f8c7dAnna Zaks// The LLVM Compiler Infrastructure 4196b8cfe9cfcc452eb2f83aa4ad330c2324f8c7dAnna Zaks// 5196b8cfe9cfcc452eb2f83aa4ad330c2324f8c7dAnna Zaks// This file is distributed under the University of Illinois Open Source 6196b8cfe9cfcc452eb2f83aa4ad330c2324f8c7dAnna Zaks// License. See LICENSE.TXT for details. 7196b8cfe9cfcc452eb2f83aa4ad330c2324f8c7dAnna Zaks// 8196b8cfe9cfcc452eb2f83aa4ad330c2324f8c7dAnna Zaks//===----------------------------------------------------------------------===// 9196b8cfe9cfcc452eb2f83aa4ad330c2324f8c7dAnna Zaks// 10196b8cfe9cfcc452eb2f83aa4ad330c2324f8c7dAnna Zaks// This file defines the AST-based CallGraph. 11196b8cfe9cfcc452eb2f83aa4ad330c2324f8c7dAnna Zaks// 12196b8cfe9cfcc452eb2f83aa4ad330c2324f8c7dAnna Zaks//===----------------------------------------------------------------------===// 134f858dfd42c89b67200dac0afc228a0baa323691Anna Zaks#define DEBUG_TYPE "CallGraph" 144f858dfd42c89b67200dac0afc228a0baa323691Anna Zaks 15196b8cfe9cfcc452eb2f83aa4ad330c2324f8c7dAnna Zaks#include "clang/Analysis/CallGraph.h" 16196b8cfe9cfcc452eb2f83aa4ad330c2324f8c7dAnna Zaks#include "clang/AST/ASTContext.h" 17196b8cfe9cfcc452eb2f83aa4ad330c2324f8c7dAnna Zaks#include "clang/AST/Decl.h" 18196b8cfe9cfcc452eb2f83aa4ad330c2324f8c7dAnna Zaks#include "clang/AST/StmtVisitor.h" 19bd80231672a7418aa1a99d3dbbe1774205c88f74Anna Zaks#include "llvm/ADT/PostOrderIterator.h" 204f858dfd42c89b67200dac0afc228a0baa323691Anna Zaks#include "llvm/ADT/Statistic.h" 21196b8cfe9cfcc452eb2f83aa4ad330c2324f8c7dAnna Zaks#include "llvm/Support/GraphWriter.h" 22196b8cfe9cfcc452eb2f83aa4ad330c2324f8c7dAnna Zaks 23196b8cfe9cfcc452eb2f83aa4ad330c2324f8c7dAnna Zaksusing namespace clang; 24196b8cfe9cfcc452eb2f83aa4ad330c2324f8c7dAnna Zaks 2508165d8c9e954574408de59988b3331be58c3b36Anna ZaksSTATISTIC(NumObjCCallEdges, "Number of Objective-C method call edges"); 264f858dfd42c89b67200dac0afc228a0baa323691Anna ZaksSTATISTIC(NumBlockCallEdges, "Number of block call edges"); 274f858dfd42c89b67200dac0afc228a0baa323691Anna Zaks 28196b8cfe9cfcc452eb2f83aa4ad330c2324f8c7dAnna Zaksnamespace { 29196b8cfe9cfcc452eb2f83aa4ad330c2324f8c7dAnna Zaks/// A helper class, which walks the AST and locates all the call sites in the 30196b8cfe9cfcc452eb2f83aa4ad330c2324f8c7dAnna Zaks/// given function body. 31196b8cfe9cfcc452eb2f83aa4ad330c2324f8c7dAnna Zaksclass CGBuilder : public StmtVisitor<CGBuilder> { 32196b8cfe9cfcc452eb2f83aa4ad330c2324f8c7dAnna Zaks CallGraph *G; 33196b8cfe9cfcc452eb2f83aa4ad330c2324f8c7dAnna Zaks CallGraphNode *CallerNode; 34196b8cfe9cfcc452eb2f83aa4ad330c2324f8c7dAnna Zaks 35196b8cfe9cfcc452eb2f83aa4ad330c2324f8c7dAnna Zakspublic: 36facde171ae4b8926622a1bffa833732a06f1875bBenjamin Kramer CGBuilder(CallGraph *g, CallGraphNode *N) 37facde171ae4b8926622a1bffa833732a06f1875bBenjamin Kramer : G(g), CallerNode(N) {} 38196b8cfe9cfcc452eb2f83aa4ad330c2324f8c7dAnna Zaks 39196b8cfe9cfcc452eb2f83aa4ad330c2324f8c7dAnna Zaks void VisitStmt(Stmt *S) { VisitChildren(S); } 40196b8cfe9cfcc452eb2f83aa4ad330c2324f8c7dAnna Zaks 414f858dfd42c89b67200dac0afc228a0baa323691Anna Zaks Decl *getDeclFromCall(CallExpr *CE) { 42196b8cfe9cfcc452eb2f83aa4ad330c2324f8c7dAnna Zaks if (FunctionDecl *CalleeDecl = CE->getDirectCallee()) 434f858dfd42c89b67200dac0afc228a0baa323691Anna Zaks return CalleeDecl; 444f858dfd42c89b67200dac0afc228a0baa323691Anna Zaks 454f858dfd42c89b67200dac0afc228a0baa323691Anna Zaks // Simple detection of a call through a block. 464f858dfd42c89b67200dac0afc228a0baa323691Anna Zaks Expr *CEE = CE->getCallee()->IgnoreParenImpCasts(); 474f858dfd42c89b67200dac0afc228a0baa323691Anna Zaks if (BlockExpr *Block = dyn_cast<BlockExpr>(CEE)) { 484f858dfd42c89b67200dac0afc228a0baa323691Anna Zaks NumBlockCallEdges++; 494f858dfd42c89b67200dac0afc228a0baa323691Anna Zaks return Block->getBlockDecl(); 504f858dfd42c89b67200dac0afc228a0baa323691Anna Zaks } 514f858dfd42c89b67200dac0afc228a0baa323691Anna Zaks 524f858dfd42c89b67200dac0afc228a0baa323691Anna Zaks return 0; 534f858dfd42c89b67200dac0afc228a0baa323691Anna Zaks } 544f858dfd42c89b67200dac0afc228a0baa323691Anna Zaks 554f858dfd42c89b67200dac0afc228a0baa323691Anna Zaks void addCalledDecl(Decl *D) { 564f858dfd42c89b67200dac0afc228a0baa323691Anna Zaks if (G->includeInGraph(D)) { 574f858dfd42c89b67200dac0afc228a0baa323691Anna Zaks CallGraphNode *CalleeNode = G->getOrInsertNode(D); 584f858dfd42c89b67200dac0afc228a0baa323691Anna Zaks CallerNode->addCallee(CalleeNode, G); 594f858dfd42c89b67200dac0afc228a0baa323691Anna Zaks } 604f858dfd42c89b67200dac0afc228a0baa323691Anna Zaks } 614f858dfd42c89b67200dac0afc228a0baa323691Anna Zaks 624f858dfd42c89b67200dac0afc228a0baa323691Anna Zaks void VisitCallExpr(CallExpr *CE) { 634f858dfd42c89b67200dac0afc228a0baa323691Anna Zaks if (Decl *D = getDeclFromCall(CE)) 644f858dfd42c89b67200dac0afc228a0baa323691Anna Zaks addCalledDecl(D); 654f858dfd42c89b67200dac0afc228a0baa323691Anna Zaks } 664f858dfd42c89b67200dac0afc228a0baa323691Anna Zaks 674f858dfd42c89b67200dac0afc228a0baa323691Anna Zaks // Adds may-call edges for the ObjC message sends. 684f858dfd42c89b67200dac0afc228a0baa323691Anna Zaks void VisitObjCMessageExpr(ObjCMessageExpr *ME) { 694f858dfd42c89b67200dac0afc228a0baa323691Anna Zaks if (ObjCInterfaceDecl *IDecl = ME->getReceiverInterface()) { 704f858dfd42c89b67200dac0afc228a0baa323691Anna Zaks Selector Sel = ME->getSelector(); 714f858dfd42c89b67200dac0afc228a0baa323691Anna Zaks 7208165d8c9e954574408de59988b3331be58c3b36Anna Zaks // Find the callee definition within the same translation unit. 734f858dfd42c89b67200dac0afc228a0baa323691Anna Zaks Decl *D = 0; 744f858dfd42c89b67200dac0afc228a0baa323691Anna Zaks if (ME->isInstanceMessage()) 754f858dfd42c89b67200dac0afc228a0baa323691Anna Zaks D = IDecl->lookupPrivateMethod(Sel); 764f858dfd42c89b67200dac0afc228a0baa323691Anna Zaks else 774f858dfd42c89b67200dac0afc228a0baa323691Anna Zaks D = IDecl->lookupPrivateClassMethod(Sel); 784f858dfd42c89b67200dac0afc228a0baa323691Anna Zaks if (D) { 794f858dfd42c89b67200dac0afc228a0baa323691Anna Zaks addCalledDecl(D); 804f858dfd42c89b67200dac0afc228a0baa323691Anna Zaks NumObjCCallEdges++; 81196b8cfe9cfcc452eb2f83aa4ad330c2324f8c7dAnna Zaks } 824f858dfd42c89b67200dac0afc228a0baa323691Anna Zaks } 83a50a5cd9db67f061c94557d188b992be34ccad2fDaniel Dunbar } 84196b8cfe9cfcc452eb2f83aa4ad330c2324f8c7dAnna Zaks 85196b8cfe9cfcc452eb2f83aa4ad330c2324f8c7dAnna Zaks void VisitChildren(Stmt *S) { 86196b8cfe9cfcc452eb2f83aa4ad330c2324f8c7dAnna Zaks for (Stmt::child_range I = S->children(); I; ++I) 87196b8cfe9cfcc452eb2f83aa4ad330c2324f8c7dAnna Zaks if (*I) 88196b8cfe9cfcc452eb2f83aa4ad330c2324f8c7dAnna Zaks static_cast<CGBuilder*>(this)->Visit(*I); 89196b8cfe9cfcc452eb2f83aa4ad330c2324f8c7dAnna Zaks } 90196b8cfe9cfcc452eb2f83aa4ad330c2324f8c7dAnna Zaks}; 91a2e589e60d147f4f04cee5682b8389b55c410244Anna Zaks 92196b8cfe9cfcc452eb2f83aa4ad330c2324f8c7dAnna Zaks} // end anonymous namespace 93196b8cfe9cfcc452eb2f83aa4ad330c2324f8c7dAnna Zaks 944f858dfd42c89b67200dac0afc228a0baa323691Anna Zaksvoid CallGraph::addNodesForBlocks(DeclContext *D) { 954f858dfd42c89b67200dac0afc228a0baa323691Anna Zaks if (BlockDecl *BD = dyn_cast<BlockDecl>(D)) 964f858dfd42c89b67200dac0afc228a0baa323691Anna Zaks addNodeForDecl(BD, true); 974f858dfd42c89b67200dac0afc228a0baa323691Anna Zaks 984f858dfd42c89b67200dac0afc228a0baa323691Anna Zaks for (DeclContext::decl_iterator I = D->decls_begin(), E = D->decls_end(); 994f858dfd42c89b67200dac0afc228a0baa323691Anna Zaks I!=E; ++I) 1004f858dfd42c89b67200dac0afc228a0baa323691Anna Zaks if (DeclContext *DC = dyn_cast<DeclContext>(*I)) 1014f858dfd42c89b67200dac0afc228a0baa323691Anna Zaks addNodesForBlocks(DC); 1024f858dfd42c89b67200dac0afc228a0baa323691Anna Zaks} 1034f858dfd42c89b67200dac0afc228a0baa323691Anna Zaks 104196b8cfe9cfcc452eb2f83aa4ad330c2324f8c7dAnna ZaksCallGraph::CallGraph() { 1056a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks Root = getOrInsertNode(0); 106196b8cfe9cfcc452eb2f83aa4ad330c2324f8c7dAnna Zaks} 107196b8cfe9cfcc452eb2f83aa4ad330c2324f8c7dAnna Zaks 108196b8cfe9cfcc452eb2f83aa4ad330c2324f8c7dAnna ZaksCallGraph::~CallGraph() { 109196b8cfe9cfcc452eb2f83aa4ad330c2324f8c7dAnna Zaks if (!FunctionMap.empty()) { 110196b8cfe9cfcc452eb2f83aa4ad330c2324f8c7dAnna Zaks for (FunctionMapTy::iterator I = FunctionMap.begin(), E = FunctionMap.end(); 111196b8cfe9cfcc452eb2f83aa4ad330c2324f8c7dAnna Zaks I != E; ++I) 112196b8cfe9cfcc452eb2f83aa4ad330c2324f8c7dAnna Zaks delete I->second; 113196b8cfe9cfcc452eb2f83aa4ad330c2324f8c7dAnna Zaks FunctionMap.clear(); 114196b8cfe9cfcc452eb2f83aa4ad330c2324f8c7dAnna Zaks } 115196b8cfe9cfcc452eb2f83aa4ad330c2324f8c7dAnna Zaks} 116196b8cfe9cfcc452eb2f83aa4ad330c2324f8c7dAnna Zaks 1176a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaksbool CallGraph::includeInGraph(const Decl *D) { 1184f858dfd42c89b67200dac0afc228a0baa323691Anna Zaks assert(D); 1194f858dfd42c89b67200dac0afc228a0baa323691Anna Zaks if (!D->getBody()) 1204f858dfd42c89b67200dac0afc228a0baa323691Anna Zaks return false; 1214f858dfd42c89b67200dac0afc228a0baa323691Anna Zaks 1226a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) { 1236a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks // We skip function template definitions, as their semantics is 1246a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks // only determined when they are instantiated. 1256a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks if (!FD->isThisDeclarationADefinition() || 1266a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks FD->isDependentContext()) 1276a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks return false; 1286a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks 1296a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks IdentifierInfo *II = FD->getIdentifier(); 1306a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks if (II && II->getName().startswith("__inline")) 1316a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks return false; 1326a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks } 1336a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks 1346a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks if (const ObjCMethodDecl *ID = dyn_cast<ObjCMethodDecl>(D)) { 1356a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks if (!ID->isThisDeclarationADefinition()) 1366a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks return false; 1376a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks } 1386a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks 1396a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks return true; 1406a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks} 1416a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks 1426a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaksvoid CallGraph::addNodeForDecl(Decl* D, bool IsGlobal) { 143d2776613703a516f107decc06b38a0b60a10542cAnna Zaks assert(D); 144196b8cfe9cfcc452eb2f83aa4ad330c2324f8c7dAnna Zaks 1456a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks // Allocate a new node, mark it as root, and process it's calls. 1466a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks CallGraphNode *Node = getOrInsertNode(D); 147196b8cfe9cfcc452eb2f83aa4ad330c2324f8c7dAnna Zaks 148196b8cfe9cfcc452eb2f83aa4ad330c2324f8c7dAnna Zaks // Process all the calls by this function as well. 149facde171ae4b8926622a1bffa833732a06f1875bBenjamin Kramer CGBuilder builder(this, Node); 150bb3d20f80c98e7919411bc7e062d69b17462899bTed Kremenek if (Stmt *Body = D->getBody()) 151bb3d20f80c98e7919411bc7e062d69b17462899bTed Kremenek builder.Visit(Body); 152196b8cfe9cfcc452eb2f83aa4ad330c2324f8c7dAnna Zaks} 153196b8cfe9cfcc452eb2f83aa4ad330c2324f8c7dAnna Zaks 154a5d531f67de0cfeb56b843da15146f3b4cd75bd9Anna ZaksCallGraphNode *CallGraph::getNode(const Decl *F) const { 155d53e877ddf885da28aa4668148a5f0ce0045ab54Matt Beaumont-Gay FunctionMapTy::const_iterator I = FunctionMap.find(F); 156d53e877ddf885da28aa4668148a5f0ce0045ab54Matt Beaumont-Gay if (I == FunctionMap.end()) return 0; 157d53e877ddf885da28aa4668148a5f0ce0045ab54Matt Beaumont-Gay return I->second; 158a5d531f67de0cfeb56b843da15146f3b4cd75bd9Anna Zaks} 159a5d531f67de0cfeb56b843da15146f3b4cd75bd9Anna Zaks 1606a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna ZaksCallGraphNode *CallGraph::getOrInsertNode(Decl *F) { 161196b8cfe9cfcc452eb2f83aa4ad330c2324f8c7dAnna Zaks CallGraphNode *&Node = FunctionMap[F]; 162196b8cfe9cfcc452eb2f83aa4ad330c2324f8c7dAnna Zaks if (Node) 163196b8cfe9cfcc452eb2f83aa4ad330c2324f8c7dAnna Zaks return Node; 164196b8cfe9cfcc452eb2f83aa4ad330c2324f8c7dAnna Zaks 165196b8cfe9cfcc452eb2f83aa4ad330c2324f8c7dAnna Zaks Node = new CallGraphNode(F); 166bd80231672a7418aa1a99d3dbbe1774205c88f74Anna Zaks // Make Root node a parent of all functions to make sure all are reachable. 167d2776613703a516f107decc06b38a0b60a10542cAnna Zaks if (F != 0) 168bd80231672a7418aa1a99d3dbbe1774205c88f74Anna Zaks Root->addCallee(Node, this); 169196b8cfe9cfcc452eb2f83aa4ad330c2324f8c7dAnna Zaks return Node; 170196b8cfe9cfcc452eb2f83aa4ad330c2324f8c7dAnna Zaks} 171196b8cfe9cfcc452eb2f83aa4ad330c2324f8c7dAnna Zaks 172196b8cfe9cfcc452eb2f83aa4ad330c2324f8c7dAnna Zaksvoid CallGraph::print(raw_ostream &OS) const { 173196b8cfe9cfcc452eb2f83aa4ad330c2324f8c7dAnna Zaks OS << " --- Call graph Dump --- \n"; 174bd80231672a7418aa1a99d3dbbe1774205c88f74Anna Zaks 175bd80231672a7418aa1a99d3dbbe1774205c88f74Anna Zaks // We are going to print the graph in reverse post order, partially, to make 176bd80231672a7418aa1a99d3dbbe1774205c88f74Anna Zaks // sure the output is deterministic. 177bd80231672a7418aa1a99d3dbbe1774205c88f74Anna Zaks llvm::ReversePostOrderTraversal<const clang::CallGraph*> RPOT(this); 178bd80231672a7418aa1a99d3dbbe1774205c88f74Anna Zaks for (llvm::ReversePostOrderTraversal<const clang::CallGraph*>::rpo_iterator 179bd80231672a7418aa1a99d3dbbe1774205c88f74Anna Zaks I = RPOT.begin(), E = RPOT.end(); I != E; ++I) { 180bd80231672a7418aa1a99d3dbbe1774205c88f74Anna Zaks const CallGraphNode *N = *I; 181bd80231672a7418aa1a99d3dbbe1774205c88f74Anna Zaks 182196b8cfe9cfcc452eb2f83aa4ad330c2324f8c7dAnna Zaks OS << " Function: "; 183bd80231672a7418aa1a99d3dbbe1774205c88f74Anna Zaks if (N == Root) 184196b8cfe9cfcc452eb2f83aa4ad330c2324f8c7dAnna Zaks OS << "< root >"; 185196b8cfe9cfcc452eb2f83aa4ad330c2324f8c7dAnna Zaks else 186bd80231672a7418aa1a99d3dbbe1774205c88f74Anna Zaks N->print(OS); 187bd80231672a7418aa1a99d3dbbe1774205c88f74Anna Zaks 188196b8cfe9cfcc452eb2f83aa4ad330c2324f8c7dAnna Zaks OS << " calls: "; 189bd80231672a7418aa1a99d3dbbe1774205c88f74Anna Zaks for (CallGraphNode::const_iterator CI = N->begin(), 190bd80231672a7418aa1a99d3dbbe1774205c88f74Anna Zaks CE = N->end(); CI != CE; ++CI) { 191196b8cfe9cfcc452eb2f83aa4ad330c2324f8c7dAnna Zaks assert(*CI != Root && "No one can call the root node."); 192196b8cfe9cfcc452eb2f83aa4ad330c2324f8c7dAnna Zaks (*CI)->print(OS); 193196b8cfe9cfcc452eb2f83aa4ad330c2324f8c7dAnna Zaks OS << " "; 194196b8cfe9cfcc452eb2f83aa4ad330c2324f8c7dAnna Zaks } 195196b8cfe9cfcc452eb2f83aa4ad330c2324f8c7dAnna Zaks OS << '\n'; 196196b8cfe9cfcc452eb2f83aa4ad330c2324f8c7dAnna Zaks } 197196b8cfe9cfcc452eb2f83aa4ad330c2324f8c7dAnna Zaks OS.flush(); 198196b8cfe9cfcc452eb2f83aa4ad330c2324f8c7dAnna Zaks} 199196b8cfe9cfcc452eb2f83aa4ad330c2324f8c7dAnna Zaks 200196b8cfe9cfcc452eb2f83aa4ad330c2324f8c7dAnna Zaksvoid CallGraph::dump() const { 201196b8cfe9cfcc452eb2f83aa4ad330c2324f8c7dAnna Zaks print(llvm::errs()); 202196b8cfe9cfcc452eb2f83aa4ad330c2324f8c7dAnna Zaks} 203196b8cfe9cfcc452eb2f83aa4ad330c2324f8c7dAnna Zaks 204196b8cfe9cfcc452eb2f83aa4ad330c2324f8c7dAnna Zaksvoid CallGraph::viewGraph() const { 205196b8cfe9cfcc452eb2f83aa4ad330c2324f8c7dAnna Zaks llvm::ViewGraph(this, "CallGraph"); 206196b8cfe9cfcc452eb2f83aa4ad330c2324f8c7dAnna Zaks} 207196b8cfe9cfcc452eb2f83aa4ad330c2324f8c7dAnna Zaks 208196b8cfe9cfcc452eb2f83aa4ad330c2324f8c7dAnna Zaksvoid CallGraphNode::print(raw_ostream &os) const { 2094f858dfd42c89b67200dac0afc228a0baa323691Anna Zaks if (const NamedDecl *ND = dyn_cast_or_null<NamedDecl>(FD)) 2104f858dfd42c89b67200dac0afc228a0baa323691Anna Zaks return ND->printName(os); 2114f858dfd42c89b67200dac0afc228a0baa323691Anna Zaks os << "< >"; 212196b8cfe9cfcc452eb2f83aa4ad330c2324f8c7dAnna Zaks} 213196b8cfe9cfcc452eb2f83aa4ad330c2324f8c7dAnna Zaks 214196b8cfe9cfcc452eb2f83aa4ad330c2324f8c7dAnna Zaksvoid CallGraphNode::dump() const { 215196b8cfe9cfcc452eb2f83aa4ad330c2324f8c7dAnna Zaks print(llvm::errs()); 216196b8cfe9cfcc452eb2f83aa4ad330c2324f8c7dAnna Zaks} 217196b8cfe9cfcc452eb2f83aa4ad330c2324f8c7dAnna Zaks 218196b8cfe9cfcc452eb2f83aa4ad330c2324f8c7dAnna Zaksnamespace llvm { 219196b8cfe9cfcc452eb2f83aa4ad330c2324f8c7dAnna Zaks 220196b8cfe9cfcc452eb2f83aa4ad330c2324f8c7dAnna Zakstemplate <> 221196b8cfe9cfcc452eb2f83aa4ad330c2324f8c7dAnna Zaksstruct DOTGraphTraits<const CallGraph*> : public DefaultDOTGraphTraits { 222196b8cfe9cfcc452eb2f83aa4ad330c2324f8c7dAnna Zaks 223196b8cfe9cfcc452eb2f83aa4ad330c2324f8c7dAnna Zaks DOTGraphTraits (bool isSimple=false) : DefaultDOTGraphTraits(isSimple) {} 224196b8cfe9cfcc452eb2f83aa4ad330c2324f8c7dAnna Zaks 225196b8cfe9cfcc452eb2f83aa4ad330c2324f8c7dAnna Zaks static std::string getNodeLabel(const CallGraphNode *Node, 226196b8cfe9cfcc452eb2f83aa4ad330c2324f8c7dAnna Zaks const CallGraph *CG) { 227196b8cfe9cfcc452eb2f83aa4ad330c2324f8c7dAnna Zaks if (CG->getRoot() == Node) { 228196b8cfe9cfcc452eb2f83aa4ad330c2324f8c7dAnna Zaks return "< root >"; 229196b8cfe9cfcc452eb2f83aa4ad330c2324f8c7dAnna Zaks } 2304f858dfd42c89b67200dac0afc228a0baa323691Anna Zaks if (const NamedDecl *ND = dyn_cast_or_null<NamedDecl>(Node->getDecl())) 2314f858dfd42c89b67200dac0afc228a0baa323691Anna Zaks return ND->getNameAsString(); 2324f858dfd42c89b67200dac0afc228a0baa323691Anna Zaks else 2334f858dfd42c89b67200dac0afc228a0baa323691Anna Zaks return "< >"; 234196b8cfe9cfcc452eb2f83aa4ad330c2324f8c7dAnna Zaks } 235196b8cfe9cfcc452eb2f83aa4ad330c2324f8c7dAnna Zaks 236196b8cfe9cfcc452eb2f83aa4ad330c2324f8c7dAnna Zaks}; 237196b8cfe9cfcc452eb2f83aa4ad330c2324f8c7dAnna Zaks} 238