NoQ created this revision.
NoQ added reviewers: dcoughlin, xazax.hun, a.sidorin, george.karpenkov, szepet, 
rnkovacs.
Herald added subscribers: cfe-commits, baloghadamsoftware.

`CXXBindTemporaryExpr ` is used for attaching the destructor of the temporary 
object to it.

If the object is lifetime-extended (which is indicated by the surrounding 
`MaterializeTemporaryExpr`'s storage duration property), then it doesn't 
require a temporary object destructor; it'll instead be destroyed automatically.

Remove `CXXBindTemporaryExpr` completely from the `ConstructionContext` in this 
case, instead of making clients take care of it.


Repository:
  rC Clang

https://reviews.llvm.org/D47667

Files:
  lib/Analysis/ConstructionContext.cpp
  lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
  test/Analysis/auto-obj-dtors-cfg-output.cpp
  test/Analysis/cfg-rich-constructors.cpp
  test/Analysis/temp-obj-dtors-cfg-output.cpp

Index: test/Analysis/temp-obj-dtors-cfg-output.cpp
===================================================================
--- test/Analysis/temp-obj-dtors-cfg-output.cpp
+++ test/Analysis/temp-obj-dtors-cfg-output.cpp
@@ -857,7 +857,7 @@
 // CHECK:     3: [B11.2] (ImplicitCastExpr, NoOp, const class A)
 // CHECK:     4: [B11.3]
 // WARNINGS:     5: [B11.4] (CXXConstructExpr, class A)
-// ANALYZER:     5: [B11.4] (CXXConstructExpr, [B11.6], [B10.3], class A)
+// ANALYZER:     5: [B11.4] (CXXConstructExpr, [B10.3], class A)
 // CHECK:     6: [B11.5] (BindTemporary)
 // CHECK:     Preds (1): B13
 // CHECK:     Succs (1): B10
@@ -878,7 +878,7 @@
 // CHECK:    12: [B12.11] (ImplicitCastExpr, NoOp, const class A)
 // CHECK:    13: [B12.12]
 // WARNINGS:    14: [B12.13] (CXXConstructExpr, class A)
-// ANALYZER:    14: [B12.13] (CXXConstructExpr, [B12.15], [B10.3], class A)
+// ANALYZER:    14: [B12.13] (CXXConstructExpr, [B10.3], class A)
 // CHECK:    15: [B12.14] (BindTemporary)
 // CHECK:     Preds (1): B13
 // CHECK:     Succs (1): B10
@@ -1104,7 +1104,7 @@
 // CHECK:     Succs (1): B1
 // CHECK:   [B1]
 // WARNINGS:     1: A() (CXXConstructExpr, class A)
-// ANALYZER:     1: A() (CXXConstructExpr, [B1.2], [B1.4], class A)
+// ANALYZER:     1: A() (CXXConstructExpr, [B1.4], class A)
 // CHECK:     2: [B1.1] (BindTemporary)
 // CHECK:     3: [B1.2] (ImplicitCastExpr, NoOp, const class A)
 // CHECK:     4: [B1.3]
@@ -1150,7 +1150,7 @@
 // CHECK:     1: A::make
 // CHECK:     2: [B1.1] (ImplicitCastExpr, FunctionToPointerDecay, class A (*)(void))
 // WARNINGS:     3: [B1.2]()
-// ANALYZER:     3: [B1.2]() (CXXRecordTypedCall, [B1.4], [B1.6])
+// ANALYZER:     3: [B1.2]() (CXXRecordTypedCall, [B1.6])
 // CHECK:     4: [B1.3] (BindTemporary)
 // CHECK:     5: [B1.4] (ImplicitCastExpr, NoOp, const class A)
 // CHECK:     6: [B1.5]
Index: test/Analysis/cfg-rich-constructors.cpp
===================================================================
--- test/Analysis/cfg-rich-constructors.cpp
+++ test/Analysis/cfg-rich-constructors.cpp
@@ -572,7 +572,7 @@
 
 // CHECK: void referenceVariableWithConstructor()
 // CHECK:          1: 0
-// CHECK-NEXT:     2: [B1.1] (CXXConstructExpr, [B1.3], [B1.4], const class temporary_object_expr_with_dtors::D)
+// CHECK-NEXT:     2: [B1.1] (CXXConstructExpr, [B1.4], const class temporary_object_expr_with_dtors::D)
 // CHECK-NEXT:     3: [B1.2] (BindTemporary)
 // CHECK-NEXT:     4: [B1.3]
 // CHECK-NEXT:     5: const temporary_object_expr_with_dtors::D &d(0);
@@ -582,7 +582,7 @@
 }
 
 // CHECK: void referenceVariableWithInitializer()
