/// HasVFPtr - Does this class have a vftable at all (could be inherited
/// from its primary base.)
bool HasVFPtr : 1;
-
- /// HasOwnVBPtr - Does this class provide a virtual function table
- /// (vtable in Itanium, VBtbl in Microsoft) that is independent from
- /// its base classes?
- bool HasOwnVBPtr : 1;
-
+
/// AlignAfterVBases - Force appropriate alignment after virtual bases are
/// laid out in MS-C++-ABI.
bool AlignAfterVBases : 1;
/// PrimaryBase - The primary base info for this record.
llvm::PointerIntPair<const CXXRecordDecl *, 1, bool> PrimaryBase;
+
+ /// BaseSharingVBPtr - The base we share vbptr with.
+ const CXXRecordDecl *BaseSharingVBPtr;
/// FIXME: This should really use a SmallPtrMap, once we have one in LLVM :)
typedef llvm::DenseMap<const CXXRecordDecl *, CharUnits> BaseOffsetsMapTy;
typedef CXXRecordLayoutInfo::BaseOffsetsMapTy BaseOffsetsMapTy;
ASTRecordLayout(const ASTContext &Ctx,
CharUnits size, CharUnits alignment,
- bool hasOwnVFPtr, bool hasVFPtr, bool hasOwnVBPtr,
+ bool hasOwnVFPtr, bool hasVFPtr,
CharUnits vbptroffset,
CharUnits datasize,
const uint64_t *fieldoffsets, unsigned fieldcount,
CharUnits SizeOfLargestEmptySubobject,
const CXXRecordDecl *PrimaryBase,
bool IsPrimaryBaseVirtual,
+ const CXXRecordDecl *BaseSharingVBPtr,
bool ForceAlign,
const BaseOffsetsMapTy& BaseOffsets,
const VBaseOffsetsMapTy& VBaseOffsets);
/// of the ABI.
bool hasOwnVBPtr() const {
assert(CXXInfo && "Record layout does not have C++ specific info!");
- return CXXInfo->HasOwnVBPtr;
+ return hasVBPtr() && !CXXInfo->BaseSharingVBPtr;
}
/// hasVBPtr - Does this class have a virtual function table pointer.
return CXXInfo->VBPtrOffset;
}
+ const CXXRecordDecl *getBaseSharingVBPtr() const {
+ assert(CXXInfo && "Record layout does not have C++ specific info!");
+ return CXXInfo->BaseSharingVBPtr;
+ }
+
const VBaseOffsetsMapTy &getVBaseOffsetsMap() const {
assert(CXXInfo && "Record layout does not have C++ specific info!");
return CXXInfo->VBaseOffsets;
ASTRecordLayout::ASTRecordLayout(const ASTContext &Ctx,
CharUnits size, CharUnits alignment,
bool hasOwnVFPtr, bool hasVFPtr,
- bool hasOwnVBPtr,
CharUnits vbptroffset,
CharUnits datasize,
const uint64_t *fieldoffsets,
CharUnits SizeOfLargestEmptySubobject,
const CXXRecordDecl *PrimaryBase,
bool IsPrimaryBaseVirtual,
+ const CXXRecordDecl *BaseSharingVBPtr,
bool AlignAfterVBases,
const BaseOffsetsMapTy& BaseOffsets,
const VBaseOffsetsMapTy& VBaseOffsets)
CXXInfo->HasOwnVFPtr = hasOwnVFPtr;
CXXInfo->VBPtrOffset = vbptroffset;
CXXInfo->HasVFPtr = hasVFPtr;
- CXXInfo->HasOwnVBPtr = hasOwnVBPtr;
+ CXXInfo->BaseSharingVBPtr = BaseSharingVBPtr;
CXXInfo->AlignAfterVBases = AlignAfterVBases;
return new (*this) ASTRecordLayout(
*this, Builder.Size, Builder.Alignment,
Builder.HasVFPtr && !Builder.PrimaryBase, Builder.HasVFPtr,
- Builder.HasVBPtr && !Builder.SharedVBPtrBase, Builder.VBPtrOffset,
- Builder.DataSize, Builder.FieldOffsets.data(),
+ Builder.VBPtrOffset, Builder.DataSize, Builder.FieldOffsets.data(),
Builder.FieldOffsets.size(), Builder.DataSize,
Builder.NonVirtualAlignment, CharUnits::Zero(), Builder.PrimaryBase,
- false, Builder.AlignAfterVBases, Builder.Bases, Builder.VBases);
+ false, Builder.SharedVBPtrBase, Builder.AlignAfterVBases, Builder.Bases,
+ Builder.VBases);
} else {
Builder.layout(D);
return new (*this) ASTRecordLayout(
Builder.Alignment,
Builder.HasOwnVFPtr,
RD->isDynamicClass(),
- false,
CharUnits::fromQuantity(-1),
DataSize,
Builder.FieldOffsets.data(),
EmptySubobjects.SizeOfLargestEmptySubobject,
Builder.PrimaryBase,
Builder.PrimaryBaseIsVirtual,
- true,
+ 0, true,
Builder.Bases, Builder.VBases);
} else {
RecordLayoutBuilder Builder(*this, /*EmptySubobjects=*/0);
const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD);
BasesSetVectorTy VisitedBases;
- // First, see if the Derived class shared the vbptr
- // with the first non-virtual base.
- for (CXXRecordDecl::base_class_const_iterator I = RD->bases_begin(),
- E = RD->bases_end(); I != E; ++I) {
- if (I->isVirtual())
- continue;
-
- const CXXRecordDecl *CurBase = I->getType()->getAsCXXRecordDecl();
- CharUnits DerivedVBPtrOffset = Layout.getVBPtrOffset(),
- BaseOffset = Layout.getBaseClassOffset(CurBase);
- const ASTRecordLayout &BaseLayout = Context.getASTRecordLayout(CurBase);
- if (!BaseLayout.hasVBPtr() ||
- DerivedVBPtrOffset != BaseOffset + BaseLayout.getVBPtrOffset())
- continue;
-
+ // First, see if the Derived class shared the vbptr with a non-virtual base.
+ if (const CXXRecordDecl *VBPtrBase = Layout.getBaseSharingVBPtr()) {
// If the Derived class shares the vbptr with a non-virtual base,
// it inherits its vbase indices.
- computeVBTableRelatedInformation(CurBase);
- for (CXXRecordDecl::base_class_const_iterator J = CurBase->vbases_begin(),
- F = CurBase->vbases_end(); J != F; ++J) {
- const CXXRecordDecl *SubVBase = J->getType()->getAsCXXRecordDecl();
- assert(VBTableIndices.count(ClassPairTy(CurBase, SubVBase)));
+ computeVBTableRelatedInformation(VBPtrBase);
+ for (CXXRecordDecl::base_class_const_iterator I = VBPtrBase->vbases_begin(),
+ E = VBPtrBase->vbases_end(); I != E; ++I) {
+ const CXXRecordDecl *SubVBase = I->getType()->getAsCXXRecordDecl();
+ assert(VBTableIndices.count(ClassPairTy(VBPtrBase, SubVBase)));
VBTableIndices[ClassPairTy(RD, SubVBase)] =
- VBTableIndices[ClassPairTy(CurBase, SubVBase)];
+ VBTableIndices[ClassPairTy(VBPtrBase, SubVBase)];
VisitedBases.insert(SubVBase);
}
}