[PATCH] D43062: [analyzer] Support CXXTemporaryObjectExpr constructors that have destructors.

2018-02-14 Thread Phabricator via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rL325211: [analyzer] Inline constructors for destroyable 
temporaries. (authored by dergachev, committed by ).
Herald added a subscriber: llvm-commits.

Changed prior to commit:
  https://reviews.llvm.org/D43062?vs=133475=134368#toc

Repository:
  rL LLVM

https://reviews.llvm.org/D43062

Files:
  cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
  cfe/trunk/test/Analysis/temporaries.cpp

Index: cfe/trunk/test/Analysis/temporaries.cpp
===
--- cfe/trunk/test/Analysis/temporaries.cpp
+++ cfe/trunk/test/Analysis/temporaries.cpp
@@ -607,22 +607,37 @@
   clang_analyzer_eval(c3.getY() == 2); // expected-warning{{TRUE}}
 
   C c4 = returnTemporaryWithConstruction();
-  // Should be TRUE under TEMPORARY_DTORS once this sort of construction
-  // in the inlined function is supported.
-  clang_analyzer_eval(c4.getX() == 1); // expected-warning{{UNKNOWN}}
-  clang_analyzer_eval(c4.getY() == 2); // expected-warning{{UNKNOWN}}
+  clang_analyzer_eval(c4.getX() == 1);
+  clang_analyzer_eval(c4.getY() == 2);
+#ifdef TEMPORARY_DTORS
+  // expected-warning@-3{{TRUE}}
+  // expected-warning@-3{{TRUE}}
+#else
+  // expected-warning@-6{{UNKNOWN}}
+  // expected-warning@-6{{UNKNOWN}}
+#endif
 
   C c5 = returnTemporaryWithAnotherFunctionWithConstruction();
-  // Should be TRUE under TEMPORARY_DTORS once this sort of construction
-  // in the inlined function is supported.
-  clang_analyzer_eval(c5.getX() == 1); // expected-warning{{UNKNOWN}}
-  clang_analyzer_eval(c5.getY() == 2); // expected-warning{{UNKNOWN}}
+  clang_analyzer_eval(c5.getX() == 1);
+  clang_analyzer_eval(c5.getY() == 2);
+#ifdef TEMPORARY_DTORS
+  // expected-warning@-3{{TRUE}}
+  // expected-warning@-3{{TRUE}}
+#else
+  // expected-warning@-6{{UNKNOWN}}
+  // expected-warning@-6{{UNKNOWN}}
+#endif
 
   C c6 = returnTemporaryWithCopyConstructionWithConstruction();
-  // Should be TRUE under TEMPORARY_DTORS once this sort of construction
-  // in the inlined function is supported.
-  clang_analyzer_eval(c5.getX() == 1); // expected-warning{{UNKNOWN}}
-  clang_analyzer_eval(c5.getY() == 2); // expected-warning{{UNKNOWN}}
+  clang_analyzer_eval(c5.getX() == 1);
+  clang_analyzer_eval(c5.getY() == 2);
+#ifdef TEMPORARY_DTORS
+  // expected-warning@-3{{TRUE}}
+  // expected-warning@-3{{TRUE}}
+#else
+  // expected-warning@-6{{UNKNOWN}}
+  // expected-warning@-6{{UNKNOWN}}
+#endif
 
 #if __cplusplus >= 201103L
 
@@ -683,10 +698,84 @@
   // expected-warning@-6{{UNKNOWN}}
 #endif
 
-  // Should be TRUE under TEMPORARY_DTORS once this sort of construction
-  // in the inlined function is supported.
   D d3 = returnTemporaryWithCopyConstructionWithVariableAndNonTrivialCopy();
