r219781 - CodeGen: Use the initing member's type for a union's storage type more often
David Majnemer
david.majnemer at gmail.com
Wed Oct 15 00:57:41 PDT 2014
Author: majnemer
Date: Wed Oct 15 02:57:41 2014
New Revision: 219781
URL: http://llvm.org/viewvc/llvm-project?rev=219781&view=rev
Log:
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.
Modified:
cfe/trunk/lib/CodeGen/CGRecordLayoutBuilder.cpp
cfe/trunk/test/CodeGenCXX/pointers-to-data-members.cpp
Modified: cfe/trunk/lib/CodeGen/CGRecordLayoutBuilder.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGRecordLayoutBuilder.cpp?rev=219781&r1=219780&r2=219781&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGRecordLayoutBuilder.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGRecordLayoutBuilder.cpp Wed Oct 15 02:57:41 2014
@@ -279,6 +279,8 @@ void CGRecordLowering::lower(bool NVBase
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)
Modified: cfe/trunk/test/CodeGenCXX/pointers-to-data-members.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/pointers-to-data-members.cpp?rev=219781&r1=219780&r2=219781&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenCXX/pointers-to-data-members.cpp (original)
+++ cfe/trunk/test/CodeGenCXX/pointers-to-data-members.cpp Wed Oct 15 02:57:41 2014
@@ -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{{.*}} }
More information about the cfe-commits
mailing list