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