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 do not increase the alignment greater than the MaxFieldAlignment, or 1 + // if packed. + if (isAIXLayout(Context) && !FieldSize) { + if (FieldPacked) + FieldAlign = 1; + 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 @@ -1,14 +1,18 @@ // RUN: %clang_cc1 -triple powerpc-ibm-aix-xcoff -fdump-record-layouts \ -// RUN: -fsyntax-only -fxl-pragma-pack -x c %s | FileCheck %s +// RUN: -fsyntax-only -fxl-pragma-pack -x c %s | \ +// RUN: FileCheck --check-prefixes=CHECK,32BIT %s // RUN: %clang_cc1 -triple powerpc-ibm-aix-xcoff -fdump-record-layouts \ -// RUN: -fsyntax-only -fxl-pragma-pack -x c++ %s | FileCheck %s -// +// RUN: -fsyntax-only -fxl-pragma-pack -x c++ %s | \ +// RUN: FileCheck --check-prefixes=CHECK,32BIT %s + // RUN: %clang_cc1 -triple powerpc64-ibm-aix-xcoff -fdump-record-layouts \ -// RUN: -fsyntax-only -fxl-pragma-pack -x c %s | FileCheck %s -// +// RUN: -fsyntax-only -fxl-pragma-pack -x c %s | \ +// RUN: FileCheck --check-prefixes=CHECK,64BIT %s + // RUN: %clang_cc1 -triple powerpc64-ibm-aix-xcoff -fdump-record-layouts \ -// RUN: -fsyntax-only -fxl-pragma-pack -x c++ %s | FileCheck %s +// RUN: -fsyntax-only -fxl-pragma-pack -x c++ %s | \ +// RUN: FileCheck --check-prefixes=CHECK,64BIT %s struct A { int a1 : 30; @@ -75,3 +79,35 @@ // 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; + long long : 0; +}; +#pragma pack(pop) + +int f = sizeof(struct PackedAttrAndPragma); +// CHECK: *** Dumping AST Record Layout +// CHECK-NEXT: 0 | struct PackedAttrAndPragma +// CHECK-NEXT: 0 | char f1 +// 32BIT-NEXT: 4:- | long long +// 32BIT-NEXT: sizeof=4, {{(dsize=4, )?}}align=1, preferredalign=1 +// 64BIT-NEXT: 8:- | long long +// 64BIT-NEXT: sizeof=8, {{(dsize=8, )?}}align=1, preferredalign=1