Make std::initializer_list member initializers 'work'.

llvm-svn: 150930
This commit is contained in:
Sebastian Redl 2012-02-19 15:41:54 +00:00
parent 7c24d8e70b
commit 4e04dd1979
2 changed files with 67 additions and 30 deletions

View File

@ -418,40 +418,46 @@ static void EmitAggMemberInitializer(CodeGenFunction &CGF,
ArrayRef<VarDecl *> 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);
{ // Scope for Cleanups.
CodeGenFunction::RunCleanupsScope Cleanups(CGF);
// Update the LValue.
LV.setAddress(Dest);
CharUnits Align = CGF.getContext().getTypeAlignInChars(T);
LV.setAlignment(std::min(Align, LV.getAlignment()));
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;
}

View File

@ -164,3 +164,34 @@ void fn9() {
// CHECK-NOT: call void @_ZN10destroyme1D1Ev
// CHECK: ret void
}
struct haslist1 {
std::initializer_list<int> 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<destroyme1> il;
haslist2();
};
// CHECK: define void @_ZN8haslist2C2Ev
haslist2::haslist2()
: il{destroyme1(), destroyme1()}
{
destroyme2 dm2;
// CHECK: call void @_ZN10destroyme2D1Ev
// CHECK: call void @_ZN10destroyme1D1Ev
}