-// CHECK:          1: temporary_object_expr_with_dtors::D() (CXXConstructExpr, [B1.2], [B1.4], class temporary_object_expr_with_dtors::D)
+// CHECK:          1: temporary_object_expr_with_dtors::D() (CXXConstructExpr, [B1.4], class temporary_object_expr_with_dtors::D)
 // CHECK-NEXT:     2: [B1.1] (BindTemporary)
 // CHECK-NEXT:     3: [B1.2] (ImplicitCastExpr, NoOp, const class temporary_object_expr_with_dtors::D)
 // CHECK-NEXT:     4: [B1.3]
@@ -612,16 +612,16 @@
 // CXX11-NEXT:     4: [B5.3] (BindTemporary)
 // CXX11-NEXT:     5: [B5.4] (ImplicitCastExpr, NoOp, const class temporary_object_expr_with_dtors::D)
 // CXX11-NEXT:     6: [B5.5]
-// CXX11-NEXT:     7: [B5.6] (CXXConstructExpr, [B5.8], [B4.3], class temporary_object_expr_with_dtors::D)
+// CXX11-NEXT:     7: [B5.6] (CXXConstructExpr, [B4.3], class temporary_object_expr_with_dtors::D)
 // CXX11-NEXT:     8: [B5.7] (BindTemporary)
 // CXX11:        [B6]
 // CXX11-NEXT:     1: 0
 // CXX11-NEXT:     2: [B6.1] (CXXConstructExpr, [B6.3], [B6.6], [B6.7], class temporary_object_expr_with_dtors::D)
 // CXX11-NEXT:     3: [B6.2] (BindTemporary)
 // CXX11-NEXT:     4: temporary_object_expr_with_dtors::D([B6.3]) (CXXFunctionalCastExpr, ConstructorConversion, class temporary_object_expr_with_dtors::D)
 // CXX11-NEXT:     5: [B6.4] (ImplicitCastExpr, NoOp, const class temporary_object_expr_with_dtors::D)
 // CXX11-NEXT:     6: [B6.5]
-// CXX11-NEXT:     7: [B6.6] (CXXConstructExpr, [B6.8], [B4.3], class temporary_object_expr_with_dtors::D)
+// CXX11-NEXT:     7: [B6.6] (CXXConstructExpr, [B4.3], class temporary_object_expr_with_dtors::D)
 // CXX11-NEXT:     8: [B6.7] (BindTemporary)
 // CXX11:        [B7]
 // CXX11-NEXT:     1: coin
@@ -636,11 +636,11 @@
 // CXX17:        [B2]
 // CXX17-NEXT:     1: D::get
 // CXX17-NEXT:     2: [B2.1] (ImplicitCastExpr, FunctionToPointerDecay, class temporary_object_expr_with_dtors::D (*)(void))
-// CXX17-NEXT:     3: [B2.2]() (CXXRecordTypedCall, [B2.4], [B1.3])
+// CXX17-NEXT:     3: [B2.2]() (CXXRecordTypedCall, [B1.3])
 // CXX17-NEXT:     4: [B2.3] (BindTemporary)
 // CXX17:        [B3]
 // CXX17-NEXT:     1: 0
