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 &c1 = 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<ReturnStmt>(TriggerStmt)) {
         CallOpts.IsTemporaryCtorOrDtor = true;
         return MRMgr.getCXXTempObjectRegion(CE, LCtx);
+      } else if (auto *BTE = dyn_cast<CXXBindTemporaryExpr>(TriggerStmt)) {
+        CallOpts.IsTemporaryCtorOrDtor = true;
+        return MRMgr.getCXXTempObjectRegion(CE, LCtx);
       }
       // TODO: Consider other directly initialized elements.
     } else if (const CXXCtorInitializer *Init = CC->getTriggerInit()) {
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to