-  clang_analyzer_eval(d3.getX() == 1); // expected-warning{{UNKNOWN}}
-  clang_analyzer_eval(d3.getY() == 2); // expected-warning{{UNKNOWN}}
+  clang_analyzer_eval(d3.getX() == 1);
+  clang_analyzer_eval(d3.getY() == 2);
+#ifdef TEMPORARY_DTORS
+  // expected-warning@-3{{TRUE}}
+  // expected-warning@-3{{TRUE}}
+#else
+  // expected-warning@-6{{UNKNOWN}}
+  // expected-warning@-6{{UNKNOWN}}
+#endif
 }
 } // namespace test_return_temporary
+
+
+namespace test_temporary_object_expr_without_dtor {
+class C {
+  int x;
+public:
+  C(int x) : x(x) {}
+  int getX() const { return x; }
+};
+
+void test() {
+  clang_analyzer_eval(C(3).getX() == 3); // expected-warning{{TRUE}}
+};
+}
+
+namespace test_temporary_object_expr_with_dtor {
+class C {
+  int x;
+
+public:
+  C(int x) : x(x) {}
+  ~C() {}
+  int getX() const { return x; }
+};
+
+void test(int coin) {
+  clang_analyzer_eval(C(3).getX() == 3);
+#ifdef TEMPORARY_DTORS
+  // expected-warning@-2{{TRUE}}
+#else
+  // expected-warning@-4{{UNKNOWN}}
+#endif
+
+  const C  = coin ? C(1) : C(2);
+  if (coin) {
+clang_analyzer_eval(c1.getX() == 1);
+#ifdef TEMPORARY_DTORS
+  // expected-warning@-2{{TRUE}}
+#else
+  // expected-warning@-4{{UNKNOWN}}
+#endif
+  } else {
+clang_analyzer_eval(c1.getX() == 2);
+#ifdef TEMPORARY_DTORS
+  // expected-warning@-2{{TRUE}}
+#else
+  // expected-warning@-4{{UNKNOWN}}
+#endif
+  }
+
+  C c2 = coin ? C(1) : C(2);
+  if (coin) {
+clang_analyzer_eval(c2.getX() == 1);
+#ifdef TEMPORARY_DTORS
+  // expected-warning@-2{{TRUE}}
+#else
+  // expected-warning@-4{{UNKNOWN}}
+#endif
+  } else {
+clang_analyzer_eval(c2.getX() == 2);
+#ifdef TEMPORARY_DTORS
+  // expected-warning@-2{{TRUE}}
+#else
+  // expected-warning@-4{{UNKNOWN}}
+#endif
+  }
+}
+
+} // namespace test_temporary_object_expr
Index: cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
===
--- cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
+++ cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
@@ -148,6 +148,9 @@
 // construction context that'd give us the right temporary expression.
 

[PATCH] D43062: [analyzer] Support CXXTemporaryObjectExpr constructors that have destructors.

2018-02-08 Thread Artem Dergachev via Phabricator via cfe-commits
NoQ updated this revision to Diff 133475.
NoQ added a comment.

Add a simple test for a class with no destructor.


https://reviews.llvm.org/D43062

Files:
  lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
  test/Analysis/temporaries.cpp

Index: test/Analysis/temporaries.cpp
===
--- test/Analysis/temporaries.cpp
+++ test/Analysis/temporaries.cpp
@@ -607,22 +607,37 @@
   clang_analyzer_eval(c3.getY() == 2); // expected-warning{{TRUE}}
 
   C c4 = returnTemporaryWithConstruction();
-  // Should be TRUE under TEMPORARY_DTORS once this sort of construction
-  // in the inlined function is supported.
-  clang_analyzer_eval(c4.getX() == 1); // expected-warning{{UNKNOWN}}
-  clang_analyzer_eval(c4.getY() == 2); // expected-warning{{UNKNOWN}}
+  clang_analyzer_eval(c4.getX() == 1);
+  clang_analyzer_eval(c4.getY() == 2);
+#ifdef TEMPORARY_DTORS
+  // expected-warning@-3{{TRUE}}
+  // expected-warning@-3{{TRUE}}
+#else
+  // expected-warning@-6{{UNKNOWN}}
+  // expected-warning@-6{{UNKNOWN}}
+#endif
 
   C c5 = returnTemporaryWithAnotherFunctionWithConstruction();
