summaryrefslogtreecommitdiffstats
path: root/clang/lib/AST/RecordLayoutBuilder.cpp
diff options
context:
space:
mode:
authorDavid Majnemer <david.majnemer@gmail.com>2014-02-12 00:43:02 +0000
committerDavid Majnemer <david.majnemer@gmail.com>2014-02-12 00:43:02 +0000
commit79a1c8906686d11a9fe7463cd0b5ebb26c39d101 (patch)
tree3446a27b94afaef7aeca3229c08b3ba092f3ba7f /clang/lib/AST/RecordLayoutBuilder.cpp
parent5b85858b77ee745253097642666b195e13e5e9ce (diff)
downloadbcm5719-llvm-79a1c8906686d11a9fe7463cd0b5ebb26c39d101.tar.gz
bcm5719-llvm-79a1c8906686d11a9fe7463cd0b5ebb26c39d101.zip
MS ABI: vptr injection should obey alignment requirements
vptr injection must inject padding equivalent to the alignment of the most aligned non-virtual subobject, not the alignment of the enclosing record. To fascilitate this change, don't let record layout observe the alignment of the record until we've injected our vptrs. Also, do not allow the alignment of vbases to affect required alignment until just before we insert the vtordisp field. llvm-svn: 201199
Diffstat (limited to 'clang/lib/AST/RecordLayoutBuilder.cpp')
-rw-r--r--clang/lib/AST/RecordLayoutBuilder.cpp28
1 files changed, 20 insertions, 8 deletions
diff --git a/clang/lib/AST/RecordLayoutBuilder.cpp b/clang/lib/AST/RecordLayoutBuilder.cpp
index 903f973e616..1f64b4be507 100644
--- a/clang/lib/AST/RecordLayoutBuilder.cpp
+++ b/clang/lib/AST/RecordLayoutBuilder.cpp
@@ -2277,6 +2277,8 @@ void MicrosoftRecordLayoutBuilder::layout(const RecordDecl *RD) {
initializeLayout(RD);
layoutFields(RD);
DataSize = Size = Size.RoundUpToAlignment(Alignment);
+ RequiredAlignment = std::max(
+ RequiredAlignment, Context.toCharUnitsFromBits(RD->getMaxAlignment()));
finalizeLayout(RD);
}
@@ -2287,6 +2289,8 @@ void MicrosoftRecordLayoutBuilder::cxxLayout(const CXXRecordDecl *RD) {
layoutFields(RD);
injectVPtrs(RD);
DataSize = Size = Size.RoundUpToAlignment(Alignment);
+ RequiredAlignment = std::max(
+ RequiredAlignment, Context.toCharUnitsFromBits(RD->getMaxAlignment()));
layoutVirtualBases(RD);
finalizeLayout(RD);
}
@@ -2300,8 +2304,6 @@ void MicrosoftRecordLayoutBuilder::initializeLayout(const RecordDecl *RD) {
// In 32-bit mode we do not. The check to see if we need to perform alignment
// checks the RequiredAlignment field and performs alignment if it isn't 0.
RequiredAlignment = Is64BitMode ? CharUnits::One() : CharUnits::Zero();
- RequiredAlignment = std::max(RequiredAlignment,
- Context.toCharUnitsFromBits(RD->getMaxAlignment()));
// Compute the maximum field alignment.
MaxFieldAlignment = CharUnits::Zero();
// Honor the default struct packing maximum alignment flag.
@@ -2352,14 +2354,14 @@ MicrosoftRecordLayoutBuilder::layoutNonVirtualBases(const CXXRecordDecl *RD) {
i != e; ++i) {
const CXXRecordDecl *BaseDecl = i->getType()->getAsCXXRecordDecl();
const ASTRecordLayout &BaseLayout = Context.getASTRecordLayout(BaseDecl);
- // Track RequiredAlignment for all bases in this pass.
- RequiredAlignment = std::max(RequiredAlignment,
- BaseLayout.getRequiredAlignment());
// Mark and skip virtual bases.
if (i->isVirtual()) {
HasVBPtr = true;
continue;
}
+ // Track RequiredAlignment for all bases in this pass.
+ RequiredAlignment = std::max(RequiredAlignment,
+ BaseLayout.getRequiredAlignment());
// Check fo a base to share a VBPtr with.
if (!SharedVBPtrBase && BaseLayout.hasVBPtr()) {
SharedVBPtrBase = BaseDecl;
@@ -2525,7 +2527,8 @@ void MicrosoftRecordLayoutBuilder::injectVBPtr(const CXXRecordDecl *RD) {
CharUnits FieldStart = VBPtrOffset + PointerInfo.Size;
// Make sure that the amount we push the fields back by is a multiple of the
// alignment.
- CharUnits Offset = (FieldStart - InjectionSite).RoundUpToAlignment(Alignment);
+ CharUnits Offset = (FieldStart - InjectionSite).RoundUpToAlignment(
+ std::max(RequiredAlignment, Alignment));
// Increase the size of the object and push back all fields by the offset
// amount.
Size += Offset;
@@ -2547,11 +2550,12 @@ void MicrosoftRecordLayoutBuilder::injectVFPtr(const CXXRecordDecl *RD) {
return;
// Make sure that the amount we push the struct back by is a multiple of the
// alignment.
- CharUnits Offset = PointerInfo.Size.RoundUpToAlignment(Alignment);
+ CharUnits Offset = PointerInfo.Size.RoundUpToAlignment(
+ std::max(RequiredAlignment, Alignment));
// Increase the size of the object and push back all fields, the vbptr and all
// bases by the offset amount.
Size += Offset;
- for (SmallVector<uint64_t, 16>::iterator i = FieldOffsets.begin(),
+ for (SmallVectorImpl<uint64_t>::iterator i = FieldOffsets.begin(),
e = FieldOffsets.end();
i != e; ++i)
*i += Context.toBits(Offset);
@@ -2646,6 +2650,14 @@ void MicrosoftRecordLayoutBuilder::layoutVirtualBases(const CXXRecordDecl *RD) {
// The alignment of the vtordisp is at least the required alignment of the
// entire record. This requirement may be present to support vtordisp
// injection.
+ for (CXXRecordDecl::base_class_const_iterator i = RD->vbases_begin(),
+ e = RD->vbases_end();
+ i != e; ++i) {
+ const CXXRecordDecl *BaseDecl = i->getType()->getAsCXXRecordDecl();
+ const ASTRecordLayout &BaseLayout = Context.getASTRecordLayout(BaseDecl);
+ RequiredAlignment =
+ std::max(RequiredAlignment, BaseLayout.getRequiredAlignment());
+ }
VtorDispAlignment = std::max(VtorDispAlignment, RequiredAlignment);
// Compute the vtordisp set.
llvm::SmallPtrSet<const CXXRecordDecl *, 2> HasVtordispSet =
OpenPOWER on IntegriCloud