]> granicus.if.org Git - clang/commitdiff
[CFG] Provide construction contexts for temporaries in conditional operators.
authorArtem Dergachev <artem.dergachev@gmail.com>
Sat, 24 Feb 2018 03:10:15 +0000 (03:10 +0000)
committerArtem Dergachev <artem.dergachev@gmail.com>
Sat, 24 Feb 2018 03:10:15 +0000 (03:10 +0000)
When a lifetime-extended temporary is on a branch of a conditional operator,
materialization of such temporary occurs after the condition is resolved.

This change allows us to understand, by including the MaterializeTemporaryExpr
in the construction context, the target for temporary materialization in such
cases.

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

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@326019 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Analysis/CFG.cpp
test/Analysis/cfg-rich-constructors.cpp
test/Analysis/temp-obj-dtors-cfg-output.cpp

index 4c6eff300f80a33e76bce40425a46970030e7e96..7ad6fbbf90bd80b2abb57c6916128f3105e8c176 100644 (file)
@@ -1187,6 +1187,9 @@ void CFGBuilder::findConstructionContexts(
         ConstructionContext::create(cfg->getBumpVectorContext(), BTE,
                                     ContextSoFar),
         BTE->getSubExpr());
+  } else if (auto *CO = dyn_cast<ConditionalOperator>(Child)) {
+    findConstructionContexts(ContextSoFar, CO->getLHS());
+    findConstructionContexts(ContextSoFar, CO->getRHS());
   }
 }
 
index 6dee2dc4dfb3726176bc0044dcd7ca06f0e6a454..9613fa2fbead7c2bfa4f02dbc38231121c142843 100644 (file)
@@ -105,7 +105,6 @@ void simpleVariableInitializedByValue() {
   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 @@ void simpleVariableInitializedByValue() {
 // 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 @@ void referenceVariableWithInitializer() {
   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 @@ void referenceVariableWithInitializer() {
 // 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,7 +439,7 @@ void referenceVariableWithInitializer() {
 // 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
@@ -450,7 +448,7 @@ void referenceVariableWithInitializer() {
 // 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 referenceVariableWithTernaryOperator(bool coin) {
 void referenceWithFunctionalCast() {
   D &&d = D(1);
 }
+
+// Test the condition constructor, we don't care about branch constructors here.
+// CHECK: void constructorInTernaryCondition()
+// CHECK:          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 7d3a4002f2fadbc3f5889f4650e1757c1d674222..d17c5beff4a641dddd90ad9a6dba5e7139cb5bdd 100644 (file)
@@ -537,7 +537,7 @@ int testConsistencyNestedNormalReturn(bool value) {
 // 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 @@ int testConsistencyNestedNormalReturn(bool value) {
 // 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 @@ int testConsistencyNestedNormalReturn(bool value) {
 // 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 @@ int testConsistencyNestedNormalReturn(bool value) {
 // 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 @@ int testConsistencyNestedNormalReturn(bool value) {
 // 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 @@ int testConsistencyNestedNormalReturn(bool value) {
 // 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