Stub out IsOverriderUsed.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@96883 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/CodeGen/CGVtable.cpp b/lib/CodeGen/CGVtable.cpp
index 9af81ab..5ef44f1 100644
--- a/lib/CodeGen/CGVtable.cpp
+++ b/lib/CodeGen/CGVtable.cpp
@@ -992,9 +992,33 @@
void AddMethod(const CXXMethodDecl *MD, ReturnAdjustment ReturnAdjustment,
ThisAdjustment ThisAdjustment);
+ /// IsOverriderUsed - Returns whether the overrider will ever be used in this
+ /// part of the vtable.
+ ///
+ /// Itanium C++ ABI 2.5.2:
+ ///
+ /// struct A { virtual void f(); };
+ /// struct B : virtual public A { int i; };
+ /// struct C : virtual public A { int j; };
+ /// struct D : public B, public C {};
+ ///
+ /// When B and C are declared, A is a primary base in each case, so although
+ /// vcall offsets are allocated in the A-in-B and A-in-C vtables, no this
+ /// adjustment is required and no thunk is generated. However, inside D
+ /// objects, A is no longer a primary base of C, so if we allowed calls to
+ /// C::f() to use the copy of A's vtable in the C subobject, we would need
+ /// to adjust this from C* to B::A*, which would require a third-party
+ /// thunk. Since we require that a call to C::f() first convert to A*,
+ /// C-in-D's copy of A's vtable is never referenced, so this is not
+ /// necessary.
+ bool IsOverriderUsed(BaseSubobject Base,
+ BaseSubobject FirstBaseInPrimaryBaseChain,
+ FinalOverriders::OverriderInfo Overrider) const;
+
/// AddMethods - Add the methods of this base subobject and all its
/// primary bases to the vtable components vector.
- void AddMethods(BaseSubobject Base, PrimaryBasesSetTy &PrimaryBases);
+ void AddMethods(BaseSubobject Base, BaseSubobject FirstBaseInPrimaryBaseChain,
+ PrimaryBasesSetTy &PrimaryBases);
// LayoutVtable - Layout the vtable for the most derived class, including its
// secondary vtables and any vtables for virtual bases.
@@ -1257,8 +1281,22 @@
}
}
+bool
+VtableBuilder::IsOverriderUsed(BaseSubobject Base,
+ BaseSubobject FirstBaseInPrimaryBaseChain,
+ FinalOverriders::OverriderInfo Overrider) const {
+ // If the base and the first base in the primary base chain have the same
+ // offsets, then this overrider will be used.
+ if (Base.getBaseOffset() == FirstBaseInPrimaryBaseChain.getBaseOffset())
+ return true;
+
+ return true;
+}
+
void
-VtableBuilder::AddMethods(BaseSubobject Base, PrimaryBasesSetTy &PrimaryBases) {
+VtableBuilder::AddMethods(BaseSubobject Base,
+ BaseSubobject FirstBaseInPrimaryBaseChain,
+ PrimaryBasesSetTy &PrimaryBases) {
const CXXRecordDecl *RD = Base.getBase();
const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD);
@@ -1283,7 +1321,8 @@
BaseOffset = Base.getBaseOffset();
}
- AddMethods(BaseSubobject(PrimaryBase, BaseOffset), PrimaryBases);
+ AddMethods(BaseSubobject(PrimaryBase, BaseOffset),
+ FirstBaseInPrimaryBaseChain, PrimaryBases);
if (!PrimaryBases.insert(PrimaryBase))
assert(false && "Found a duplicate primary base!");
@@ -1311,6 +1350,13 @@
continue;
}
+ // Check if this overrider is going to be used.
+ if (!IsOverriderUsed(Base, FirstBaseInPrimaryBaseChain, Overrider)) {
+ const CXXMethodDecl *OverriderMD = Overrider.Method;
+ Components.push_back(VtableComponent::MakeUnusedFunction(OverriderMD));
+ continue;
+ }
+
// Check if this overrider needs a return adjustment.
BaseOffset ReturnAdjustmentOffset =
Overriders.getReturnAdjustmentOffset(Base, MD);
@@ -1363,7 +1409,7 @@
// Now go through all virtual member functions and add them.
PrimaryBasesSetTy PrimaryBases;
- AddMethods(Base, PrimaryBases);
+ AddMethods(Base, Base, PrimaryBases);
// Record the address point.
AddressPoints.insert(std::make_pair(Base, AddressPoint));