<html><head></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space; "><div><div>On Jul 13, 2009, at 6:31 AM, Zhongxing Xu wrote:</div><br class="Apple-interchange-newline"><blockquote type="cite"><div>This is an initial implementation of call graph building based on pch<br>reader and the new Program/Entity facility. It is very primitive but<br>functional.<br>Put the files under clang/tools/wpa (meaning 'whole program<br>analysis'). After 'make', a new command 'clang-analyze' will be<br>generated. It takes a list of .ast files and build call graph over<br>them.<br></div></blockquote><div><br></div><div>Hi Zhongxing,</div><div><br></div><div>I would call the program 'clang-callgraph' so that people don't confuse it with the "static analyzer".  Comments inline.</div><div><br></div><div><blockquote type="cite"><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 14px/normal Inconsolata; color: rgb(224, 0, 0); "><span style="color: #7e4623">#include </span>"CallGraph.h"</div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 14px/normal Inconsolata; min-height: 15px; "><br></div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 14px/normal Inconsolata; color: rgb(224, 0, 0); "><span style="color: #7e4623">#include </span>"clang/AST/ASTContext.h"</div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 14px/normal Inconsolata; color: rgb(224, 0, 0); "><span style="color: #7e4623">#include </span>"clang/AST/StmtVisitor.h"</div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 14px/normal Inconsolata; min-height: 15px; "><br></div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 14px/normal Inconsolata; color: rgb(200, 0, 163); ">using<span style="color: #000000"> </span>namespace<span style="color: #000000"> clang;</span></div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 14px/normal Inconsolata; color: rgb(200, 0, 163); ">using<span style="color: #000000"> </span>namespace<span style="color: #000000"> idx;</span></div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 14px/normal Inconsolata; min-height: 15px; "><br></div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 14px/normal Inconsolata; ">CallGraph *CallGraph::G = <span style="color: #2f00dd">0</span>;</div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 14px/normal Inconsolata; min-height: 15px; "><br></div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 14px/normal Inconsolata; color: rgb(200, 0, 163); ">namespace<span style="color: #000000"> {</span></div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 14px/normal Inconsolata; "><span style="color: #c800a3">class</span> CGBuilder : <span style="color: #c800a3">public</span> StmtVisitor<CGBuilder> {</div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 14px/normal Inconsolata; min-height: 15px; "><br></div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 14px/normal Inconsolata; ">  CallGraph &G;</div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 14px/normal Inconsolata; ">  FunctionDecl *FD;</div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 14px/normal Inconsolata; min-height: 15px; "><br></div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 14px/normal Inconsolata; color: rgb(200, 0, 163); ">public<span style="color: #000000">:</span></div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 14px/normal Inconsolata; ">  CGBuilder(CallGraph &g, FunctionDecl *fd)</div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 14px/normal Inconsolata; ">    : G(g), FD(fd) {}</div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 14px/normal Inconsolata; min-height: 15px; "><br></div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 14px/normal Inconsolata; ">  <span style="color: #c800a3">void</span> VisitCompoundStmt(CompoundStmt *S) {</div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 14px/normal Inconsolata; ">    VisitChildren(S);</div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 14px/normal Inconsolata; ">  }</div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 14px/normal Inconsolata; min-height: 15px; "><br></div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 14px/normal Inconsolata; ">  <span style="color: #c800a3">void</span> VisitCallExpr(CallExpr *CE);</div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 14px/normal Inconsolata; min-height: 15px; "><br></div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 14px/normal Inconsolata; ">  <span style="color: #c800a3">void</span> VisitChildren(Stmt *S) {</div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 14px/normal Inconsolata; ">    <span style="color: #c800a3">for</span> (Stmt::child_iterator I=S->child_begin(), E=S->child_end(); I != E;++I)</div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 14px/normal Inconsolata; ">      <span style="color: #c800a3">if</span> (*I) </div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 14px/normal Inconsolata; ">        <span style="color: #c800a3">static_cast</span><CGBuilder*>(<span style="color: #c800a3">this</span>)->Visit(*I);    </div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 14px/normal Inconsolata; ">  }</div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 14px/normal Inconsolata; ">};</div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 14px/normal Inconsolata; ">}</div></blockquote><div><br></div><div>You can make this a little shorter by using 'CFGRecStmtVisitor' instead of StmtVisitor.  It basically does the recursion for you.</div><br><blockquote type="cite"><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 14px/normal Inconsolata; min-height: 15px; "><span style="color: #c800a3">void</span> CGBuilder::VisitCallExpr(CallExpr *CE) {</div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 14px/normal Inconsolata; ">  <span style="color: #c800a3">const</span> Entity *CallerEnt = Entity::get(FD, G.getProgram());</div></blockquote><div><br></div><div>Seems like you can make things a little faster by making 'CallerEnt' an instance variable that is initialized to NULL, and then lazily initialize it here if it is NULL.  This will speed things up when there are no calls.</div><br><blockquote type="cite"><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 14px/normal Inconsolata; min-height: 15px; ">  CallGraphNode *Node = G.getOrInsertFunction(CallerEnt);</div></blockquote><div><br></div><div>This too can probably be memoized, since it seems that a CGBuilder is built on a per-function basis.</div><br><blockquote type="cite"><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 14px/normal Inconsolata; min-height: 15px; "><br></div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 14px/normal Inconsolata; ">  Expr *Callee = CE->getCallee();</div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 14px/normal Inconsolata; min-height: 15px; "><br></div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 14px/normal Inconsolata; ">  <span style="color: #c800a3">if</span> (CastExpr *CE = dyn_cast<CastExpr>(Callee))</div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 14px/normal Inconsolata; ">    Callee = CE->getSubExpr();</div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 14px/normal Inconsolata; min-height: 15px; "><br></div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 14px/normal Inconsolata; ">  <span style="color: #c800a3">if</span> (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(Callee)) {</div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 14px/normal Inconsolata; ">    Decl *D = DRE->getDecl();</div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 14px/normal Inconsolata; ">    <span style="color: #c800a3">if</span> (FunctionDecl *CalleeDecl = dyn_cast<FunctionDecl>(D)) {</div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 14px/normal Inconsolata; min-height: 15px; "><br></div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 14px/normal Inconsolata; ">      <span style="color: #c800a3">const</span> Entity *Ent = Entity::get(CalleeDecl, G.getProgram());</div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 14px/normal Inconsolata; min-height: 15px; "><br></div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 14px/normal Inconsolata; ">      CallGraphNode *CalleeNode = G.getOrInsertFunction(Ent);</div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 14px/normal Inconsolata; min-height: 15px; "><br></div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 14px/normal Inconsolata; ">      Node->addCallee(ASTLocation(FD, CE), CalleeNode);</div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 14px/normal Inconsolata; ">    }</div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 14px/normal Inconsolata; ">  }</div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 14px/normal Inconsolata; ">}</div></blockquote><div><br></div><div>Seems reasonable.</div><br><blockquote type="cite"><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 14px/normal Inconsolata; min-height: 15px; "><br></div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 14px/normal Inconsolata; "><span style="color: #c800a3">void</span> CallGraph::addTU(<span style="color: #c800a3">const</span> ASTUnit &AST) {</div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 14px/normal Inconsolata; ">  <span style="color: #c800a3">if</span> (!G)</div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 14px/normal Inconsolata; ">    G = <span style="color: #c800a3">new</span> CallGraph();</div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 14px/normal Inconsolata; min-height: 15px; "><br></div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 14px/normal Inconsolata; ">  <span style="color: #c800a3">const</span> ASTContext &Ctx = AST.getASTContext();</div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 14px/normal Inconsolata; ">  DeclContext *DC = Ctx.getTranslationUnitDecl();</div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 14px/normal Inconsolata; min-height: 15px; "><br></div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 14px/normal Inconsolata; ">  <span style="color: #c800a3">for</span> (DeclContext::decl_iterator I = DC->decls_begin(), E = DC->decls_end();</div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 14px/normal Inconsolata; ">       I != E; ++I) {</div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 14px/normal Inconsolata; min-height: 15px; "><br></div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 14px/normal Inconsolata; ">    <span style="color: #c800a3">if</span> (FunctionDecl *FD = dyn_cast<FunctionDecl>(*I)) {</div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 14px/normal Inconsolata; ">      <span style="color: #c800a3">if</span> (FD->isThisDeclarationADefinition()) {</div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 14px/normal Inconsolata; ">        CGBuilder builder(*G, FD);</div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 14px/normal Inconsolata; ">        builder.Visit(FD->getBody());</div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 14px/normal Inconsolata; ">      }</div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 14px/normal Inconsolata; ">    }</div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 14px/normal Inconsolata; ">  }</div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 14px/normal Inconsolata; ">}</div></blockquote><div><br></div><div>Seems reasonable.  I'm not certain if this will handle code buried in C++ namespaces, but this implementation right now doesn't handle C++ anyway (so it can be done later).</div><br><blockquote type="cite"><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 14px/normal Inconsolata; min-height: 15px; "><br></div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 14px/normal Inconsolata; ">CallGraphNode *CallGraph::getOrInsertFunction(<span style="color: #c800a3">const</span> Entity *F) {</div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 14px/normal Inconsolata; ">  CallGraphNode *&Node = FunctionMap[F];</div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 14px/normal Inconsolata; ">  <span style="color: #c800a3">if</span> (Node)</div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 14px/normal Inconsolata; ">    <span style="color: #c800a3">return</span> Node;</div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 14px/normal Inconsolata; min-height: 15px; "><br></div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 14px/normal Inconsolata; ">  <span style="color: #c800a3">return</span> Node = <span style="color: #c800a3">new</span> CallGraphNode(F);</div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 14px/normal Inconsolata; ">}</div></blockquote><div><br></div>Seems reasonable.</div><div><br></div><div><blockquote type="cite"><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 14px/normal Inconsolata; color: rgb(126, 70, 35); ">#ifndef LLVM_CLANG_ANALYSIS_CALLGRAPH</div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 14px/normal Inconsolata; color: rgb(126, 70, 35); ">#define LLVM_CLANG_ANALYSIS_CALLGRAPH</div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 14px/normal Inconsolata; min-height: 15px; "><br></div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 14px/normal Inconsolata; color: rgb(224, 0, 0); "><span style="color: #7e4623">#include </span>"clang/Index/ASTLocation.h"</div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 14px/normal Inconsolata; color: rgb(224, 0, 0); "><span style="color: #7e4623">#include </span>"clang/Index/Entity.h"</div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 14px/normal Inconsolata; color: rgb(224, 0, 0); "><span style="color: #7e4623">#include </span>"clang/Index/Program.h"</div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 14px/normal Inconsolata; color: rgb(224, 0, 0); "><span style="color: #7e4623">#include </span>"clang/Frontend/ASTUnit.h"</div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 14px/normal Inconsolata; min-height: 15px; "><br></div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 14px/normal Inconsolata; color: rgb(126, 70, 35); ">#include <span style="color: #e00000"><vector></span></div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 14px/normal Inconsolata; color: rgb(126, 70, 35); ">#include <span style="color: #e00000"><map></span></div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 14px/normal Inconsolata; min-height: 15px; "><br></div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 14px/normal Inconsolata; color: rgb(200, 0, 163); ">namespace<span style="color: #000000"> clang {</span></div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 14px/normal Inconsolata; min-height: 15px; "><br></div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 14px/normal Inconsolata; "><span style="color: #c800a3">class</span> CallGraphNode {</div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 14px/normal Inconsolata; ">  <span style="color: #c800a3">const</span> idx::Entity *F;</div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 14px/normal Inconsolata; ">  <span style="color: #c800a3">typedef</span> std::pair<idx::ASTLocation, CallGraphNode*> CallRecord;</div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 14px/normal Inconsolata; ">  std::vector<CallRecord> CalledFunctions;</div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 14px/normal Inconsolata; min-height: 15px; "><br></div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 14px/normal Inconsolata; color: rgb(200, 0, 163); ">public<span style="color: #000000">:</span></div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 14px/normal Inconsolata; ">  CallGraphNode(<span style="color: #c800a3">const</span> idx::Entity *f) : F(f) {}</div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 14px/normal Inconsolata; min-height: 15px; "><br></div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 14px/normal Inconsolata; ">  <span style="color: #c800a3">void</span> addCallee(idx::ASTLocation L, CallGraphNode *Node) {</div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 14px/normal Inconsolata; ">    CalledFunctions.push_back(std::make_pair(L, Node));</div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 14px/normal Inconsolata; ">  }</div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 14px/normal Inconsolata; ">};</div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 14px/normal Inconsolata; min-height: 15px; "><br></div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 14px/normal Inconsolata; "><span style="color: #c800a3">class</span> CallGraph {</div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 14px/normal Inconsolata; ">  <span style="color: #c800a3">static</span> CallGraph *G;</div></blockquote><blockquote type="cite"><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 14px/normal Inconsolata; min-height: 15px; "><br></div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 14px/normal Inconsolata; ">  idx::Program Prog;</div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 14px/normal Inconsolata; min-height: 15px; "><br></div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 14px/normal Inconsolata; ">  <span style="color: #c800a3">typedef</span> std::map<<span style="color: #c800a3">const</span> idx::Entity *, CallGraphNode *> FunctionMapTy;</div></blockquote><div><br></div><div>Eventually, if you care about speed, you'll probably want to use a DenseMap.  I don't see you using the sortedness property of std::map here.</div><blockquote type="cite"><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 14px/normal Inconsolata; min-height: 15px; "><font class="Apple-style-span" color="#000000" face="Helvetica"><span class="Apple-style-span" style="font-size: medium;"><br></span></font></div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 14px/normal Inconsolata; ">  FunctionMapTy FunctionMap;</div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 14px/normal Inconsolata; min-height: 15px; "><br></div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 14px/normal Inconsolata; color: rgb(200, 0, 163); ">public<span style="color: #000000">:</span></div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 14px/normal Inconsolata; ">  <span style="color: #c800a3">static</span> CallGraph *get() { <span style="color: #c800a3">return</span> G; }</div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 14px/normal Inconsolata; min-height: 15px; "><br></div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 14px/normal Inconsolata; ">  <span style="color: #c800a3">static</span> <span style="color: #c800a3">void</span> addTU(<span style="color: #c800a3">const</span> ASTUnit &AST);</div></blockquote><div><br></div><div>Is there a reason you are using static methods/instance variables?  I know this is a small program, but if you wanted to design this to be more reusable I think you'll want to to avoid using them in this way.</div><br><blockquote type="cite"><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 14px/normal Inconsolata; min-height: 15px; "><br></div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 14px/normal Inconsolata; ">  idx::Program &getProgram() { <span style="color: #c800a3">return</span> Prog; }</div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 14px/normal Inconsolata; min-height: 15px; "><br></div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 14px/normal Inconsolata; ">  CallGraphNode *getOrInsertFunction(<span style="color: #c800a3">const</span> idx::Entity * F);</div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 14px/normal Inconsolata; ">};</div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 14px/normal Inconsolata; min-height: 15px; "><br></div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 14px/normal Inconsolata; ">}</div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 14px/normal Inconsolata; min-height: 15px; "><br></div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 14px/normal Inconsolata; color: rgb(126, 70, 35); ">#endif</div></blockquote><div><br></div><div><blockquote type="cite"><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 14px/normal Inconsolata; color: rgb(224, 0, 0); "><span style="color: #7e4623">#include </span>"CallGraph.h"</div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 14px/normal Inconsolata; min-height: 15px; "><br></div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 14px/normal Inconsolata; color: rgb(224, 0, 0); "><span style="color: #7e4623">#include </span>"clang/Basic/FileManager.h"</div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 14px/normal Inconsolata; color: rgb(224, 0, 0); "><span style="color: #7e4623">#include </span>"clang/Index/TranslationUnit.h"</div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 14px/normal Inconsolata; color: rgb(224, 0, 0); "><span style="color: #7e4623">#include </span>"llvm/Support/CommandLine.h"</div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 14px/normal Inconsolata; color: rgb(224, 0, 0); "><span style="color: #7e4623">#include </span>"llvm/Support/raw_ostream.h"</div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 14px/normal Inconsolata; color: rgb(200, 0, 163); ">using<span style="color: #000000"> </span>namespace<span style="color: #000000"> clang;</span></div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 14px/normal Inconsolata; color: rgb(200, 0, 163); ">using<span style="color: #000000"> </span>namespace<span style="color: #000000"> idx;</span></div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 14px/normal Inconsolata; min-height: 15px; "><br></div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 14px/normal Inconsolata; "><span style="color: #c800a3">static</span> llvm::cl::list<std::string></div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 14px/normal Inconsolata; ">InputFilenames(llvm::cl::Positional, llvm::cl::desc(<span style="color: #e00000">"<input AST files>"</span>));</div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 14px/normal Inconsolata; min-height: 15px; "><br></div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 14px/normal Inconsolata; "><span style="color: #c800a3">class</span> TUnit : <span style="color: #c800a3">public</span> TranslationUnit {</div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 14px/normal Inconsolata; color: rgb(200, 0, 163); ">public<span style="color: #000000">:</span></div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 14px/normal Inconsolata; ">  TUnit(ASTUnit *ast, <span style="color: #c800a3">const</span> std::string &filename)</div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 14px/normal Inconsolata; ">    : AST(ast), Filename(filename) {}</div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 14px/normal Inconsolata; ">  ASTContext &getASTContext() { <span style="color: #c800a3">return</span> AST->getASTContext(); }</div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 14px/normal Inconsolata; ">  llvm::OwningPtr<ASTUnit> AST;</div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 14px/normal Inconsolata; ">  std::string Filename;</div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 14px/normal Inconsolata; ">};</div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 14px/normal Inconsolata; min-height: 15px; "><br></div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 14px/normal Inconsolata; "><span style="color: #c800a3">int</span> main(<span style="color: #c800a3">int</span> argc, <span style="color: #c800a3">char</span> **argv) {</div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 14px/normal Inconsolata; ">  llvm::cl::ParseCommandLineOptions(argc, argv, <span style="color: #e00000">"clang analyzer"</span>);</div></blockquote><div><br></div><div>"clang analyzer" is the name people associate with the static analyzer.  I'd just use 'clang-callgraph', since that is what this tool does.</div><br><blockquote type="cite"><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 14px/normal Inconsolata; ">  FileManager FileMgr;</div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 14px/normal Inconsolata; ">  std::vector<TUnit*> TUnits;</div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 14px/normal Inconsolata; min-height: 15px; "><br></div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 14px/normal Inconsolata; ">  <span style="color: #c800a3">if</span> (InputFilenames.empty())</div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 14px/normal Inconsolata; ">    <span style="color: #c800a3">return</span> <span style="color: #2f00dd">0</span>;</div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 14px/normal Inconsolata; min-height: 15px; "><br></div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 14px/normal Inconsolata; ">  <span style="color: #c800a3">for</span> (<span style="color: #c800a3">unsigned</span> i = <span style="color: #2f00dd">0</span>, e = InputFilenames.size(); i != e; ++i) {</div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 14px/normal Inconsolata; ">    <span style="color: #c800a3">const</span> std::string &InFile = InputFilenames[i];</div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 14px/normal Inconsolata; min-height: 15px; "><br></div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 14px/normal Inconsolata; ">    std::string ErrMsg;</div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 14px/normal Inconsolata; ">    llvm::OwningPtr<ASTUnit> AST;</div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 14px/normal Inconsolata; min-height: 15px; "><br></div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 14px/normal Inconsolata; ">    AST.reset(ASTUnit::LoadFromPCHFile(InFile, FileMgr, &ErrMsg));</div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 14px/normal Inconsolata; min-height: 15px; "><br></div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 14px/normal Inconsolata; ">    <span style="color: #c800a3">if</span> (!AST) {</div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 14px/normal Inconsolata; ">      llvm::errs() << <span style="color: #e00000">"["</span> << InFile << <span style="color: #e00000">"] error: "</span> << ErrMsg << <span style="color: #2f00dd">'\n'</span>;</div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 14px/normal Inconsolata; ">      <span style="color: #c800a3">return</span> <span style="color: #2f00dd">1</span>;</div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 14px/normal Inconsolata; ">    }</div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 14px/normal Inconsolata; min-height: 15px; "><br></div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 14px/normal Inconsolata; ">    TUnit *TU = <span style="color: #c800a3">new</span> TUnit(AST.take(), InFile);</div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 14px/normal Inconsolata; ">    TUnits.push_back(TU);</div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 14px/normal Inconsolata; ">  }</div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 14px/normal Inconsolata; min-height: 15px; "><br></div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 14px/normal Inconsolata; ">  <span style="color: #c800a3">for</span> (<span style="color: #c800a3">unsigned</span> i = <span style="color: #2f00dd">0</span>, e = TUnits.size(); i != e; ++i)</div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 14px/normal Inconsolata; ">    CallGraph::addTU(*(TUnits[i]->AST));</div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 14px/normal Inconsolata; min-height: 15px; "><br></div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 14px/normal Inconsolata; ">  CallGraph *CG = CallGraph::get();</div><div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font: normal normal normal 14px/normal Inconsolata; ">}</div></blockquote><div><br></div>I think this has the potentially to be a nice little tool, but I think in order for it to be useful it should produce some basic output.  I think printing out the callgraph would be nice.  You can also defined some GraphTraits for the CallGraph (similar to what we do in clang/include/AST/CFG.h) to get automatic GraphViz visualization.</div><div><br></div><div>All in all I think this is cool, I can look forward to playing around with it!</div></div></div></body></html>