-  // Should be TRUE under TEMPORARY_DTORS once this sort of construction
-  // in the inlined function is supported.
-  clang_analyzer_eval(c5.getX() == 1); // expected-warning{{UNKNOWN}}
-  clang_analyzer_eval(c5.getY() == 2); // expected-warning{{UNKNOWN}}
+  clang_analyzer_eval(c5.getX() == 1);
+  clang_analyzer_eval(c5.getY() == 2);
+#ifdef TEMPORARY_DTORS
+  // expected-warning@-3{{TRUE}}
+  // expected-warning@-3{{TRUE}}
+#else
+  // expected-warning@-6{{UNKNOWN}}
+  // expected-warning@-6{{UNKNOWN}}
+#endif
 
   C c6 = returnTemporaryWithCopyConstructionWithConstruction();
-  // Should be TRUE under TEMPORARY_DTORS once this sort of construction
-  // in the inlined function is supported.
-  clang_analyzer_eval(c5.getX() == 1); // expected-warning{{UNKNOWN}}
-  clang_analyzer_eval(c5.getY() == 2); // expected-warning{{UNKNOWN}}
+  clang_analyzer_eval(c5.getX() == 1);
+  clang_analyzer_eval(c5.getY() == 2);
+#ifdef TEMPORARY_DTORS
+  // expected-warning@-3{{TRUE}}
+  // expected-warning@-3{{TRUE}}
+#else
+  // expected-warning@-6{{UNKNOWN}}
+  // expected-warning@-6{{UNKNOWN}}
+#endif
 
 #if __cplusplus >= 201103L
 
@@ -683,10 +698,84 @@
   // expected-warning@-6{{UNKNOWN}}
 #endif
 
-  // Should be TRUE under TEMPORARY_DTORS once this sort of construction
-  // in the inlined function is supported.
   D d3 = returnTemporaryWithCopyConstructionWithVariableAndNonTrivialCopy();
-  clang_analyzer_eval(d3.getX() == 1); // expected-warning{{UNKNOWN}}
-  clang_analyzer_eval(d3.getY() == 2); // expected-warning{{UNKNOWN}}
+  clang_analyzer_eval(d3.getX() == 1);
+  clang_analyzer_eval(d3.getY() == 2);
+#ifdef TEMPORARY_DTORS
+  // expected-warning@-3{{TRUE}}
+  // expected-warning@-3{{TRUE}}
+#else
+  // expected-warning@-6{{UNKNOWN}}
+  // expected-warning@-6{{UNKNOWN}}
+#endif
 }
 } // namespace test_return_temporary
