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