diff --git a/clang/lib/AST/RecordLayoutBuilder.cpp b/clang/lib/AST/RecordLayoutBuilder.cpp --- a/clang/lib/AST/RecordLayoutBuilder.cpp +++ b/clang/lib/AST/RecordLayoutBuilder.cpp @@ -1775,11 +1775,18 @@ !D->getIdentifier()) FieldAlign = UnpackedFieldAlign = 1; - // On AIX, zero-width bitfields pad out to the alignment boundary, but then - // do not affect overall record alignment if there is a pragma pack or - // pragma align(packed). - if (isAIXLayout(Context) && !MaxFieldAlignment.isZero() && !FieldSize) - FieldAlign = std::min(FieldAlign, MaxFieldAlignmentInBits); + // On AIX, zero-width bitfields pad out to the natural alignment boundary, + // but dont increase the alignment greater than the MaxFieldAlignment, or 1 + // if packed. + if (isAIXLayout(Context) && !FieldSize) { + if (FieldPacked) { + FieldAlign = UnpackedFieldAlign = 1; + } else if (!MaxFieldAlignment.isZero()) { + UnpackedFieldAlign = + std::min(UnpackedFieldAlign, MaxFieldAlignmentInBits); + FieldAlign = std::min(FieldAlign, MaxFieldAlignmentInBits); + } + } // Diagnose differences in layout due to padding or packing. if (!UseExternalLayout) diff --git a/clang/test/Layout/aix-packed-bitfields.c b/clang/test/Layout/aix-packed-bitfields.c --- a/clang/test/Layout/aix-packed-bitfields.c +++ b/clang/test/Layout/aix-packed-bitfields.c @@ -75,3 +75,33 @@ // CHECK-NEXT: 3:6-35 | int a2 // CHECK-NEXT: 7:4-7 | int a3 // CHECK-NEXT: sizeof=8, {{(dsize=8, )?}}align=2, preferredalign=2 +// +struct __attribute__((packed)) PackedAttr { + char f1; + int : 0; + short : 3; + char f4 : 2; +}; + +int e = sizeof(struct PackedAttr); +// CHECK: *** Dumping AST Record Layout +// CHECK-NEXT: 0 | struct PackedAttr +// CHECK-NEXT: 0 | char f1 +// CHECK-NEXT: 4:- | int +// CHECK-NEXT: 4:0-2 | short +// CHECK-NEXT: 4:3-4 | char f4 +// CHECK-NEXT: sizeof=5, {{(dsize=5, )?}}align=1, preferredalign=1 + +#pragma pack(2) +struct __attribute__((packed)) PackedAttrAndPragma { + char f1; + int : 0; +}; +#pragma pack(pop) + +int f = sizeof(struct PackedAttrAndPragma); +// CHECK: *** Dumping AST Record Layout +// CHECK-NEXT: 0 | struct PackedAttrAndPragma +// CHECK-NEXT: 0 | char f1 +// CHECK-NEXT: 4:- | int +// CHECK-NEXT: sizeof=4, {{(dsize=4, )?}}align=1, preferredalign=1