From 0cfc51eb0988aea7ba89f838d32872d6d3f98428 Mon Sep 17 00:00:00 2001 From: John McCall Date: Wed, 19 Aug 2015 22:42:36 +0000 Subject: [PATCH] Fix the layout of bitfields in ms_struct unions: their alignment is ignored, and they always allocate a complete storage unit. Also, change the dumping of AST record layouts: use the more readable C++-style dumping even in C, include bitfield offset information in the dump, and don't print sizeof/alignof information for fields of record type, since we don't do so for bases or other kinds of field. rdar://22275433 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@245514 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/AST/RecordLayoutBuilder.cpp | 242 +++++++++++------- test/CodeGen/ms_struct-pack.c | 14 +- test/CodeGen/override-layout.c | 5 +- test/Layout/itanium-union-bitfield.cpp | 16 +- .../Layout/ms-x86-alias-avoidance-padding.cpp | 24 -- test/Layout/ms-x86-bitfields-vbases.cpp | 24 +- test/Layout/ms-x86-empty-layout.c | 56 ++-- test/Layout/ms-x86-empty-nonvirtual-bases.cpp | 12 - test/Layout/ms-x86-empty-virtual-base.cpp | 4 - test/Layout/ms-x86-pack-and-align.cpp | 80 ++---- test/Layout/ms_struct-bitfields.c | 48 ++++ test/Sema/ms_bitfield_layout.c | 220 ++++++++++------ test/Sema/ms_class_layout.cpp | 11 +- 13 files changed, 424 insertions(+), 332 deletions(-) create mode 100644 test/Layout/ms_struct-bitfields.c diff --git a/lib/AST/RecordLayoutBuilder.cpp b/lib/AST/RecordLayoutBuilder.cpp index d3aeb3e41a..36c5817a0b 100644 --- a/lib/AST/RecordLayoutBuilder.cpp +++ b/lib/AST/RecordLayoutBuilder.cpp @@ -1565,6 +1565,12 @@ void ItaniumRecordLayoutBuilder::LayoutBitField(const FieldDecl *D) { UnpackedFieldAlign = std::min(UnpackedFieldAlign, MaxFieldAlignmentInBits); } + // But, ms_struct just ignores all of that in unions, even explicit + // alignment attributes. + if (IsMsStruct && IsUnion) { + FieldAlign = UnpackedFieldAlign = 1; + } + // For purposes of diagnostics, we're going to simultaneously // compute the field offsets that we would have used if we weren't // adding any alignment padding or if the field weren't packed. @@ -1631,9 +1637,20 @@ void ItaniumRecordLayoutBuilder::LayoutBitField(const FieldDecl *D) { // For unions, this is just a max operation, as usual. if (IsUnion) { - uint64_t RoundedFieldSize = roundUpSizeToCharAlignment(FieldSize, - Context); + // For ms_struct, allocate the entire storage unit --- unless this + // is a zero-width bitfield, in which case just use a size of 1. + uint64_t RoundedFieldSize; + if (IsMsStruct) { + RoundedFieldSize = + (FieldSize ? TypeSize : Context.getTargetInfo().getCharWidth()); + + // Otherwise, allocate just the number of bytes required to store + // the bitfield. + } else { + RoundedFieldSize = roundUpSizeToCharAlignment(FieldSize, Context); + } setDataSize(std::max(getDataSizeInBits(), RoundedFieldSize)); + // For non-zero-width bitfields in ms_struct structs, allocate a new // storage unit if necessary. } else if (IsMsStruct && FieldSize) { @@ -3045,144 +3062,189 @@ ASTContext::getObjCLayout(const ObjCInterfaceDecl *D, static void PrintOffset(raw_ostream &OS, CharUnits Offset, unsigned IndentLevel) { - OS << llvm::format("%4" PRId64 " | ", (int64_t)Offset.getQuantity()); + OS << llvm::format("%10" PRId64 " | ", (int64_t)Offset.getQuantity()); + OS.indent(IndentLevel * 2); +} + +static void PrintBitFieldOffset(raw_ostream &OS, CharUnits Offset, + unsigned Begin, unsigned Width, + unsigned IndentLevel) { + llvm::SmallString<10> Buffer; + { + llvm::raw_svector_ostream BufferOS(Buffer); + BufferOS << Offset.getQuantity() << ':'; + if (Width == 0) { + BufferOS << '-'; + } else { + BufferOS << Begin << '-' << (Begin + Width - 1); + } + } + + OS << llvm::right_justify(Buffer, 10) << " | "; OS.indent(IndentLevel * 2); } static void PrintIndentNoOffset(raw_ostream &OS, unsigned IndentLevel) { - OS << " | "; + OS << " | "; OS.indent(IndentLevel * 2); } -static void DumpCXXRecordLayout(raw_ostream &OS, - const CXXRecordDecl *RD, const ASTContext &C, - CharUnits Offset, - unsigned IndentLevel, - const char* Description, - bool IncludeVirtualBases) { +static void DumpRecordLayout(raw_ostream &OS, const RecordDecl *RD, + const ASTContext &C, + CharUnits Offset, + unsigned IndentLevel, + const char* Description, + bool PrintSizeInfo, + bool IncludeVirtualBases) { const ASTRecordLayout &Layout = C.getASTRecordLayout(RD); + auto CXXRD = dyn_cast(RD); PrintOffset(OS, Offset, IndentLevel); - OS << C.getTypeDeclType(const_cast(RD)).getAsString(); + OS << C.getTypeDeclType(const_cast(RD)).getAsString(); if (Description) OS << ' ' << Description; - if (RD->isEmpty()) + if (CXXRD && CXXRD->isEmpty()) OS << " (empty)"; OS << '\n'; IndentLevel++; - const CXXRecordDecl *PrimaryBase = Layout.getPrimaryBase(); - bool HasOwnVFPtr = Layout.hasOwnVFPtr(); - bool HasOwnVBPtr = Layout.hasOwnVBPtr(); - - // Vtable pointer. - if (RD->isDynamicClass() && !PrimaryBase && !isMsLayout(C)) { - PrintOffset(OS, Offset, IndentLevel); - OS << '(' << *RD << " vtable pointer)\n"; - } else if (HasOwnVFPtr) { - PrintOffset(OS, Offset, IndentLevel); - // vfptr (for Microsoft C++ ABI) - OS << '(' << *RD << " vftable pointer)\n"; - } - - // Collect nvbases. - SmallVector Bases; - for (const CXXBaseSpecifier &Base : RD->bases()) { - assert(!Base.getType()->isDependentType() && - "Cannot layout class with dependent bases."); - if (!Base.isVirtual()) - Bases.push_back(Base.getType()->getAsCXXRecordDecl()); - } + // Dump bases. + if (CXXRD) { + const CXXRecordDecl *PrimaryBase = Layout.getPrimaryBase(); + bool HasOwnVFPtr = Layout.hasOwnVFPtr(); + bool HasOwnVBPtr = Layout.hasOwnVBPtr(); + + // Vtable pointer. + if (CXXRD->isDynamicClass() && !PrimaryBase && !isMsLayout(C)) { + PrintOffset(OS, Offset, IndentLevel); + OS << '(' << *RD << " vtable pointer)\n"; + } else if (HasOwnVFPtr) { + PrintOffset(OS, Offset, IndentLevel); + // vfptr (for Microsoft C++ ABI) + OS << '(' << *RD << " vftable pointer)\n"; + } - // Sort nvbases by offset. - std::stable_sort(Bases.begin(), Bases.end(), - [&](const CXXRecordDecl *L, const CXXRecordDecl *R) { - return Layout.getBaseClassOffset(L) < Layout.getBaseClassOffset(R); - }); + // Collect nvbases. + SmallVector Bases; + for (const CXXBaseSpecifier &Base : CXXRD->bases()) { + assert(!Base.getType()->isDependentType() && + "Cannot layout class with dependent bases."); + if (!Base.isVirtual()) + Bases.push_back(Base.getType()->getAsCXXRecordDecl()); + } - // Dump (non-virtual) bases - for (const CXXRecordDecl *Base : Bases) { - CharUnits BaseOffset = Offset + Layout.getBaseClassOffset(Base); - DumpCXXRecordLayout(OS, Base, C, BaseOffset, IndentLevel, - Base == PrimaryBase ? "(primary base)" : "(base)", - /*IncludeVirtualBases=*/false); - } + // Sort nvbases by offset. + std::stable_sort(Bases.begin(), Bases.end(), + [&](const CXXRecordDecl *L, const CXXRecordDecl *R) { + return Layout.getBaseClassOffset(L) < Layout.getBaseClassOffset(R); + }); + + // Dump (non-virtual) bases + for (const CXXRecordDecl *Base : Bases) { + CharUnits BaseOffset = Offset + Layout.getBaseClassOffset(Base); + DumpRecordLayout(OS, Base, C, BaseOffset, IndentLevel, + Base == PrimaryBase ? "(primary base)" : "(base)", + /*PrintSizeInfo=*/false, + /*IncludeVirtualBases=*/false); + } - // vbptr (for Microsoft C++ ABI) - if (HasOwnVBPtr) { - PrintOffset(OS, Offset + Layout.getVBPtrOffset(), IndentLevel); - OS << '(' << *RD << " vbtable pointer)\n"; + // vbptr (for Microsoft C++ ABI) + if (HasOwnVBPtr) { + PrintOffset(OS, Offset + Layout.getVBPtrOffset(), IndentLevel); + OS << '(' << *RD << " vbtable pointer)\n"; + } } // Dump fields. uint64_t FieldNo = 0; - for (CXXRecordDecl::field_iterator I = RD->field_begin(), + for (RecordDecl::field_iterator I = RD->field_begin(), E = RD->field_end(); I != E; ++I, ++FieldNo) { const FieldDecl &Field = **I; - CharUnits FieldOffset = Offset + - C.toCharUnitsFromBits(Layout.getFieldOffset(FieldNo)); - - if (const CXXRecordDecl *D = Field.getType()->getAsCXXRecordDecl()) { - DumpCXXRecordLayout(OS, D, C, FieldOffset, IndentLevel, - Field.getName().data(), - /*IncludeVirtualBases=*/true); + uint64_t LocalFieldOffsetInBits = Layout.getFieldOffset(FieldNo); + CharUnits FieldOffset = + Offset + C.toCharUnitsFromBits(LocalFieldOffsetInBits); + + // Recursively dump fields of record type. + if (auto RT = Field.getType()->getAs()) { + DumpRecordLayout(OS, RT->getDecl(), C, FieldOffset, IndentLevel, + Field.getName().data(), + /*PrintSizeInfo=*/false, + /*IncludeVirtualBases=*/true); continue; } - PrintOffset(OS, FieldOffset, IndentLevel); + if (Field.isBitField()) { + uint64_t LocalFieldByteOffsetInBits = C.toBits(FieldOffset - Offset); + unsigned Begin = LocalFieldOffsetInBits - LocalFieldByteOffsetInBits; + unsigned Width = Field.getBitWidthValue(C); + PrintBitFieldOffset(OS, FieldOffset, Begin, Width, IndentLevel); + } else { + PrintOffset(OS, FieldOffset, IndentLevel); + } OS << Field.getType().getAsString() << ' ' << Field << '\n'; } - if (!IncludeVirtualBases) - return; - // Dump virtual bases. - const ASTRecordLayout::VBaseOffsetsMapTy &vtordisps = - Layout.getVBaseOffsetsMap(); - for (const CXXBaseSpecifier &Base : RD->vbases()) { - assert(Base.isVirtual() && "Found non-virtual class!"); - const CXXRecordDecl *VBase = Base.getType()->getAsCXXRecordDecl(); + if (CXXRD && IncludeVirtualBases) { + const ASTRecordLayout::VBaseOffsetsMapTy &VtorDisps = + Layout.getVBaseOffsetsMap(); - CharUnits VBaseOffset = Offset + Layout.getVBaseClassOffset(VBase); + for (const CXXBaseSpecifier &Base : CXXRD->vbases()) { + assert(Base.isVirtual() && "Found non-virtual class!"); + const CXXRecordDecl *VBase = Base.getType()->getAsCXXRecordDecl(); - if (vtordisps.find(VBase)->second.hasVtorDisp()) { - PrintOffset(OS, VBaseOffset - CharUnits::fromQuantity(4), IndentLevel); - OS << "(vtordisp for vbase " << *VBase << ")\n"; - } + CharUnits VBaseOffset = Offset + Layout.getVBaseClassOffset(VBase); - DumpCXXRecordLayout(OS, VBase, C, VBaseOffset, IndentLevel, - VBase == PrimaryBase ? - "(primary virtual base)" : "(virtual base)", - /*IncludeVirtualBases=*/false); + if (VtorDisps.find(VBase)->second.hasVtorDisp()) { + PrintOffset(OS, VBaseOffset - CharUnits::fromQuantity(4), IndentLevel); + OS << "(vtordisp for vbase " << *VBase << ")\n"; + } + + DumpRecordLayout(OS, VBase, C, VBaseOffset, IndentLevel, + VBase == Layout.getPrimaryBase() ? + "(primary virtual base)" : "(virtual base)", + /*PrintSizeInfo=*/false, + /*IncludeVirtualBases=*/false); + } } + if (!PrintSizeInfo) return; + PrintIndentNoOffset(OS, IndentLevel - 1); OS << "[sizeof=" << Layout.getSize().getQuantity(); - if (!isMsLayout(C)) + if (CXXRD && !isMsLayout(C)) OS << ", dsize=" << Layout.getDataSize().getQuantity(); - OS << ", align=" << Layout.getAlignment().getQuantity() << '\n'; + OS << ", align=" << Layout.getAlignment().getQuantity(); - PrintIndentNoOffset(OS, IndentLevel - 1); - OS << " nvsize=" << Layout.getNonVirtualSize().getQuantity(); - OS << ", nvalign=" << Layout.getNonVirtualAlignment().getQuantity() << "]\n"; + if (CXXRD) { + OS << ",\n"; + PrintIndentNoOffset(OS, IndentLevel - 1); + OS << " nvsize=" << Layout.getNonVirtualSize().getQuantity(); + OS << ", nvalign=" << Layout.getNonVirtualAlignment().getQuantity(); + } + OS << "]\n"; } void ASTContext::DumpRecordLayout(const RecordDecl *RD, raw_ostream &OS, bool Simple) const { - const ASTRecordLayout &Info = getASTRecordLayout(RD); + if (!Simple) { + ::DumpRecordLayout(OS, RD, *this, CharUnits(), 0, nullptr, + /*PrintSizeInfo*/true, + /*IncludeVirtualBases=*/true); + return; + } - if (const CXXRecordDecl *CXXRD = dyn_cast(RD)) - if (!Simple) - return DumpCXXRecordLayout(OS, CXXRD, *this, CharUnits(), 0, nullptr, - /*IncludeVirtualBases=*/true); + // The "simple" format is designed to be parsed by the + // layout-override testing code. There shouldn't be any external + // uses of this format --- when LLDB overrides a layout, it sets up + // the data structures directly --- so feel free to adjust this as + // you like as long as you also update the rudimentary parser for it + // in libFrontend. + const ASTRecordLayout &Info = getASTRecordLayout(RD); OS << "Type: " << getTypeDeclType(RD).getAsString() << "\n"; - if (!Simple) { - OS << "Record: "; - RD->dump(); - } OS << "\nLayout: "; OS << " +// CHECK: 0 | struct test0 +// CHECK-NEXT: 0:0-7 | unsigned long a +// CHECK-NEXT: 1:0-7 | unsigned long b +// CHECK-NEXT: 2:0-7 | unsigned long c +// CHECK-NEXT: 4:0-9 | unsigned long d +// CHECK-NEXT: 5:2-2 | unsigned long e +// CHECK-NEXT: | [sizeof=8, align=2] static int test0[(sizeof(struct test0) == 8) ? 1 : -1]; diff --git a/test/CodeGen/override-layout.c b/test/CodeGen/override-layout.c index 57de8b525d..9907fec318 100644 --- a/test/CodeGen/override-layout.c +++ b/test/CodeGen/override-layout.c @@ -1,7 +1,6 @@ -// RUN: %clang_cc1 -w -fdump-record-layouts %s > %t.layouts -// RUN: %clang_cc1 -w -fdump-record-layouts-simple %s > %t.before +// RUN: %clang_cc1 -w -fdump-record-layouts-simple %s > %t.layouts // RUN: %clang_cc1 -w -DPACKED= -DALIGNED16= -fdump-record-layouts-simple -foverride-record-layout=%t.layouts %s > %t.after -// RUN: diff %t.before %t.after +// RUN: diff %t.layouts %t.after // RUN: FileCheck %s < %t.after // If not explicitly disabled, set PACKED to the packed attribute. diff --git a/test/Layout/itanium-union-bitfield.cpp b/test/Layout/itanium-union-bitfield.cpp index b06fd36071..289a565359 100644 --- a/test/Layout/itanium-union-bitfield.cpp +++ b/test/Layout/itanium-union-bitfield.cpp @@ -16,14 +16,14 @@ union B { B::B() {} // CHECK:*** Dumping AST Record Layout -// CHECK-NEXT: 0 | union A -// CHECK-NEXT: 0 | int f1 -// CHECK-NEXT: | [sizeof=4, dsize=1, align=4 -// CHECK-NEXT: | nvsize=1, nvalign=4] +// CHECK-NEXT: 0 | union A +// CHECK-NEXT: 0:0-2 | int f1 +// CHECK-NEXT: | [sizeof=4, dsize=1, align=4 +// CHECK-NEXT: | nvsize=1, nvalign=4] // CHECK:*** Dumping AST Record Layout -// CHECK-NEXT: 0 | union B -// CHECK-NEXT: 0 | char f1 -// CHECK-NEXT: | [sizeof=8, dsize=5, align=4 -// CHECK-NEXT: | nvsize=5, nvalign=4] +// CHECK-NEXT: 0 | union B +// CHECK-NEXT: 0:0-34 | char f1 +// CHECK-NEXT: | [sizeof=8, dsize=5, align=4 +// CHECK-NEXT: | nvsize=5, nvalign=4] diff --git a/test/Layout/ms-x86-alias-avoidance-padding.cpp b/test/Layout/ms-x86-alias-avoidance-padding.cpp index 1d77bf9e90..203927b69a 100644 --- a/test/Layout/ms-x86-alias-avoidance-padding.cpp +++ b/test/Layout/ms-x86-alias-avoidance-padding.cpp @@ -391,8 +391,6 @@ struct RZ3 : RX3, RY {}; // CHECK-NEXT: 0 | struct RA (base) (empty) // CHECK-NEXT: 0 | struct RB a // CHECK-NEXT: 0 | char c -// CHECK-NEXT: | [sizeof=1, align=1 -// CHECK-NEXT: | nvsize=1, nvalign=1] // CHECK-NEXT: 1 | struct RY (base) (empty) // CHECK-NEXT: | [sizeof=1, align=1 // CHECK-NEXT: | nvsize=1, nvalign=1] @@ -403,8 +401,6 @@ struct RZ3 : RX3, RY {}; // CHECK-X64-NEXT: 0 | struct RA (base) (empty) // CHECK-X64-NEXT: 0 | struct RB a // CHECK-X64-NEXT: 0 | char c -// CHECK-X64-NEXT: | [sizeof=1, align=1 -// CHECK-X64-NEXT: | nvsize=1, nvalign=1] // CHECK-X64-NEXT: 1 | struct RY (base) (empty) // CHECK-X64-NEXT: | [sizeof=1, align=1 // CHECK-X64-NEXT: | nvsize=1, nvalign=1] @@ -415,8 +411,6 @@ struct RZ4 : RX4, RY {}; // CHECK-NEXT: 0 | struct RZ4 // CHECK-NEXT: 0 | struct RX4 (base) // CHECK-NEXT: 0 | struct RA a (empty) -// CHECK-NEXT: | [sizeof=1, align=1 -// CHECK-NEXT: | nvsize=0, nvalign=1] // CHECK-NEXT: 1 | char b // CHECK-NEXT: 3 | struct RY (base) (empty) // CHECK-NEXT: | [sizeof=3, align=1 @@ -426,8 +420,6 @@ struct RZ4 : RX4, RY {}; // CHECK-X64-NEXT: 0 | struct RZ4 // CHECK-X64-NEXT: 0 | struct RX4 (base) // CHECK-X64-NEXT: 0 | struct RA a (empty) -// CHECK-X64-NEXT: | [sizeof=1, align=1 -// CHECK-X64-NEXT: | nvsize=0, nvalign=1] // CHECK-X64-NEXT: 1 | char b // CHECK-X64-NEXT: 3 | struct RY (base) (empty) // CHECK-X64-NEXT: | [sizeof=3, align=1 @@ -439,12 +431,8 @@ struct RZ5 : RX5, RY {}; // CHECK-NEXT: 0 | struct RZ5 // CHECK-NEXT: 0 | struct RX5 (base) // CHECK-NEXT: 0 | struct RA a (empty) -// CHECK-NEXT: | [sizeof=1, align=1 -// CHECK-NEXT: | nvsize=0, nvalign=1] // CHECK-NEXT: 1 | struct RB b // CHECK-NEXT: 1 | char c -// CHECK-NEXT: | [sizeof=1, align=1 -// CHECK-NEXT: | nvsize=1, nvalign=1] // CHECK-NEXT: 2 | struct RY (base) (empty) // CHECK-NEXT: | [sizeof=2, align=1 // CHECK-NEXT: | nvsize=2, nvalign=1] @@ -453,12 +441,8 @@ struct RZ5 : RX5, RY {}; // CHECK-X64-NEXT: 0 | struct RZ5 // CHECK-X64-NEXT: 0 | struct RX5 (base) // CHECK-X64-NEXT: 0 | struct RA a (empty) -// CHECK-X64-NEXT: | [sizeof=1, align=1 -// CHECK-X64-NEXT: | nvsize=0, nvalign=1] // CHECK-X64-NEXT: 1 | struct RB b // CHECK-X64-NEXT: 1 | char c -// CHECK-X64-NEXT: | [sizeof=1, align=1 -// CHECK-X64-NEXT: | nvsize=1, nvalign=1] // CHECK-X64-NEXT: 2 | struct RY (base) (empty) // CHECK-X64-NEXT: | [sizeof=2, align=1 // CHECK-X64-NEXT: | nvsize=2, nvalign=1] @@ -472,8 +456,6 @@ struct RZ6 : RX6, RY {}; // CHECK-NEXT: 0 | (RX6 vbtable pointer) // CHECK-NEXT: 4 | struct RB a // CHECK-NEXT: 4 | char c -// CHECK-NEXT: | [sizeof=1, align=1 -// CHECK-NEXT: | nvsize=1, nvalign=1] // CHECK-NEXT: 9 | struct RY (base) (empty) // CHECK-NEXT: 12 | struct RV (virtual base) (empty) // CHECK-NEXT: | [sizeof=12, align=4 @@ -486,8 +468,6 @@ struct RZ6 : RX6, RY {}; // CHECK-X64-NEXT: 0 | (RX6 vbtable pointer) // CHECK-X64-NEXT: 8 | struct RB a // CHECK-X64-NEXT: 8 | char c -// CHECK-X64-NEXT: | [sizeof=1, align=1 -// CHECK-X64-NEXT: | nvsize=1, nvalign=1] // CHECK-X64-NEXT: 17 | struct RY (base) (empty) // CHECK-X64-NEXT: 24 | struct RV (virtual base) (empty) // CHECK-X64-NEXT: | [sizeof=24, align=8 @@ -501,8 +481,6 @@ struct RZ7 : RX7, RY {}; // CHECK-NEXT: 0 | struct RX7 (base) // CHECK-NEXT: 0 | (RX7 vbtable pointer) // CHECK-NEXT: 4 | struct RA a (empty) -// CHECK-NEXT: | [sizeof=1, align=1 -// CHECK-NEXT: | nvsize=0, nvalign=1] // CHECK-NEXT: 8 | struct RY (base) (empty) // CHECK-NEXT: 8 | struct RW (virtual base) // CHECK-NEXT: 8 | char c @@ -515,8 +493,6 @@ struct RZ7 : RX7, RY {}; // CHECK-X64-NEXT: 0 | struct RX7 (base) // CHECK-X64-NEXT: 0 | (RX7 vbtable pointer) // CHECK-X64-NEXT: 8 | struct RA a (empty) -// CHECK-X64-NEXT: | [sizeof=1, align=1 -// CHECK-X64-NEXT: | nvsize=0, nvalign=1] // CHECK-X64-NEXT: 16 | struct RY (base) (empty) // CHECK-X64-NEXT: 16 | struct RW (virtual base) // CHECK-X64-NEXT: 16 | char c diff --git a/test/Layout/ms-x86-bitfields-vbases.cpp b/test/Layout/ms-x86-bitfields-vbases.cpp index 5b54596bbb..a78fdad7e2 100644 --- a/test/Layout/ms-x86-bitfields-vbases.cpp +++ b/test/Layout/ms-x86-bitfields-vbases.cpp @@ -12,7 +12,7 @@ struct A : virtual B0 { char a : 1; }; // CHECK: *** Dumping AST Record Layout // CHECK-NEXT: 0 | struct A // CHECK-NEXT: 0 | (A vbtable pointer) -// CHECK-NEXT: 4 | char a +// CHECK-NEXT: 4:0-0 | char a // CHECK-NEXT: 8 | struct B0 (virtual base) // CHECK-NEXT: 8 | int a // CHECK-NEXT: | [sizeof=12, align=4 @@ -21,7 +21,7 @@ struct A : virtual B0 { char a : 1; }; // CHECK-X64: *** Dumping AST Record Layout // CHECK-X64-NEXT: 0 | struct A // CHECK-X64-NEXT: 0 | (A vbtable pointer) -// CHECK-X64-NEXT: 8 | char a +// CHECK-X64-NEXT: 8:0-0 | char a // CHECK-X64-NEXT: 16 | struct B0 (virtual base) // CHECK-X64-NEXT: 16 | int a // CHECK-X64-NEXT: | [sizeof=24, align=8 @@ -32,7 +32,7 @@ struct B : virtual B0 { short a : 1; }; // CHECK: *** Dumping AST Record Layout // CHECK-NEXT: 0 | struct B // CHECK-NEXT: 0 | (B vbtable pointer) -// CHECK-NEXT: 4 | short a +// CHECK-NEXT: 4:0-0 | short a // CHECK-NEXT: 8 | struct B0 (virtual base) // CHECK-NEXT: 8 | int a // CHECK-NEXT: | [sizeof=12, align=4 @@ -40,7 +40,7 @@ struct B : virtual B0 { short a : 1; }; // CHECK-X64: *** Dumping AST Record Layout // CHECK-X64-NEXT: 0 | struct B // CHECK-X64-NEXT: 0 | (B vbtable pointer) -// CHECK-X64-NEXT: 8 | short a +// CHECK-X64-NEXT: 8:0-0 | short a // CHECK-X64-NEXT: 16 | struct B0 (virtual base) // CHECK-X64-NEXT: 16 | int a // CHECK-X64-NEXT: | [sizeof=24, align=8 @@ -51,8 +51,8 @@ struct C : virtual B0 { char a : 1; char : 0; }; // CHECK: *** Dumping AST Record Layout // CHECK-NEXT: 0 | struct C // CHECK-NEXT: 0 | (C vbtable pointer) -// CHECK-NEXT: 4 | char a -// CHECK-NEXT: 5 | char +// CHECK-NEXT: 4:0-0 | char a +// CHECK-NEXT: 5:- | char // CHECK-NEXT: 8 | struct B0 (virtual base) // CHECK-NEXT: 8 | int a // CHECK-NEXT: | [sizeof=12, align=4 @@ -60,8 +60,8 @@ struct C : virtual B0 { char a : 1; char : 0; }; // CHECK-X64: *** Dumping AST Record Layout // CHECK-X64-NEXT: 0 | struct C // CHECK-X64-NEXT: 0 | (C vbtable pointer) -// CHECK-X64-NEXT: 8 | char a -// CHECK-X64-NEXT: 9 | char +// CHECK-X64-NEXT: 8:0-0 | char a +// CHECK-X64-NEXT: 9:- | char // CHECK-X64-NEXT: 16 | struct B0 (virtual base) // CHECK-X64-NEXT: 16 | int a // CHECK-X64-NEXT: | [sizeof=24, align=8 @@ -72,7 +72,7 @@ struct D : virtual B0 { char a : 1; char b; }; // CHECK: *** Dumping AST Record Layout // CHECK-NEXT: 0 | struct D // CHECK-NEXT: 0 | (D vbtable pointer) -// CHECK-NEXT: 4 | char a +// CHECK-NEXT: 4:0-0 | char a // CHECK-NEXT: 5 | char b // CHECK-NEXT: 8 | struct B0 (virtual base) // CHECK-NEXT: 8 | int a @@ -81,7 +81,7 @@ struct D : virtual B0 { char a : 1; char b; }; // CHECK-X64: *** Dumping AST Record Layout // CHECK-X64-NEXT: 0 | struct D // CHECK-X64-NEXT: 0 | (D vbtable pointer) -// CHECK-X64-NEXT: 8 | char a +// CHECK-X64-NEXT: 8:0-0 | char a // CHECK-X64-NEXT: 9 | char b // CHECK-X64-NEXT: 16 | struct B0 (virtual base) // CHECK-X64-NEXT: 16 | int a @@ -93,7 +93,7 @@ struct E : virtual B0, virtual B1 { long long : 1; }; // CHECK: *** Dumping AST Record Layout // CHECK-NEXT: 0 | struct E // CHECK-NEXT: 0 | (E vbtable pointer) -// CHECK-NEXT: 8 | long long +// CHECK-NEXT: 8:0-0 | long long // CHECK-NEXT: 16 | struct B0 (virtual base) // CHECK-NEXT: 16 | int a // CHECK-NEXT: 20 | struct B1 (virtual base) @@ -104,7 +104,7 @@ struct E : virtual B0, virtual B1 { long long : 1; }; // CHECK-X64: *** Dumping AST Record Layout // CHECK-X64-NEXT: 0 | struct E // CHECK-X64-NEXT: 0 | (E vbtable pointer) -// CHECK-X64-NEXT: 8 | long long +// CHECK-X64-NEXT: 8:0-0 | long long // CHECK-X64-NEXT: 16 | struct B0 (virtual base) // CHECK-X64-NEXT: 16 | int a // CHECK-X64-NEXT: 20 | struct B1 (virtual base) diff --git a/test/Layout/ms-x86-empty-layout.c b/test/Layout/ms-x86-empty-layout.c index 3554baf3a8..5dbd844659 100644 --- a/test/Layout/ms-x86-empty-layout.c +++ b/test/Layout/ms-x86-empty-layout.c @@ -6,48 +6,36 @@ struct EmptyIntMemb { int FlexArrayMemb[0]; }; -// CHECK: *** Dumping AST Record Layout -// CHECK: Type: struct EmptyIntMemb -// CHECK: Record: -// CHECK: Layout: +// CHECK: *** Dumping AST Record Layout +// CHECK-NEXT: 0 | struct EmptyIntMemb +// CHECK-NEXT: 0 | int [0] FlexArrayMemb +// CHECK-NEXT: | [sizeof=4, align=4 struct EmptyLongLongMemb { long long FlexArrayMemb[0]; }; // CHECK: *** Dumping AST Record Layout -// CHECK: Type: struct EmptyLongLongMemb -// CHECK: Record: -// CHECK: Layout: +// CHECK-NEXT: 0 | struct EmptyLongLongMemb +// CHECK-NEXT: 0 | long long [0] FlexArrayMemb +// CHECK-NEXT: | [sizeof=4, align=8 struct EmptyAligned2LongLongMemb { long long __declspec(align(2)) FlexArrayMemb[0]; }; // CHECK: *** Dumping AST Record Layout -// CHECK: Type: struct EmptyAligned2LongLongMemb -// CHECK: Record: -// CHECK: Layout: +// CHECK-NEXT: 0 | struct EmptyAligned2LongLongMemb +// CHECK-NEXT: 0 | long long [0] FlexArrayMemb +// CHECK-NEXT: | [sizeof=4, align=8 struct EmptyAligned8LongLongMemb { long long __declspec(align(8)) FlexArrayMemb[0]; }; // CHECK: *** Dumping AST Record Layout -// CHECK: Type: struct EmptyAligned8LongLongMemb -// CHECK: Record: -// CHECK: Layout: +// CHECK-NEXT: 0 | struct EmptyAligned8LongLongMemb +// CHECK-NEXT: 0 | long long [0] FlexArrayMemb +// CHECK-NEXT: | [sizeof=8, align=8 #pragma pack(1) struct __declspec(align(4)) EmptyPackedAligned4LongLongMemb { @@ -56,12 +44,9 @@ struct __declspec(align(4)) EmptyPackedAligned4LongLongMemb { #pragma pack() // CHECK: *** Dumping AST Record Layout -// CHECK: Type: struct EmptyPackedAligned4LongLongMemb -// CHECK: Record: -// CHECK: Layout: +// CHECK-NEXT: 0 | struct EmptyPackedAligned4LongLongMemb +// CHECK-NEXT: 0 | long long [0] FlexArrayMemb +// CHECK-NEXT: | [sizeof=4, align=4 #pragma pack(1) struct EmptyPackedAligned8LongLongMemb { @@ -70,12 +55,9 @@ struct EmptyPackedAligned8LongLongMemb { #pragma pack() // CHECK: *** Dumping AST Record Layout -// CHECK: Type: struct EmptyPackedAligned8LongLongMemb -// CHECK: Record: -// CHECK: Layout: +// CHECK-NEXT: 0 | struct EmptyPackedAligned8LongLongMemb +// CHECK-NEXT: 0 | long long [0] FlexArrayMemb +// CHECK-NEXT: | [sizeof=8, align=8 int a[ diff --git a/test/Layout/ms-x86-empty-nonvirtual-bases.cpp b/test/Layout/ms-x86-empty-nonvirtual-bases.cpp index 3fca32444b..00906e9862 100644 --- a/test/Layout/ms-x86-empty-nonvirtual-bases.cpp +++ b/test/Layout/ms-x86-empty-nonvirtual-bases.cpp @@ -40,8 +40,6 @@ struct B : B0 { // CHECK-NEXT: 0 | struct B // CHECK-NEXT: 0 | struct B0 (base) (empty) // CHECK-NEXT: 0 | struct B0 b0 (empty) -// CHECK-NEXT: | [sizeof=8, align=8 -// CHECK-NEXT: | nvsize=0, nvalign=8] // CHECK: 8 | int a // CHECK-NEXT: | [sizeof=16, align=8 // CHECK-NEXT: | nvsize=16, nvalign=8] @@ -82,23 +80,13 @@ struct D { // CHECK: *** Dumping AST Record Layout // CHECK-NEXT: 0 | struct D // CHECK-NEXT: 0 | struct B0 b0 (empty) -// CHECK-NEXT: | [sizeof=8, align=8 -// CHECK-NEXT: | nvsize=0, nvalign=8] // CHECK: 8 | struct C0 c0 // CHECK-NEXT: 8 | int a -// CHECK-NEXT: | [sizeof=4, align=4 -// CHECK-NEXT: | nvsize=4, nvalign=4] // CHECK: 12 | struct C1 c1 // CHECK-NEXT: 12 | int a -// CHECK-NEXT: | [sizeof=4, align=4 -// CHECK-NEXT: | nvsize=4, nvalign=4] // CHECK: 16 | struct C2 c2 // CHECK-NEXT: 16 | int a -// CHECK-NEXT: | [sizeof=4, align=4 -// CHECK-NEXT: | nvsize=4, nvalign=4] // CHECK: 24 | struct B1 b1 (empty) -// CHECK-NEXT: | [sizeof=8, align=8 -// CHECK-NEXT: | nvsize=0, nvalign=8] // CHECK: 32 | int a // CHECK-NEXT: | [sizeof=40, align=8 // CHECK-NEXT: | nvsize=40, nvalign=8] diff --git a/test/Layout/ms-x86-empty-virtual-base.cpp b/test/Layout/ms-x86-empty-virtual-base.cpp index 2d0e55a01c..b732415152 100644 --- a/test/Layout/ms-x86-empty-virtual-base.cpp +++ b/test/Layout/ms-x86-empty-virtual-base.cpp @@ -53,8 +53,6 @@ struct B : virtual B0 { // CHECK-NEXT: 0 | struct B // CHECK-NEXT: 0 | (B vbtable pointer) // CHECK-NEXT: 8 | struct B0 b0 (empty) -// CHECK-NEXT: | [sizeof=8, align=8 -// CHECK-NEXT: | nvsize=0, nvalign=8] // CHECK: 16 | int a // CHECK-NEXT: 24 | struct B0 (virtual base) (empty) // CHECK-NEXT: | [sizeof=24, align=8 @@ -63,8 +61,6 @@ struct B : virtual B0 { // CHECK-X64-NEXT: 0 | struct B // CHECK-X64-NEXT: 0 | (B vbtable pointer) // CHECK-X64-NEXT: 8 | struct B0 b0 (empty) -// CHECK-X64-NEXT: | [sizeof=8, align=8 -// CHECK-X64-NEXT: | nvsize=0, nvalign=8] // CHECK-X64: 16 | int a // CHECK-X64-NEXT: 24 | struct B0 (virtual base) (empty) // CHECK-X64-NEXT: | [sizeof=24, align=8 diff --git a/test/Layout/ms-x86-pack-and-align.cpp b/test/Layout/ms-x86-pack-and-align.cpp index 9ded22ec85..958ee19581 100644 --- a/test/Layout/ms-x86-pack-and-align.cpp +++ b/test/Layout/ms-x86-pack-and-align.cpp @@ -40,8 +40,6 @@ struct X { // CHECK-NEXT: 0 | struct X // CHECK-NEXT: 0 | struct B a // CHECK-NEXT: 0 | long long a -// CHECK-NEXT: | [sizeof=8, align=8 -// CHECK-NEXT: | nvsize=8, nvalign=8] // CHECK-NEXT: 8 | char b // CHECK-NEXT: 10 | int c // CHECK-NEXT: | [sizeof=16, align=4 @@ -51,8 +49,6 @@ struct X { // CHECK-X64-NEXT: 0 | struct X // CHECK-X64-NEXT: 0 | struct B a // CHECK-X64-NEXT: 0 | long long a -// CHECK-X64-NEXT: | [sizeof=8, align=8 -// CHECK-X64-NEXT: | nvsize=8, nvalign=8] // CHECK-X64-NEXT: 8 | char b // CHECK-X64-NEXT: 10 | int c // CHECK-X64-NEXT: | [sizeof=16, align=4 @@ -193,12 +189,12 @@ struct YA { }; // CHECK: *** Dumping AST Record Layout // CHECK-NEXT: 0 | struct YA (empty) -// CHECK-NEXT: 0 | char +// CHECK-NEXT:0:0-0 | char // CHECK-NEXT: | [sizeof=32, align=32 // CHECK-NEXT: | nvsize=32, nvalign=32] // CHECK-X64: *** Dumping AST Record Layout // CHECK-X64-NEXT: 0 | struct YA (empty) -// CHECK-X64-NEXT: 0 | char +// CHECK-X64-NEXT:0:0-0 | char // CHECK-X64-NEXT: | [sizeof=32, align=32 // CHECK-X64-NEXT: | nvsize=32, nvalign=32] @@ -211,18 +207,14 @@ struct YB { // CHECK-NEXT: 0 | struct YB // CHECK-NEXT: 0 | char a // CHECK-NEXT: 1 | struct YA b (empty) -// CHECK-NEXT: 1 | char -// CHECK-NEXT: | [sizeof=32, align=32 -// CHECK-NEXT: | nvsize=32, nvalign=32] +// CHECK-NEXT:1:0-0 | char // CHECK-NEXT: | [sizeof=33, align=1 // CHECK-NEXT: | nvsize=33, nvalign=1] // CHECK-X64: *** Dumping AST Record Layout // CHECK-X64-NEXT: 0 | struct YB // CHECK-X64-NEXT: 0 | char a // CHECK-X64-NEXT: 1 | struct YA b (empty) -// CHECK-X64-NEXT: 1 | char -// CHECK-X64-NEXT: | [sizeof=32, align=32 -// CHECK-X64-NEXT: | nvsize=32, nvalign=32] +// CHECK-X64-NEXT:1:0-0 | char // CHECK-X64-NEXT: | [sizeof=33, align=1 // CHECK-X64-NEXT: | nvsize=33, nvalign=1] @@ -232,12 +224,12 @@ struct YC { }; // CHECK: *** Dumping AST Record Layout // CHECK-NEXT: 0 | struct YC (empty) -// CHECK-NEXT: 0 | char +// CHECK-NEXT:0:0-0 | char // CHECK-NEXT: | [sizeof=32, align=32 // CHECK-NEXT: | nvsize=32, nvalign=32] // CHECK-X64: *** Dumping AST Record Layout // CHECK-X64-NEXT: 0 | struct YC (empty) -// CHECK-X64-NEXT: 0 | char +// CHECK-X64-NEXT: 0:0-0 | char // CHECK-X64-NEXT: | [sizeof=8, align=32 // CHECK-X64-NEXT: | nvsize=8, nvalign=32] @@ -250,18 +242,14 @@ struct YD { // CHECK-NEXT: 0 | struct YD // CHECK-NEXT: 0 | char a // CHECK-NEXT: 1 | struct YC b (empty) -// CHECK-NEXT: 1 | char -// CHECK-NEXT: | [sizeof=32, align=32 -// CHECK-NEXT: | nvsize=32, nvalign=32] +// CHECK-NEXT:1:0-0 | char // CHECK-NEXT: | [sizeof=33, align=1 // CHECK-NEXT: | nvsize=33, nvalign=1] // CHECK-X64: *** Dumping AST Record Layout // CHECK-X64-NEXT: 0 | struct YD // CHECK-X64-NEXT: 0 | char a // CHECK-X64-NEXT: 1 | struct YC b (empty) -// CHECK-X64-NEXT: 1 | char -// CHECK-X64-NEXT: | [sizeof=8, align=32 -// CHECK-X64-NEXT: | nvsize=8, nvalign=32] +// CHECK-X64-NEXT:1:0-0 | char // CHECK-X64-NEXT: | [sizeof=9, align=1 // CHECK-X64-NEXT: | nvsize=9, nvalign=1] @@ -271,12 +259,12 @@ struct YE { }; // CHECK: *** Dumping AST Record Layout // CHECK-NEXT: 0 | struct YE (empty) -// CHECK-NEXT: 0 | char +// CHECK-NEXT: 0:0-0 | char // CHECK-NEXT: | [sizeof=4, align=32 // CHECK-NEXT: | nvsize=4, nvalign=32] // CHECK-X64: *** Dumping AST Record Layout // CHECK-X64-NEXT: 0 | struct YE (empty) -// CHECK-X64-NEXT: 0 | char +// CHECK-X64-NEXT: 0:0-0 | char // CHECK-X64-NEXT: | [sizeof=4, align=32 // CHECK-X64-NEXT: | nvsize=4, nvalign=32] @@ -289,18 +277,14 @@ struct YF { // CHECK-NEXT: 0 | struct YF // CHECK-NEXT: 0 | char a // CHECK-NEXT: 1 | struct YE b (empty) -// CHECK-NEXT: 1 | char -// CHECK-NEXT: | [sizeof=4, align=32 -// CHECK-NEXT: | nvsize=4, nvalign=32] +// CHECK-NEXT:1:0-0 | char // CHECK-NEXT: | [sizeof=5, align=1 // CHECK-NEXT: | nvsize=5, nvalign=1] // CHECK-X64: *** Dumping AST Record Layout // CHECK-X64-NEXT: 0 | struct YF // CHECK-X64-NEXT: 0 | char a // CHECK-X64-NEXT: 1 | struct YE b (empty) -// CHECK-X64-NEXT: 1 | char -// CHECK-X64-NEXT: | [sizeof=4, align=32 -// CHECK-X64-NEXT: | nvsize=4, nvalign=32] +// CHECK-X64-NEXT:1:0-0 | char // CHECK-X64-NEXT: | [sizeof=5, align=1 // CHECK-X64-NEXT: | nvsize=5, nvalign=1] @@ -459,20 +443,20 @@ struct RE { // CHECK: *** Dumping AST Record Layout // CHECK-NEXT: 0 | struct RB0 -// CHECK-NEXT: 0 | int b +// CHECK-NEXT:0:0-2 | int b // CHECK-NEXT: | [sizeof=8, align=1024 // CHECK-NEXT: | nvsize=4, nvalign=1024] // CHECK: *** Dumping AST Record Layout // CHECK-NEXT: 0 | struct RB1 // CHECK-NEXT: 0 | (RB1 vftable pointer) -// CHECK-NEXT: 1024 | int b +// CHECK-NEXT: 1024:0-2 | int b // CHECK-NEXT: | [sizeof=1032, align=1024 // CHECK-NEXT: | nvsize=1028, nvalign=1024] // CHECK: *** Dumping AST Record Layout // CHECK: *** Dumping AST Record Layout // CHECK-NEXT: 0 | struct RB2 // CHECK-NEXT: 0 | (RB2 vbtable pointer) -// CHECK-NEXT: 1024 | int b +// CHECK-NEXT: 1024:0-2 | int b // CHECK-NEXT: 1028 | struct RA (virtual base) (empty) // CHECK-NEXT: | [sizeof=1032, align=1024 // CHECK-NEXT: | nvsize=1028, nvalign=1024] @@ -480,14 +464,14 @@ struct RE { // CHECK-NEXT: 0 | struct RB3 // CHECK-NEXT: 0 | (RB3 vftable pointer) // CHECK-NEXT: 1024 | (RB3 vbtable pointer) -// CHECK-NEXT: 2048 | int b +// CHECK-NEXT: 2048:0-2 | int b // CHECK-NEXT: 2052 | struct RA (virtual base) (empty) // CHECK-NEXT: | [sizeof=2056, align=1024 // CHECK-NEXT: | nvsize=2052, nvalign=1024] // CHECK: *** Dumping AST Record Layout // CHECK-NEXT: 0 | struct RC // CHECK-NEXT: 0 | char _ -// CHECK-NEXT: 1024 | int c +// CHECK-NEXT: 1024:0-2 | int c // CHECK-NEXT: | [sizeof=1028, align=1024 // CHECK-NEXT: | nvsize=1028, nvalign=1024] // CHECK: *** Dumping AST Record Layout @@ -495,27 +479,25 @@ struct RE { // CHECK-NEXT: 0 | char _ // CHECK-NEXT: 1 | struct RC c // CHECK-NEXT: 1 | char _ -// CHECK-NEXT: 1025 | int c -// CHECK-NEXT: | [sizeof=1028, align=1024 -// CHECK-NEXT: | nvsize=1028, nvalign=1024] +// CHECK-NEXT: 1025:0-2 | int c // CHECK-NEXT: | [sizeof=1029, align=1 // CHECK-NEXT: | nvsize=1029, nvalign=1] // CHECK-X64: *** Dumping AST Record Layout // CHECK-X64-NEXT: 0 | struct RB0 -// CHECK-X64-NEXT: 0 | int b +// CHECK-X64-NEXT: 0:0-2 | int b // CHECK-X64-NEXT: | [sizeof=8, align=1024 // CHECK-X64-NEXT: | nvsize=4, nvalign=1024] // CHECK-X64: *** Dumping AST Record Layout // CHECK-X64-NEXT: 0 | struct RB1 // CHECK-X64-NEXT: 0 | (RB1 vftable pointer) -// CHECK-X64-NEXT: 1024 | int b +// CHECK-X64-NEXT: 1024:0-2 | int b // CHECK-X64-NEXT: | [sizeof=1032, align=1024 // CHECK-X64-NEXT: | nvsize=1028, nvalign=1024] // CHECK-X64: *** Dumping AST Record Layout // CHECK-X64: *** Dumping AST Record Layout // CHECK-X64-NEXT: 0 | struct RB2 // CHECK-X64-NEXT: 0 | (RB2 vbtable pointer) -// CHECK-X64-NEXT: 1024 | int b +// CHECK-X64-NEXT: 1024:0-2 | int b // CHECK-X64-NEXT: 1028 | struct RA (virtual base) (empty) // CHECK-X64-NEXT: | [sizeof=1032, align=1024 // CHECK-X64-NEXT: | nvsize=1028, nvalign=1024] @@ -523,14 +505,14 @@ struct RE { // CHECK-X64-NEXT: 0 | struct RB3 // CHECK-X64-NEXT: 0 | (RB3 vftable pointer) // CHECK-X64-NEXT: 1024 | (RB3 vbtable pointer) -// CHECK-X64-NEXT: 2048 | int b +// CHECK-X64-NEXT: 2048:0-2 | int b // CHECK-X64-NEXT: 2052 | struct RA (virtual base) (empty) // CHECK-X64-NEXT: | [sizeof=2056, align=1024 // CHECK-X64-NEXT: | nvsize=2052, nvalign=1024] // CHECK-X64: *** Dumping AST Record Layout // CHECK-X64-NEXT: 0 | struct RC // CHECK-X64-NEXT: 0 | char _ -// CHECK-X64-NEXT: 1024 | int c +// CHECK-X64-NEXT: 1024:0-2 | int c // CHECK-X64-NEXT: | [sizeof=1028, align=1024 // CHECK-X64-NEXT: | nvsize=1028, nvalign=1024] // CHECK-X64: *** Dumping AST Record Layout @@ -538,9 +520,7 @@ struct RE { // CHECK-X64-NEXT: 0 | char _ // CHECK-X64-NEXT: 1 | struct RC c // CHECK-X64-NEXT: 1 | char _ -// CHECK-X64-NEXT: 1025 | int c -// CHECK-X64-NEXT: | [sizeof=1028, align=1024 -// CHECK-X64-NEXT: | nvsize=1028, nvalign=1024] +// CHECK-X64-NEXT: 1025:0-2 | int c // CHECK-X64-NEXT: | [sizeof=1029, align=1 // CHECK-X64-NEXT: | nvsize=1029, nvalign=1] @@ -670,8 +650,6 @@ struct PC { // CHECK-NEXT: 0 | char a // CHECK-NEXT: 8 | struct PA x // CHECK-NEXT: 8 | int c -// CHECK-NEXT: | [sizeof=4, align=4 -// CHECK-NEXT: | nvsize=4, nvalign=4] // CHECK-NEXT: | [sizeof=16, align=8 // CHECK-NEXT: | nvsize=12, nvalign=8] // CHECK-X64: *** Dumping AST Record Layout @@ -679,8 +657,6 @@ struct PC { // CHECK-X64-NEXT: 0 | char a // CHECK-X64-NEXT: 8 | struct PA x // CHECK-X64-NEXT: 8 | int c -// CHECK-X64-NEXT: | [sizeof=4, align=4 -// CHECK-X64-NEXT: | nvsize=4, nvalign=4] // CHECK-X64-NEXT: | [sizeof=16, align=8 // CHECK-X64-NEXT: | nvsize=12, nvalign=8] @@ -698,8 +674,6 @@ struct PE { // CHECK-NEXT: 0 | char a // CHECK-NEXT: 8 | struct PA x // CHECK-NEXT: 8 | int c -// CHECK-NEXT: | [sizeof=4, align=4 -// CHECK-NEXT: | nvsize=4, nvalign=4] // CHECK-NEXT: | [sizeof=16, align=8 // CHECK-NEXT: | nvsize=12, nvalign=8] // CHECK-X64: *** Dumping AST Record Layout @@ -707,8 +681,6 @@ struct PE { // CHECK-X64-NEXT: 0 | char a // CHECK-X64-NEXT: 8 | struct PA x // CHECK-X64-NEXT: 8 | int c -// CHECK-X64-NEXT: | [sizeof=4, align=4 -// CHECK-X64-NEXT: | nvsize=4, nvalign=4] // CHECK-X64-NEXT: | [sizeof=16, align=8 // CHECK-X64-NEXT: | nvsize=12, nvalign=8] @@ -759,13 +731,13 @@ struct QD { // CHECK: *** Dumping AST Record Layout // CHECK-NEXT: 0 | struct QD // CHECK-NEXT: 0 | char a -// CHECK-NEXT: 4 | QA b +// CHECK-NEXT:4:0-2 | QA b // CHECK-NEXT: | [sizeof=8, align=4 // CHECK-NEXT: | nvsize=8, nvalign=4] // CHECK-X64: *** Dumping AST Record Layout // CHECK-X64-NEXT: 0 | struct QD // CHECK-X64-NEXT: 0 | char a -// CHECK-X64-NEXT: 4 | QA b +// CHECK-X64-NEXT:4:0-2 | QA b // CHECK-X64-NEXT: | [sizeof=8, align=4 // CHECK-X64-NEXT: | nvsize=8, nvalign=4] diff --git a/test/Layout/ms_struct-bitfields.c b/test/Layout/ms_struct-bitfields.c new file mode 100644 index 0000000000..9cb455b5cc --- /dev/null +++ b/test/Layout/ms_struct-bitfields.c @@ -0,0 +1,48 @@ +// RUN: %clang_cc1 -emit-llvm-only -triple armv7-apple-darwin -fdump-record-layouts %s 2>/dev/null \ +// RUN: | FileCheck %s + +// rdar://22275433 + +#pragma ms_struct on + +union A { + unsigned long long x : 32; + unsigned long long y : 32; +} a; +// CHECK:*** Dumping AST Record Layout +// CHECK-NEXT: 0 | union A +// CHECK-NEXT: 0:0-31 | unsigned long long x +// CHECK-NEXT: 0:0-31 | unsigned long long y +// CHECK-NEXT: | [sizeof=8, align=1] + +union B { + __attribute__((aligned(4))) + unsigned long long x : 32; + unsigned long long y : 32; +} b; +// CHECK:*** Dumping AST Record Layout +// CHECK-NEXT: 0 | union B +// CHECK-NEXT: 0:0-31 | unsigned long long x +// CHECK-NEXT: 0:0-31 | unsigned long long y +// CHECK-NEXT: | [sizeof=8, align=1] + +union C { + unsigned long long : 0; + unsigned short y : 8; +} c; +// CHECK:*** Dumping AST Record Layout +// CHECK-NEXT: 0 | union C +// CHECK-NEXT: 0:- | unsigned long long +// CHECK-NEXT: 0:0-7 | unsigned short y +// CHECK-NEXT: | [sizeof=2, align=1] + +union D { + unsigned long long : 0; + unsigned short : 0; +} d; +// CHECK:*** Dumping AST Record Layout +// CHECK-NEXT: 0 | union D +// CHECK-NEXT: 0:- | unsigned long long +// CHECK-NEXT: 0:- | unsigned short +// CHECK-NEXT: | [sizeof=1, align=1] + diff --git a/test/Sema/ms_bitfield_layout.c b/test/Sema/ms_bitfield_layout.c index 293df770cd..8d377bc28d 100644 --- a/test/Sema/ms_bitfield_layout.c +++ b/test/Sema/ms_bitfield_layout.c @@ -13,10 +13,16 @@ typedef struct A { short y; } A; -// CHECK: Type: struct A -// CHECK: Size:128 -// CHECK: Alignment:32 -// CHECK: FieldOffsets: [0, 32, 64, 64, 96, 99, 112]> +// CHECK:*** Dumping AST Record Layout +// CHECK-NEXT: 0 | struct A +// CHECK-NEXT: 0 | char x +// CHECK-NEXT: 4:0-21 | int a +// CHECK-NEXT: 8:- | int +// CHECK-NEXT: 8:0-9 | int c +// CHECK-NEXT: 12:0-2 | char b +// CHECK-NEXT: 12:3-6 | char d +// CHECK-NEXT: 14 | short y +// CHECK-NEXT: | [sizeof=16, align=4] typedef struct B { char x; @@ -25,10 +31,13 @@ typedef struct B { char y; } B; -// CHECK: Type: struct B -// CHECK: Size:48 -// CHECK: Alignment:16 -// CHECK: FieldOffsets: [0, 8, 16, 32]> +// CHECK:*** Dumping AST Record Layout +// CHECK-NEXT: 0 | struct B +// CHECK-NEXT: 0 | char x +// CHECK-NEXT: 1:- | int +// CHECK-NEXT: 2:0-3 | short a +// CHECK-NEXT: 4 | char y +// CHECK-NEXT: | [sizeof=6, align=2] typedef struct C { char x; @@ -37,10 +46,13 @@ typedef struct C { char y; } C; -// CHECK: Type: struct C -// CHECK: Size:64 -// CHECK: Alignment:32 -// CHECK: FieldOffsets: [0, 16, 32, 32]> +// CHECK:*** Dumping AST Record Layout +// CHECK-NEXT: 0 | struct C +// CHECK-NEXT: 0 | char x +// CHECK-NEXT: 2:0-3 | short a +// CHECK-NEXT: 4:- | int +// CHECK-NEXT: 4 | char y +// CHECK-NEXT: | [sizeof=8, align=4] typedef struct D { char x; @@ -49,10 +61,13 @@ typedef struct D { char y; } D; -// CHECK: Type: struct D -// CHECK: Size:16 -// CHECK: Alignment:8 -// CHECK: FieldOffsets: [0, 8, 8, 8]> +// CHECK:*** Dumping AST Record Layout +// CHECK-NEXT: 0 | struct D +// CHECK-NEXT: 0 | char x +// CHECK-NEXT: 1:- | short +// CHECK-NEXT: 1:- | int +// CHECK-NEXT: 1 | char y +// CHECK-NEXT: | [sizeof=2, align=1] typedef union E { char x; @@ -62,10 +77,15 @@ typedef union E { short y; } E; -// CHECK: Type: union E -// CHECK: Size:64 -// CHECK: Alignment:16 -// CHECK: FieldOffsets: [0, 0, 0, 0, 0]> + +// CHECK:*** Dumping AST Record Layout +// CHECK-NEXT: 0 | union E +// CHECK-NEXT: 0 | char x +// CHECK-NEXT: 0:0-2 | long long a +// CHECK-NEXT: 0:0-2 | int b +// CHECK-NEXT: 0:- | long long +// CHECK-NEXT: 0 | short +// CHECK-NEXT: | [sizeof=8, align=2] typedef struct F { char x; @@ -81,10 +101,20 @@ typedef struct F { short y; } F; -// CHECK: Type: struct F -// CHECK: Size:128 -// CHECK: Alignment:16 -// CHECK: FieldOffsets: [0, 8, 11, 16, 32, 38, 48, 64, 80, 96, 112]> +// CHECK:*** Dumping AST Record Layout +// CHECK-NEXT: 0 | struct F +// CHECK-NEXT: 0 | char x +// CHECK-NEXT: 1:0-2 | char a +// CHECK-NEXT: 1:3-5 | char b +// CHECK-NEXT: 2:0-2 | char c +// CHECK-NEXT: 4:0-5 | short d +// CHECK-NEXT: 4:6-11 | short e +// CHECK-NEXT: 6:0-5 | short f +// CHECK-NEXT: 8:0-10 | short g +// CHECK-NEXT:10:0-10 | short h +// CHECK-NEXT:12:0-10 | short i +// CHECK-NEXT: 14 | short y +// CHECK-NEXT: | [sizeof=16, align=2] typedef union G { char x; @@ -94,10 +124,14 @@ typedef union G { short y; } G; -// CHECK: Type: union G -// CHECK: Size:32 -// CHECK: Alignment:16 -// CHECK: FieldOffsets: [0, 0, 0, 0, 0]> +// CHECK:*** Dumping AST Record Layout +// CHECK-NEXT: 0 | union G +// CHECK-NEXT: 0 | char x +// CHECK-NEXT: 0:0-2 | int a +// CHECK-NEXT: 0:- | int +// CHECK-NEXT: 0:- | long long +// CHECK-NEXT: 0 | short y +// CHECK-NEXT: | [sizeof=4, align=2] typedef struct H { unsigned short a : 1; @@ -106,20 +140,25 @@ typedef struct H { unsigned short c : 1; } H; -// CHECK: Type: struct H -// CHECK: Size:32 -// CHECK: Alignment:16 -// CHECK: FieldOffsets: [0, 16, 16, 16]> +// CHECK:*** Dumping AST Record Layout +// CHECK-NEXT: 0 | struct H +// CHECK-NEXT: 0:0-0 | unsigned short a +// CHECK-NEXT: 2:- | unsigned char +// CHECK-NEXT: 2:- | unsigned long +// CHECK-NEXT: 2:0-0 | unsigned short c +// CHECK-NEXT: | [sizeof=4, align=2] typedef struct I { short : 8; __declspec(align(16)) short : 8; } I; -// CHECK: Type: struct I -// CHECK: Size:16 -// CHECK: Alignment:16 -// CHECK: FieldOffsets: [0, 8] + +// CHECK:*** Dumping AST Record Layout +// CHECK-NEXT: 0 | struct I +// CHECK-NEXT: 0:0-7 | short +// CHECK-NEXT: 1:0-7 | short +// CHECK-NEXT: | [sizeof=2, align=2] #pragma pack(push, 1) @@ -133,10 +172,16 @@ typedef struct A1 { short y; } A1; -// CHECK: Type: struct A1 -// CHECK: Size:96 -// CHECK: Alignment:8 -// CHECK: FieldOffsets: [0, 8, 40, 40, 72, 75, 80]> +// CHECK:*** Dumping AST Record Layout +// CHECK-NEXT: 0 | struct A1 +// CHECK-NEXT: 0 | char x +// CHECK-NEXT: 1:0-21 | int a +// CHECK-NEXT: 5:- | int +// CHECK-NEXT: 5:0-9 | int c +// CHECK-NEXT: 9:0-2 | char b +// CHECK-NEXT: 9:3-6 | char d +// CHECK-NEXT: 10 | short y +// CHECK-NEXT: | [sizeof=12, align=1] typedef struct B1 { char x; @@ -145,10 +190,13 @@ typedef struct B1 { char y; } B1; -// CHECK: Type: struct B1 -// CHECK: Size:32 -// CHECK: Alignment:8 -// CHECK: FieldOffsets: [0, 8, 8, 24]> +// CHECK:*** Dumping AST Record Layout +// CHECK-NEXT: 0 | struct B1 +// CHECK-NEXT: 0 | char x +// CHECK-NEXT: 1:- | int +// CHECK-NEXT: 1:0-3 | short +// CHECK-NEXT: 3 | char y +// CHECK-NEXT: | [sizeof=4, align=1] typedef struct C1 { char x; @@ -157,10 +205,13 @@ typedef struct C1 { char y; } C1; -// CHECK: Type: struct C1 -// CHECK: Size:32 -// CHECK: Alignment:8 -// CHECK: FieldOffsets: [0, 8, 24, 24]> +// CHECK:*** Dumping AST Record Layout +// CHECK-NEXT: 0 | struct C1 +// CHECK-NEXT: 0 | char x +// CHECK-NEXT: 1:0-3 | short +// CHECK-NEXT: 3:- | int +// CHECK-NEXT: 3 | char y +// CHECK-NEXT: | [sizeof=4, align=1] typedef struct D1 { char x; @@ -169,10 +220,13 @@ typedef struct D1 { char y; } D1; -// CHECK: Type: struct D1 -// CHECK: Size:16 -// CHECK: Alignment:8 -// CHECK: FieldOffsets: [0, 8, 8, 8]> +// CHECK:*** Dumping AST Record Layout +// CHECK-NEXT: 0 | struct D1 +// CHECK-NEXT: 0 | char x +// CHECK-NEXT: 1:- | short +// CHECK-NEXT: 1:- | int +// CHECK-NEXT: 1 | char y +// CHECK-NEXT: | [sizeof=2, align=1] typedef union E1 { char x; @@ -182,10 +236,14 @@ typedef union E1 { short y; } E1; -// CHECK: Type: union E1 -// CHECK: Size:64 -// CHECK: Alignment:8 -// CHECK: FieldOffsets: [0, 0, 0, 0, 0]> +// CHECK:*** Dumping AST Record Layout +// CHECK-NEXT: 0 | union E1 +// CHECK-NEXT: 0 | char x +// CHECK-NEXT: 0:0-2 | long long a +// CHECK-NEXT: 0:0-2 | int b +// CHECK-NEXT: 0:- | long long +// CHECK-NEXT: 0 | short y +// CHECK-NEXT: | [sizeof=8, align=1] typedef struct F1 { char x; @@ -201,10 +259,20 @@ typedef struct F1 { short y; } F1; -// CHECK: Type: struct F1 -// CHECK: Size:120 -// CHECK: Alignment:8 -// CHECK: FieldOffsets: [0, 8, 11, 16, 24, 30, 40, 56, 72, 88, 104]> +// CHECK:*** Dumping AST Record Layout +// CHECK-NEXT: 0 | struct F1 +// CHECK-NEXT: 0 | char x +// CHECK-NEXT: 1:0-2 | char a +// CHECK-NEXT: 1:3-5 | char b +// CHECK-NEXT: 2:0-2 | char c +// CHECK-NEXT: 3:0-5 | short d +// CHECK-NEXT: 3:6-11 | short e +// CHECK-NEXT: 5:0-5 | short f +// CHECK-NEXT: 7:0-10 | short g +// CHECK-NEXT: 9:0-10 | short h +// CHECK-NEXT:11:0-10 | short i +// CHECK-NEXT: 13 | short y +// CHECK-NEXT: | [sizeof=15, align=1] typedef union G1 { char x; @@ -214,10 +282,14 @@ typedef union G1 { short y; } G1; -// CHECK: Type: union G1 -// CHECK: Size:32 -// CHECK: Alignment:8 -// CHECK: FieldOffsets: [0, 0, 0, 0, 0]> +// CHECK:*** Dumping AST Record Layout +// CHECK-NEXT: 0 | union G1 +// CHECK-NEXT: 0 | char x +// CHECK-NEXT: 0:0-2 | int a +// CHECK-NEXT: 0:- | int +// CHECK-NEXT: 0:- | long long +// CHECK-NEXT: 0 | short y +// CHECK-NEXT: | [sizeof=4, align=1] typedef struct H1 { unsigned long a : 1; @@ -226,20 +298,24 @@ typedef struct H1 { unsigned long c : 1; } H1; -// CHECK: Type: struct H1 -// CHECK: Size:64 -// CHECK: Alignment:8 -// CHECK: FieldOffsets: [0, 32, 32, 32]> +// CHECK:*** Dumping AST Record Layout +// CHECK-NEXT: 0 | struct H1 +// CHECK-NEXT: 0:0-0 | unsigned long a +// CHECK-NEXT: 4:- | unsigned char +// CHECK-NEXT: 4:- | unsigned long +// CHECK-NEXT: 4:0-0 | unsigned long c +// CHECK-NEXT: | [sizeof=8, align=1] typedef struct I1 { short : 8; __declspec(align(16)) short : 8; } I1; -// CHECK: Type: struct I1 -// CHECK: Size:16 -// CHECK: Alignment:8 -// CHECK: FieldOffsets: [0, 8] +// CHECK:*** Dumping AST Record Layout +// CHECK-NEXT: 0 | struct I1 +// CHECK-NEXT: 0:0-7 | short +// CHECK-NEXT: 1:0-7 | short +// CHECK-NEXT: | [sizeof=2, align=1] #pragma pack(pop) diff --git a/test/Sema/ms_class_layout.cpp b/test/Sema/ms_class_layout.cpp index 896d3edfda..8638972430 100644 --- a/test/Sema/ms_class_layout.cpp +++ b/test/Sema/ms_class_layout.cpp @@ -236,11 +236,7 @@ int main() { // CHECK-NEXT: 84 | int b_field // CHECK-NEXT: 88 | int a_field // CHECK-NEXT: 92 | char one - -// CHECK-NEXT: sizeof=80, align=8 -// CHECK-NEXT: nvsize=64, nvalign=8 - -// CHECK: sizeof=96, align=8 +// CHECK-NEXT: sizeof=96, align=8 // CHECK-NEXT: nvsize=96, nvalign=8 // CHECK: %struct.BaseStruct = type { double, float, %class.C } @@ -267,10 +263,7 @@ int main() { // CHECK-NEXT: 84 | int b_field // CHECK-NEXT: 88 | int a_field // CHECK-NEXT: 92 | char one -// CHECK-NEXT: sizeof=80, align=8 -// CHECK-NEXT: nvsize=64, nvalign=8 - -// CHECK: 96 | int x +// CHECK-NEXT: 96 | int x // CHECK-NEXT: sizeof=104, align=8 // CHECK-NEXT: nvsize=104, nvalign=8 -- 2.40.0