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,6 +1775,12 @@ !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); + // Diagnose differences in layout due to padding or packing. if (!UseExternalLayout) CheckFieldPadding(FieldOffset, UnpaddedFieldOffset, UnpackedFieldOffset, diff --git a/clang/test/Layout/aix-bitfield-alignment.c b/clang/test/Layout/aix-bitfield-alignment.c --- a/clang/test/Layout/aix-bitfield-alignment.c +++ b/clang/test/Layout/aix-bitfield-alignment.c @@ -232,3 +232,37 @@ // CHECK-NEXT: 0 | struct G // CHECK-NEXT: 0:0-44 | long long ll // CHECK-NEXT: sizeof=8, {{(dsize=8, )?}}align=8, preferredalign=8 + +#pragma align(packed) +struct H { + char c; + int : 0; + int i; +} H; +#pragma align(reset) + +int h = sizeof(H); + +// CHECK: *** Dumping AST Record Layout +// CHECK-NEXT: 0 | struct H +// CHECK-NEXT: 0 | char c +// CHECK-NEXT: 4:- | int +// CHECK-NEXT: 4 | int i +// CHECK-NEXT: sizeof=8, {{(dsize=8, )?}}align=1, preferredalign=1 + +#pragma pack(2) +struct I { + char c; + int : 0; + int i; +} I; +#pragma pack(pop) + +int i = sizeof(I); + +// CHECK: *** Dumping AST Record Layout +// CHECK-NEXT: 0 | struct I +// CHECK-NEXT: 0 | char c +// CHECK-NEXT: 4:- | int +// CHECK-NEXT: 4 | int i +// CHECK-NEXT: sizeof=8, {{(dsize=8, )?}}align=2, preferredalign=2 diff --git a/clang/test/Layout/aix-packed-bitfields.c b/clang/test/Layout/aix-packed-bitfields.c new file mode 100644 --- /dev/null +++ b/clang/test/Layout/aix-packed-bitfields.c @@ -0,0 +1,77 @@ +// RUN: %clang_cc1 -triple powerpc-ibm-aix-xcoff -fdump-record-layouts \ +// RUN: -fsyntax-only -fxl-pragma-pack -x c %s | FileCheck %s + +// RUN: %clang_cc1 -triple powerpc-ibm-aix-xcoff -fdump-record-layouts \ +// RUN: -fsyntax-only -fxl-pragma-pack -x c++ %s | FileCheck %s +// +// RUN: %clang_cc1 -triple powerpc64-ibm-aix-xcoff -fdump-record-layouts \ +// RUN: -fsyntax-only -fxl-pragma-pack -x c %s | FileCheck %s +// +// RUN: %clang_cc1 -triple powerpc64-ibm-aix-xcoff -fdump-record-layouts \ +// RUN: -fsyntax-only -fxl-pragma-pack -x c++ %s | FileCheck %s + +struct A { + int a1 : 30; + int a2 : 30; + int a3 : 4; +}; + +int a = sizeof(struct A); + +// CHECK: *** Dumping AST Record Layout +// CHECK-NEXT: 0 | struct A +// CHECK-NEXT: 0:0-29 | int a1 +// CHECK-NEXT: 4:0-29 | int a2 +// CHECK-NEXT: 8:0-3 | int a3 +// CHECK-NEXT: sizeof=12, {{(dsize=12, )?}}align=4, preferredalign=4 + +#pragma align(packed) +struct AlignPacked { + int a1 : 30; + int a2 : 30; + int a3 : 4; +}; +#pragma align(reset) + +int b = sizeof(struct AlignPacked); + +// CHECK: *** Dumping AST Record Layout +// CHECK-NEXT: 0 | struct AlignPacked +// CHECK-NEXT: 0:0-29 | int a1 +// CHECK-NEXT: 3:6-35 | int a2 +// CHECK-NEXT: 7:4-7 | int a3 +// CHECK-NEXT: sizeof=8, {{(dsize=8, )?}}align=1, preferredalign=1 + +#pragma pack(1) +struct Pack1 { + int a1 : 30; + int a2 : 30; + int a3 : 4; +}; +#pragma pack(pop) + +int c = sizeof(struct Pack1); + +// CHECK: *** Dumping AST Record Layout +// CHECK-NEXT: 0 | struct Pack1 +// CHECK-NEXT: 0:0-29 | int a1 +// CHECK-NEXT: 3:6-35 | int a2 +// CHECK-NEXT: 7:4-7 | int a3 +// CHECK-NEXT: sizeof=8, {{(dsize=8, )?}}align=1, preferredalign=1 + +#pragma pack(2) +struct Pack2 { + int a1 : 30; + int a2 : 30; + int a3 : 4; +}; +#pragma pack(pop) + +int d = sizeof(struct Pack2); + +// CHECK: *** Dumping AST Record Layout +// CHECK-NEXT: 0 | struct Pack2 +// CHECK-NEXT: 0:0-29 | int a1 +// CHECK-NEXT: 3:6-35 | int a2 +// CHECK-NEXT: 7:4-7 | int a3 +// CHECK-NEXT: sizeof=8, {{(dsize=8, )?}}align=2, preferredalign=2