From 3e7a382f0e854b3f5d51665f7da56b3b90be9301 Mon Sep 17 00:00:00 2001 From: Alexey Bataev Date: Fri, 19 Feb 2016 11:23:28 +0000 Subject: [PATCH] pr26544: Bitfield layout with pragma pack and attributes "packed" and "aligned", by Vladimir Yakovlev Fix clang/gcc incompatibility of bitfields layout in the presence of pragma packed and attributes aligned and packed. Differential Revision: http://reviews.llvm.org/D17023 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@261321 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/AST/RecordLayoutBuilder.cpp | 11 +- test/Sema/bitfield-layout_1.c | 202 ++++++++++++++++++++++++++++++++ 2 files changed, 211 insertions(+), 2 deletions(-) create mode 100644 test/Sema/bitfield-layout_1.c diff --git a/lib/AST/RecordLayoutBuilder.cpp b/lib/AST/RecordLayoutBuilder.cpp index c79cf6cabb..6a7d5144c8 100644 --- a/lib/AST/RecordLayoutBuilder.cpp +++ b/lib/AST/RecordLayoutBuilder.cpp @@ -1558,10 +1558,13 @@ void ItaniumRecordLayoutBuilder::LayoutBitField(const FieldDecl *D) { // But, if there's a #pragma pack in play, that takes precedent over // even the 'aligned' attribute, for non-zero-width bitfields. + unsigned MaxFieldAlignmentInBits = Context.toBits(MaxFieldAlignment); if (!MaxFieldAlignment.isZero() && FieldSize) { - unsigned MaxFieldAlignmentInBits = Context.toBits(MaxFieldAlignment); - FieldAlign = std::min(FieldAlign, MaxFieldAlignmentInBits); UnpackedFieldAlign = std::min(UnpackedFieldAlign, MaxFieldAlignmentInBits); + if (FieldPacked) + FieldAlign = UnpackedFieldAlign; + else + FieldAlign = std::min(FieldAlign, MaxFieldAlignmentInBits); } // But, ms_struct just ignores all of that in unions, even explicit @@ -1601,6 +1604,8 @@ void ItaniumRecordLayoutBuilder::LayoutBitField(const FieldDecl *D) { (FieldOffset & (FieldAlign-1)) + FieldSize > TypeSize)) { FieldOffset = llvm::alignTo(FieldOffset, FieldAlign); } else if (ExplicitFieldAlign && + (MaxFieldAlignmentInBits == 0 || + ExplicitFieldAlign <= MaxFieldAlignmentInBits) && Context.getTargetInfo().useExplicitBitFieldAlignment()) { // TODO: figure it out what needs to be done on targets that don't honor // bit-field type alignment like ARM APCS ABI. @@ -1614,6 +1619,8 @@ void ItaniumRecordLayoutBuilder::LayoutBitField(const FieldDecl *D) { UnpackedFieldOffset = llvm::alignTo(UnpackedFieldOffset, UnpackedFieldAlign); else if (ExplicitFieldAlign && + (MaxFieldAlignmentInBits == 0 || + ExplicitFieldAlign <= MaxFieldAlignmentInBits) && Context.getTargetInfo().useExplicitBitFieldAlignment()) UnpackedFieldOffset = llvm::alignTo(UnpackedFieldOffset, ExplicitFieldAlign); diff --git a/test/Sema/bitfield-layout_1.c b/test/Sema/bitfield-layout_1.c new file mode 100644 index 0000000000..24277c3911 --- /dev/null +++ b/test/Sema/bitfield-layout_1.c @@ -0,0 +1,202 @@ +// RUN: %clang_cc1 %s -fsyntax-only -verify -triple=i686-apple-darwin9 +// RUN: %clang_cc1 %s -fsyntax-only -verify -triple=arm-linux-gnueabihf +// RUN: %clang_cc1 %s -fsyntax-only -verify -triple=aarch64-linux-gnu +// RUN: %clang_cc1 %s -fsyntax-only -verify -triple=x86_64-pc-linux-gnu +// expected-no-diagnostics + +#define CHECK_SIZE(name, size) \ + extern int name##_1[sizeof(name) == size ? 1 : -1]; + + +struct __attribute__((packed)) { + int a; + int b : 4; + int c : 32; +} s0; +CHECK_SIZE(s0,9) + +#pragma pack (1) +struct { + int a; + int b : 4; + int c : 32; +} s1; +CHECK_SIZE(s1,9) + +#pragma pack (2) +struct { + int a; + int b : 4; + int c : 32; +} s2; +CHECK_SIZE(s2,10) + +#pragma pack (2) +struct __attribute__((packed)) { + int a; + int b : 4; + int c : 32; +} s3; +CHECK_SIZE(s3,10) + +#pragma pack (4) +struct __attribute__((packed)) { + int a; + int b : 4; + int c : 32; +} s4; +CHECK_SIZE(s4,12) + +#pragma pack (16) +struct { + int a; + int __attribute__((packed)) b : 4; + int __attribute__((packed)) c : 32; +} s41; +CHECK_SIZE(s41,12) + +#pragma pack (16) +struct { + int a; + int b : 4; + int c : 32; +} s5; +CHECK_SIZE(s5,12) + +#pragma pack (1) +struct __attribute__((aligned(4))) { + int a; + int b : 4; + int c : 32; +} s6; +CHECK_SIZE(s6,12) + +#pragma pack (2) +struct { + char a; + int b : 4; + int c : 32; + char s; +} s7; +CHECK_SIZE(s7,8) + +#pragma pack (1) +struct { + char a; + int b : 4; + int c : 28; + char s; +} s8; +CHECK_SIZE(s8,6) + +#pragma pack (8) +struct { + char a; + int b : 4; + int c : 28; + char s; +} s9; +CHECK_SIZE(s9,8) + +#pragma pack (8) +struct { + char a; + char s; +} s10; +CHECK_SIZE(s10,2) + +#pragma pack(4) +struct { + char a; + int b : 4; + int c : 28; + char s1; + char s2; + char s3; +} s11; +CHECK_SIZE(s11,8) + +#pragma pack(4) +struct { + short s1; + int a1 : 17; + int a2 : 17; + int a3 : 30; + short s2; +} s12; +CHECK_SIZE(s12,12) + +#pragma pack(4) +struct { + char c1; + int i1 : 17; + int i2 : 17; + int i3 : 30; + char c2; +} s13; +CHECK_SIZE(s13,12) + +#pragma pack(2) +struct { + char a; + int s; +} s14; +CHECK_SIZE(s14,6) + +#pragma pack(4) +struct { + char a; + short s; +} s15; +CHECK_SIZE(s15,4) + +#pragma pack(2) +struct { + char a; + int b : 4; + int c : 28; + char s1; + char s2; + char s3; +} s16; +CHECK_SIZE(s16,8) + +#pragma pack (16) +struct { + int __attribute__((packed)) a; + int __attribute__((packed)) b : 4; + int __attribute__((packed)) c : 32; +} s17; +CHECK_SIZE(s17,12) + +#pragma pack (16) +struct { + int __attribute__((aligned(8))) a; + int __attribute__((aligned(8))) b : 4; + int __attribute__((aligned(8))) c : 32; +} s18; +CHECK_SIZE(s18,24) + +#pragma pack (16) +struct { + int __attribute__((aligned(1))) a; + int __attribute__((aligned(1))) b : 4; + int __attribute__((aligned(1))) c : 32; +} s19; +CHECK_SIZE(s19,12) + +#pragma pack (1) +struct __attribute__((aligned(8))) { + int a; + int b : 4; + int c : 32; +} s20; +CHECK_SIZE(s20,16) + +#pragma pack (2) +struct { + int __attribute__((aligned(8))) a; + int __attribute__((aligned(8))) b : 4; + int __attribute__((aligned(8))) c : 32; +} s21; +CHECK_SIZE(s21,10) -- 2.40.0