diff options
Diffstat (limited to 'clang/lib/CodeGen/CGRecordLayoutBuilder.cpp')
-rw-r--r-- | clang/lib/CodeGen/CGRecordLayoutBuilder.cpp | 29 |
1 files changed, 23 insertions, 6 deletions
diff --git a/clang/lib/CodeGen/CGRecordLayoutBuilder.cpp b/clang/lib/CodeGen/CGRecordLayoutBuilder.cpp index b7ab169a64f..eb2d524ef77 100644 --- a/clang/lib/CodeGen/CGRecordLayoutBuilder.cpp +++ b/clang/lib/CodeGen/CGRecordLayoutBuilder.cpp @@ -414,10 +414,11 @@ CGRecordLowering::accumulateBitFields(RecordDecl::field_iterator Field, void CGRecordLowering::accumulateBases() { // If we've got a primary virtual base, we need to add it with the bases. - if (Layout.isPrimaryBaseVirtual()) - Members.push_back(StorageInfo( - CharUnits::Zero(), - getStorageType(Layout.getPrimaryBase()))); + if (Layout.isPrimaryBaseVirtual()) { + const CXXRecordDecl *BaseDecl = Layout.getPrimaryBase(); + Members.push_back(MemberInfo(CharUnits::Zero(), MemberInfo::Base, + getStorageType(BaseDecl), BaseDecl)); + } // Accumulate the non-virtual bases. for (const auto &Base : RD->bases()) { if (Base.isVirtual()) @@ -440,8 +441,24 @@ void CGRecordLowering::accumulateVPtrs() { } void CGRecordLowering::accumulateVBases() { - Members.push_back(MemberInfo(Layout.getNonVirtualSize(), - MemberInfo::Scissor, 0, RD)); + CharUnits ScissorOffset = Layout.getNonVirtualSize(); + // In the itanium ABI, it's possible to place a vbase at a dsize that is + // smaller than the nvsize. Here we check to see if such a base is placed + // before the nvsize and set the scissor offset to that, instead of the + // nvsize. + if (!useMSABI()) + for (const auto &Base : RD->vbases()) { + const CXXRecordDecl *BaseDecl = Base.getType()->getAsCXXRecordDecl(); + if (BaseDecl->isEmpty()) + continue; + // If the vbase is a primary virtual base of some base, then it doesn't + // get its own storage location but instead lives inside of that base. + if (Context.isNearlyEmpty(BaseDecl) && !hasOwnStorage(RD, BaseDecl)) + continue; + ScissorOffset = std::min(ScissorOffset, + Layout.getVBaseClassOffset(BaseDecl)); + } + Members.push_back(MemberInfo(ScissorOffset, MemberInfo::Scissor, 0, RD)); for (const auto &Base : RD->vbases()) { const CXXRecordDecl *BaseDecl = Base.getType()->getAsCXXRecordDecl(); if (BaseDecl->isEmpty()) |