From: Sebastian Redl Date: Sun, 19 Feb 2012 15:41:54 +0000 (+0000) Subject: Make std::initializer_list member initializers 'work'. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=924db71fc8f6076c532c8c2ae93acc7f477452c8;p=clang Make std::initializer_list member initializers 'work'. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@150930 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/CodeGen/CGClass.cpp b/lib/CodeGen/CGClass.cpp index 7b492fba17..f269b675a0 100644 --- a/lib/CodeGen/CGClass.cpp +++ b/lib/CodeGen/CGClass.cpp @@ -418,40 +418,46 @@ static void EmitAggMemberInitializer(CodeGenFunction &CGF, ArrayRef ArrayIndexes, unsigned Index) { if (Index == ArrayIndexes.size()) { - CodeGenFunction::RunCleanupsScope Cleanups(CGF); - LValue LV = LHS; - if (ArrayIndexVar) { - // If we have an array index variable, load it and use it as an offset. - // Then, increment the value. - llvm::Value *Dest = LHS.getAddress(); - llvm::Value *ArrayIndex = CGF.Builder.CreateLoad(ArrayIndexVar); - Dest = CGF.Builder.CreateInBoundsGEP(Dest, ArrayIndex, "destaddress"); - llvm::Value *Next = llvm::ConstantInt::get(ArrayIndex->getType(), 1); - Next = CGF.Builder.CreateAdd(ArrayIndex, Next, "inc"); - CGF.Builder.CreateStore(Next, ArrayIndexVar); - - // Update the LValue. - LV.setAddress(Dest); - CharUnits Align = CGF.getContext().getTypeAlignInChars(T); - LV.setAlignment(std::min(Align, LV.getAlignment())); - } + { // Scope for Cleanups. + CodeGenFunction::RunCleanupsScope Cleanups(CGF); + + if (ArrayIndexVar) { + // If we have an array index variable, load it and use it as an offset. + // Then, increment the value. + llvm::Value *Dest = LHS.getAddress(); + llvm::Value *ArrayIndex = CGF.Builder.CreateLoad(ArrayIndexVar); + Dest = CGF.Builder.CreateInBoundsGEP(Dest, ArrayIndex, "destaddress"); + llvm::Value *Next = llvm::ConstantInt::get(ArrayIndex->getType(), 1); + Next = CGF.Builder.CreateAdd(ArrayIndex, Next, "inc"); + CGF.Builder.CreateStore(Next, ArrayIndexVar); + + // Update the LValue. + LV.setAddress(Dest); + CharUnits Align = CGF.getContext().getTypeAlignInChars(T); + LV.setAlignment(std::min(Align, LV.getAlignment())); + } - if (!CGF.hasAggregateLLVMType(T)) { - CGF.EmitScalarInit(Init, /*decl*/ 0, LV, false); - } else if (T->isAnyComplexType()) { - CGF.EmitComplexExprIntoAddr(Init, LV.getAddress(), - LV.isVolatileQualified()); - } else { - AggValueSlot Slot = - AggValueSlot::forLValue(LV, - AggValueSlot::IsDestructed, - AggValueSlot::DoesNotNeedGCBarriers, - AggValueSlot::IsNotAliased); - - CGF.EmitAggExpr(Init, Slot); + if (!CGF.hasAggregateLLVMType(T)) { + CGF.EmitScalarInit(Init, /*decl*/ 0, LV, false); + } else if (T->isAnyComplexType()) { + CGF.EmitComplexExprIntoAddr(Init, LV.getAddress(), + LV.isVolatileQualified()); + } else { + AggValueSlot Slot = + AggValueSlot::forLValue(LV, + AggValueSlot::IsDestructed, + AggValueSlot::DoesNotNeedGCBarriers, + AggValueSlot::IsNotAliased); + + CGF.EmitAggExpr(Init, Slot); + } } - + + // Now, outside of the initializer cleanup scope, destroy the backing array + // for a std::initializer_list member. + CGF.MaybeEmitStdInitializerListCleanup(LV, Init); + return; } diff --git a/test/CodeGenCXX/cxx0x-initializer-stdinitializerlist.cpp b/test/CodeGenCXX/cxx0x-initializer-stdinitializerlist.cpp index 7dc5503c96..55e3992238 100644 --- a/test/CodeGenCXX/cxx0x-initializer-stdinitializerlist.cpp +++ b/test/CodeGenCXX/cxx0x-initializer-stdinitializerlist.cpp @@ -164,3 +164,34 @@ void fn9() { // CHECK-NOT: call void @_ZN10destroyme1D1Ev // CHECK: ret void } + +struct haslist1 { + std::initializer_list il; + haslist1(); +}; + +// CHECK: define void @_ZN8haslist1C2Ev +haslist1::haslist1() +// CHECK: alloca [3 x i32] +// CHECK: store i32 1 +// CHECK: store i32 2 +// CHECK: store i32 3 +// CHECK: store i{{32|64}} 3 + : il{1, 2, 3} +{ + destroyme2 dm2; +} + +struct haslist2 { + std::initializer_list il; + haslist2(); +}; + +// CHECK: define void @_ZN8haslist2C2Ev +haslist2::haslist2() + : il{destroyme1(), destroyme1()} +{ + destroyme2 dm2; + // CHECK: call void @_ZN10destroyme2D1Ev + // CHECK: call void @_ZN10destroyme1D1Ev +}