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/Analysis/CallGraph.h"
16 #include "clang/AST/ASTContext.h"
17 #include "clang/AST/StmtVisitor.h"
19 using namespace clang
;
23 class CGBuilder
: public StmtVisitor
<CGBuilder
> {
30 CallGraphNode
*CallerNode
;
33 CGBuilder(CallGraph
&g
, FunctionDecl
*fd
, Entity
*E
, CallGraphNode
*N
)
34 : G(g
), FD(fd
), CallerEnt(E
), CallerNode(N
) {}
36 void VisitStmt(Stmt
*S
) { VisitChildren(S
); }
38 void VisitCallExpr(CallExpr
*CE
);
40 void VisitChildren(Stmt
*S
) {
41 for (Stmt::child_iterator I
=S
->child_begin(), E
=S
->child_end(); I
!= E
;++I
)
43 static_cast<CGBuilder
*>(this)->Visit(*I
);
48 void CGBuilder::VisitCallExpr(CallExpr
*CE
) {
49 if (FunctionDecl
*CalleeDecl
= CE
->getDirectCallee()) {
50 Entity
*Ent
= Entity::get(CalleeDecl
, G
.getProgram());
51 CallGraphNode
*CalleeNode
= G
.getOrInsertFunction(Ent
);
53 Decl
*Parent
= ASTLocation::FindImmediateParent(FD
, CE
);
55 CallerNode
->addCallee(ASTLocation(Parent
, CE
), CalleeNode
);
59 CallGraph::~CallGraph() {
60 if (!FunctionMap
.empty()) {
61 for (FunctionMapTy::iterator I
= FunctionMap
.begin(), E
= FunctionMap
.end();
68 void CallGraph::addTU(ASTUnit
&AST
) {
69 ASTContext
&Ctx
= AST
.getASTContext();
70 DeclContext
*DC
= Ctx
.getTranslationUnitDecl();
72 for (DeclContext::decl_iterator I
= DC
->decls_begin(), E
= DC
->decls_end();
75 if (FunctionDecl
*FD
= dyn_cast
<FunctionDecl
>(*I
)) {
76 if (FD
->isThisDeclarationADefinition()) {
77 // Set caller's ASTContext.
78 Entity
*Ent
= Entity::get(FD
, Prog
);
79 CallGraphNode
*Node
= getOrInsertFunction(Ent
);
80 CallerCtx
[Node
] = &Ctx
;
82 CGBuilder
builder(*this, FD
, Ent
, Node
);
83 builder
.Visit(FD
->getBody());
89 CallGraphNode
*CallGraph::getOrInsertFunction(Entity
*F
) {
90 CallGraphNode
*&Node
= FunctionMap
[F
];
94 return Node
= new CallGraphNode(F
);
97 void CallGraph::print(llvm::raw_ostream
&os
) {
98 for (iterator I
= begin(), E
= end(); I
!= E
; ++I
) {
99 if (I
->second
->hasCallee()) {
100 ASTContext
&Ctx
= *CallerCtx
[I
->second
];
101 os
<< "function: " << I
->first
->getPrintableName(Ctx
).c_str()
103 for (CallGraphNode::iterator CI
= I
->second
->begin(),
104 CE
= I
->second
->end(); CI
!= CE
; ++CI
) {
105 os
<< " " << CI
->second
->getName(Ctx
).c_str();
112 void CallGraph::dump() {