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( 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; Index: lib/StaticAnalyzer/Core/ExprEngineCXX.cpp =================================================================== --- lib/StaticAnalyzer/Core/ExprEngineCXX.cpp +++ lib/StaticAnalyzer/Core/ExprEngineCXX.cpp @@ -217,6 +217,7 @@ const auto *TCC = cast(CC); const CXXBindTemporaryExpr *BTE = TCC->getCXXBindTemporaryExpr(); const MaterializeTemporaryExpr *MTE = TCC->getMaterializedTemporaryExpr(); + SVal V = UnknownVal(); if (MTE) { if (const ValueDecl *VD = MTE->getExtendingDecl()) { @@ -230,14 +231,6 @@ CallOpts.IsTemporaryLifetimeExtendedViaAggregate = true; } } - } - - SVal V = UnknownVal(); - if (MTE && 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) 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: test/Analysis/cfg-rich-constructors.cpp =================================================================== --- test/Analysis/cfg-rich-constructors.cpp +++ test/Analysis/cfg-rich-constructors.cpp @@ -597,7 +597,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); @@ -607,7 +607,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] @@ -638,7 +638,7 @@ // 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 @@ -648,7 +648,7 @@ // 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 @@ -663,11 +663,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] @@ -680,7 +680,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/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]