r325211 - [analyzer] Inline constructors for destroyable temporaries.

Artem Dergachev via cfe-commits cfe-commits at lists.llvm.org
Wed Feb 14 19:26:43 PST 2018


Author: dergachev
Date: Wed Feb 14 19:26:43 2018
New Revision: 325211

URL: http://llvm.org/viewvc/llvm-project?rev=325211&view=rev
Log:
[analyzer] Inline constructors for destroyable temporaries.

Since r325210, in cfg-temporary-dtors mode, we can rely on the CFG to tell us
that we're indeed constructing a temporary, so we can trivially construct a
temporary region and inline the constructor.

Much like r325202, this is only done under the off-by-default
cfg-temporary-dtors flag because the temporary destructor, even if available,
will not be inlined and won't have the correct object value (target region).
Unless this is fixed, it is quite unsafe to inline the constructor.

If the temporary is lifetime-extended, the destructor would be an automatic
destructor, which would be evaluated with a "correct" target region - modulo
the series of incorrect relocations performed during the lifetime extension.
It means that at least, values within the object are guaranteed to be properly
escaped or invalidated.

Differential Revision: https://reviews.llvm.org/D43062

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

Modified: cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp?rev=325211&r1=325210&r2=325211&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp Wed Feb 14 19:26:43 2018
@@ -148,6 +148,9 @@ ExprEngine::getRegionForConstructedObjec
         // construction context that'd give us the right temporary expression.
         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()) {

Modified: cfe/trunk/test/Analysis/temporaries.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/temporaries.cpp?rev=325211&r1=325210&r2=325211&view=diff
==============================================================================
--- cfe/trunk/test/Analysis/temporaries.cpp (original)
+++ cfe/trunk/test/Analysis/temporaries.cpp Wed Feb 14 19:26:43 2018
@@ -607,22 +607,37 @@ void test() {
   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 at -3{{TRUE}}
+  // expected-warning at -3{{TRUE}}
+#else
+  // expected-warning at -6{{UNKNOWN}}
+  // expected-warning at -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 at -3{{TRUE}}
+  // expected-warning at -3{{TRUE}}
+#else
+  // expected-warning at -6{{UNKNOWN}}
+  // expected-warning at -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 at -3{{TRUE}}
+  // expected-warning at -3{{TRUE}}
+#else
+  // expected-warning at -6{{UNKNOWN}}
+  // expected-warning at -6{{UNKNOWN}}
+#endif
 
 #if __cplusplus >= 201103L
 
@@ -683,10 +698,84 @@ void test() {
   // expected-warning at -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 at -3{{TRUE}}
+  // expected-warning at -3{{TRUE}}
+#else
+  // expected-warning at -6{{UNKNOWN}}
+  // expected-warning at -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 at -2{{TRUE}}
+#else
+  // expected-warning at -4{{UNKNOWN}}
+#endif
+
+  const C &c1 = coin ? C(1) : C(2);
+  if (coin) {
+    clang_analyzer_eval(c1.getX() == 1);
+#ifdef TEMPORARY_DTORS
+  // expected-warning at -2{{TRUE}}
+#else
+  // expected-warning at -4{{UNKNOWN}}
+#endif
+  } else {
+    clang_analyzer_eval(c1.getX() == 2);
+#ifdef TEMPORARY_DTORS
+  // expected-warning at -2{{TRUE}}
+#else
+  // expected-warning at -4{{UNKNOWN}}
+#endif
+  }
+
+  C c2 = coin ? C(1) : C(2);
+  if (coin) {
+    clang_analyzer_eval(c2.getX() == 1);
+#ifdef TEMPORARY_DTORS
+  // expected-warning at -2{{TRUE}}
+#else
+  // expected-warning at -4{{UNKNOWN}}
+#endif
+  } else {
+    clang_analyzer_eval(c2.getX() == 2);
+#ifdef TEMPORARY_DTORS
+  // expected-warning at -2{{TRUE}}
+#else
+  // expected-warning at -4{{UNKNOWN}}
+#endif
+  }
+}
+
+} // namespace test_temporary_object_expr




More information about the cfe-commits mailing list