[CFG] Provide construction contexts for functional cast-like constructors.

When a constructor of a temporary with a single argument is treated
as a functional cast expression, skip the functional cast expression
and provide the correct construction context for the temporary.

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

llvm-svn: 326015
This commit is contained in:
Artem Dergachev 2018-02-24 02:05:11 +00:00
parent f43ac4c9ac
commit ceb7d91a48
2 changed files with 32 additions and 8 deletions

View File

@ -1177,6 +1177,8 @@ void CFGBuilder::findConstructionContexts(
consumeConstructionContext(ContextSoFar, CE); consumeConstructionContext(ContextSoFar, CE);
} else if (auto *Cleanups = dyn_cast<ExprWithCleanups>(Child)) { } else if (auto *Cleanups = dyn_cast<ExprWithCleanups>(Child)) {
findConstructionContexts(ContextSoFar, Cleanups->getSubExpr()); findConstructionContexts(ContextSoFar, Cleanups->getSubExpr());
} else if (auto *Cast = dyn_cast<CXXFunctionalCastExpr>(Child)) {
findConstructionContexts(ContextSoFar, Cast->getSubExpr());
} else if (auto *BTE = dyn_cast<CXXBindTemporaryExpr>(Child)) { } else if (auto *BTE = dyn_cast<CXXBindTemporaryExpr>(Child)) {
findConstructionContexts( findConstructionContexts(
ConstructionContext::create(cfg->getBumpVectorContext(), BTE, ConstructionContext::create(cfg->getBumpVectorContext(), BTE,

View File

@ -105,7 +105,7 @@ void simpleVariableInitializedByValue() {
C c = C::get(); C c = C::get();
} }
// TODO: Should find construction target for the three temporaries as well. // TODO: Should find construction target for the elidable constructors as well.
// CHECK: void simpleVariableWithTernaryOperator(bool coin) // CHECK: void simpleVariableWithTernaryOperator(bool coin)
// CHECK: [B1] // CHECK: [B1]
// CHECK-NEXT: 1: [B4.2] ? [B2.5] : [B3.6] // CHECK-NEXT: 1: [B4.2] ? [B2.5] : [B3.6]
@ -121,7 +121,7 @@ void simpleVariableInitializedByValue() {
// CHECK: [B3] // CHECK: [B3]
// CHECK-NEXT: 1: 0 // CHECK-NEXT: 1: 0
// CHECK-NEXT: 2: [B3.1] (ImplicitCastExpr, NullToPointer, class C *) // CHECK-NEXT: 2: [B3.1] (ImplicitCastExpr, NullToPointer, class C *)
// CHECK-NEXT: 3: [B3.2] (CXXConstructExpr, class C) // CHECK-NEXT: 3: [B3.2] (CXXConstructExpr, [B3.5], class C)
// CHECK-NEXT: 4: C([B3.3]) (CXXFunctionalCastExpr, ConstructorConversion, class C) // CHECK-NEXT: 4: C([B3.3]) (CXXFunctionalCastExpr, ConstructorConversion, class C)
// CHECK-NEXT: 5: [B3.4] // CHECK-NEXT: 5: [B3.4]
// CHECK-NEXT: 6: [B3.5] (CXXConstructExpr, class C) // CHECK-NEXT: 6: [B3.5] (CXXConstructExpr, class C)
@ -133,6 +133,18 @@ void simpleVariableWithTernaryOperator(bool coin) {
C c = coin ? C::get() : C(0); C c = coin ? C::get() : C(0);
} }
// CHECK: void simpleVariableWithElidableCopy()
// CHECK: 1: 0
// CHECK-NEXT: 2: [B1.1] (ImplicitCastExpr, NullToPointer, class C *)
// CHECK-NEXT: 3: [B1.2] (CXXConstructExpr, [B1.5], class C)
// CHECK-NEXT: 4: C([B1.3]) (CXXFunctionalCastExpr, ConstructorConversion, class C)
// CHECK-NEXT: 5: [B1.4]
// CHECK-NEXT: 6: [B1.5] (CXXConstructExpr, [B1.7], class C)
// CHECK-NEXT: 7: C c = C(0);
void simpleVariableWithElidableCopy() {
C c = C(0);
}
// CHECK: void referenceVariableWithConstructor() // CHECK: void referenceVariableWithConstructor()
// CHECK: 1: 0 // CHECK: 1: 0
// CHECK-NEXT: 2: [B1.1] (ImplicitCastExpr, NullToPointer, class C *) // CHECK-NEXT: 2: [B1.1] (ImplicitCastExpr, NullToPointer, class C *)
@ -153,7 +165,7 @@ void referenceVariableWithInitializer() {
const C &c = C(); const C &c = C();
} }
// TODO: Should find construction targets here. // TODO: Should find construction targets for the elidable constructors as well.
// CHECK: void referenceVariableWithTernaryOperator(bool coin) // CHECK: void referenceVariableWithTernaryOperator(bool coin)
// CHECK: [B1] // CHECK: [B1]
// CHECK-NEXT: 1: [B4.2] ? [B2.5] : [B3.6] // CHECK-NEXT: 1: [B4.2] ? [B2.5] : [B3.6]
@ -169,7 +181,7 @@ void referenceVariableWithInitializer() {
// CHECK: [B3] // CHECK: [B3]
// CHECK-NEXT: 1: 0 // CHECK-NEXT: 1: 0
// CHECK-NEXT: 2: [B3.1] (ImplicitCastExpr, NullToPointer, class C *) // CHECK-NEXT: 2: [B3.1] (ImplicitCastExpr, NullToPointer, class C *)
// CHECK-NEXT: 3: [B3.2] (CXXConstructExpr, class C) // CHECK-NEXT: 3: [B3.2] (CXXConstructExpr, [B3.5], class C)
// CHECK-NEXT: 4: C([B3.3]) (CXXFunctionalCastExpr, ConstructorConversion, class C) // CHECK-NEXT: 4: C([B3.3]) (CXXFunctionalCastExpr, ConstructorConversion, class C)
// CHECK-NEXT: 5: [B3.4] // CHECK-NEXT: 5: [B3.4]
// CHECK-NEXT: 6: [B3.5] (CXXConstructExpr, class C) // CHECK-NEXT: 6: [B3.5] (CXXConstructExpr, class C)
@ -275,11 +287,10 @@ C returnTemporary() {
return C(); return C();
} }
// TODO: Should find construction targets for the first constructor as well.
// CHECK: C returnTemporaryWithArgument() // CHECK: C returnTemporaryWithArgument()
// CHECK: 1: nullptr // CHECK: 1: nullptr
// CHECK-NEXT: 2: [B1.1] (ImplicitCastExpr, NullToPointer, class C *) // CHECK-NEXT: 2: [B1.1] (ImplicitCastExpr, NullToPointer, class C *)
// CHECK-NEXT: 3: [B1.2] (CXXConstructExpr, class C) // CHECK-NEXT: 3: [B1.2] (CXXConstructExpr, [B1.5], class C)
// CHECK-NEXT: 4: C([B1.3]) (CXXFunctionalCastExpr, ConstructorConversion, class C) // CHECK-NEXT: 4: C([B1.3]) (CXXFunctionalCastExpr, ConstructorConversion, class C)
// CHECK-NEXT: 5: [B1.4] // CHECK-NEXT: 5: [B1.4]
// CHECK-NEXT: 6: [B1.5] (CXXConstructExpr, [B1.7], class C) // CHECK-NEXT: 6: [B1.5] (CXXConstructExpr, [B1.7], class C)
@ -299,13 +310,12 @@ C returnTemporaryConstructedByFunction() {
return C::get(); return C::get();
} }
// TODO: Should find construction targets for the first constructor as well.
// CHECK: C returnChainOfCopies() // CHECK: C returnChainOfCopies()
// CHECK: 1: C::get // CHECK: 1: C::get
// CHECK-NEXT: 2: [B1.1] (ImplicitCastExpr, FunctionToPointerDecay, class C (*)(void)) // CHECK-NEXT: 2: [B1.1] (ImplicitCastExpr, FunctionToPointerDecay, class C (*)(void))
// CHECK-NEXT: 3: [B1.2]() // CHECK-NEXT: 3: [B1.2]()
// CHECK-NEXT: 4: [B1.3] // CHECK-NEXT: 4: [B1.3]
// CHECK-NEXT: 5: [B1.4] (CXXConstructExpr, class C) // CHECK-NEXT: 5: [B1.4] (CXXConstructExpr, [B1.7], class C)
// CHECK-NEXT: 6: C([B1.5]) (CXXFunctionalCastExpr, ConstructorConversion, class C) // CHECK-NEXT: 6: C([B1.5]) (CXXFunctionalCastExpr, ConstructorConversion, class C)
// CHECK-NEXT: 7: [B1.6] // CHECK-NEXT: 7: [B1.6]
// CHECK-NEXT: 8: [B1.7] (CXXConstructExpr, [B1.9], class C) // CHECK-NEXT: 8: [B1.7] (CXXConstructExpr, [B1.9], class C)
@ -450,4 +460,16 @@ void referenceVariableWithInitializer() {
void referenceVariableWithTernaryOperator(bool coin) { void referenceVariableWithTernaryOperator(bool coin) {
const D &d = coin ? D::get() : D(0); const D &d = coin ? D::get() : D(0);
} }
// 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: 3: [B1.2] (BindTemporary)
// CHECK-NEXT: 4: temporary_object_expr_with_dtors::D([B1.3]) (CXXFunctionalCastExpr, ConstructorCon
// CHECK-NEXT: 5: [B1.4]
// CHECK-NEXT: 6: temporary_object_expr_with_dtors::D &&d = temporary_object_expr_with_dtors::D(1);
// CHECK-NEXT: 7: [B1.6].~D() (Implicit destructor)
void referenceWithFunctionalCast() {
D &&d = D(1);
}
} // end namespace temporary_object_expr_with_dtors } // end namespace temporary_object_expr_with_dtors