diff options
author | Eli Friedman <eli.friedman@gmail.com> | 2011-12-02 02:38:48 +0000 |
---|---|---|
committer | Eli Friedman <eli.friedman@gmail.com> | 2011-12-02 02:38:48 +0000 |
commit | a91d38a435431672404a65030f6b5896e4564d0e (patch) | |
tree | 927ddc3ccaf8a6a75404d47173eaf9bc36af258b | |
parent | a48d32bc9c5f6cfcde7234ab1d81fdccb051c7b7 (diff) | |
download | bcm5719-llvm-a91d38a435431672404a65030f6b5896e4564d0e.tar.gz bcm5719-llvm-a91d38a435431672404a65030f6b5896e4564d0e.zip |
Fix bitfield handling for record layout with #pragma pack. <rdar://problem/10494810> and PR9560.
llvm-svn: 145673
-rw-r--r-- | clang/lib/AST/RecordLayoutBuilder.cpp | 8 | ||||
-rw-r--r-- | clang/test/Sema/pragma-pack-5.c | 45 |
2 files changed, 50 insertions, 3 deletions
diff --git a/clang/lib/AST/RecordLayoutBuilder.cpp b/clang/lib/AST/RecordLayoutBuilder.cpp index 88a90a41729..c92116ac6c4 100644 --- a/clang/lib/AST/RecordLayoutBuilder.cpp +++ b/clang/lib/AST/RecordLayoutBuilder.cpp @@ -1690,18 +1690,20 @@ void RecordLayoutBuilder::LayoutBitField(const FieldDecl *D) { UnpackedFieldAlign = std::max(UnpackedFieldAlign, D->getMaxAlignment()); // The maximum field alignment overrides the aligned attribute. - if (!MaxFieldAlignment.isZero()) { + if (!MaxFieldAlignment.isZero() && FieldSize != 0) { unsigned MaxFieldAlignmentInBits = Context.toBits(MaxFieldAlignment); FieldAlign = std::min(FieldAlign, MaxFieldAlignmentInBits); UnpackedFieldAlign = std::min(UnpackedFieldAlign, MaxFieldAlignmentInBits); } // Check if we need to add padding to give the field the correct alignment. - if (FieldSize == 0 || (FieldOffset & (FieldAlign-1)) + FieldSize > TypeSize) + if (FieldSize == 0 || (MaxFieldAlignment.isZero() && + (FieldOffset & (FieldAlign-1)) + FieldSize > TypeSize)) FieldOffset = llvm::RoundUpToAlignment(FieldOffset, FieldAlign); if (FieldSize == 0 || - (UnpackedFieldOffset & (UnpackedFieldAlign-1)) + FieldSize > TypeSize) + (MaxFieldAlignment.isZero() && + (UnpackedFieldOffset & (UnpackedFieldAlign-1)) + FieldSize > TypeSize)) UnpackedFieldOffset = llvm::RoundUpToAlignment(UnpackedFieldOffset, UnpackedFieldAlign); diff --git a/clang/test/Sema/pragma-pack-5.c b/clang/test/Sema/pragma-pack-5.c new file mode 100644 index 00000000000..95bbe1fe7e9 --- /dev/null +++ b/clang/test/Sema/pragma-pack-5.c @@ -0,0 +1,45 @@ +// RUN: %clang_cc1 -triple x86_64-apple-darwin9 %s -fsyntax-only -verify -ffreestanding +// <rdar://problem/10494810> and PR9560 +// Check #pragma pack handling with bitfields. + +#include <stddef.h> +#pragma pack(2) + +struct s0 { + char f1; + unsigned f2 : 32; + char f3; +}; +extern int check[sizeof(struct s0) == 6 ? 1 : -1]; + +struct s1 { + char f1; + unsigned : 0; + char f3; +}; +extern int check[sizeof(struct s1) == 5 ? 1 : -1]; + +struct s2 { + char f1; + unsigned : 0; + unsigned f3 : 8; + char f4; +}; +extern int check[sizeof(struct s2) == 6 ? 1 : -1]; + +struct s3 { + char f1; + unsigned : 0; + unsigned f3 : 16; + char f4; +}; +extern int check[sizeof(struct s3) == 8 ? 1 : -1]; +extern int check[offsetof(struct s3, f4) == 6 ? 1 : -1]; + +struct s4 { + char f1; + unsigned f2 : 8; + char f3; +}; +extern int check[sizeof(struct s4) == 4 ? 1 : -1]; +extern int check[offsetof(struct s4, f3) == 2 ? 1 : -1]; |