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