+
+
+namespace test_temporary_object_expr_without_dtor {
+class C {
+  int x;
+public:
+  C(int x) : x(x) {}
+  int getX() const { return x; }
+};
+
+void test() {
+  clang_analyzer_eval(C(3).getX() == 3); // expected-warning{{TRUE}}
+};
+}
+
+namespace test_temporary_object_expr_with_dtor {
+class C {
+  int x;
+
+public:
+  C(int x) : x(x) {}
+  ~C() {}
+  int getX() const { return x; }
+};
+
+void test(int coin) {
+  clang_analyzer_eval(C(3).getX() == 3);
+#ifdef TEMPORARY_DTORS
+  // expected-warning@-2{{TRUE}}
+#else
+  // expected-warning@-4{{UNKNOWN}}
+#endif
+
+  const C  = coin ? C(1) : C(2);
+  if (coin) {
+clang_analyzer_eval(c1.getX() == 1);
+#ifdef TEMPORARY_DTORS
+  // expected-warning@-2{{TRUE}}
+#else
+  // expected-warning@-4{{UNKNOWN}}
+#endif
+  } else {
+clang_analyzer_eval(c1.getX() == 2);
+#ifdef TEMPORARY_DTORS
+  // expected-warning@-2{{TRUE}}
+#else
+  // expected-warning@-4{{UNKNOWN}}
+#endif
+  }
+
+  C c2 = coin ? C(1) : C(2);
+  if (coin) {
+clang_analyzer_eval(c2.getX() == 1);
+#ifdef TEMPORARY_DTORS
+  // expected-warning@-2{{TRUE}}
+#else
+  // expected-warning@-4{{UNKNOWN}}
+#endif
+  } else {
+clang_analyzer_eval(c2.getX() == 2);
+#ifdef TEMPORARY_DTORS
+  // expected-warning@-2{{TRUE}}
+#else
+  // expected-warning@-4{{UNKNOWN}}
+#endif
+  }
+}
+
+} // namespace test_temporary_object_expr
Index: lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
===
--- lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
+++ lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
@@ -137,6 +137,9 @@
   } else if (auto *RS = dyn_cast(TriggerStmt)) {
 CallOpts.IsTemporaryCtorOrDtor = true;
 return MRMgr.getCXXTempObjectRegion(CE, LCtx);
+  } else if (auto *BTE = dyn_cast(TriggerStmt)) {
+CallOpts.IsTemporaryCtorOrDtor = true;
+return MRMgr.getCXXTempObjectRegion(CE, LCtx);
   }
   // TODO: Consider other directly initialized elements.
 } else if (const CXXCtorInitializer 

[PATCH] D43062: [analyzer] Support CXXTemporaryObjectExpr constructors that have destructors.

2018-02-07 Thread Artem Dergachev via Phabricator via cfe-commits
NoQ created this revision.
NoQ added reviewers: dcoughlin, xazax.hun, a.sidorin, george.karpenkov, szepet.
Herald added subscribers: cfe-commits, rnkovacs.
NoQ added a dependency: D43056: [CFG] [analyzer] Add construction context for 
CXXBindTemporaryExpr..

Patch https://reviews.llvm.org/D43056 adds support for such 
`CXXTemporaryObjectExpr` kind of constructors in the CFG. Here i add a 
straightforward analyzer-side support.

Note that when we don't have destructors (i.e. we have trivial destructors), 
the analyzer inlines the temporary constructor regardless of whether it has a 
destructor in the CFG or not, actually also regardless of whether the target 
region is correct, so it kinda worked before, in simple cases.


Repository:
  rC Clang

https://reviews.llvm.org/D43062

Files:
  lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
  test/Analysis/temporaries.cpp

Index: test/Analysis/temporaries.cpp
===
--- test/Analysis/temporaries.cpp
+++ test/Analysis/temporaries.cpp
@@ -607,22 +607,37 @@
   clang_analyzer_eval(c3.getY() == 2); // expected-warning{{TRUE}}
 
   C c4 = returnTemporaryWithConstruction();
-  // Should be TRUE under TEMPORARY_DTORS once this sort of construction
-  // in the inlined function is supported.
-  clang_analyzer_eval(c4.getX() == 1); // expected-warning{{UNKNOWN}}
-  clang_analyzer_eval(c4.getY() == 2); // expected-warning{{UNKNOWN}}
+  clang_analyzer_eval(c4.getX() == 1);
+  clang_analyzer_eval(c4.getY() == 2);
+#ifdef TEMPORARY_DTORS
+  // expected-warning@-3{{TRUE}}
+  // expected-warning@-3{{TRUE}}
+#else
+  // expected-warning@-6{{UNKNOWN}}
+  // expected-warning@-6{{UNKNOWN}}
+#endif
 
   C c5 = returnTemporaryWithAnotherFunctionWithConstruction();
-  // Should be TRUE under TEMPORARY_DTORS once this sort of construction
-  // in the inlined function is supported.
-  clang_analyzer_eval(c5.getX() == 1); // expected-warning{{UNKNOWN}}
-  clang_analyzer_eval(c5.getY() == 2); // expected-warning{{UNKNOWN}}
+  clang_analyzer_eval(c5.getX() == 1);
+  clang_analyzer_eval(c5.getY() == 2);
+#ifdef TEMPORARY_DTORS
+  // expected-warning@-3{{TRUE}}
+  // expected-warning@-3{{TRUE}}
+#else
+  // expected-warning@-6{{UNKNOWN}}
+  // expected-warning@-6{{UNKNOWN}}
+#endif
 
   C c6 = returnTemporaryWithCopyConstructionWithConstruction();
-  // Should be TRUE under TEMPORARY_DTORS once this sort of construction
-  // in the inlined function is supported.
-  clang_analyzer_eval(c5.getX() == 1); // expected-warning{{UNKNOWN}}
-  clang_analyzer_eval(c5.getY() == 2); // expected-warning{{UNKNOWN}}
+  clang_analyzer_eval(c5.getX() == 1);
+  clang_analyzer_eval(c5.getY() == 2);
+#ifdef TEMPORARY_DTORS
+  // expected-warning@-3{{TRUE}}
+  // expected-warning@-3{{TRUE}}
+#else
+  // expected-warning@-6{{UNKNOWN}}
+  // expected-warning@-6{{UNKNOWN}}
+#endif
 
 #if __cplusplus >= 201103L
 
@@ -683,10 +698,71 @@
   // expected-warning@-6{{UNKNOWN}}
 #endif
 
-  // Should be TRUE under TEMPORARY_DTORS once this sort of construction
-  // in the inlined function is supported.
   D d3 = returnTemporaryWithCopyConstructionWithVariableAndNonTrivialCopy();
-  clang_analyzer_eval(d3.getX() == 1); // expected-warning{{UNKNOWN}}
-  clang_analyzer_eval(d3.getY() == 2); // expected-warning{{UNKNOWN}}
+  clang_analyzer_eval(d3.getX() == 1);
+  clang_analyzer_eval(d3.getY() == 2);
+#ifdef TEMPORARY_DTORS
+  // expected-warning@-3{{TRUE}}
+  // expected-warning@-3{{TRUE}}
+#else
+  // expected-warning@-6{{UNKNOWN}}
+  // expected-warning@-6{{UNKNOWN}}
+#endif
 }
 } // namespace test_return_temporary
