Hi rnk, rsmith,

Adds a new file and some tests for laying out C records in a manner consistent 
with cl.exe.

http://llvm-reviews.chandlerc.com/D1026

Files:
  include/clang/AST/ASTContext.h
  lib/AST/CMakeLists.txt
  lib/AST/MicrosoftRecordLayoutBuilder.cpp
  lib/AST/RecordLayoutBuilder.cpp
  test/Sema/ms_bitfield_layout.c
Index: include/clang/AST/ASTContext.h
===================================================================
--- include/clang/AST/ASTContext.h
+++ include/clang/AST/ASTContext.h
@@ -1618,6 +1618,7 @@
   /// record (struct/union/class) \p D, which indicates its size and field
   /// position information.
   const ASTRecordLayout &getASTRecordLayout(const RecordDecl *D) const;
+  const ASTRecordLayout *BuildMicrosoftASTRecordLayout(const RecordDecl *D) const;
 
   /// \brief Get or compute information about the layout of the specified
   /// Objective-C interface.
Index: lib/AST/CMakeLists.txt
===================================================================
--- lib/AST/CMakeLists.txt
+++ lib/AST/CMakeLists.txt
@@ -39,6 +39,7 @@
   Mangle.cpp
   MicrosoftCXXABI.cpp
   MicrosoftMangle.cpp
+  MicrosoftRecordLayoutBuilder.cpp
   NestedNameSpecifier.cpp
   NSAPI.cpp
   ParentMap.cpp
