summaryrefslogtreecommitdiffstats
path: root/clang/lib
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib')
-rw-r--r--clang/lib/AST/RecordLayoutBuilder.cpp12
-rw-r--r--clang/lib/CodeGen/CGRecordLayoutBuilder.cpp76
2 files changed, 81 insertions, 7 deletions
diff --git a/clang/lib/AST/RecordLayoutBuilder.cpp b/clang/lib/AST/RecordLayoutBuilder.cpp
index 515088e67bb..ceb49ff0bf2 100644
--- a/clang/lib/AST/RecordLayoutBuilder.cpp
+++ b/clang/lib/AST/RecordLayoutBuilder.cpp
@@ -2157,7 +2157,7 @@ MicrosoftRecordLayoutBuilder::getAdjustedElementInfo(
// 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;
}
@@ -2538,17 +2538,17 @@ void MicrosoftRecordLayoutBuilder::injectVPtrs(const CXXRecordDecl *RD) {
// 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;
@@ -2601,7 +2601,7 @@ void MicrosoftRecordLayoutBuilder::layoutVirtualBases(const CXXRecordDecl *RD) {
CharUnits BaseOffset = Size.RoundUpToAlignment(Info.Alignment);
VBases.insert(std::make_pair(BaseDecl,
ASTRecordLayout::VBaseInfo(BaseOffset, HasVtordisp)));
- Size = BaseOffset + BaseLayout.getNonVirtualSize();
+ Size = BaseOffset + BaseLayout.getDataSize();
updateAlignment(Info.Alignment);
PreviousBaseLayout = &BaseLayout;
}
diff --git a/clang/lib/CodeGen/CGRecordLayoutBuilder.cpp b/clang/lib/CodeGen/CGRecordLayoutBuilder.cpp
index c3338a17b36..3aa1f81c737 100644
--- a/clang/lib/CodeGen/CGRecordLayoutBuilder.cpp
+++ b/clang/lib/CodeGen/CGRecordLayoutBuilder.cpp
@@ -144,6 +144,11 @@ private:
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);
@@ -708,6 +713,72 @@ CGRecordLayoutBuilder::LayoutNonVirtualBases(const CXXRecordDecl *RD,
}
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);
@@ -755,7 +826,10 @@ bool CGRecordLayoutBuilder::LayoutFields(const RecordDecl *D) {
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;
OpenPOWER on IntegriCloud