summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTom Stellard <tstellar@redhat.com>2017-05-16 13:33:48 +0000
committerTom Stellard <tstellar@redhat.com>2017-05-16 13:33:48 +0000
commitbef8b2603310dafa0a8ca19fe043b8b00ec4804f (patch)
tree738152d14febf19a1d549a438d9c406e4a3a7262
parentf1f6d664a69eabbd91046ce9212da890802be843 (diff)
Merging r302817:
------------------------------------------------------------------------ r302817 | rsmith | 2017-05-11 14:58:24 -0400 (Thu, 11 May 2017) | 9 lines 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: 303167
-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 009244784e50..b10a549338fd 100644
--- a/clang/lib/CodeGen/CGExprAgg.cpp
+++ b/clang/lib/CodeGen/CGExprAgg.cpp
@@ -505,12 +505,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 000000000000..8376b4f340c5
--- /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(
+}