};
void VtableBuilder::AddThunk(const CXXMethodDecl *MD, const ThunkInfo &Thunk) {
- if (isBuildingConstructorVtable())
- return;
+ assert(!isBuildingConstructorVtable() &&
+ "Can't add thunks for construction vtable");
llvm::SmallVector<ThunkInfo, 1> &ThunksVector = MethodThunks[MD];
Overriders.getOverrider(BaseSubobject(MD->getParent(),
MethodInfo.BaseOffset), MD);
+ // Check if we need an adjustment at all.
+ if (MethodInfo.BaseOffsetInLayoutClass == Overrider.Offset)
+ continue;
+
ThisAdjustment ThisAdjustment =
ComputeThisAdjustment(MD, MethodInfo.BaseOffsetInLayoutClass, Overrider);
I != E; ++I) {
const VtableComponent &Component = Components[I->first];
const ThunkInfo &Thunk = I->second;
+ const CXXMethodDecl *MD;
switch (Component.getKind()) {
default:
llvm_unreachable("Unexpected vtable component kind!");
case VtableComponent::CK_FunctionPointer:
- AddThunk(Component.getFunctionDecl(), Thunk);
+ MD = Component.getFunctionDecl();
break;
case VtableComponent::CK_CompleteDtorPointer:
- AddThunk(Component.getDestructorDecl(), Thunk);
+ MD = Component.getDestructorDecl();
break;
case VtableComponent::CK_DeletingDtorPointer:
// We've already added the thunk when we saw the complete dtor pointer.
- break;
+ continue;
}
+
+ if (MD->getParent() == MostDerivedClass)
+ AddThunk(MD, Thunk);
}
}
VtableBuilder::ComputeThisAdjustment(const CXXMethodDecl *MD,
uint64_t BaseOffsetInLayoutClass,
FinalOverriders::OverriderInfo Overrider) {
- // Check if we need an adjustment at all.
- if (BaseOffsetInLayoutClass == Overrider.Offset)
- return ThisAdjustment();
-
// Ignore adjustments for pure virtual member functions.
if (Overrider.Method->isPure())
return ThisAdjustment();
MethodInfoMap.insert(std::make_pair(MD, MethodInfo));
MethodInfoMap.erase(OverriddenMD);
+
+ // If the overridden method exists in a virtual base class or a direct
+ // or indirect base class of a virtual base class, we need to emit a
+ // thunk if we ever have a class hierarchy where the base class is not
+ // a primary base in the complete object.
+ if (!isBuildingConstructorVtable() && OverriddenMD != MD) {
+ // Compute the this adjustment.
+ ThisAdjustment ThisAdjustment =
+ ComputeThisAdjustment(OverriddenMD, BaseOffsetInLayoutClass,
+ Overrider);
+
+ if (ThisAdjustment.VCallOffsetOffset) {
+ // This is a virtual thunk, add it.
+ AddThunk(Overrider.Method,
+ ThunkInfo(ThisAdjustment, ReturnAdjustment()));
+ }
+ }
+
continue;
}
}
Out << '\n';
}
+
+ Out << '\n';
+
}
}
}