Index: cfe/trunk/include/clang/Analysis/CallGraph.h =================================================================== --- cfe/trunk/include/clang/Analysis/CallGraph.h +++ cfe/trunk/include/clang/Analysis/CallGraph.h @@ -131,6 +131,7 @@ bool shouldWalkTypesOfTypeLocs() const { return false; } bool shouldVisitTemplateInstantiations() const { return true; } + bool shouldVisitImplicitCode() const { return true; } private: /// Add the given declaration to the call graph. Index: cfe/trunk/lib/Analysis/CallGraph.cpp =================================================================== --- cfe/trunk/lib/Analysis/CallGraph.cpp +++ cfe/trunk/lib/Analysis/CallGraph.cpp @@ -79,6 +79,34 @@ VisitChildren(CE); } + void VisitLambdaExpr(LambdaExpr *LE) { + if (CXXMethodDecl *MD = LE->getCallOperator()) + G->VisitFunctionDecl(MD); + } + + void VisitCXXNewExpr(CXXNewExpr *E) { + if (FunctionDecl *FD = E->getOperatorNew()) + addCalledDecl(FD); + VisitChildren(E); + } + + void VisitCXXConstructExpr(CXXConstructExpr *E) { + CXXConstructorDecl *Ctor = E->getConstructor(); + if (FunctionDecl *Def = Ctor->getDefinition()) + addCalledDecl(Def); + VisitChildren(E); + } + + // Include the evaluation of the default argument. + void VisitCXXDefaultArgExpr(CXXDefaultArgExpr *E) { + Visit(E->getExpr()); + } + + // Include the evaluation of the default initializers in a class. + void VisitCXXDefaultInitExpr(CXXDefaultInitExpr *E) { + Visit(E->getExpr()); + } + // Adds may-call edges for the ObjC message sends. void VisitObjCMessageExpr(ObjCMessageExpr *ME) { if (ObjCInterfaceDecl *IDecl = ME->getReceiverInterface()) { @@ -143,13 +171,20 @@ void CallGraph::addNodeForDecl(Decl* D, bool IsGlobal) { assert(D); - // Allocate a new node, mark it as root, and process it's calls. + // Allocate a new node, mark it as root, and process its calls. CallGraphNode *Node = getOrInsertNode(D); // Process all the calls by this function as well. CGBuilder builder(this, Node); if (Stmt *Body = D->getBody()) builder.Visit(Body); + + // Include C++ constructor member initializers. + if (auto constructor = dyn_cast(D)) { + for (CXXCtorInitializer *init : constructor->inits()) { + builder.Visit(init->getInit()); + } + } } CallGraphNode *CallGraph::getNode(const Decl *F) const { Index: cfe/trunk/test/Analysis/cxx-callgraph.cpp =================================================================== --- cfe/trunk/test/Analysis/cxx-callgraph.cpp +++ cfe/trunk/test/Analysis/cxx-callgraph.cpp @@ -0,0 +1,29 @@ +// RUN: %clang_analyze_cc1 -analyzer-checker=debug.DumpCallGraph %s 2>&1 | FileCheck %s + +static int aaa() { + return 0; +} + +static int bbb(int param=aaa()) { + return 1; +} + +int ddd(); + +struct c { + c(int param=2) : val(bbb(param)) {} + int val; + int val2 = ddd(); +}; + +int ddd() { + c c; + return bbb(); +} + +// CHECK:--- Call graph Dump --- +// CHECK-NEXT: {{Function: < root > calls: aaa bbb c::c ddd}} +// CHECK-NEXT: {{Function: c::c calls: bbb ddd $}} +// CHECK-NEXT: {{Function: ddd calls: c::c bbb aaa $}} +// CHECK-NEXT: {{Function: bbb calls: $}} +// CHECK-NEXT: {{Function: aaa calls: $}} Index: cfe/trunk/test/Analysis/exploded-graph-rewriter/objects_under_construction.cpp =================================================================== --- cfe/trunk/test/Analysis/exploded-graph-rewriter/objects_under_construction.cpp +++ cfe/trunk/test/Analysis/exploded-graph-rewriter/objects_under_construction.cpp @@ -1,5 +1,6 @@ // FIXME: Figure out how to use %clang_analyze_cc1 with our lit.local.cfg. // RUN: %clang_cc1 -analyze -triple x86_64-unknown-linux-gnu \ +// RUN: -analyze-function "test()" \ // RUN: -analyzer-checker=core \ // RUN: -analyzer-dump-egraph=%t.dot %s // RUN: %exploded_graph_rewriter %t.dot | FileCheck %s