NoQ created this revision. NoQ added reviewers: dcoughlin, xazax.hun, a.sidorin, george.karpenkov, szepet. Herald added subscribers: cfe-commits, rnkovacs.
Similarly to https://reviews.llvm.org/D43480 and https://reviews.llvm.org/D43481, we need to skip the ternary conditional operator `... ? ... : ...` when it stands between the `MaterializeTemporaryExpr` and the `CXXBindTemporaryExpr`. This allows us to find the common materialization target (`MaterializeTemporaryExpr`) for the two branches of the conditional operator, which would later be used for improving lifetime extension support in the analyzer, but for now the change has no immediate effect on the analyzer. GNU binary conditional operator is not supported yet. Repository: rC Clang https://reviews.llvm.org/D43483 Files: lib/Analysis/CFG.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 @@ -537,7 +537,7 @@ // CHECK: 3: [B8.2] (ImplicitCastExpr, NoOp, const class A) // CHECK: 4: [B8.3] // WARNINGS: 5: [B8.4] (CXXConstructExpr, class A) -// ANALYZER: 5: [B8.4] (CXXConstructExpr, [B8.6], class A) +// ANALYZER: 5: [B8.4] (CXXConstructExpr, [B8.6], [B7.3], class A) // CHECK: 6: [B8.5] (BindTemporary) // CHECK: Preds (1): B10 // CHECK: Succs (1): B7 @@ -558,7 +558,7 @@ // CHECK: 12: [B9.11] (ImplicitCastExpr, NoOp, const class A) // CHECK: 13: [B9.12] // WARNINGS: 14: [B9.13] (CXXConstructExpr, class A) -// ANALYZER: 14: [B9.13] (CXXConstructExpr, [B9.15], class A) +// ANALYZER: 14: [B9.13] (CXXConstructExpr, [B9.15], [B7.3], class A) // CHECK: 15: [B9.14] (BindTemporary) // CHECK: Preds (1): B10 // CHECK: Succs (1): B7 @@ -776,7 +776,7 @@ // CHECK: 3: [B5.2] (ImplicitCastExpr, NoOp, const class A) // CHECK: 4: [B5.3] // WARNINGS: 5: [B5.4] (CXXConstructExpr, class A) -// ANALYZER: 5: [B5.4] (CXXConstructExpr, [B5.6], class A) +// ANALYZER: 5: [B5.4] (CXXConstructExpr, [B5.6], [B4.3], class A) // CHECK: 6: [B5.5] (BindTemporary) // CHECK: Preds (1): B7 // CHECK: Succs (1): B4 @@ -797,7 +797,7 @@ // CHECK: 12: [B6.11] (ImplicitCastExpr, NoOp, const class A) // CHECK: 13: [B6.12] // WARNINGS: 14: [B6.13] (CXXConstructExpr, class A) -// ANALYZER: 14: [B6.13] (CXXConstructExpr, [B6.15], class A) +// ANALYZER: 14: [B6.13] (CXXConstructExpr, [B6.15], [B4.3], class A) // CHECK: 15: [B6.14] (BindTemporary) // CHECK: Preds (1): B7 // CHECK: Succs (1): B4 @@ -839,7 +839,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], class A) +// ANALYZER: 5: [B11.4] (CXXConstructExpr, [B11.6], [B10.3], class A) // CHECK: 6: [B11.5] (BindTemporary) // CHECK: Preds (1): B13 // CHECK: Succs (1): B10 @@ -860,7 +860,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], class A) +// ANALYZER: 14: [B12.13] (CXXConstructExpr, [B12.15], [B10.3], class A) // CHECK: 15: [B12.14] (BindTemporary) // CHECK: Preds (1): B13 // CHECK: Succs (1): B10 Index: test/Analysis/cfg-rich-constructors.cpp =================================================================== --- test/Analysis/cfg-rich-constructors.cpp +++ test/Analysis/cfg-rich-constructors.cpp @@ -105,7 +105,6 @@ C c = C::get(); } -// TODO: Should find construction target for the elidable constructors as well. // CHECK: void simpleVariableWithTernaryOperator(bool coin) // CHECK: [B1] // CHECK-NEXT: 1: [B4.2] ? [B2.5] : [B3.6] @@ -117,14 +116,14 @@ // CHECK-NEXT: 2: [B2.1] (ImplicitCastExpr, FunctionToPointerDecay, class C (*)(void)) // CHECK-NEXT: 3: [B2.2]() // CHECK-NEXT: 4: [B2.3] -// CHECK-NEXT: 5: [B2.4] (CXXConstructExpr, class C) +// CHECK-NEXT: 5: [B2.4] (CXXConstructExpr, [B1.2], class C) // CHECK: [B3] // CHECK-NEXT: 1: 0 // CHECK-NEXT: 2: [B3.1] (ImplicitCastExpr, NullToPointer, class C *) // CHECK-NEXT: 3: [B3.2] (CXXConstructExpr, [B3.5], class C) // CHECK-NEXT: 4: C([B3.3]) (CXXFunctionalCastExpr, ConstructorConversion, class C) // CHECK-NEXT: 5: [B3.4] -// CHECK-NEXT: 6: [B3.5] (CXXConstructExpr, class C) +// CHECK-NEXT: 6: [B3.5] (CXXConstructExpr, [B1.2], class C) // CHECK: [B4] // CHECK-NEXT: 1: coin // CHECK-NEXT: 2: [B4.1] (ImplicitCastExpr, LValueToRValue, _Bool) @@ -164,7 +163,6 @@ const C &c = C(); } -// TODO: Should find construction targets for the elidable constructors as well. // CHECK: void referenceVariableWithTernaryOperator(bool coin) // CHECK: [B1] // CHECK-NEXT: 1: [B4.2] ? [B2.5] : [B3.6] @@ -176,14 +174,14 @@ // CHECK-NEXT: 2: [B2.1] (ImplicitCastExpr, FunctionToPointerDecay, class C (*)(void)) // CHECK-NEXT: 3: [B2.2]() // CHECK-NEXT: 4: [B2.3] -// CHECK-NEXT: 5: [B2.4] (CXXConstructExpr, class C) +// CHECK-NEXT: 5: [B2.4] (CXXConstructExpr, [B1.3], class C) // CHECK: [B3] // CHECK-NEXT: 1: 0 // CHECK-NEXT: 2: [B3.1] (ImplicitCastExpr, NullToPointer, class C *) // CHECK-NEXT: 3: [B3.2] (CXXConstructExpr, [B3.5], class C) // CHECK-NEXT: 4: C([B3.3]) (CXXFunctionalCastExpr, ConstructorConversion, class C) // CHECK-NEXT: 5: [B3.4] -// CHECK-NEXT: 6: [B3.5] (CXXConstructExpr, class C) +// CHECK-NEXT: 6: [B3.5] (CXXConstructExpr, [B1.3], class C) // CHECK: [B4] // CHECK-NEXT: 1: coin // CHECK-NEXT: 2: [B4.1] (ImplicitCastExpr, LValueToRValue, _Bool) @@ -441,16 +439,16 @@ // CHECK-NEXT: 4: [B5.3] (BindTemporary) // CHECK-NEXT: 5: [B5.4] (ImplicitCastExpr, NoOp, const class temporary_object_expr_with_dtors::D) // CHECK-NEXT: 6: [B5.5] -// CHECK-NEXT: 7: [B5.6] (CXXConstructExpr, [B5.8], class temporary_object_expr_with_dtors::D) +// CHECK-NEXT: 7: [B5.6] (CXXConstructExpr, [B5.8], [B4.3], class temporary_object_expr_with_dtors::D) // CHECK-NEXT: 8: [B5.7] (BindTemporary) // CHECK: [B6] // CHECK-NEXT: 1: 0 // CHECK-NEXT: 2: [B6.1] (CXXConstructExpr, [B6.3], [B6.6], class temporary_object_expr_with_dtors::D) // CHECK-NEXT: 3: [B6.2] (BindTemporary) // CHECK-NEXT: 4: temporary_object_expr_with_dtors::D([B6.3]) (CXXFunctionalCastExpr, ConstructorConversion, class temporary_object_expr_with_dtors::D) // CHECK-NEXT: 5: [B6.4] (ImplicitCastExpr, NoOp, const class temporary_object_expr_with_dtors::D) // CHECK-NEXT: 6: [B6.5] -// CHECK-NEXT: 7: [B6.6] (CXXConstructExpr, [B6.8], class temporary_object_expr_with_dtors::D) +// CHECK-NEXT: 7: [B6.6] (CXXConstructExpr, [B6.8], [B4.3], class temporary_object_expr_with_dtors::D) // CHECK-NEXT: 8: [B6.7] (BindTemporary) // CHECK: [B7] // CHECK-NEXT: 1: coin @@ -471,4 +469,19 @@ void referenceWithFunctionalCast() { D &&d = D(1); } + +// Test the condition constructor, we don't care about branch constructors here. +// CHECK-NEXT: void constructorInTernaryCondition() +// CHECK-NEXT: 1: 1 +// CHECK-NEXT: 2: [B7.1] (CXXConstructExpr, [B7.3], class temporary_object_expr_with_dtors::D) +// CHECK-NEXT: 3: [B7.2] (BindTemporary) +// CHECK-NEXT: 4: temporary_object_expr_with_dtors::D([B7.3]) (CXXFunctionalCastExpr, ConstructorConv +// CHECK-NEXT: 5: [B7.4] (ImplicitCastExpr, NoOp, const class temporary_object_expr_with_dtors::D) +// CHECK-NEXT: 6: [B7.5].operator bool +// CHECK-NEXT: 7: [B7.5] +// CHECK-NEXT: 8: [B7.7] (ImplicitCastExpr, UserDefinedConversion, _Bool) +// CHECK-NEXT: T: [B7.8] ? ... : ... +void constructorInTernaryCondition() { + const D &d = D(1) ? D(2) : D(3); +} } // end namespace temporary_object_expr_with_dtors Index: lib/Analysis/CFG.cpp =================================================================== --- lib/Analysis/CFG.cpp +++ lib/Analysis/CFG.cpp @@ -1178,6 +1178,9 @@ ConstructionContext::create(cfg->getBumpVectorContext(), BTE, ContextSoFar), BTE->getSubExpr()); + } else if (auto *CO = dyn_cast<ConditionalOperator>(Child)) { + findConstructionContexts(ContextSoFar, CO->getLHS()); + findConstructionContexts(ContextSoFar, CO->getRHS()); } }
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits