Index: lib/AST/RecordLayoutBuilder.cpp =================================================================== --- lib/AST/RecordLayoutBuilder.cpp +++ lib/AST/RecordLayoutBuilder.cpp @@ -1345,6 +1345,14 @@ LayoutField(Field); } +// Rounds the specified field up to have it multiple of the char size. +static uint64_t +RoundUpFieldSizeToCharAlignment(const uint64_t FieldSize, + const ASTContext &Context) { + uint64_t CharAlignment = Context.getTargetInfo().getCharAlign(); + return llvm::RoundUpToAlignment(FieldSize, CharAlignment); +} + void RecordLayoutBuilder::LayoutWideBitField(uint64_t FieldSize, uint64_t TypeSize, bool FieldPacked, @@ -1382,7 +1390,9 @@ uint64_t UnpaddedFieldOffset = getDataSizeInBits() - UnfilledBitsInLastUnit; if (IsUnion) { - setDataSize(std::max(getDataSizeInBits(), FieldSize)); + uint64_t RoundedFieldSize = RoundUpFieldSizeToCharAlignment(FieldSize, + Context); + setDataSize(std::max(getDataSizeInBits(), RoundedFieldSize)); FieldOffset = 0; } else { // The bitfield is allocated starting at the next offset aligned @@ -1607,9 +1617,9 @@ // For unions, this is just a max operation, as usual. if (IsUnion) { - // FIXME: I think FieldSize should be TypeSize here. - setDataSize(std::max(getDataSizeInBits(), FieldSize)); - + uint64_t RoundedFieldSize = RoundUpFieldSizeToCharAlignment(FieldSize, + Context); + setDataSize(std::max(getDataSizeInBits(), RoundedFieldSize)); // For non-zero-width bitfields in ms_struct structs, allocate a new // storage unit if necessary. } else if (IsMsStruct && FieldSize) { Index: test/Layout/union_regular_bit_field.cpp =================================================================== --- /dev/null +++ test/Layout/union_regular_bit_field.cpp @@ -0,0 +1,15 @@ +// RUN: %clang_cc1 -emit-llvm-only -triple aarch64 -fdump-record-layouts %s 2>/dev/null \ +// RUN: | FileCheck %s +// RUN: %clang_cc1 -emit-llvm-only -triple x86_64 -fdump-record-layouts %s 2>/dev/null \ +// RUN: | FileCheck %s + +union A { + int f1: 3; + A(); +}; + +A::A() {} + +// CHECK: | [sizeof=4, dsize=1, align=4 +// CHECK-NEXT: | nvsize=1, nvalign=4] + Index: test/Layout/union_wide_bit_field.cpp =================================================================== --- /dev/null +++ test/Layout/union_wide_bit_field.cpp @@ -0,0 +1,15 @@ +// RUN: %clang_cc1 -emit-llvm-only -triple aarch64 -fdump-record-layouts %s 2>/dev/null \ +// RUN: | FileCheck %s +// RUN: %clang_cc1 -emit-llvm-only -triple x86_64 -fdump-record-layouts %s 2>/dev/null \ +// RUN: | FileCheck %s + +union A { + int f1: 69; + A(); +}; + +A::A() {} + +// CHECK: | [sizeof=16, dsize=9, align=8 +// CHECK-NEXT: | nvsize=9, nvalign=8] +