diff options
| author | Artem Dergachev <artem.dergachev@gmail.com> | 2018-02-24 02:05:11 +0000 |
|---|---|---|
| committer | Artem Dergachev <artem.dergachev@gmail.com> | 2018-02-24 02:05:11 +0000 |
| commit | ceb7d91a484982cfca84c102cfddb90b3963c46e (patch) | |
| tree | cc1383f10e70f864e3f97dc2ecc1cde4ae5c4698 /clang | |
| parent | f43ac4c9acb023ac9fd44e2836d852dc5ce9d0e2 (diff) | |
| download | bcm5719-llvm-ceb7d91a484982cfca84c102cfddb90b3963c46e.tar.gz bcm5719-llvm-ceb7d91a484982cfca84c102cfddb90b3963c46e.zip | |
[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
Diffstat (limited to 'clang')
| -rw-r--r-- | clang/lib/Analysis/CFG.cpp | 2 | ||||
| -rw-r--r-- | clang/test/Analysis/cfg-rich-constructors.cpp | 38 |
2 files changed, 32 insertions, 8 deletions
diff --git a/clang/lib/Analysis/CFG.cpp b/clang/lib/Analysis/CFG.cpp index 13804746b27..0d100397c0c 100644 --- a/clang/lib/Analysis/CFG.cpp +++ b/clang/lib/Analysis/CFG.cpp @@ -1177,6 +1177,8 @@ void CFGBuilder::findConstructionContexts( consumeConstructionContext(ContextSoFar, CE); } else if (auto *Cleanups = dyn_cast<ExprWithCleanups>(Child)) { findConstructionContexts(ContextSoFar, Cleanups->getSubExpr()); + } else if (auto *Cast = dyn_cast<CXXFunctionalCastExpr>(Child)) { + findConstructionContexts(ContextSoFar, Cast->getSubExpr()); } else if (auto *BTE = dyn_cast<CXXBindTemporaryExpr>(Child)) { findConstructionContexts( ConstructionContext::create(cfg->getBumpVectorContext(), BTE, diff --git a/clang/test/Analysis/cfg-rich-constructors.cpp b/clang/test/Analysis/cfg-rich-constructors.cpp index 5dadb6cd819..6333e327b36 100644 --- a/clang/test/Analysis/cfg-rich-constructors.cpp +++ b/clang/test/Analysis/cfg-rich-constructors.cpp @@ -105,7 +105,7 @@ void simpleVariableInitializedByValue() { 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: [B1] // CHECK-NEXT: 1: [B4.2] ? [B2.5] : [B3.6] @@ -121,7 +121,7 @@ void simpleVariableInitializedByValue() { // CHECK: [B3] // CHECK-NEXT: 1: 0 // 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: 5: [B3.4] // CHECK-NEXT: 6: [B3.5] (CXXConstructExpr, class C) @@ -133,6 +133,18 @@ void simpleVariableWithTernaryOperator(bool coin) { 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: 1: 0 // CHECK-NEXT: 2: [B1.1] (ImplicitCastExpr, NullToPointer, class C *) @@ -153,7 +165,7 @@ void referenceVariableWithInitializer() { 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: [B1] // CHECK-NEXT: 1: [B4.2] ? [B2.5] : [B3.6] @@ -169,7 +181,7 @@ void referenceVariableWithInitializer() { // CHECK: [B3] // CHECK-NEXT: 1: 0 // 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: 5: [B3.4] // CHECK-NEXT: 6: [B3.5] (CXXConstructExpr, class C) @@ -275,11 +287,10 @@ C returnTemporary() { return C(); } -// TODO: Should find construction targets for the first constructor as well. // CHECK: C returnTemporaryWithArgument() // CHECK: 1: nullptr // 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: 5: [B1.4] // CHECK-NEXT: 6: [B1.5] (CXXConstructExpr, [B1.7], class C) @@ -299,13 +310,12 @@ C returnTemporaryConstructedByFunction() { return C::get(); } -// TODO: Should find construction targets for the first constructor as well. // CHECK: C returnChainOfCopies() // CHECK: 1: C::get // CHECK-NEXT: 2: [B1.1] (ImplicitCastExpr, FunctionToPointerDecay, class C (*)(void)) // CHECK-NEXT: 3: [B1.2]() // 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: 7: [B1.6] // CHECK-NEXT: 8: [B1.7] (CXXConstructExpr, [B1.9], class C) @@ -450,4 +460,16 @@ void referenceVariableWithInitializer() { void referenceVariableWithTernaryOperator(bool coin) { 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 |

