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;
}
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)
// 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{{.*}} }