From 07a8a21c3376f3a2ee470bfa3549c6f3ac4e236d Mon Sep 17 00:00:00 2001 From: Fariborz Jahanian <fjahanian@apple.com> Date: Thu, 28 Apr 2011 22:49:46 +0000 Subject: [PATCH] ms_struct patch for initialization and field access irgen. // rdar://8823265 - wip. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@130451 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/AST/Decl.cpp | 15 +++++- lib/CodeGen/CGExprConstant.cpp | 16 +++++- test/CodeGen/ms_struct-bitfield-init.c | 68 ++++++++++++++++++++++++++ 3 files changed, 96 insertions(+), 3 deletions(-) create mode 100644 test/CodeGen/ms_struct-bitfield-init.c diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp index d37099f8644..89c7d47cb71 100644 --- a/lib/AST/Decl.cpp +++ b/lib/AST/Decl.cpp @@ -2047,13 +2047,24 @@ unsigned FieldDecl::getFieldIndex() const { if (CachedFieldIndex) return CachedFieldIndex - 1; unsigned index = 0; - RecordDecl::field_iterator - i = getParent()->field_begin(), e = getParent()->field_end(); + const RecordDecl *RD = getParent(); + const FieldDecl *LastFD = 0; + bool IsMsStruct = RD->hasAttr<MsStructAttr>(); + + RecordDecl::field_iterator i = RD->field_begin(), e = RD->field_end(); while (true) { assert(i != e && "failed to find field in parent!"); if (*i == this) break; + if (IsMsStruct) { + // Zero-length bitfields following non-bitfield members are ignored. + if (getASTContext().ZeroBitfieldFollowsNonBitfield((*i), LastFD)) { + ++i; + continue; + } + LastFD = (*i); + } ++i; ++index; } diff --git a/lib/CodeGen/CGExprConstant.cpp b/lib/CodeGen/CGExprConstant.cpp index 338fb03b8a0..8054d4b0372 100644 --- a/lib/CodeGen/CGExprConstant.cpp +++ b/lib/CodeGen/CGExprConstant.cpp @@ -344,16 +344,30 @@ bool ConstStructBuilder::Build(InitListExpr *ILE) { unsigned FieldNo = 0; unsigned ElementNo = 0; + const FieldDecl *LastFD = 0; + bool IsMsStruct = RD->hasAttr<MsStructAttr>(); + for (RecordDecl::field_iterator Field = RD->field_begin(), FieldEnd = RD->field_end(); Field != FieldEnd; ++Field, ++FieldNo) { + if (IsMsStruct) { + // Zero-length bitfields following non-bitfield members are + // ignored: + if (CGM.getContext().ZeroBitfieldFollowsNonBitfield((*Field), LastFD)) { + --FieldNo; + continue; + } + LastFD = (*Field); + } // If this is a union, skip all the fields that aren't being initialized. if (RD->isUnion() && ILE->getInitializedFieldInUnion() != *Field) continue; // Don't emit anonymous bitfields, they just affect layout. - if (Field->isBitField() && !Field->getIdentifier()) + if (Field->isBitField() && !Field->getIdentifier()) { + LastFD = (*Field); continue; + } // Get the initializer. A struct can include fields without initializers, // we just use explicit null values for them. diff --git a/test/CodeGen/ms_struct-bitfield-init.c b/test/CodeGen/ms_struct-bitfield-init.c new file mode 100644 index 00000000000..7a483fb84b8 --- /dev/null +++ b/test/CodeGen/ms_struct-bitfield-init.c @@ -0,0 +1,68 @@ +// RUN: %clang_cc1 -emit-llvm-only -triple x86_64-apple-darwin9 %s +// rdar://8823265 + +extern void abort(void); +#define ATTR __attribute__((__ms_struct__)) + +struct +{ + char foo; + long : 0; + char : 0; + int : 0; + char bar; +} ATTR t1 = {'a', 'b'}; + +struct +{ + char bar0; + long : 0; + int : 0; + char bar1; + char bar2; + long : 0; + char bar3; + char bar4; + char : 0; + char bar5; + char bar6; + char : 0; + char bar7; + char bar8; +} ATTR t2 = {'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i'}; + +struct { + int : 0; + int i1; + int : 0; + int i2; + int : 0; + int i3; + int : 0; + int i4; +} t3 = {1,2,3,4}; + +int main() { + if (sizeof(t1) != 2) + abort(); + if (t1.foo != 'a') + abort(); + if (t1.bar != 'b') + abort(); + t1.foo = 'c'; + t1.bar = 'd'; + if (t1.foo != 'c') + abort(); + if (t1.bar != 'd') + abort(); + if (sizeof(t2) != 9) + abort(); + if (t2.bar0 != 'a' || t2.bar8 != 'i') + abort(); + if (sizeof(t3) != 16) + abort(); + if (t3.i1 != 1 || t3.i4 != 4) + abort(); + return 0; +} + -- GitLab