Index: lib/AST/MicrosoftRecordLayoutBuilder.cpp
===================================================================
--- /dev/null
+++ lib/AST/MicrosoftRecordLayoutBuilder.cpp
@@ -0,0 +1,303 @@
+//=== MicrosoftRecordLayoutBuilder.cpp - Microsoft record layout helpers ---==//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/AST/RecordLayout.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/Attr.h"
+#include "clang/AST/CXXInheritance.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/DeclCXX.h"
+#include "clang/AST/DeclObjC.h"
+#include "clang/AST/Expr.h"
+#include "clang/Basic/TargetInfo.h"
+#include "clang/Sema/SemaDiagnostic.h"
+#include "llvm/ADT/SmallSet.h"
+#include "llvm/Support/CrashRecoveryContext.h"
+#include "llvm/Support/Format.h"
+#include "llvm/Support/MathExtras.h"
+
+using namespace clang;
+
+namespace {
+struct MicrosoftRecordLayoutBuilder {
+  const ASTContext &Context;
+
+  MicrosoftRecordLayoutBuilder(const ASTContext &Context)
+    : Context(Context) { }
+
+  MicrosoftRecordLayoutBuilder(
+      const MicrosoftRecordLayoutBuilder &) LLVM_DELETED_FUNCTION;
+  void operator=(const MicrosoftRecordLayoutBuilder &) LLVM_DELETED_FUNCTION;
+
+  void Layout(const RecordDecl *RD);
+  void InitializeLayout(const RecordDecl *RD);
+  void FinalizeLayout(const RecordDecl *RD);
+
+  void LayoutField(const FieldDecl *FD);
+  void LayoutBitField(const FieldDecl *FD);
+  void LayoutZeroWidthBitField(const FieldDecl *FD);
+
+  CharUnits getSize() const { return Size; }
+  void setSize(CharUnits NewSize) { Size = NewSize; }
+
+  void UpdateAlignment(CharUnits NewAlignment);
+  CharUnits getAlignment() const { return Alignment; }
+
+  const uint64_t* getFieldOffsets() const { return FieldOffsets.data(); }
+  size_t getNumFieldOffsets() const { return FieldOffsets.size(); }
+
+  /// getAdjustedFieldInfo - Gets the size and alignment.  This function
+  /// takes the field packed attribute and MaxFieldAlignment into
+  /// account when returning alignment.
+  inline std::pair<CharUnits, CharUnits> getAdjustedFieldInfo(
+      const FieldDecl *FD) const;
+
+  void PlaceFieldAtZero() {
+    FieldOffsets.push_back(0);
+  }
+  void PlaceFieldAtOffset(CharUnits FieldOffset) {
+    FieldOffsets.push_back(Context.toBits(FieldOffset));
+  }
+  void PlaceFieldAtBitOffset(uint64_t FieldOffset) {
+    FieldOffsets.push_back(FieldOffset);
+  }
+
+  void WarnIgnoredBitfieldAndAlignment();
+  void WarnUnionedBitfieldAndAlignment();
+  void ErrorBitfieldIsTooWide();
+
+private:
+  // ------ Output Values ------
+  /// Size - The size of the record being laid out.
+  CharUnits Size;
+  /// Alignment - The current alignment of the record layout.
+  CharUnits Alignment;
+  /// FieldOffsets - The collection of field offsets.
+  SmallVector<uint64_t, 16> FieldOffsets;
+
+  // ------ Layout Properties ------
+  bool IsUnion;
+  /// MaxFieldAlignment - The maximum allowed field alignment. This is set by
+  /// #pragma pack.
+  CharUnits MaxFieldAlignment;
+
+  // ------ Intermediate state ------
+  // Bit-Field intermediate state
+  /// LastFieldIsNonZeroWidthBitfield - True if the last field layed out was
+  /// a bitfield and was not 0 width.
+  bool LastFieldIsNonZeroWidthBitfield;
+  /// CurrentBitfieldSize - The size of the allocation of the currently active
+  /// bitfield.  This value isn't meaningful unless
+  /// LastFieldIsNonZeroWidthBitfield is true.
+  CharUnits CurrentBitfieldSize;
+  /// RemainingBitsInField - The number of remaining bits in our last bitfield
+  /// allocation.  This value isn't meaningful unless
+  /// LastFieldIsNonZeroWidthBitfield is true.
+  unsigned RemainingBitsInField;
+};
+} // end anonymous namespace
+
+std::pair<CharUnits, CharUnits>
+MicrosoftRecordLayoutBuilder::getAdjustedFieldInfo(const FieldDecl *FD) const {
+  std::pair<CharUnits, CharUnits> FieldInfo;
+  if (FD->getType()->isIncompleteArrayType()) {
+    // This is a flexible array member; we can't directly
+    // query getTypeInfo about these, so we figure it out here.
+    // Flexible array members don't have any size, but they
+    // have to be aligned appropriately for their element type.
+    FieldInfo.first = CharUnits::Zero();
+    const ArrayType* ATy = Context.getAsArrayType(FD->getType());
+    FieldInfo.second = Context.getTypeAlignInChars(ATy->getElementType());
+  } else
+    FieldInfo = Context.getTypeInfoInChars(FD->getType());
+
+  // Respect alignment attributes.
+  FieldInfo.second = std::max(FieldInfo.second, 
+    Context.toCharUnitsFromBits(FD->getMaxAlignment()));
+  // Respect packed attribute.
+  if (FD->hasAttr<PackedAttr>())
+    FieldInfo.second = CharUnits::One();
+  // Respect pack pragma.
+  else if (!MaxFieldAlignment.isZero())
+      FieldInfo.second = std::min(FieldInfo.second, MaxFieldAlignment);
+  return FieldInfo;
+}
+
+void MicrosoftRecordLayoutBuilder::UpdateAlignment(CharUnits NewAlignment) {
+  if (NewAlignment > Alignment) {
+    assert(llvm::isPowerOf2_32(NewAlignment.getQuantity() &&
+           "Alignment not a power of 2"));
+    Alignment = NewAlignment;
+  }
+}
+
+void MicrosoftRecordLayoutBuilder::InitializeLayout(const RecordDecl *RD) {
+  // Read layout properties
+  IsUnion = RD->isUnion();
+
+  // Initalize Output State.
+  Alignment = CharUnits::One();
+  Size = CharUnits::Zero();
+  FieldOffsets.erase(FieldOffsets.begin(), FieldOffsets.end());
+
+  // Clear our bit-fild related temporaries.
+  LastFieldIsNonZeroWidthBitfield = false;
+
+  // Honor the default struct packing maximum alignment flag.
+  MaxFieldAlignment = CharUnits::Zero();
+  if (unsigned DefaultMaxFieldAlignment = Context.getLangOpts().PackStruct)
+    MaxFieldAlignment = CharUnits::fromQuantity(DefaultMaxFieldAlignment);
+  if (const MaxFieldAlignmentAttr *MFAA = RD->getAttr<MaxFieldAlignmentAttr>())
+    MaxFieldAlignment = Context.toCharUnitsFromBits(MFAA->getAlignment());
+  // Packed attribute forces max field alignment to be 1.
+  if (RD->hasAttr<PackedAttr>())
+    MaxFieldAlignment = CharUnits::One();
+
+  // Set the alignment to the maximum alignment set by any attribute.
+  if (unsigned MaxAlign = RD->getMaxAlignment())
+    UpdateAlignment(Context.toCharUnitsFromBits(MaxAlign));
+}
+
+void MicrosoftRecordLayoutBuilder::FinalizeLayout(const RecordDecl *RD) {
+  Size = Size.RoundUpToAlignment(Alignment);
+}
+
+void MicrosoftRecordLayoutBuilder::Layout(const RecordDecl *RD) {
+  InitializeLayout(RD);
+  for (RecordDecl::field_iterator Field = RD->field_begin(),
+       FieldEnd = RD->field_end(); Field != FieldEnd; ++Field)
+      LayoutField(*Field);
+  FinalizeLayout(RD);
+}
+
+void MicrosoftRecordLayoutBuilder::LayoutField(const FieldDecl *FD) {
+  if (FD->isBitField()) {
+    LayoutBitField(FD);
+    return;
+  }
+
+  std::pair<CharUnits, CharUnits> FieldInfo = getAdjustedFieldInfo(FD);
+  CharUnits FieldSize = FieldInfo.first;
+  CharUnits FieldAlign = FieldInfo.second;
+
+  LastFieldIsNonZeroWidthBitfield = false;
+  UpdateAlignment(FieldAlign);
+  if (IsUnion) {
+    PlaceFieldAtZero();
+    setSize(std::max(getSize(), FieldSize));
+  } else {
+    // Round up the current record size to the field's alignment boundary.
+    CharUnits FieldOffset = getSize().RoundUpToAlignment(FieldAlign);
+    PlaceFieldAtOffset(FieldOffset);
+    setSize(FieldOffset + FieldSize);
+  }
+}
+
+void MicrosoftRecordLayoutBuilder::LayoutBitField(const FieldDecl *FD) {
+  unsigned Width = FD->getBitWidthValue(Context);
+  if (Width == 0) {
+    LayoutZeroWidthBitField(FD);
+    return;
+  }
+
+  std::pair<CharUnits, CharUnits> FieldInfo = getAdjustedFieldInfo(FD);
+  CharUnits FieldSize = FieldInfo.first;
+  CharUnits FieldAlign = FieldInfo.second;
+
+  // Check for bitfields that are wider than their storage type.
+  if (Width > Context.toBits(FieldSize))
+    ErrorBitfieldIsTooWide();
+
+  // Check to see if this bitfield fits into an existing allocation.
+  if (!IsUnion &&
+      LastFieldIsNonZeroWidthBitfield &&
+      CurrentBitfieldSize == FieldSize &&
+      Width <= RemainingBitsInField) {
+    PlaceFieldAtBitOffset(Context.toBits(getSize()) - RemainingBitsInField);
+    RemainingBitsInField -= Width;
+    return;
+  }
+
+  LastFieldIsNonZeroWidthBitfield = true;
+  CurrentBitfieldSize = FieldSize;
+  if (IsUnion) {
+    PlaceFieldAtZero();
+    setSize(std::max(getSize(), FieldSize));
+    if (FieldAlign > Alignment)
+      WarnUnionedBitfieldAndAlignment();
+  } else {
+    // Allocate a new block of memory and place the bitfield in it.
+    CharUnits FieldOffset = getSize().RoundUpToAlignment(FieldAlign);
+    PlaceFieldAtOffset(FieldOffset);
+    setSize(FieldOffset + FieldSize);
+    UpdateAlignment(FieldAlign);
+    RemainingBitsInField = Context.toBits(FieldSize) - Width;
+  }
+}
+
+void
+MicrosoftRecordLayoutBuilder::LayoutZeroWidthBitField(const FieldDecl *FD) {
+  // Zero-width bitfields are ignored unless they follow a non-zero-width
+  // bitfield.
+  std::pair<CharUnits, CharUnits> FieldInfo = getAdjustedFieldInfo(FD);
+  CharUnits FieldSize = FieldInfo.first;
+  CharUnits FieldAlign = FieldInfo.second;
+
+  if (!LastFieldIsNonZeroWidthBitfield) {
+    PlaceFieldAtOffset(IsUnion ? CharUnits::Zero() : Size);
+    if (FieldAlign > Alignment)
+      WarnIgnoredBitfieldAndAlignment();
+    return;
+  }
+
+  LastFieldIsNonZeroWidthBitfield = false;
+  if (IsUnion) {
+    PlaceFieldAtZero();
+    setSize(std::max(getSize(), FieldSize));
+    if (FieldAlign > Alignment)
+      WarnUnionedBitfieldAndAlignment();
+  } else {
+    // Round up the current record size to the field's alignment boundary.
+    CharUnits FieldOffset = getSize().RoundUpToAlignment(FieldAlign);
+    PlaceFieldAtOffset(FieldOffset);
+    setSize(FieldOffset);
+    UpdateAlignment(FieldAlign);
+  }
+}
+
+void MicrosoftRecordLayoutBuilder::WarnIgnoredBitfieldAndAlignment() {
+}
+
+void MicrosoftRecordLayoutBuilder::WarnUnionedBitfieldAndAlignment() {
+}
+
+void MicrosoftRecordLayoutBuilder::ErrorBitfieldIsTooWide() {
+  assert(false && "TODO(whunt): throw the correct error here");
+}
+
+/// BuildMicrosoftASTRecordLayout - Get or compute information about the
+/// layout of the specified record (struct/union/class), which indicates its
+/// size and field position information.
+const ASTRecordLayout *
+ASTContext::BuildMicrosoftASTRecordLayout(const RecordDecl *D) const {
+  if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(D)) {
+    assert(false && "we don't yet support C++ struct layout");
+    return 0;
+  } else {
+    MicrosoftRecordLayoutBuilder Builder(*this);
+    Builder.Layout(D);
+    return new (*this) ASTRecordLayout(
+        *this,
+        Builder.getSize(),
+        Builder.getAlignment(),
+        Builder.getSize(),
+        Builder.getFieldOffsets(),
+        Builder.getNumFieldOffsets());
+  }
+}
Index: lib/AST/RecordLayoutBuilder.cpp
===================================================================
--- lib/AST/RecordLayoutBuilder.cpp
+++ lib/AST/RecordLayoutBuilder.cpp
@@ -2524,15 +2524,21 @@
                                   Builder.PrimaryBaseIsVirtual,
                                   Builder.Bases, Builder.VBases);
   } else {
-    RecordLayoutBuilder Builder(*this, /*EmptySubobjects=*/0);
-    Builder.Layout(D);
-
-    NewEntry =
-      new (*this) ASTRecordLayout(*this, Builder.getSize(), 
-                                  Builder.Alignment,
-                                  Builder.getSize(),
-                                  Builder.FieldOffsets.data(),
-                                  Builder.FieldOffsets.size());
+    if (getTargetInfo().getPointerWidth(0) == 32 &&
+        getTargetInfo().getCXXABI().isMicrosoft() &&
+        !D->isMsStruct(*this))
+      NewEntry = BuildMicrosoftASTRecordLayout(D);
+    else {
+      RecordLayoutBuilder Builder(*this, /*EmptySubobjects=*/0);
+      Builder.Layout(D);
+
+      NewEntry =
+        new (*this) ASTRecordLayout(*this, Builder.getSize(), 
+                                    Builder.Alignment,
+                                    Builder.getSize(),
+                                    Builder.FieldOffsets.data(),
+                                    Builder.FieldOffsets.size());
+    }
   }
 
   ASTRecordLayouts[D] = NewEntry;
