Fix up EmitMemberInitializer to handle many more cases.

llvm-svn: 88999
This commit is contained in:
Eli Friedman 2009-11-16 23:53:01 +00:00
parent b43e1ff236
commit e85ef718d5
2 changed files with 43 additions and 12 deletions

View File

@ -1543,6 +1543,18 @@ static void EmitMemberInitializer(CodeGenFunction &CGF,
if (Array) if (Array)
FieldType = CGF.getContext().getBaseElementType(FieldType); FieldType = CGF.getContext().getBaseElementType(FieldType);
// We lose the constructor for anonymous union members, so handle them
// explicitly.
// FIXME: This is somwhat ugly.
if (MemberInit->getAnonUnionMember() && FieldType->getAs<RecordType>()) {
if (MemberInit->getNumArgs())
CGF.EmitAggExpr(*MemberInit->arg_begin(), LHS.getAddress(),
LHS.isVolatileQualified());
else
CGF.EmitAggregateClear(LHS.getAddress(), Field->getType());
return;
}
if (FieldType->getAs<RecordType>()) { if (FieldType->getAs<RecordType>()) {
assert(MemberInit->getConstructor() && assert(MemberInit->getConstructor() &&
"EmitCtorPrologue - no constructor to initialize member"); "EmitCtorPrologue - no constructor to initialize member");
@ -1565,21 +1577,22 @@ static void EmitMemberInitializer(CodeGenFunction &CGF,
assert(MemberInit->getNumArgs() == 1 && "Initializer count must be 1 only"); assert(MemberInit->getNumArgs() == 1 && "Initializer count must be 1 only");
Expr *RhsExpr = *MemberInit->arg_begin(); Expr *RhsExpr = *MemberInit->arg_begin();
RValue RHS; RValue RHS;
if (FieldType->isReferenceType()) if (FieldType->isReferenceType()) {
RHS = CGF.EmitReferenceBindingToExpr(RhsExpr, FieldType, RHS = CGF.EmitReferenceBindingToExpr(RhsExpr, FieldType,
/*IsInitializer=*/true); /*IsInitializer=*/true);
else if (FieldType->isMemberFunctionPointerType())
RHS = RValue::get(CGF.CGM.EmitConstantExpr(RhsExpr, FieldType, &CGF));
else
RHS = RValue::get(CGF.EmitScalarExpr(RhsExpr, true));
if (Array && !FieldType->getAs<RecordType>()) {
// value initialize a non-class array data member using arr() syntax in
// initializer list.
QualType Ty = CGF.getContext().getCanonicalType((Field)->getType());
CGF.EmitMemSetToZero(LHS.getAddress(), Ty);
}
else
CGF.EmitStoreThroughLValue(RHS, LHS, FieldType); CGF.EmitStoreThroughLValue(RHS, LHS, FieldType);
} else if (Array) {
CGF.EmitMemSetToZero(LHS.getAddress(), Field->getType());
} else if (!CGF.hasAggregateLLVMType(RhsExpr->getType())) {
RHS = RValue::get(CGF.EmitScalarExpr(RhsExpr, true));
CGF.EmitStoreThroughLValue(RHS, LHS, FieldType);
} else if (RhsExpr->getType()->isAnyComplexType()) {
CGF.EmitComplexExprIntoAddr(RhsExpr, LHS.getAddress(),
LHS.isVolatileQualified());
} else {
// Handle member function pointers; other aggregates shouldn't get this far.
CGF.EmitAggExpr(RhsExpr, LHS.getAddress(), LHS.isVolatileQualified());
}
} }
/// EmitCtorPrologue - This routine generates necessary code to initialize /// EmitCtorPrologue - This routine generates necessary code to initialize

View File

@ -0,0 +1,18 @@
// RUN: clang-cc %s -emit-llvm-only -verify
struct A {int a;};
struct B {float a;};
struct C {
union {
A a;
B b[10];
};
_Complex float c;
int d[10];
void (C::*e)();
C() : a(), c(), d(), e() {}
C(A x) : a(x) {}
C(void (C::*x)(), int y) : b(), c(y), e(x) {}
};
A x;
C a, b(x), c(0, 2);