[PATCH] D65453: Improve the accuracy of the Clang call graph analysis

2019-08-15 Thread Artem Dergachev via Phabricator via cfe-commits
NoQ added a comment.

Thanks! This looks very useful.




Comment at: clang/lib/Analysis/CallGraph.cpp:97-102
+const auto *ConstructedType = Ctor->getParent();
+if (ConstructedType->hasUserDeclaredDestructor()) {
+  CXXDestructorDecl *Dtor = ConstructedType->getDestructor();
+  if (FunctionDecl *Def = Dtor->getDefinition())
+addCalledDecl(Def);
+}

Ugh this is questionable. The object may easily outlive the function, so the 
destructor may be called from another function. I see where this was supposed 
to go (i.e., this is perfectly correct when the constructor is constructing a 
non-RVO'd temporary or a non-NRVO'd local variable), but in the general case 
it's not true.

The really nice way to implement this functionality would be to rely on the 
constructor's `ConstructionContext`, but as of now it's only available in the 
CFG and there's no easy way to retrieve it by looking at the AST node (and if 
you have a CFG you might as well look at destructors directly, as they're 
listed there explicitly).

It should also be possible to do that by hand by matching `DeclStmt`s and 
`CXXBindTemporaryExpr`s.

Let's omit this part for now because currently the analysis seems to be 
conservative in the sense that it doesn't add calls when it's not sure.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D65453/new/

https://reviews.llvm.org/D65453



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D65453: Improve the accuracy of the Clang call graph analysis

2019-08-15 Thread Joshua Cranmer via Phabricator via cfe-commits
jcranmer-intel updated this revision to Diff 215462.
jcranmer-intel added a comment.

I've rolled the relevant call graph analysis changes from the prior commit into 
this updated patch.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D65453/new/

https://reviews.llvm.org/D65453

Files:
  clang/include/clang/Analysis/CallGraph.h
  clang/lib/Analysis/CallGraph.cpp
  clang/test/Analysis/cxx-callgraph.cpp

Index: clang/test/Analysis/cxx-callgraph.cpp
===
--- /dev/null
+++ clang/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: clang/lib/Analysis/CallGraph.cpp
===
--- clang/lib/Analysis/CallGraph.cpp
+++ clang/lib/Analysis/CallGraph.cpp
@@ -79,6 +79,40 @@
 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);