Index: test/Sema/ms_bitfield_layout.c
===================================================================
--- /dev/null
+++ test/Sema/ms_bitfield_layout.c
@@ -0,0 +1,404 @@
+// RUN: %clang_cc1 -emit-llvm-only -triple i686-pc-win32 -fdump-record-layouts -cxx-abi microsoft %s 2>&1 \
+// RUN:            | FileCheck %s
+
+typedef __SIZE_TYPE__ size_t;
+int printf(const char *fmt, ...);
+void* memset(void* ptr, int value, size_t num);
+
+typedef struct A {
+	char x;
+	int a : 22;
+	int : 0;
+	int c : 10;
+	char b : 3;
+	char d: 4;
+	short y;
+} A;
+
+typedef struct B {
+	char x;
+	int : 0;
+	short a : 4;
+	char y;
+} B;
+
+typedef struct C {
+	char x;
+	short a : 4;
+	int : 0;
+	char y;
+} C;
+
+typedef struct D {
+	char x;
+	short : 0;
+	int : 0;
+	char y;
+} D;
+
+typedef union E {
+	char x;
+	long long a : 3;
+	int b : 3;
+	long long : 0;
+	short y;
+} E;
+
+typedef struct F {
+	char x;
+	char a : 3;
+	char b : 3;
+	char c : 3;
+	short d : 6;
+	short e : 6;
+	short f : 6;
+	short g : 11;
+	short h : 11;
+	short i : 11;
+	short y;
+} F;
+
+typedef union G {
+	char x;
+	int a : 3;
+	int : 0;
+	long long : 0;
+	short y;
+} G;
+
+typedef struct H {
+	unsigned short a : 1;
+	unsigned char : 0;
+	unsigned long : 0;
+	unsigned short c : 1;
+} H;
+
+#pragma pack(push, 1)
+
+typedef struct A1 {
+	char x;
+	int a : 22;
+	int : 0;
+	int c : 10;
+	char b : 3;
+	char d: 4;
+	short y;
+} A1;
+
+typedef struct B1 {
+	char x;
+	int : 0;
+	short a : 4;
+	char y;
+} B1;
+
+typedef struct C1 {
+	char x;
+	short a : 4;
+	int : 0;
+	char y;
+} C1;
+
+typedef struct D1 {
+	char x;
+	short : 0;
+	int : 0;
+	char y;
+} D1;
+
+typedef union E1 {
+	char x;
+	long long a : 3;
+	int b : 3;
+	long long : 0;
+	short y;
+} E1;
+
+typedef struct F1 {
+	char x;
+	char a : 3;
+	char b : 3;
+	char c : 3;
+	short d : 6;
+	short e : 6;
+	short f : 6;
+	short g : 11;
+	short h : 11;
+	short i : 11;
+	short y;
+} F1;
+
+typedef union G1 {
+	char x;
+	int a : 3;
+	int : 0;
+	long long : 0;
+	short y;
+} G1;
+
+typedef struct H1 {
+	unsigned long a : 1;
+	unsigned char : 0;
+	unsigned long : 0;
+	unsigned long c : 1;
+} H1;
+
+#pragma pack(pop)
+
+void PrintBits(char* p, size_t n) {
+	size_t i, j;
+	for (i = 0; i < n; i++) {
+		for (j = 0; j < 8; j++)
+			printf("%d", (p[i] >> j)&1);
+		printf(" ");
+	}
+	printf("\n");
+}
+
+int main() {
+	A a;
+	B b;
+	C c;
+	D d;
+	E e;
+	F f;
+	G g;
+	H h;
+	A1 a1;
+	B1 b1;
+	C1 c1;
+	D1 d1;
+	E1 e1;
+	F1 f1;
+	G1 g1;
+	H1 h1;
+
+	memset(&a, 0, sizeof(A));
+	a.a = -1;
+	a.b = -1;
+	a.c = -1;
+	a.d = -1;
+	a.x = -1;
+	a.y = -1;
+	printf("size = %d\nalignment = %d\n", sizeof(A), __alignof(A));
+	PrintBits((char*)&a, sizeof(A));
+
+	memset(&b, 0, sizeof(B));
+	b.x = -1;
+	b.a = -1;
+	b.y = -1;
+	printf("size = %d\nalignment = %d\n", sizeof(B), __alignof(B));
+	PrintBits((char*)&b, sizeof(B));
+
+	memset(&c, 0, sizeof(C));
+	c.x = -1;
+	c.a = -1;
+	c.y = -1;
+	printf("size = %d\nalignment = %d\n", sizeof(C), __alignof(C));
+	PrintBits((char*)&c, sizeof(C));
+
+	memset(&d, 0, sizeof(D));
+	d.x = -1;
+	d.y = -1;
+	printf("size = %d\nalignment = %d\n", sizeof(D), __alignof(D));
+	PrintBits((char*)&d, sizeof(D));
+
+	memset(&e, 0, sizeof(E));
+	e.x = -1;
+	e.a = -1;
+	e.b = -1;
+	e.y = -1;
+	printf("size = %d\nalignment = %d\n", sizeof(E), __alignof(E));
+	PrintBits((char*)&e, sizeof(E));
+
+	memset(&f, 0, sizeof(F));
+	f.x = -1;
+	f.a = -1;
+	f.b = -1;
+	f.c = -1;
+	f.d = -1;
+	f.e = -1;
+	f.f = -1;
+	f.g = -1;
+	f.h = -1;
+	f.i = -1;
+	f.y = -1;
+	printf("size = %d\nalignment = %d\n", sizeof(F), __alignof(F));
+	PrintBits((char*)&f, sizeof(F));
+
+	memset(&g, 0, sizeof(G));
+	g.x = -1;
+	g.a = -1;
+	g.y = -1;
+	printf("size = %d\nalignment = %d\n", sizeof(G), __alignof(G));
+	PrintBits((char*)&g, sizeof(G));
+
+	memset(&h, 0, sizeof(H));
+	h.a = -1;
+	h.c = -1;
+	printf("size = %d\nalignment = %d\n", sizeof(H), __alignof(H));
+	PrintBits((char*)&h, sizeof(H));
+
+
+	memset(&a1, 0, sizeof(A1));
+	a1.a = -1;
+	a1.b = -1;
+	a1.c = -1;
+	a1.d = -1;
+	a1.x = -1;
+	a1.y = -1;
+	printf("size = %d\nalignment = %d\n", sizeof(A1), __alignof(A1));
+	PrintBits((char*)&a1, sizeof(A1));
+
+	memset(&b1, 0, sizeof(B1));
+	b1.x = -1;
+	b1.a = -1;
+	b1.y = -1;
+	printf("size = %d\nalignment = %d\n", sizeof(B1), __alignof(B1));
+	PrintBits((char*)&b1, sizeof(B1));
+
+	memset(&c1, 0, sizeof(C1));
+	c1.x = -1;
+	c1.a = -1;
+	c1.y = -1;
+	printf("size = %d\nalignment = %d\n", sizeof(C1), __alignof(C1));
+	PrintBits((char*)&c1, sizeof(C1));
+
+	memset(&d1, 0, sizeof(D1));
+	d1.x = -1;
+	d1.y = -1;
+	printf("size = %d\nalignment = %d\n", sizeof(D1), __alignof(D1));
+	PrintBits((char*)&d1, sizeof(D1));
+
+	memset(&e1, 0, sizeof(E1));
+	e1.x = -1;
+	e1.a = -1;
+	e1.b = -1;
+	e1.y = -1;
+	printf("size = %d\nalignment = %d\n", sizeof(E1), __alignof(E1));
+	PrintBits((char*)&e1, sizeof(E1));
+
+	memset(&f1, 0, sizeof(F1));
+	f1.x = -1;
+	f1.a = -1;
+	f1.b = -1;
+	f1.c = -1;
+	f1.d = -1;
+	f1.e = -1;
+	f1.f = -1;
+	f1.g = -1;
+	f1.h = -1;
+	f1.i = -1;
+	f1.y = -1;
+	printf("size = %d\nalignment = %d\n", sizeof(F1), __alignof(F1));
+	PrintBits((char*)&f1, sizeof(F1));
+
+	memset(&g1, 0, sizeof(G1));
+	g1.x = -1;
+	g1.a = -1;
+	g1.y = -1;
+	printf("size = %d\nalignment = %d\n", sizeof(G1), __alignof(G1));
+	PrintBits((char*)&g1, sizeof(G1));
+
+	memset(&h1, 0, sizeof(H1));
+	h1.a = -1;
+	h1.c = -1;
+	printf("size = %d\nalignment = %d\n", sizeof(H1), __alignof(H1));
+	PrintBits((char*)&h1, sizeof(H1));
+}
+
+// CHECK: Type: struct A
+// CHECK:   Size:128
+// CHECK:   DataSize:128
+// CHECK:   Alignment:32
+// CHECK:   FieldOffsets: [0, 32, 64, 64, 96, 99, 112]>
+
+// CHECK: Type: struct B
+// CHECK:   Size:48
+// CHECK:   DataSize:48
+// CHECK:   Alignment:16
+// CHECK:   FieldOffsets: [0, 8, 16, 32]>
+
+// CHECK: Type: struct C
+// CHECK:   Size:64
+// CHECK:   DataSize:64
+// CHECK:   Alignment:32
+// CHECK:   FieldOffsets: [0, 16, 32, 32]>
+
+// CHECK: Type: struct D
+// CHECK:   Size:16
+// CHECK:   DataSize:16
+// CHECK:   Alignment:8
+// CHECK:   FieldOffsets: [0, 8, 8, 8]>
+
+// CHECK: Type: union E
+// CHECK:   Size:64
+// CHECK:   DataSize:64
+// CHECK:   Alignment:16
+// CHECK:   FieldOffsets: [0, 0, 0, 0, 0]>
+
+// CHECK: Type: struct F
+// CHECK:   Size:128
+// CHECK:   DataSize:128
+// CHECK:   Alignment:16
+// CHECK:   FieldOffsets: [0, 8, 11, 16, 32, 38, 48, 64, 80, 96, 112]>
+
+// CHECK: Type: union G
+// CHECK:   Size:32
+// CHECK:   DataSize:32
+// CHECK:   Alignment:16
+// CHECK:   FieldOffsets: [0, 0, 0, 0, 0]>
+
+// CHECK: Type: struct H
+// CHECK:   Size:32
+// CHECK:   DataSize:32
+// CHECK:   Alignment:16
+// CHECK:   FieldOffsets: [0, 16, 16, 16]>
+
+// CHECK: Type: struct A1
+// CHECK:   Size:96
+// CHECK:   DataSize:96
+// CHECK:   Alignment:8
+// CHECK:   FieldOffsets: [0, 8, 40, 40, 72, 75, 80]>
+
+// CHECK: Type: struct B1
+// CHECK:   Size:32
+// CHECK:   DataSize:32
+// CHECK:   Alignment:8
+// CHECK:   FieldOffsets: [0, 8, 8, 24]>
+
+// CHECK: Type: struct C1
+// CHECK:   Size:32
+// CHECK:   DataSize:32
+// CHECK:   Alignment:8
+// CHECK:   FieldOffsets: [0, 8, 24, 24]>
+
+// CHECK: Type: struct D1
+// CHECK:   Size:16
+// CHECK:   DataSize:16
+// CHECK:   Alignment:8
+// CHECK:   FieldOffsets: [0, 8, 8, 8]>
+
+// CHECK: Type: union E1
+// CHECK:   Size:64
+// CHECK:   DataSize:64
+// CHECK:   Alignment:8
+// CHECK:   FieldOffsets: [0, 0, 0, 0, 0]>
+
+// CHECK: Type: struct F1
+// CHECK:   Size:120
+// CHECK:   DataSize:120
+// CHECK:   Alignment:8
+// CHECK:   FieldOffsets: [0, 8, 11, 16, 24, 30, 40, 56, 72, 88, 104]>
+
+// CHECK: Type: union G1
+// CHECK:   Size:32
+// CHECK:   DataSize:32
+// CHECK:   Alignment:8
+// CHECK:   FieldOffsets: [0, 0, 0, 0, 0]>
+
+// CHECK: Type: struct H1
+// CHECK:   Size:64
+// CHECK:   DataSize:64
+// CHECK:   Alignment:8
+// CHECK:   FieldOffsets: [0, 32, 32, 32]>
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits

Reply via email to