Index: cfe/trunk/lib/AST/RecordLayoutBuilder.cpp =================================================================== --- cfe/trunk/lib/AST/RecordLayoutBuilder.cpp +++ cfe/trunk/lib/AST/RecordLayoutBuilder.cpp @@ -2452,7 +2452,9 @@ auto RoundingAlignment = Alignment; if (!MaxFieldAlignment.isZero()) RoundingAlignment = std::min(RoundingAlignment, MaxFieldAlignment); - NonVirtualSize = Size = Size.alignTo(RoundingAlignment); + if (!UseExternalLayout) + Size = Size.alignTo(RoundingAlignment); + NonVirtualSize = Size; RequiredAlignment = std::max( RequiredAlignment, Context.toCharUnitsFromBits(RD->getMaxAlignment())); layoutVirtualBases(RD); @@ -2653,21 +2655,16 @@ LastFieldIsNonZeroWidthBitfield = false; ElementInfo Info = getAdjustedElementInfo(FD); Alignment = std::max(Alignment, Info.Alignment); - if (IsUnion) { - placeFieldAtOffset(CharUnits::Zero()); - Size = std::max(Size, Info.Size); - } else { - CharUnits FieldOffset; - if (UseExternalLayout) { - FieldOffset = - Context.toCharUnitsFromBits(External.getExternalFieldOffset(FD)); - assert(FieldOffset >= Size && "field offset already allocated"); - } else { - FieldOffset = Size.alignTo(Info.Alignment); - } - placeFieldAtOffset(FieldOffset); - Size = FieldOffset + Info.Size; - } + CharUnits FieldOffset; + if (UseExternalLayout) + FieldOffset = + Context.toCharUnitsFromBits(External.getExternalFieldOffset(FD)); + else if (IsUnion) + FieldOffset = CharUnits::Zero(); + else + FieldOffset = Size.alignTo(Info.Alignment); + placeFieldAtOffset(FieldOffset); + Size = std::max(Size, FieldOffset + Info.Size); } void MicrosoftRecordLayoutBuilder::layoutBitField(const FieldDecl *FD) { @@ -2692,18 +2689,17 @@ } LastFieldIsNonZeroWidthBitfield = true; CurrentBitfieldSize = Info.Size; - if (IsUnion) { - placeFieldAtOffset(CharUnits::Zero()); - Size = std::max(Size, Info.Size); - // TODO: Add a Sema warning that MS ignores bitfield alignment in unions. - } else if (UseExternalLayout) { + if (UseExternalLayout) { auto FieldBitOffset = External.getExternalFieldOffset(FD); placeFieldAtBitOffset(FieldBitOffset); auto NewSize = Context.toCharUnitsFromBits( llvm::alignTo(FieldBitOffset + Width, Context.getCharWidth())); - assert(NewSize >= Size && "bit field offset already allocated"); - Size = NewSize; + Size = std::max(Size, NewSize); Alignment = std::max(Alignment, Info.Alignment); + } else if (IsUnion) { + placeFieldAtOffset(CharUnits::Zero()); + Size = std::max(Size, Info.Size); + // TODO: Add a Sema warning that MS ignores bitfield alignment in unions. } else { // Allocate a new block of memory and place the bitfield in it. CharUnits FieldOffset = Size.alignTo(Info.Alignment); Index: cfe/trunk/test/CodeGenCXX/Inputs/override-layout-nameless-struct-union.layout =================================================================== --- cfe/trunk/test/CodeGenCXX/Inputs/override-layout-nameless-struct-union.layout +++ cfe/trunk/test/CodeGenCXX/Inputs/override-layout-nameless-struct-union.layout @@ -0,0 +1,16 @@ + +*** Dumping AST Record Layout +Type: struct S + +Layout: + +*** Dumping AST Record Layout +Type: union U + +Layout: Index: cfe/trunk/test/CodeGenCXX/Inputs/override-layout-packed-base.layout =================================================================== --- cfe/trunk/test/CodeGenCXX/Inputs/override-layout-packed-base.layout +++ cfe/trunk/test/CodeGenCXX/Inputs/override-layout-packed-base.layout @@ -0,0 +1,18 @@ + +*** Dumping AST Record Layout +Type: class B<0> + +Layout: + +*** Dumping AST Record Layout +Type: class B<1> + +Layout: + +*** Dumping AST Record Layout +Type: class C + +Layout: Index: cfe/trunk/test/CodeGenCXX/override-layout-nameless-struct-union.cpp =================================================================== --- cfe/trunk/test/CodeGenCXX/override-layout-nameless-struct-union.cpp +++ cfe/trunk/test/CodeGenCXX/override-layout-nameless-struct-union.cpp @@ -0,0 +1,33 @@ +// RUN: %clang_cc1 -w -fdump-record-layouts-simple -foverride-record-layout=%S/Inputs/override-layout-nameless-struct-union.layout %s | FileCheck %s + +// CHECK: Type: struct S +// CHECK: Size:64 +// CHECK: Alignment:32 +// CHECK: FieldOffsets: [0, 32, 32] +struct S { + short _s; +//union { + int _su0; + char _su1; +//}; +}; + +// CHECK: Type: union U +// CHECK: Size:96 +// CHECK: Alignment:32 +// CHECK: FieldOffsets: [0, 0, 32, 64, 68, 73] +union U { + short _u; +//struct { + char _us0; + int _us1; + unsigned _us20 : 4; + unsigned _us21 : 5; + unsigned _us22 : 6; +//}; +}; + +void use_structs() { + S ss[sizeof(S)]; + U us[sizeof(U)]; +} Index: cfe/trunk/test/CodeGenCXX/override-layout-packed-base.cpp =================================================================== --- cfe/trunk/test/CodeGenCXX/override-layout-packed-base.cpp +++ cfe/trunk/test/CodeGenCXX/override-layout-packed-base.cpp @@ -0,0 +1,26 @@ +// RUN: %clang_cc1 -w -fdump-record-layouts-simple -foverride-record-layout=%S/Inputs/override-layout-packed-base.layout %s | FileCheck %s + +// CHECK: Type: class B<0> +// CHECK: FieldOffsets: [0, 32] + +// CHECK: Type: class B<1> +// CHECK: FieldOffsets: [0, 32] + +//#pragma pack(push, 1) +template +class B { + int _b1; + char _b2; +}; +//#pragma pack(pop) + +// CHECK: Type: class C +// CHECK: FieldOffsets: [80] + +class C : B<0>, B<1> { + char _c; +}; + +void use_structs() { + C cs[sizeof(C)]; +}