forked from OSchip/llvm-project
[MS-ABI] Update to alias-avoidance padding
This patch changes how we determine if padding is needed between two bases in msvc compatibility mode. Test cases included. In addition, a very minor change to the printing of structures to ease lit testing. llvm-svn: 205933
This commit is contained in:
parent
699e14f3ce
commit
39a907b1c2
|
@ -2099,12 +2099,13 @@ static bool isMsLayout(const RecordDecl* D) {
|
||||||
// * The ABI attempts to avoid aliasing of zero sized bases by adding padding
|
// * The ABI attempts to avoid aliasing of zero sized bases by adding padding
|
||||||
// between bases or vbases with specific properties. The criteria for
|
// between bases or vbases with specific properties. The criteria for
|
||||||
// additional padding between two bases is that the first base is zero sized
|
// additional padding between two bases is that the first base is zero sized
|
||||||
// or has a zero sized subobject and the second base is zero sized or leads
|
// or ends with a zero sized subobject and the second base is zero sized or
|
||||||
// with a zero sized base (sharing of vfptrs can reorder the layout of the
|
// leads with a zero sized base (sharing of vfptrs can reorder the layout of
|
||||||
// so the leading base is not always the first one declared). The padding
|
// the so the leading base is not always the first one declared). This rule
|
||||||
// added for bases is 1 byte. The padding added for vbases depends on the
|
// is slightly buggy (conservative) because it doesn't take into account
|
||||||
// alignment of the object but is at least 4 bytes (in both 32 and 64 bit
|
// fields that are not records. The padding added for bases is 1 byte. The
|
||||||
// modes).
|
// padding added for vbases depends on the alignment of the object but is at
|
||||||
|
// least 4 bytes (in both 32 and 64 bit modes).
|
||||||
// * There is no concept of non-virtual alignment or any distinction between
|
// * There is no concept of non-virtual alignment or any distinction between
|
||||||
// data size and non-virtual size.
|
// data size and non-virtual size.
|
||||||
// * __declspec(align) on bitfields has the effect of changing the bitfield's
|
// * __declspec(align) on bitfields has the effect of changing the bitfield's
|
||||||
|
@ -2213,9 +2214,10 @@ public:
|
||||||
bool HasVBPtr : 1;
|
bool HasVBPtr : 1;
|
||||||
/// \brief Lets us know if we're in 64-bit mode
|
/// \brief Lets us know if we're in 64-bit mode
|
||||||
bool Is64BitMode : 1;
|
bool Is64BitMode : 1;
|
||||||
/// \brief True if this class contains a zero sized member or base or a base
|
/// \brief True if the last sub-object within the type is zero sized or the
|
||||||
/// with a zero sized member or base. Only used for MS-ABI.
|
/// object itself is zero sized. This *does not* count members that are not
|
||||||
bool HasZeroSizedSubObject : 1;
|
/// records. Only used for MS-ABI.
|
||||||
|
bool EndsWithZeroSizedObject : 1;
|
||||||
/// \brief True if this class is zero sized or first base is zero sized or
|
/// \brief True if this class is zero sized or first base is zero sized or
|
||||||
/// has this property. Only used for MS-ABI.
|
/// has this property. Only used for MS-ABI.
|
||||||
bool LeadsWithZeroSizedBase : 1;
|
bool LeadsWithZeroSizedBase : 1;
|
||||||
|
@ -2231,8 +2233,7 @@ MicrosoftRecordLayoutBuilder::getAdjustedElementInfo(
|
||||||
if (!MaxFieldAlignment.isZero())
|
if (!MaxFieldAlignment.isZero())
|
||||||
Info.Alignment = std::min(Info.Alignment, MaxFieldAlignment);
|
Info.Alignment = std::min(Info.Alignment, MaxFieldAlignment);
|
||||||
// Track zero-sized subobjects here where it's already available.
|
// Track zero-sized subobjects here where it's already available.
|
||||||
if (Layout.hasZeroSizedSubObject())
|
EndsWithZeroSizedObject = Layout.hasZeroSizedSubObject();
|
||||||
HasZeroSizedSubObject = true;
|
|
||||||
// Respect required alignment, this is necessary because we may have adjusted
|
// Respect required alignment, this is necessary because we may have adjusted
|
||||||
// the alignment in the case of pragam pack. Note that the required alignment
|
// the alignment in the case of pragam pack. Note that the required alignment
|
||||||
// doesn't actually apply to the struct alignment at this point.
|
// doesn't actually apply to the struct alignment at this point.
|
||||||
|
@ -2339,7 +2340,7 @@ void MicrosoftRecordLayoutBuilder::initializeLayout(const RecordDecl *RD) {
|
||||||
|
|
||||||
void
|
void
|
||||||
MicrosoftRecordLayoutBuilder::initializeCXXLayout(const CXXRecordDecl *RD) {
|
MicrosoftRecordLayoutBuilder::initializeCXXLayout(const CXXRecordDecl *RD) {
|
||||||
HasZeroSizedSubObject = false;
|
EndsWithZeroSizedObject = false;
|
||||||
LeadsWithZeroSizedBase = false;
|
LeadsWithZeroSizedBase = false;
|
||||||
HasOwnVFPtr = false;
|
HasOwnVFPtr = false;
|
||||||
HasVBPtr = false;
|
HasVBPtr = false;
|
||||||
|
@ -2617,7 +2618,6 @@ void MicrosoftRecordLayoutBuilder::layoutVirtualBases(const CXXRecordDecl *RD) {
|
||||||
if (HasVtordisp)
|
if (HasVtordisp)
|
||||||
Size = Size.RoundUpToAlignment(VtorDispAlignment) + VtorDispSize;
|
Size = Size.RoundUpToAlignment(VtorDispAlignment) + VtorDispSize;
|
||||||
// Insert the virtual base.
|
// Insert the virtual base.
|
||||||
HasZeroSizedSubObject = false;
|
|
||||||
ElementInfo Info = getAdjustedElementInfo(BaseLayout);
|
ElementInfo Info = getAdjustedElementInfo(BaseLayout);
|
||||||
CharUnits BaseOffset = Size.RoundUpToAlignment(Info.Alignment);
|
CharUnits BaseOffset = Size.RoundUpToAlignment(Info.Alignment);
|
||||||
VBases.insert(std::make_pair(BaseDecl,
|
VBases.insert(std::make_pair(BaseDecl,
|
||||||
|
@ -2637,7 +2637,7 @@ void MicrosoftRecordLayoutBuilder::finalizeLayout(const RecordDecl *RD) {
|
||||||
}
|
}
|
||||||
// Zero-sized structures have size equal to their alignment.
|
// Zero-sized structures have size equal to their alignment.
|
||||||
if (Size.isZero()) {
|
if (Size.isZero()) {
|
||||||
HasZeroSizedSubObject = true;
|
EndsWithZeroSizedObject = true;
|
||||||
LeadsWithZeroSizedBase = true;
|
LeadsWithZeroSizedBase = true;
|
||||||
Size = Alignment;
|
Size = Alignment;
|
||||||
}
|
}
|
||||||
|
@ -2750,7 +2750,7 @@ ASTContext::BuildMicrosoftASTRecordLayout(const RecordDecl *D) const {
|
||||||
Builder.FieldOffsets.size(), Builder.NonVirtualSize,
|
Builder.FieldOffsets.size(), Builder.NonVirtualSize,
|
||||||
Builder.Alignment, CharUnits::Zero(), Builder.PrimaryBase,
|
Builder.Alignment, CharUnits::Zero(), Builder.PrimaryBase,
|
||||||
false, Builder.SharedVBPtrBase,
|
false, Builder.SharedVBPtrBase,
|
||||||
Builder.HasZeroSizedSubObject, Builder.LeadsWithZeroSizedBase,
|
Builder.EndsWithZeroSizedObject, Builder.LeadsWithZeroSizedBase,
|
||||||
Builder.Bases, Builder.VBases);
|
Builder.Bases, Builder.VBases);
|
||||||
} else {
|
} else {
|
||||||
Builder.layout(D);
|
Builder.layout(D);
|
||||||
|
@ -3078,7 +3078,6 @@ static void DumpCXXRecordLayout(raw_ostream &OS,
|
||||||
PrintIndentNoOffset(OS, IndentLevel - 1);
|
PrintIndentNoOffset(OS, IndentLevel - 1);
|
||||||
OS << " nvsize=" << Layout.getNonVirtualSize().getQuantity();
|
OS << " nvsize=" << Layout.getNonVirtualSize().getQuantity();
|
||||||
OS << ", nvalign=" << Layout.getNonVirtualAlignment().getQuantity() << "]\n";
|
OS << ", nvalign=" << Layout.getNonVirtualAlignment().getQuantity() << "]\n";
|
||||||
OS << '\n';
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ASTContext::DumpRecordLayout(const RecordDecl *RD,
|
void ASTContext::DumpRecordLayout(const RecordDecl *RD,
|
||||||
|
|
|
@ -298,6 +298,257 @@ struct JC4 : JC1, JC2 {
|
||||||
// CHECK-X64-NEXT: | [sizeof=24, align=8
|
// CHECK-X64-NEXT: | [sizeof=24, align=8
|
||||||
// CHECK-X64-NEXT: | nvsize=24, nvalign=8]
|
// CHECK-X64-NEXT: | nvsize=24, nvalign=8]
|
||||||
|
|
||||||
|
struct RA {};
|
||||||
|
struct RB { char c; };
|
||||||
|
struct RV {};
|
||||||
|
struct RW { char c; };
|
||||||
|
struct RY { RY() { printf("%Id\n", (char*)this - buffer); } };
|
||||||
|
struct RX0 : RB, RA {};
|
||||||
|
struct RX1 : RA, RB {};
|
||||||
|
struct RX2 : RA { char a; };
|
||||||
|
struct RX3 : RA { RB a; };
|
||||||
|
struct RX4 { RA a; char b; };
|
||||||
|
struct RX5 { RA a; RB b; };
|
||||||
|
struct RX6 : virtual RV { RB a; };
|
||||||
|
struct RX7 : virtual RW { RA a; };
|
||||||
|
struct RX8 : RA, virtual RW {};
|
||||||
|
|
||||||
|
struct RZ0 : RX0, RY {};
|
||||||
|
// CHECK: *** Dumping AST Record Layout
|
||||||
|
// CHECK: *** Dumping AST Record Layout
|
||||||
|
// CHECK: *** Dumping AST Record Layout
|
||||||
|
// CHECK: *** Dumping AST Record Layout
|
||||||
|
// CHECK: *** Dumping AST Record Layout
|
||||||
|
// CHECK-NEXT: 0 | struct RZ0
|
||||||
|
// CHECK-NEXT: 0 | struct RX0 (base)
|
||||||
|
// CHECK-NEXT: 0 | struct RB (base)
|
||||||
|
// CHECK-NEXT: 0 | char c
|
||||||
|
// CHECK-NEXT: 1 | struct RA (base) (empty)
|
||||||
|
// CHECK-NEXT: 2 | struct RY (base) (empty)
|
||||||
|
// CHECK-NEXT: | [sizeof=2, align=1
|
||||||
|
// CHECK-NEXT: | nvsize=2, nvalign=1]
|
||||||
|
// CHECK-X64: *** Dumping AST Record Layout
|
||||||
|
// CHECK-X64: *** Dumping AST Record Layout
|
||||||
|
// CHECK-X64: *** Dumping AST Record Layout
|
||||||
|
// CHECK-X64: *** Dumping AST Record Layout
|
||||||
|
// CHECK-X64: *** Dumping AST Record Layout
|
||||||
|
// CHECK-X64-NEXT: 0 | struct RZ0
|
||||||
|
// CHECK-X64-NEXT: 0 | struct RX0 (base)
|
||||||
|
// CHECK-X64-NEXT: 0 | struct RB (base)
|
||||||
|
// CHECK-X64-NEXT: 0 | char c
|
||||||
|
// CHECK-X64-NEXT: 1 | struct RA (base) (empty)
|
||||||
|
// CHECK-X64-NEXT: 2 | struct RY (base) (empty)
|
||||||
|
// CHECK-X64-NEXT: | [sizeof=2, align=1
|
||||||
|
// CHECK-X64-NEXT: | nvsize=2, nvalign=1]
|
||||||
|
|
||||||
|
struct RZ1 : RX1, RY {};
|
||||||
|
// CHECK: *** Dumping AST Record Layout
|
||||||
|
// CHECK: *** Dumping AST Record Layout
|
||||||
|
// CHECK-NEXT: 0 | struct RZ1
|
||||||
|
// CHECK-NEXT: 0 | struct RX1 (base)
|
||||||
|
// CHECK-NEXT: 0 | struct RA (base) (empty)
|
||||||
|
// CHECK-NEXT: 0 | struct RB (base)
|
||||||
|
// CHECK-NEXT: 0 | char c
|
||||||
|
// CHECK-NEXT: 1 | struct RY (base) (empty)
|
||||||
|
// CHECK-NEXT: | [sizeof=1, align=1
|
||||||
|
// CHECK-NEXT: | nvsize=1, nvalign=1]
|
||||||
|
// CHECK-X64: *** Dumping AST Record Layout
|
||||||
|
// CHECK-X64: *** Dumping AST Record Layout
|
||||||
|
// CHECK-X64-NEXT: 0 | struct RZ1
|
||||||
|
// CHECK-X64-NEXT: 0 | struct RX1 (base)
|
||||||
|
// CHECK-X64-NEXT: 0 | struct RA (base) (empty)
|
||||||
|
// CHECK-X64-NEXT: 0 | struct RB (base)
|
||||||
|
// CHECK-X64-NEXT: 0 | char c
|
||||||
|
// CHECK-X64-NEXT: 1 | struct RY (base) (empty)
|
||||||
|
// CHECK-X64-NEXT: | [sizeof=1, align=1
|
||||||
|
// CHECK-X64-NEXT: | nvsize=1, nvalign=1]
|
||||||
|
|
||||||
|
struct RZ2 : RX2, RY {};
|
||||||
|
// CHECK: *** Dumping AST Record Layout
|
||||||
|
// CHECK: *** Dumping AST Record Layout
|
||||||
|
// CHECK-NEXT: 0 | struct RZ2
|
||||||
|
// CHECK-NEXT: 0 | struct RX2 (base)
|
||||||
|
// CHECK-NEXT: 0 | struct RA (base) (empty)
|
||||||
|
// CHECK-NEXT: 0 | char a
|
||||||
|
// CHECK-NEXT: 2 | struct RY (base) (empty)
|
||||||
|
// CHECK-NEXT: | [sizeof=2, align=1
|
||||||
|
// CHECK-NEXT: | nvsize=2, nvalign=1]
|
||||||
|
// CHECK-X64: *** Dumping AST Record Layout
|
||||||
|
// CHECK-X64: *** Dumping AST Record Layout
|
||||||
|
// CHECK-X64-NEXT: 0 | struct RZ2
|
||||||
|
// CHECK-X64-NEXT: 0 | struct RX2 (base)
|
||||||
|
// CHECK-X64-NEXT: 0 | struct RA (base) (empty)
|
||||||
|
// CHECK-X64-NEXT: 0 | char a
|
||||||
|
// CHECK-X64-NEXT: 2 | struct RY (base) (empty)
|
||||||
|
// CHECK-X64-NEXT: | [sizeof=2, align=1
|
||||||
|
// CHECK-X64-NEXT: | nvsize=2, nvalign=1]
|
||||||
|
|
||||||
|
struct RZ3 : RX3, RY {};
|
||||||
|
// CHECK: *** Dumping AST Record Layout
|
||||||
|
// CHECK: *** Dumping AST Record Layout
|
||||||
|
// CHECK-NEXT: 0 | struct RZ3
|
||||||
|
// CHECK-NEXT: 0 | struct RX3 (base)
|
||||||
|
// 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]
|
||||||
|
// CHECK-X64: *** Dumping AST Record Layout
|
||||||
|
// CHECK-X64: *** Dumping AST Record Layout
|
||||||
|
// CHECK-X64-NEXT: 0 | struct RZ3
|
||||||
|
// CHECK-X64-NEXT: 0 | struct RX3 (base)
|
||||||
|
// 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]
|
||||||
|
|
||||||
|
struct RZ4 : RX4, RY {};
|
||||||
|
// CHECK: *** Dumping AST Record Layout
|
||||||
|
// CHECK: *** Dumping AST Record Layout
|
||||||
|
// 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
|
||||||
|
// CHECK-NEXT: | nvsize=3, nvalign=1]
|
||||||
|
// CHECK-X64: *** Dumping AST Record Layout
|
||||||
|
// CHECK-X64: *** Dumping AST Record Layout
|
||||||
|
// 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
|
||||||
|
// CHECK-X64-NEXT: | nvsize=3, nvalign=1]
|
||||||
|
|
||||||
|
struct RZ5 : RX5, RY {};
|
||||||
|
// CHECK: *** Dumping AST Record Layout
|
||||||
|
// CHECK: *** Dumping AST Record Layout
|
||||||
|
// 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]
|
||||||
|
// CHECK-X64: *** Dumping AST Record Layout
|
||||||
|
// CHECK-X64: *** Dumping AST Record Layout
|
||||||
|
// 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]
|
||||||
|
|
||||||
|
struct RZ6 : RX6, RY {};
|
||||||
|
// CHECK: *** Dumping AST Record Layout
|
||||||
|
// CHECK: *** Dumping AST Record Layout
|
||||||
|
// CHECK: *** Dumping AST Record Layout
|
||||||
|
// CHECK-NEXT: 0 | struct RZ6
|
||||||
|
// CHECK-NEXT: 0 | struct RX6 (base)
|
||||||
|
// 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
|
||||||
|
// CHECK-NEXT: | nvsize=12, nvalign=4]
|
||||||
|
// CHECK-X64: *** Dumping AST Record Layout
|
||||||
|
// CHECK-X64: *** Dumping AST Record Layout
|
||||||
|
// CHECK-X64: *** Dumping AST Record Layout
|
||||||
|
// CHECK-X64-NEXT: 0 | struct RZ6
|
||||||
|
// CHECK-X64-NEXT: 0 | struct RX6 (base)
|
||||||
|
// 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
|
||||||
|
// CHECK-X64-NEXT: | nvsize=24, nvalign=8]
|
||||||
|
|
||||||
|
struct RZ7 : RX7, RY {};
|
||||||
|
// CHECK: *** Dumping AST Record Layout
|
||||||
|
// CHECK: *** Dumping AST Record Layout
|
||||||
|
// CHECK: *** Dumping AST Record Layout
|
||||||
|
// CHECK-NEXT: 0 | struct RZ7
|
||||||
|
// 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
|
||||||
|
// CHECK-NEXT: | [sizeof=9, align=4
|
||||||
|
// CHECK-NEXT: | nvsize=8, nvalign=4]
|
||||||
|
// CHECK-X64: *** Dumping AST Record Layout
|
||||||
|
// CHECK-X64: *** Dumping AST Record Layout
|
||||||
|
// CHECK-X64: *** Dumping AST Record Layout
|
||||||
|
// CHECK-X64-NEXT: 0 | struct RZ7
|
||||||
|
// 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
|
||||||
|
// CHECK-X64-NEXT: | [sizeof=24, align=8
|
||||||
|
// CHECK-X64-NEXT: | nvsize=16, nvalign=8]
|
||||||
|
|
||||||
|
struct RZ8 : RX8, RY {};
|
||||||
|
// CHECK: *** Dumping AST Record Layout
|
||||||
|
// CHECK: *** Dumping AST Record Layout
|
||||||
|
// CHECK-NEXT: 0 | struct RZ8
|
||||||
|
// CHECK-NEXT: 0 | struct RX8 (base)
|
||||||
|
// CHECK-NEXT: 4 | struct RA (base) (empty)
|
||||||
|
// CHECK-NEXT: 0 | (RX8 vbtable pointer)
|
||||||
|
// CHECK-NEXT: 4 | struct RY (base) (empty)
|
||||||
|
// CHECK-NEXT: 4 | struct RW (virtual base)
|
||||||
|
// CHECK-NEXT: 4 | char c
|
||||||
|
// CHECK-NEXT: | [sizeof=5, align=4
|
||||||
|
// CHECK-NEXT: | nvsize=4, nvalign=4]
|
||||||
|
// CHECK-X64: *** Dumping AST Record Layout
|
||||||
|
// CHECK-X64: *** Dumping AST Record Layout
|
||||||
|
// CHECK-X64-NEXT: 0 | struct RZ8
|
||||||
|
// CHECK-X64-NEXT: 0 | struct RX8 (base)
|
||||||
|
// CHECK-X64-NEXT: 8 | struct RA (base) (empty)
|
||||||
|
// CHECK-X64-NEXT: 0 | (RX8 vbtable pointer)
|
||||||
|
// CHECK-X64-NEXT: 8 | struct RY (base) (empty)
|
||||||
|
// CHECK-X64-NEXT: 8 | struct RW (virtual base)
|
||||||
|
// CHECK-X64-NEXT: 8 | char c
|
||||||
|
// CHECK-X64-NEXT: | [sizeof=16, align=8
|
||||||
|
// CHECK-X64-NEXT: | nvsize=8, nvalign=8]
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
int a[
|
int a[
|
||||||
sizeof(AT3) +
|
sizeof(AT3) +
|
||||||
sizeof(BT3) +
|
sizeof(BT3) +
|
||||||
|
@ -305,4 +556,13 @@ sizeof(T3) +
|
||||||
sizeof(E) +
|
sizeof(E) +
|
||||||
sizeof(F) +
|
sizeof(F) +
|
||||||
sizeof(JC4) +
|
sizeof(JC4) +
|
||||||
|
sizeof(RZ0) +
|
||||||
|
sizeof(RZ1) +
|
||||||
|
sizeof(RZ2) +
|
||||||
|
sizeof(RZ3) +
|
||||||
|
sizeof(RZ4) +
|
||||||
|
sizeof(RZ5) +
|
||||||
|
sizeof(RZ6) +
|
||||||
|
sizeof(RZ7) +
|
||||||
|
sizeof(RZ8) +
|
||||||
0];
|
0];
|
||||||
|
|
Loading…
Reference in New Issue