DmitryPolukhin updated this revision to Diff 41481. DmitryPolukhin added a comment.
Added more testcases to cover combination of explicit alignment of bit-filed with packed attribute. Also added testing on ARM for bit-filed layout test. http://reviews.llvm.org/D14980 Files: lib/AST/RecordLayoutBuilder.cpp test/Sema/bitfield-layout.c
Index: test/Sema/bitfield-layout.c =================================================================== --- test/Sema/bitfield-layout.c +++ test/Sema/bitfield-layout.c @@ -1,41 +1,72 @@ // RUN: %clang_cc1 %s -fsyntax-only -verify -triple=i686-apple-darwin9 +// RUN: %clang_cc1 %s -fsyntax-only -verify -triple=armv7 // expected-no-diagnostics +#include <stddef.h> -#define CHECK_SIZE(kind, name, size) extern int name##1[sizeof(kind name) == size ? 1 : -1]; -#define CHECK_ALIGN(kind, name, size) extern int name##2[__alignof(kind name) == size ? 1 : -1]; +#define CHECK_SIZE(kind, name, size) \ + extern int name##1[sizeof(kind name) == size ? 1 : -1]; +#define CHECK_ALIGN(kind, name, size) \ + extern int name##2[__alignof(kind name) == size ? 1 : -1]; +#define CHECK_OFFSET(kind, name, member, offset) \ + extern int name##2[offsetof(kind name, member) == offset ? 1 : -1]; // Zero-width bit-fields struct a {char x; int : 0; char y;}; +#ifdef __ARM_EABI__ +CHECK_SIZE(struct, a, 8) +CHECK_ALIGN(struct, a, 4) +#else CHECK_SIZE(struct, a, 5) CHECK_ALIGN(struct, a, 1) +#endif // Zero-width bit-fields with packed struct __attribute__((packed)) a2 { short x : 9; char : 0; int y : 17; }; CHECK_SIZE(struct, a2, 5) CHECK_ALIGN(struct, a2, 1) // Zero-width bit-fields at the end of packed struct struct __attribute__((packed)) a3 { short x : 9; int : 0; }; +#ifdef __ARM_EABI__ +CHECK_SIZE(struct, a3, 4) +CHECK_ALIGN(struct, a3, 4) +#else CHECK_SIZE(struct, a3, 4) CHECK_ALIGN(struct, a3, 1) +#endif // For comparison, non-zero-width bit-fields at the end of packed struct struct __attribute__((packed)) a4 { short x : 9; int : 1; }; CHECK_SIZE(struct, a4, 2) CHECK_ALIGN(struct, a4, 1) union b {char x; int : 0; char y;}; +#ifdef __ARM_EABI__ +CHECK_SIZE(union, b, 4) +CHECK_ALIGN(union, b, 4) +#else CHECK_SIZE(union, b, 1) CHECK_ALIGN(union, b, 1) +#endif // Unnamed bit-field align struct c {char x; int : 20;}; +#ifdef __ARM_EABI__ +CHECK_SIZE(struct, c, 4) +CHECK_ALIGN(struct, c, 4) +#else CHECK_SIZE(struct, c, 4) CHECK_ALIGN(struct, c, 1) +#endif union d {char x; int : 20;}; +#ifdef __ARM_EABI__ +CHECK_SIZE(union, d, 4) +CHECK_ALIGN(union, d, 4) +#else CHECK_SIZE(union, d, 3) CHECK_ALIGN(union, d, 1) +#endif // Bit-field packing struct __attribute__((packed)) e {int x : 4, y : 30, z : 30;}; @@ -56,3 +87,99 @@ CHECK_SIZE(struct, s0, 0x32100008) CHECK_ALIGN(struct, s0, 4) +// Bit-field with explicit align bigger than normal. +struct g0 { + char a; + __attribute__((aligned(16))) int b : 1; + char c; +}; + +CHECK_SIZE(struct, g0, 32); +CHECK_ALIGN(struct, g0, 16); +CHECK_OFFSET(struct, g0, c, 17); + +// Bit-field with explicit align smaller than normal. +struct g1 { + char a; + __attribute__((aligned(2))) int b : 1; + char c; +}; + +CHECK_SIZE(struct, g1, 4); +CHECK_ALIGN(struct, g1, 4); +CHECK_OFFSET(struct, g1, c, 3); + +// Same as above but without explicit align. +struct g2 { + char a; + int b : 1; + char c; +}; + +CHECK_SIZE(struct, g2, 4); +CHECK_ALIGN(struct, g2, 4); +CHECK_OFFSET(struct, g2, c, 2); + +// Explicit attribute align on bit-field has precedence over packed attribute +// applied too the struct. +struct __attribute__((packed)) g3 { + char a; + __attribute__((aligned(16))) int b : 1; + char c; +}; + +CHECK_SIZE(struct, g3, 32); +CHECK_ALIGN(struct, g3, 16); +CHECK_OFFSET(struct, g3, c, 17); + +struct __attribute__((packed)) g4 { + char a; + __attribute__((aligned(2))) int b : 1; + char c; +}; + +CHECK_SIZE(struct, g4, 4); +CHECK_ALIGN(struct, g4, 2); +CHECK_OFFSET(struct, g4, c, 3); + +struct g5 { + char : 1; + __attribute__((aligned(1))) int n : 24; +}; +CHECK_SIZE(struct, g5, 4); +CHECK_ALIGN(struct, g5, 4); + +struct __attribute__((packed)) g6 { + char : 1; + __attribute__((aligned(1))) int n : 24; +}; +CHECK_SIZE(struct, g6, 4); +CHECK_ALIGN(struct, g6, 1); + +struct g7 { + char : 1; + __attribute__((aligned(1))) int n : 25; +}; +CHECK_SIZE(struct, g7, 8); +CHECK_ALIGN(struct, g7, 4); + +struct __attribute__((packed)) g8 { + char : 1; + __attribute__((aligned(1))) int n : 25; +}; +CHECK_SIZE(struct, g8, 5); +CHECK_ALIGN(struct, g8, 1); + +struct g9 { + __attribute__((aligned(1))) char a : 2, b : 2, c : 2, d : 2, e : 2; + int i; +}; +CHECK_SIZE(struct, g9, 12); +CHECK_ALIGN(struct, g9, 4); + +struct __attribute__((packed)) g10 { + __attribute__((aligned(1))) char a : 2, b : 2, c : 2, d : 2, e : 2; + int i; +}; +CHECK_SIZE(struct, g10, 9); +CHECK_ALIGN(struct, g10, 1); Index: lib/AST/RecordLayoutBuilder.cpp =================================================================== --- lib/AST/RecordLayoutBuilder.cpp +++ lib/AST/RecordLayoutBuilder.cpp @@ -1552,7 +1552,8 @@ FieldAlign = 1; // But, if there's an 'aligned' attribute on the field, honor that. - if (unsigned ExplicitFieldAlign = D->getMaxAlignment()) { + unsigned ExplicitFieldAlign = D->getMaxAlignment(); + if (ExplicitFieldAlign) { FieldAlign = std::max(FieldAlign, ExplicitFieldAlign); UnpackedFieldAlign = std::max(UnpackedFieldAlign, ExplicitFieldAlign); } @@ -1601,10 +1602,12 @@ (AllowPadding && (FieldOffset & (FieldAlign-1)) + FieldSize > TypeSize)) { FieldOffset = llvm::RoundUpToAlignment(FieldOffset, FieldAlign); - } + } else if (ExplicitFieldAlign) + FieldOffset = llvm::RoundUpToAlignment(FieldOffset, ExplicitFieldAlign); // Repeat the computation for diagnostic purposes. if (FieldSize == 0 || + ExplicitFieldAlign || (AllowPadding && (UnpackedFieldOffset & (UnpackedFieldAlign-1)) + FieldSize > TypeSize)) UnpackedFieldOffset = llvm::RoundUpToAlignment(UnpackedFieldOffset,
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits