]> granicus.if.org Git - clang/commitdiff
[analyzer] Fix for PR18394.
authorAnton Yartsev <anton.yartsev@gmail.com>
Fri, 28 Feb 2014 22:29:48 +0000 (22:29 +0000)
committerAnton Yartsev <anton.yartsev@gmail.com>
Fri, 28 Feb 2014 22:29:48 +0000 (22:29 +0000)
Additional conditions that prevent useful nodes before call from being reclaimed.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@202553 91177308-0d34-0410-b5e6-96231b3b80d8

lib/StaticAnalyzer/Core/ExplodedGraph.cpp
test/Analysis/NewDeleteLeaks-PR18394.cpp [new file with mode: 0644]

index e9c4a35de6e8dc4df3c5c929c69565d1618ee73a..7812c96f869c7d6801624c02e4c6e3a537ad3b3f 100644 (file)
@@ -90,8 +90,9 @@ bool ExplodedGraph::shouldCollect(const ExplodedNode *node) {
   // (7) The LocationContext is the same as the predecessor.
   // (8) Expressions that are *not* lvalue expressions.
   // (9) The PostStmt isn't for a non-consumed Stmt or Expr.
-  // (10) The successor is not a CallExpr StmtPoint (so that we would
-  //      be able to find it when retrying a call with no inlining).
+  // (10) The successor is neither a CallExpr StmtPoint nor a CallEnter or 
+  //      PreImplicitCall (so that we would be able to find it when retrying a 
+  //      call with no inlining).
   // FIXME: It may be safe to reclaim PreCall and PostCall nodes as well.
 
   // Conditions 1 and 2.
@@ -153,6 +154,10 @@ bool ExplodedGraph::shouldCollect(const ExplodedNode *node) {
     if (CallEvent::isCallStmt(SP->getStmt()))
       return false;
 
+  // Condition 10, continuation.
+  if (SuccLoc.getAs<CallEnter>() || SuccLoc.getAs<PreImplicitCall>())
+    return false;
+
   return true;
 }
 
diff --git a/test/Analysis/NewDeleteLeaks-PR18394.cpp b/test/Analysis/NewDeleteLeaks-PR18394.cpp
new file mode 100644 (file)
index 0000000..452781d
--- /dev/null
@@ -0,0 +1,16 @@
+// RUN: %clang_cc1 -analyzer-config graph-trim-interval=1 -analyzer-max-loop 1 -analyze -analyzer-checker=core,alpha.cplusplus.NewDeleteLeaks -verify %s\r
+// expected-no-diagnostics\r
+\r
+class A {\r
+public:\r
+  void f() {};\r
+  ~A() {\r
+    for (int i=0; i<3; i++)\r
+      f();\r
+  }\r
+};\r
+\r
+void error() {\r
+  A *a = new A();\r
+  delete a;\r
+}\r