1 //== CallGraph.cpp - Call graph building ------------------------*- C++ -*--==//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // This file defined the CallGraph and CGBuilder classes.
12 //===----------------------------------------------------------------------===//
14 #include "clang/Index/CallGraph.h"
16 #include "clang/AST/ASTContext.h"
17 #include "clang/AST/StmtVisitor.h"
19 #include "llvm/Support/GraphWriter.h"
21 using namespace clang
;
25 class CGBuilder
: public StmtVisitor
<CGBuilder
> {
32 CallGraphNode
*CallerNode
;
35 CGBuilder(CallGraph
&g
, FunctionDecl
*fd
, Entity E
, CallGraphNode
*N
)
36 : G(g
), FD(fd
), CallerEnt(E
), CallerNode(N
) {}
38 void VisitStmt(Stmt
*S
) { VisitChildren(S
); }
40 void VisitCallExpr(CallExpr
*CE
);
42 void VisitChildren(Stmt
*S
) {
43 for (Stmt::child_iterator I
=S
->child_begin(), E
=S
->child_end(); I
!= E
;++I
)
45 static_cast<CGBuilder
*>(this)->Visit(*I
);
50 void CGBuilder::VisitCallExpr(CallExpr
*CE
) {
51 if (FunctionDecl
*CalleeDecl
= CE
->getDirectCallee()) {
52 Entity Ent
= Entity::get(CalleeDecl
, G
.getProgram());
53 CallGraphNode
*CalleeNode
= G
.getOrInsertFunction(Ent
);
54 CallerNode
->addCallee(ASTLocation(FD
, CE
), CalleeNode
);
58 CallGraph::CallGraph(Program
&P
) : Prog(P
), Root(0) {
59 ExternalCallingNode
= getOrInsertFunction(Entity());
62 CallGraph::~CallGraph() {
63 if (!FunctionMap
.empty()) {
64 for (FunctionMapTy::iterator I
= FunctionMap
.begin(), E
= FunctionMap
.end();
71 void CallGraph::addTU(ASTContext
& Ctx
) {
72 DeclContext
*DC
= Ctx
.getTranslationUnitDecl();
73 for (DeclContext::decl_iterator I
= DC
->decls_begin(), E
= DC
->decls_end();
76 if (FunctionDecl
*FD
= dyn_cast
<FunctionDecl
>(*I
)) {
77 if (FD
->isThisDeclarationADefinition()) {
78 // Set caller's ASTContext.
79 Entity Ent
= Entity::get(FD
, Prog
);
80 CallGraphNode
*Node
= getOrInsertFunction(Ent
);
81 CallerCtx
[Node
] = &Ctx
;
83 // If this function has external linkage, anything could call it.
85 ExternalCallingNode
->addCallee(idx::ASTLocation(), Node
);
87 // Set root node to 'main' function.
88 if (FD
->getNameAsString() == "main")
91 CGBuilder
builder(*this, FD
, Ent
, Node
);
92 builder
.Visit(FD
->getBody());
98 CallGraphNode
*CallGraph::getOrInsertFunction(Entity F
) {
99 CallGraphNode
*&Node
= FunctionMap
[F
];
103 return Node
= new CallGraphNode(F
);
106 Decl
*CallGraph::getDecl(CallGraphNode
*Node
) {
107 // Get the function's context.
108 ASTContext
*Ctx
= CallerCtx
[Node
];
110 return Node
->getDecl(*Ctx
);
113 void CallGraph::print(llvm::raw_ostream
&os
) {
114 for (iterator I
= begin(), E
= end(); I
!= E
; ++I
) {
115 if (I
->second
->hasCallee()) {
116 os
<< "function: " << I
->first
.getPrintableName()
118 for (CallGraphNode::iterator CI
= I
->second
->begin(),
119 CE
= I
->second
->end(); CI
!= CE
; ++CI
) {
120 os
<< " " << CI
->second
->getName();
127 void CallGraph::dump() {
131 void CallGraph::ViewCallGraph() const {
132 llvm::ViewGraph(*this, "CallGraph");
138 struct DOTGraphTraits
<CallGraph
> : public DefaultDOTGraphTraits
{
140 DOTGraphTraits (bool isSimple
=false) : DefaultDOTGraphTraits(isSimple
) {}
142 static std::string
getNodeLabel(const CallGraphNode
*Node
,
143 const CallGraph
&CG
) {
144 return Node
->getName();