Generate correct vcall offsets when we have a primary virtual base that is not a primary base in the complete class hierarchy.
llvm-svn: 97039
diff --git a/clang/lib/CodeGen/CGVtable.cpp b/clang/lib/CodeGen/CGVtable.cpp
index 93ed111..61dd11e 100644
--- a/clang/lib/CodeGen/CGVtable.cpp
+++ b/clang/lib/CodeGen/CGVtable.cpp
@@ -968,6 +968,7 @@
/// AddVCallAndVBaseOffsets - Add vcall offsets and vbase offsets for the
/// given base subobject.
void AddVCallAndVBaseOffsets(BaseSubobject Base, bool BaseIsVirtual,
+ uint64_t RealBaseOffset,
VisitedVirtualBasesSetTy &VBases);
/// AddVCallOffsets - Add vcall offsets for the given base subobject.
@@ -1112,6 +1113,7 @@
void
VtableBuilder::AddVCallAndVBaseOffsets(BaseSubobject Base,
bool BaseIsVirtual,
+ uint64_t RealBaseOffset,
VisitedVirtualBasesSetTy &VBases) {
const ASTRecordLayout &Layout = Context.getASTRecordLayout(Base.getBase());
@@ -1126,8 +1128,28 @@
// emit them for the primary base first).
if (const CXXRecordDecl *PrimaryBase = Layout.getPrimaryBase()) {
bool PrimaryBaseIsVirtual = Layout.getPrimaryBaseWasVirtual();
- AddVCallAndVBaseOffsets(BaseSubobject(PrimaryBase, Base.getBaseOffset()),
- PrimaryBaseIsVirtual, VBases);
+
+ uint64_t PrimaryBaseOffset;
+
+ // Get the base offset of the primary base.
+ if (PrimaryBaseIsVirtual) {
+ assert(Layout.getVBaseClassOffset(PrimaryBase) == 0 &&
+ "Primary vbase should have a zero offset!");
+
+ const ASTRecordLayout &MostDerivedClassLayout =
+ Context.getASTRecordLayout(MostDerivedClass);
+
+ PrimaryBaseOffset =
+ MostDerivedClassLayout.getVBaseClassOffset(PrimaryBase);
+ } else {
+ assert(Layout.getBaseClassOffset(PrimaryBase) == 0 &&
+ "Primary base should have a zero offset!");
+
+ PrimaryBaseOffset = Base.getBaseOffset();
+ }
+
+ AddVCallAndVBaseOffsets(BaseSubobject(PrimaryBase, PrimaryBaseOffset),
+ PrimaryBaseIsVirtual, RealBaseOffset, VBases);
}
// FIXME: Don't use /8 here.
@@ -1136,7 +1158,7 @@
// We only want to add vcall offsets for virtual bases.
if (BaseIsVirtual)
- AddVCallOffsets(Base, Base.getBaseOffset());
+ AddVCallOffsets(Base, RealBaseOffset);
}
void VtableBuilder::AddVCallOffsets(BaseSubobject Base, uint64_t VBaseOffset) {
@@ -1434,7 +1456,7 @@
// Add vcall and vbase offsets for this vtable.
VisitedVirtualBasesSetTy VBases;
- AddVCallAndVBaseOffsets(Base, BaseIsVirtual, VBases);
+ AddVCallAndVBaseOffsets(Base, BaseIsVirtual, Base.getBaseOffset(), VBases);
// Reverse them and add them to the vtable components.
std::reverse(VCallAndVBaseOffsets.begin(), VCallAndVBaseOffsets.end());
@@ -1470,11 +1492,11 @@
AddressPoints.insert(std::make_pair(PrimaryBase, AddressPoint));
}
- // Layout secondary vtables.
- LayoutSecondaryVtables(Base);
-
// Clear the vcall offsets.
VCallOffsets.clear();
+
+ // Layout secondary vtables.
+ LayoutSecondaryVtables(Base);
}
void VtableBuilder::LayoutSecondaryVtables(BaseSubobject Base) {