summaryrefslogtreecommitdiffstats
path: root/lib/AST/RecordLayout.cpp
diff options
context:
space:
mode:
authorDavid Majnemer <david.majnemer@gmail.com>2016-05-23 17:16:12 +0000
committerDavid Majnemer <david.majnemer@gmail.com>2016-05-23 17:16:12 +0000
commit6b373d1daba236a6c672e8a4e21b519cda0540a4 (patch)
tree8146b61e6cce920f571cc747fa44cc2b55febc49 /lib/AST/RecordLayout.cpp
parentdf9c980345ef84b7c5669e80c0f264f9739ed0de (diff)
[MS ABI] Implement __declspec(empty_bases) and __declspec(layout_version)
The layout_version attribute is pretty straightforward: use the layout rules from version XYZ of MSVC when used like struct __declspec(layout_version(XYZ)) S {}; The empty_bases attribute is more interesting. It tries to get the C++ empty base optimization to fire more often by tweaking the MSVC ABI rules in subtle ways: 1. Disable the leading and trailing zero-sized object flags if a class is marked __declspec(empty_bases) and is empty. This means that given: struct __declspec(empty_bases) A {}; struct __declspec(empty_bases) B {}; struct C : A, B {}; 'C' will have size 1 and nvsize 0 despite not being annotated __declspec(empty_bases). 2. When laying out virtual or non-virtual bases, disable the injection of padding between classes if the most derived class is marked __declspec(empty_bases). This means that given: struct A {}; struct B {}; struct __declspec(empty_bases) C : A, B {}; 'C' will have size 1 and nvsize 0. 3. When calculating the offset of a non-virtual base, choose offset zero if the most derived class is marked __declspec(empty_bases) and the base is empty _and_ has an nvsize of 0. Because of the ABI rules, this does not mean that empty bases reliably get placed at offset 0! For example: struct A {}; struct B {}; struct __declspec(empty_bases) C : A, B { virtual ~C(); }; 'C' will be pointer sized to account for the vfptr at offset 0. 'A' and 'B' will _not_ be at offset 0 despite being empty! Instead, they will be located right after the vfptr. This occurs due to the interaction betweeen non-virtual base layout and virtual function pointer injection: injection occurs after the nv-bases and shifts them down by the size of a pointer. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@270457 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/AST/RecordLayout.cpp')
-rw-r--r--lib/AST/RecordLayout.cpp4
1 files changed, 2 insertions, 2 deletions
diff --git a/lib/AST/RecordLayout.cpp b/lib/AST/RecordLayout.cpp
index b2c244e379..4cee2e0631 100644
--- a/lib/AST/RecordLayout.cpp
+++ b/lib/AST/RecordLayout.cpp
@@ -58,7 +58,7 @@ ASTRecordLayout::ASTRecordLayout(const ASTContext &Ctx,
const CXXRecordDecl *PrimaryBase,
bool IsPrimaryBaseVirtual,
const CXXRecordDecl *BaseSharingVBPtr,
- bool HasZeroSizedSubObject,
+ bool EndsWithZeroSizedObject,
bool LeadsWithZeroSizedBase,
const BaseOffsetsMapTy& BaseOffsets,
const VBaseOffsetsMapTy& VBaseOffsets)
@@ -82,7 +82,7 @@ ASTRecordLayout::ASTRecordLayout(const ASTContext &Ctx,
CXXInfo->VBPtrOffset = vbptroffset;
CXXInfo->HasExtendableVFPtr = hasExtendableVFPtr;
CXXInfo->BaseSharingVBPtr = BaseSharingVBPtr;
- CXXInfo->HasZeroSizedSubObject = HasZeroSizedSubObject;
+ CXXInfo->EndsWithZeroSizedObject = EndsWithZeroSizedObject;
CXXInfo->LeadsWithZeroSizedBase = LeadsWithZeroSizedBase;