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!

llvm-svn: 302750
This commit is contained in:
Richard Smith 2017-05-11 00:17:17 +00:00
parent bfb8e189d2
commit 97a2cdbff3
2 changed files with 50 additions and 6 deletions

View File

@ -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 =

View File

@ -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}} void @_ZN1AC1Ev([[TEMPORARY:.*]])
// CHECK-EH: unwind label %[[PARTIAL_ARRAY_LPAD:.*]]
// CHECK: {{call|invoke}} void @_ZN1BC1E1A({{.*}}, [[TEMPORARY]])
// CHECK-EH: unwind label %[[A_AND_PARTIAL_ARRAY_LPAD:.*]]
// CHECK: {{call|invoke}} void @_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}} void @_ZN1BD1Ev(
}