diff --git a/clang/lib/CodeGen/CGRecordLayoutBuilder.cpp b/clang/lib/CodeGen/CGRecordLayoutBuilder.cpp index dd4c0cdb6b68..651436164177 100644 --- a/clang/lib/CodeGen/CGRecordLayoutBuilder.cpp +++ b/clang/lib/CodeGen/CGRecordLayoutBuilder.cpp @@ -277,6 +277,7 @@ void CGRecordLowering::lower(bool NVBaseType) { } void CGRecordLowering::lowerUnion() { + CharUnits LayoutSize = Layout.getSize(); llvm::Type *StorageType = 0; // Compute zero-initializable status. if (!D->field_empty() && !isZeroInitializable(*D->field_begin())) @@ -293,7 +294,10 @@ void CGRecordLowering::lowerUnion() { // Skip 0 sized bitfields. if (Field->getBitWidthValue(Context) == 0) continue; - setBitFieldInfo(*Field, CharUnits::Zero(), getStorageType(*Field)); + llvm::Type *FieldType = getStorageType(*Field); + if (LayoutSize < getSize(FieldType)) + FieldType = getByteArrayType(LayoutSize); + setBitFieldInfo(*Field, CharUnits::Zero(), FieldType); } Fields[*Field] = 0; llvm::Type *FieldType = getStorageType(*Field); @@ -304,7 +308,6 @@ void CGRecordLowering::lowerUnion() { getSize(FieldType) > getSize(StorageType))) StorageType = FieldType; } - CharUnits LayoutSize = Layout.getSize(); // If we have no storage type just pad to the appropriate size and return. if (!StorageType) return appendPaddingBytes(LayoutSize); diff --git a/clang/test/CodeGen/union.c b/clang/test/CodeGen/union.c index 5c89e2d72a7e..730218210213 100644 --- a/clang/test/CodeGen/union.c +++ b/clang/test/CodeGen/union.c @@ -44,3 +44,16 @@ typedef union T0 { unsigned int : 0; } T0; T0 t0; union { int large_bitfield: 31; char c } u2; + +struct dt_t_s { + union { + long long u : 56; + } __attribute__((packed)); +}; +struct { + struct { + struct { + struct dt_t_s t; + }; + }; +} a;