summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRichard Smith <richard-llvm@metafoo.co.uk>2017-05-11 18:58:24 +0000
committerRichard Smith <richard-llvm@metafoo.co.uk>2017-05-11 18:58:24 +0000
commit722363727d2953f62b5ccbf90da4218054583961 (patch)
treebff3a47f4fbfe1e7b7e2a0a5903c649a2a13973a
parentdbd6219f8197c2b95b33e7a83d02d87721eff649 (diff)
downloadbcm5719-llvm-722363727d2953f62b5ccbf90da4218054583961.tar.gz
bcm5719-llvm-722363727d2953f62b5ccbf90da4218054583961.zip
PR22877: When constructing an array via a constructor with a default argument
in list-initialization, run cleanups for the default argument after each iteration of the initialization loop. We previously only ran the destructor for any temporary once, at the end of the complete loop, rather than once per iteration! Re-commit of r302750, reverted in r302776. llvm-svn: 302817
-rw-r--r--clang/lib/CodeGen/CGExprAgg.cpp20
-rw-r--r--clang/test/CodeGenCXX/array-default-argument.cpp36
2 files changed, 50 insertions, 6 deletions
diff --git a/clang/lib/CodeGen/CGExprAgg.cpp b/clang/lib/CodeGen/CGExprAgg.cpp
index 49bbb4808ea..a05a088f091 100644
--- a/clang/lib/CodeGen/CGExprAgg.cpp
+++ b/clang/lib/CodeGen/CGExprAgg.cpp
@@ -512,12 +512,20 @@ void AggExprEmitter::EmitArrayInit(Address DestPtr, llvm::ArrayType *AType,
currentElement->addIncoming(element, entryBB);
// Emit the actual filler expression.
- LValue elementLV =
- CGF.MakeAddrLValue(Address(currentElement, elementAlign), elementType);
- if (filler)
- EmitInitializationToLValue(filler, elementLV);
- else
- EmitNullInitializationToLValue(elementLV);
+ {
+ // C++1z [class.temporary]p5:
+ // when a default constructor is called to initialize an element of
+ // an array with no corresponding initializer [...] the destruction of
+ // every temporary created in a default argument is sequenced before
+ // the construction of the next array element, if any
+ CodeGenFunction::RunCleanupsScope CleanupsScope(CGF);
+ LValue elementLV =
+ CGF.MakeAddrLValue(Address(currentElement, elementAlign), elementType);
+ if (filler)
+ EmitInitializationToLValue(filler, elementLV);
+ else
+ EmitNullInitializationToLValue(elementLV);
+ }
// Move on to the next element.
llvm::Value *nextElement =
diff --git a/clang/test/CodeGenCXX/array-default-argument.cpp b/clang/test/CodeGenCXX/array-default-argument.cpp
new file mode 100644
index 00000000000..8376b4f340c
--- /dev/null
+++ b/clang/test/CodeGenCXX/array-default-argument.cpp
@@ -0,0 +1,36 @@
+// RUN: %clang_cc1 -emit-llvm -o - %s -triple %itanium_abi_triple | FileCheck %s
+// RUN: %clang_cc1 -emit-llvm -o - %s -triple %itanium_abi_triple -fexceptions -fcxx-exceptions | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-EH
+
+struct A {
+ A();
+ ~A();
+};
+
+struct B {
+ B(A = A());
+ ~B();
+};
+
+void f();
+// CHECK-LABEL: define void @_Z1gv()
+void g() {
+ // CHECK: br label %[[LOOP:.*]]
+
+ // [[LOOP]]:
+ // CHECK: {{call|invoke}} {{.*}} @_ZN1AC1Ev([[TEMPORARY:.*]])
+ // CHECK-EH: unwind label %[[PARTIAL_ARRAY_LPAD:.*]]
+ // CHECK: {{call|invoke}} {{.*}} @_ZN1BC1E1A({{.*}}, [[TEMPORARY]])
+ // CHECK-EH: unwind label %[[A_AND_PARTIAL_ARRAY_LPAD:.*]]
+ // CHECK: {{call|invoke}} {{.*}} @_ZN1AD1Ev([[TEMPORARY]])
+ // CHECK-EH: unwind label %[[PARTIAL_ARRAY_LPAD]]
+ // CHECK: getelementptr {{.*}}, i{{[0-9]*}} 1
+ // CHECK: icmp eq
+ // CHECK: br i1 {{.*}} label %[[LOOP]]
+ B b[5];
+
+ // CHECK: {{call|invoke}} void @_Z1fv()
+ f();
+
+ // CHECK-NOT: @_ZN1AD1Ev(
+ // CHECK: {{call|invoke}} {{.*}} @_ZN1BD1Ev(
+}
OpenPOWER on IntegriCloud