+
+namespace test_temporary_object_expr {
+
+class C {
+  int x;
+
+public:
+  C(int x) : x(x) {}
+  ~C() {}
+  int getX() const { return x; }
+};
+
+void test(int coin) {
+  clang_analyzer_eval(C(3).getX() == 3);
+#ifdef TEMPORARY_DTORS
+  // expected-warning@-2{{TRUE}}
+#else
+  // expected-warning@-4{{UNKNOWN}}
+#endif
+
+  const C  = coin ? C(1) : C(2);
+  if (coin) {
+clang_analyzer_eval(c1.getX() == 1);
+#ifdef TEMPORARY_DTORS
+  // expected-warning@-2{{TRUE}}
+#else
+  // expected-warning@-4{{UNKNOWN}}
+#endif
+  } else {
+clang_analyzer_eval(c1.getX() == 2);
+#ifdef TEMPORARY_DTORS
+  // expected-warning@-2{{TRUE}}
+#else
+  // expected-warning@-4{{UNKNOWN}}
+#endif
+  }
+
+  C c2 = coin ? C(1) : C(2);
+  if (coin) {
+clang_analyzer_eval(c2.getX() == 1);
+#ifdef TEMPORARY_DTORS
+  // expected-warning@-2{{TRUE}}
+#else
+  // expected-warning@-4{{UNKNOWN}}
+#endif
+  } else {
+clang_analyzer_eval(c2.getX() == 2);
+#ifdef TEMPORARY_DTORS
+  // expected-warning@-2{{TRUE}}
+#else
+  // expected-warning@-4{{UNKNOWN}}
+#endif
+  }
+}
+
+} // namespace test_temporary_object_expr
Index: lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
===
--- lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
+++ lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
@@ -137,6 +137,9 @@
   } else if (auto *RS =