// Respect required alignment, this is necessary because we may have adjusted
// the alignment in the case of pragam pack.
Info.Alignment = std::max(Info.Alignment, Layout.getRequiredAlignment());
- Info.Size = Layout.getNonVirtualSize();
+ Info.Size = Layout.getDataSize();
return Info;
}
// different from the general case layout but it may have to do with lazy
// placement of zero sized bases.
VBPtrOffset = Size;
- if (LastBaseLayout && LastBaseLayout->getNonVirtualSize().isZero()) {
+ if (LastBaseLayout && LastBaseLayout->getDataSize().isZero()) {
VBPtrOffset = Bases[LastBaseDecl];
- if (PenultBaseLayout && PenultBaseLayout->getNonVirtualSize().isZero())
+ if (PenultBaseLayout && PenultBaseLayout->getDataSize().isZero())
VBPtrOffset = Bases[PenultBaseDecl];
}
// Once we've located a spot for the vbptr, place it.
VBPtrOffset = VBPtrOffset.RoundUpToAlignment(PointerInfo.Alignment);
Size = VBPtrOffset + PointerInfo.Size;
- if (LastBaseLayout && LastBaseLayout->getNonVirtualSize().isZero()) {
+ if (LastBaseLayout && LastBaseLayout->getDataSize().isZero()) {
// Add the padding between zero sized bases after the vbptr.
- if (PenultBaseLayout && PenultBaseLayout->getNonVirtualSize().isZero())
+ if (PenultBaseLayout && PenultBaseLayout->getDataSize().isZero())
Size += CharUnits::One();
Size = Size.RoundUpToAlignment(LastBaseLayout->getRequiredAlignment());
Bases[LastBaseDecl] = Size;
CharUnits BaseOffset = Size.RoundUpToAlignment(Info.Alignment);\r
VBases.insert(std::make_pair(BaseDecl,
ASTRecordLayout::VBaseInfo(BaseOffset, HasVtordisp)));
- Size = BaseOffset + BaseLayout.getNonVirtualSize();
+ Size = BaseOffset + BaseLayout.getDataSize();
updateAlignment(Info.Alignment);
PreviousBaseLayout = &BaseLayout;
}
bool LayoutNonVirtualBases(const CXXRecordDecl *RD,
const ASTRecordLayout &Layout);
+ /// MSLayoutNonVirtualBases - layout the virtual bases of a record decl,
+ /// like MSVC.
+ bool MSLayoutNonVirtualBases(const CXXRecordDecl *RD,
+ const ASTRecordLayout &Layout);
+
/// ComputeNonVirtualBaseType - Compute the non-virtual base field types.
bool ComputeNonVirtualBaseType(const CXXRecordDecl *RD);
return true;
}
+bool
+CGRecordLayoutBuilder::MSLayoutNonVirtualBases(const CXXRecordDecl *RD,
+ const ASTRecordLayout &Layout) {
+ // Add a vfptr if the layout says to do so.
+ if (Layout.hasOwnVFPtr()) {
+ llvm::Type *FunctionType =
+ llvm::FunctionType::get(llvm::Type::getInt32Ty(Types.getLLVMContext()),
+ /*isVarArg=*/true);
+ llvm::Type *VTableTy = FunctionType->getPointerTo();
+
+ if (getTypeAlignment(VTableTy) > Alignment) {
+ // FIXME: Should we allow this to happen in Sema?
+ assert(!Packed && "Alignment is wrong even with packed struct!");
+ return false;
+ }
+
+ assert(NextFieldOffset.isZero() &&
+ "VTable pointer must come first!");
+ AppendField(CharUnits::Zero(), VTableTy->getPointerTo());
+ }
+
+ // Layout the non-virtual bases that have leading vfptrs.
+ for (CXXRecordDecl::base_class_const_iterator I = RD->bases_begin(),
+ E = RD->bases_end(); I != E; ++I) {
+ if (I->isVirtual())
+ continue;
+ const CXXRecordDecl *BaseDecl =
+ cast<CXXRecordDecl>(I->getType()->getAs<RecordType>()->getDecl());
+ const ASTRecordLayout &BaseLayout
+ = Types.getContext().getASTRecordLayout(BaseDecl);
+
+ if (!BaseLayout.hasExtendableVFPtr())
+ continue;
+
+ if (!LayoutNonVirtualBase(BaseDecl, Layout.getBaseClassOffset(BaseDecl)))
+ return false;
+ }
+
+ // Layout the non-virtual bases that don't have leading vfptrs.
+ for (CXXRecordDecl::base_class_const_iterator I = RD->bases_begin(),
+ E = RD->bases_end(); I != E; ++I) {
+ if (I->isVirtual())
+ continue;
+ const CXXRecordDecl *BaseDecl =
+ cast<CXXRecordDecl>(I->getType()->getAs<RecordType>()->getDecl());
+ const ASTRecordLayout &BaseLayout
+ = Types.getContext().getASTRecordLayout(BaseDecl);
+
+ if (BaseLayout.hasExtendableVFPtr())
+ continue;
+
+ if (!LayoutNonVirtualBase(BaseDecl, Layout.getBaseClassOffset(BaseDecl)))
+ return false;
+ }
+
+ // Add a vb-table pointer if the layout insists.
+ if (Layout.hasOwnVBPtr()) {
+ CharUnits VBPtrOffset = Layout.getVBPtrOffset();
+ llvm::Type *Vbptr = llvm::Type::getInt32PtrTy(Types.getLLVMContext());
+ AppendPadding(VBPtrOffset, getTypeAlignment(Vbptr));
+ AppendField(VBPtrOffset, Vbptr);
+ }
+
+ return true;
+}
+
bool
CGRecordLayoutBuilder::ComputeNonVirtualBaseType(const CXXRecordDecl *RD) {
const ASTRecordLayout &Layout = Types.getContext().getASTRecordLayout(RD);
const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(D);
if (RD)
- if (!LayoutNonVirtualBases(RD, Layout))
+ if (Types.getTarget().getCXXABI().isMicrosoft()) {
+ if (!MSLayoutNonVirtualBases(RD, Layout))
+ return false;
+ } else if (!LayoutNonVirtualBases(RD, Layout))
return false;
unsigned FieldNo = 0;