DmitryPolukhin created this revision. DmitryPolukhin added a reviewer: rjmccall. DmitryPolukhin added a subscriber: cfe-commits.
Fix binary compatibility issue with GCC. 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,8 +1,13 @@ // RUN: %clang_cc1 %s -fsyntax-only -verify -triple=i686-apple-darwin9 // 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;}; @@ -56,3 +61,35 @@ 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); 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,
Index: test/Sema/bitfield-layout.c =================================================================== --- test/Sema/bitfield-layout.c +++ test/Sema/bitfield-layout.c @@ -1,8 +1,13 @@ // RUN: %clang_cc1 %s -fsyntax-only -verify -triple=i686-apple-darwin9 // 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;}; @@ -56,3 +61,35 @@ 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); 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