<div dir="ltr"><div><div><div><div><div><div><div><div><div><div><div>Hi all,<br><br></div>I've been working with the static analyzer and I'm having issues with the call graph that it produces. This is the same call graph that is output by the debug.DumpCallGraph and debug.ViewCallGraph checkers. I'm fairly new to clang, so I would like some feedback on this. Maybe I've missed the mark entirely or there is a better way to fix it. Thanks in advance, the static analyzer is awesome.<br></div><br></div>With clang version 3.6.0 (trunk 222230), running -analyzer-checker=debug.DumpCallGraph for two equivalent pieces of code produces different results:<br><br></div><div>First sample<br>------------------<br>void a() {}<br>void b() { a(); }<br><br></div><div></div> --- Call graph Dump --- <br>  Function: < root > calls: a b <br>  Function: b calls: a <br>  Function: a calls: <br><br></div>Second sample<br>----------------------<br>void a();<br>void b() { a(); }<br>void a() {}<br><br> --- Call graph Dump --- <br>  Function: < root > calls: b a <br>  Function: a calls: <br>  Function: b calls: <br><br></div>Shouldn't the call graph in the second code sample also have an edge from b to a?<br><br></div>I think this happens because the check at /lib/Analysis/CallGraph.cpp:119 throws out Decls based on isThisDeclarationADefinition(). The comment says that this is used to discard template definitions, but the check is too broad.<br></div><div>When the b-a CallExpr is visited, DeclRefExpr points at the declaration of the function not the definition, so it is not included in the graph. <br><br></div><div>*Feedback please*<br></div><div>I fixed it as below. The idea is to filter out template definitions in addition to function definitions that have a previous declaration, but not all declarations.<br><br>   if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {<br>+    // Skip definitions with previous declarations<br>+    if (FD->getPreviousDecl())<br>+      return false;<br>+<br>     // We skip function template definitions, as their semantics is<br>     // only determined when they are instantiated.<br>-    if (!FD->isThisDeclarationADefinition() ||<br>+    if (FD->getDescribedFunctionTemplate() ||<br>         FD->isDependentContext())<br>       return false;<br></div></div></div><div><br></div>Is this right?<br><br></div>Thanks,<br><div><br>Daniel<br></div></div>