+const auto *ConstructedType = Ctor->getParent();
+if (ConstructedType->hasUserDeclaredDestructor()) {
+  CXXDestructorDecl *Dtor = ConstructedType->getDestructor();
+  if (FunctionDecl *Def = Dtor->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 +177,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: clang/include/clang/Analysis/CallGraph.h
===
--- clang/include/clang/Analysis/CallGraph.h
+++ clang/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.
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D65453: Improve the accuracy of the Clang call graph analysis

2019-08-14 Thread Joshua Cranmer via Phabricator via cfe-commits
jcranmer-intel added a comment.

Okay, I see the issue now. I originally developed this patch on a fork with a 
whole lot of extra changes, and that fork included some extra modifications to 
the callgraph that I had missed: 
https://github.com/intel/llvm/commit/971fecdc316930c0c1c79283d1094ee4c4ca41e0#diff-cae4e2b4043cd0f49ce29e77de22a5a5.
 I'll merge the callgraph-related changes in that patch back onto a clean patch 
for upstream.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D65453/new/

https://reviews.llvm.org/D65453



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D65453: Improve the accuracy of the Clang call graph analysis

2019-08-14 Thread Artem Dergachev via Phabricator via cfe-commits
NoQ added inline comments.



Comment at: clang/lib/Analysis/CallGraph.cpp:93
 
   void VisitCXXConstructExpr(CXXConstructExpr *E) {
 CXXConstructorDecl *Ctor = E->getConstructor();

Yes, there it is. Where does it come from? I don't have it in master.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D65453/new/

https://reviews.llvm.org/D65453



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D65453: Improve the accuracy of the Clang call graph analysis

2019-08-14 Thread Artem Dergachev via Phabricator via cfe-commits
NoQ added a comment.

For me `ddd()` doesn't call `c::c()`. I can fix it by adding the following code:

  void VisitCXXConstructExpr(CXXConstructExpr *CE) {
addCalledDecl(CE->getConstructor());
VisitChildren(CE);
  }

I don't see why it would work without that code, as `CXXConstructExpr` isn't a 
sub-class of `CallExpr`. So that's another obvious omission in the `CallGraph`.

Might it be that you have it locally but forgot to include in the patch? It 
also fails a couple more unrelated tests when i add it because it affects 
analysis order.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D65453/new/

https://reviews.llvm.org/D65453



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D65453: Improve the accuracy of the Clang call graph analysis

2019-08-14 Thread Joshua Cranmer via Phabricator via cfe-commits
jcranmer-intel added a comment.

The test has been passing for me. What error are you seeing?


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D65453/new/

https://reviews.llvm.org/D65453



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D65453: Improve the accuracy of the Clang call graph analysis

2019-08-13 Thread Artem Dergachev via Phabricator via cfe-commits
NoQ added a comment.

Hmm, the patch doesn't pass its own test for me, could you double-check?


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D65453/new/

https://reviews.llvm.org/D65453



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D65453: Improve the accuracy of the Clang call graph analysis

2019-08-09 Thread Joshua Cranmer via Phabricator via cfe-commits
jcranmer-intel added a comment.

No, I do not have commit access, so if you could commit it, it would be greatly 
appreciated.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D65453/new/

https://reviews.llvm.org/D65453



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D65453: Improve the accuracy of the Clang call graph analysis

2019-08-09 Thread Artem Dergachev via Phabricator via cfe-commits
NoQ added a comment.

Do you have commit access or should i commit this for you?


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D65453/new/

https://reviews.llvm.org/D65453



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D65453: Improve the accuracy of the Clang call graph analysis

2019-08-09 Thread Artem Dergachev via Phabricator via cfe-commits
NoQ accepted this revision.
NoQ edited reviewers, added: NoQ; removed: dergachev.a.
NoQ added a comment.

This will slightly skew Static Analyzer exploration order, not necessarily in a 
good way, as default arguments and (sometimes) default initializers are not 
modeled properly. But this doesn't sound dangerous, because whether functions 
will be analyzed at top level doesn't depend on where they're positioned in the 
`CallGraph`, but instead on whether they've been actually visited during 
symbolic execution. So it's mostly about order rather than coverage. So i'm not 
worried.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D65453/new/

https://reviews.llvm.org/D65453



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D65453: Improve the accuracy of the Clang call graph analysis

2019-07-30 Thread Joshua Cranmer via Phabricator via cfe-commits
jcranmer-intel created this revision.
jcranmer-intel added a reviewer: dcoughlin.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.

This patch improves Clang call graph analysis by adding in expressions that are 
not found in regular function bodies, such as default arguments or C++ member 
initializers.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D65453

Files:
  clang/lib/Analysis/CallGraph.cpp
  clang/test/Analysis/cxx-callgraph.cpp


Index: clang/test/Analysis/cxx-callgraph.cpp
===
--- /dev/null
+++ clang/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: clang/lib/Analysis/CallGraph.cpp
===
--- clang/lib/Analysis/CallGraph.cpp
+++ clang/lib/Analysis/CallGraph.cpp
@@ -103,6 +103,16 @@
 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()) {
@@ -167,13 +177,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: clang/test/Analysis/cxx-callgraph.cpp
===
--- /dev/null
+++ clang/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: clang/lib/Analysis/CallGraph.cpp
===
--- clang/lib/Analysis/CallGraph.cpp
+++ clang/lib/Analysis/CallGraph.cpp
@@ -103,6 +103,16 @@
 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()) {
@@ -167,13 +177,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 {
___
cfe-commits mailing list
cfe-commits@lists.llvm.