-// CXX17-NEXT:     2: [B3.1] (CXXConstructExpr, [B3.3], [B1.3], class temporary_object_expr_with_dtors::D)
+// CXX17-NEXT:     2: [B3.1] (CXXConstructExpr, [B1.3], class temporary_object_expr_with_dtors::D)
 // CXX17-NEXT:     3: [B3.2] (BindTemporary)
 // CXX17-NEXT:     4: temporary_object_expr_with_dtors::D([B3.3]) (CXXFunctionalCastExpr, ConstructorConversion, class temporary_object_expr_with_dtors::D)
 // CXX17:        [B4]
@@ -653,7 +653,7 @@
 
 // CHECK: void referenceWithFunctionalCast()
 // CHECK:          1: 1
-// CHECK-NEXT:     2: [B1.1] (CXXConstructExpr, [B1.3], [B1.5], class temporary_object_expr_with_dtors::D)
+// CHECK-NEXT:     2: [B1.1] (CXXConstructExpr, [B1.5], class temporary_object_expr_with_dtors::D)
 // CHECK-NEXT:     3: [B1.2] (BindTemporary)
 // CHECK-NEXT:     4: temporary_object_expr_with_dtors::D([B1.3]) (CXXFunctionalCastExpr, ConstructorCon
 // CHECK-NEXT:     5: [B1.4]
Index: test/Analysis/auto-obj-dtors-cfg-output.cpp
===================================================================
--- test/Analysis/auto-obj-dtors-cfg-output.cpp
+++ test/Analysis/auto-obj-dtors-cfg-output.cpp
@@ -56,7 +56,7 @@
 // CHECK-NEXT:   4: [B1.3] (ImplicitCastExpr, NoOp, const class A)
 // CHECK-NEXT:   5: const A &b = a;
 // WARNINGS-NEXT:   6: A() (CXXConstructExpr, class A)
-// ANALYZER-NEXT:   6: A() (CXXConstructExpr, [B1.7], [B1.9], class A)
+// ANALYZER-NEXT:   6: A() (CXXConstructExpr, [B1.9], class A)
 // CHECK-NEXT:   7: [B1.6] (BindTemporary)
 // CHECK-NEXT:   8: [B1.7] (ImplicitCastExpr, NoOp, const class A)
 // CHECK-NEXT:   9: [B1.8]
@@ -78,7 +78,7 @@
 // CHECK:      [B1]
 // WARNINGS-NEXT:   1: A() (CXXConstructExpr, class A)
 // CXX98-ANALYZER-NEXT:   1: A() (CXXConstructExpr, [B1.2], class A)
-// CXX11-ANALYZER-NEXT:   1: A() (CXXConstructExpr, [B1.2], [B1.3], class A)
+// CXX11-ANALYZER-NEXT:   1: A() (CXXConstructExpr, [B1.3], class A)
 // CHECK-NEXT:   2: [B1.1] (BindTemporary)
 // CXX98-NEXT:   3: [B1.2].x
 // CXX98-NEXT:   4: [B1.3]
@@ -102,7 +102,7 @@
 // CHECK:        [B1]
 // WARNINGS-NEXT:     1: A() (CXXConstructExpr, class A)
 // CXX98-ANALYZER-NEXT:     1: A() (CXXConstructExpr, [B1.2], class A)
-// CXX11-ANALYZER-NEXT:     1: A() (CXXConstructExpr, [B1.2], [B1.3], class A)
+// CXX11-ANALYZER-NEXT:     1: A() (CXXConstructExpr, [B1.3], class A)
 // CHECK-NEXT:     2: [B1.1] (BindTemporary)
 // CXX98-NEXT:     3: A::x
 // CXX98-NEXT:     4: &[B1.3]
@@ -130,20 +130,20 @@
 // CHECK-NEXT:     Succs (1): B1
 // CHECK:        [B1]
 // WARNINGS-NEXT:     1: A() (CXXConstructExpr, class A)
