CodeGen: Use the initing member's type for a union's storage type more often

Unions are initialized with the default initialization of their first
named member.  If that member is not zero initialized, then we should
prefer that member's type.  Otherwise, we might try to make an otherwise
unsuitable type (like an array) which we cannot easily initialize with a
pointer to member.

llvm-svn: 219781
This commit is contained in:
David Majnemer 2014-10-15 07:57:41 +00:00
parent 2e29b40d5e
commit b00ddf31b2
2 changed files with 25 additions and 1 deletions

View File

@ -279,6 +279,8 @@ void CGRecordLowering::lower(bool NVBaseType) {
void CGRecordLowering::lowerUnion() {
CharUnits LayoutSize = Layout.getSize();
llvm::Type *StorageType = nullptr;
bool SeenNamedMember = false;
bool InitializingMemberIsNonZero = false;
// Compute zero-initializable status.
if (!D->field_empty() && !isZeroInitializable(*D->field_begin()))
IsZeroInitializable = IsZeroInitializableAsBase = false;
@ -299,12 +301,25 @@ void CGRecordLowering::lowerUnion() {
}
Fields[Field->getCanonicalDecl()] = 0;
llvm::Type *FieldType = getStorageType(Field);
// This union might not be zero initialized: it may contain a pointer to
// data member which might have some exotic initialization sequence.
// If this is the case, then we aught not to try and come up with a "better"
// type, it might not be very easy to come up with a Constant which
// correctly initializes it.
if (!SeenNamedMember && Field->getDeclName()) {
SeenNamedMember = true;
if (!isZeroInitializable(Field)) {
InitializingMemberIsNonZero = true;
StorageType = FieldType;
}
}
// Conditionally update our storage type if we've got a new "better" one.
if (!StorageType ||
getAlignment(FieldType) > getAlignment(StorageType) ||
(getAlignment(FieldType) == getAlignment(StorageType) &&
getSize(FieldType) > getSize(StorageType)))
StorageType = FieldType;
if (!InitializingMemberIsNonZero)
StorageType = FieldType;
}
// If we have no storage type just pad to the appropriate size and return.
if (!StorageType)

View File

@ -268,4 +268,13 @@ B b;
// CHECK-GLOBAL: @_ZN7PR210891bE = global %"struct.PR21089::B" { %"struct.PR21089::A.base" <{ i8 0, [7 x i8] zeroinitializer, i64 -1, i8 0 }>, [7 x i8] zeroinitializer }, align 8
}
namespace PR21282 {
union U {
int U::*x;
long y[2];
};
U u;
// CHECK-GLOBAL: @_ZN7PR212821uE = global %"union.PR21282::U" { i64 -1, [8 x i8] zeroinitializer }, align 8
}
// CHECK-O3: attributes [[NUW]] = { nounwind readnone{{.*}} }