From 1ac0f201387d84ebcf90968a7276c120c0fe7688 Mon Sep 17 00:00:00 2001 From: Richard Smith Date: Thu, 11 May 2017 00:17:17 +0000 Subject: [PATCH] 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! git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@302750 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/CGExprAgg.cpp | 20 ++++++++---- test/CodeGenCXX/array-default-argument.cpp | 36 ++++++++++++++++++++++ 2 files changed, 50 insertions(+), 6 deletions(-) create mode 100644 test/CodeGenCXX/array-default-argument.cpp diff --git a/lib/CodeGen/CGExprAgg.cpp b/lib/CodeGen/CGExprAgg.cpp index 49bbb4808e..a05a088f09 100644 --- a/lib/CodeGen/CGExprAgg.cpp +++ b/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/test/CodeGenCXX/array-default-argument.cpp b/test/CodeGenCXX/array-default-argument.cpp new file mode 100644 index 0000000000..1fba485f37 --- /dev/null +++ b/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}} 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( +} -- 2.40.0