-// ANALYZER-NEXT:     1: A() (CXXConstructExpr, [B1.2], [B1.4], class A)
+// ANALYZER-NEXT:     1: A() (CXXConstructExpr, [B1.4], class A)
 // CHECK-NEXT:     2: [B1.1] (BindTemporary)
 // CHECK-NEXT:     3: [B1.2] (ImplicitCastExpr, NoOp, const class A)
 // CHECK-NEXT:     4: [B1.3]
 // CHECK-NEXT:     5: {[B1.4]}
 // CHECK-NEXT:     6: B b = {A()};
 // WARNINGS-NEXT:     7: A() (CXXConstructExpr, class A)
-// ANALYZER-NEXT:     7: A() (CXXConstructExpr, [B1.8], [B1.10], class A)
+// ANALYZER-NEXT:     7: A() (CXXConstructExpr, [B1.10], class A)
 // CHECK-NEXT:     8: [B1.7] (BindTemporary)
 // CHECK-NEXT:     9: [B1.8] (ImplicitCastExpr, NoOp, const class A)
 // CHECK-NEXT:    10: [B1.9]
 // CHECK-NEXT:    11: {[B1.10]}
 // WARNINGS-NEXT:    12: A() (CXXConstructExpr, class A)
-// ANALYZER-NEXT:    12: A() (CXXConstructExpr, [B1.13], [B1.15], class A)
+// ANALYZER-NEXT:    12: A() (CXXConstructExpr, [B1.15], class A)
 // CHECK-NEXT:    13: [B1.12] (BindTemporary)
 // CHECK-NEXT:    14: [B1.13] (ImplicitCastExpr, NoOp, const class A)
 // CHECK-NEXT:    15: [B1.14]
Index: lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
===================================================================
--- lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
+++ lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
@@ -215,6 +215,7 @@
       const auto *TCC = cast<TemporaryObjectConstructionContext>(CC);
       const CXXBindTemporaryExpr *BTE = TCC->getCXXBindTemporaryExpr();
       const MaterializeTemporaryExpr *MTE = TCC->getMaterializedTemporaryExpr();
+      SVal V = UnknownVal();
 
       if (MTE) {
         if (const ValueDecl *VD = MTE->getExtendingDecl()) {
@@ -228,19 +229,9 @@
             CallOpts.IsTemporaryLifetimeExtendedViaAggregate = true;
           }
         }
-      }
-
-      SVal V = UnknownVal();
-      if (MTE) {
-        if (MTE->getStorageDuration() != SD_FullExpression) {
-          // If the temporary is lifetime-extended, don't save the BTE,
-          // because we don't need a temporary destructor, but an automatic
-          // destructor.
-          BTE = nullptr;
-
-          if (MTE->getStorageDuration() == SD_Static ||
-              MTE->getStorageDuration() == SD_Thread)
-            V = loc::MemRegionVal(MRMgr.getCXXStaticTempObjectRegion(E));
+        if (MTE->getStorageDuration() == SD_Static ||
+            MTE->getStorageDuration() == SD_Thread) {
+          V = loc::MemRegionVal(MRMgr.getCXXStaticTempObjectRegion(E));
         }
       }
 
Index: lib/Analysis/ConstructionContext.cpp
===================================================================
--- lib/Analysis/ConstructionContext.cpp
+++ lib/Analysis/ConstructionContext.cpp
@@ -76,6 +76,13 @@
         // both destruction and materialization info attached to it in the AST.
         if ((MTE = dyn_cast<MaterializeTemporaryExpr>(
                  ParentLayer->getTriggerStmt()))) {
+          if (MTE->getStorageDuration() != SD_FullExpression) {
+            // If the temporary is lifetime-extended, don't save the BTE,
+            // because we don't need a temporary destructor, but an automatic
+            // destructor.
+            BTE = nullptr;
+          }
+
           // Handle pre-C++17 copy and move elision.
           const CXXConstructExpr *ElidedCE = nullptr;
           const ConstructionContext *ElidedCC = nullptr;
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to