Fix PR19487, PR19505 and PR19506 -- redundant vtordisp thunks when the final overrider is present in both a vbase and nvbase
Reviewed at http://reviews.llvm.org/D3449 llvm-svn: 206908
This commit is contained in:
parent
f1a311653a
commit
6b12850d27
|
@ -64,10 +64,14 @@ public:
|
|||
/// Method - The method decl of the overrider.
|
||||
const CXXMethodDecl *Method;
|
||||
|
||||
/// VirtualBase - The virtual base class subobject of this overridder.
|
||||
/// Note that this records the closest derived virtual base class subobject.
|
||||
const CXXRecordDecl *VirtualBase;
|
||||
|
||||
/// Offset - the base offset of the overrider's parent in the layout class.
|
||||
CharUnits Offset;
|
||||
|
||||
OverriderInfo() : Method(0), Offset(CharUnits::Zero()) { }
|
||||
OverriderInfo() : Method(0), VirtualBase(0), Offset(CharUnits::Zero()) { }
|
||||
};
|
||||
|
||||
private:
|
||||
|
@ -201,6 +205,7 @@ FinalOverriders::FinalOverriders(const CXXRecordDecl *MostDerivedClass,
|
|||
|
||||
Overrider.Offset = OverriderOffset;
|
||||
Overrider.Method = Method.Method;
|
||||
Overrider.VirtualBase = Method.InVirtualSubobject;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2716,20 +2721,10 @@ void VFTableBuilder::CalculateVtordispAdjustment(
|
|||
VBaseMap.find(WhichVFPtr.getVBaseWithVPtr());
|
||||
assert(VBaseMapEntry != VBaseMap.end());
|
||||
|
||||
// If there's no vtordisp, we don't need any vtordisp adjustment.
|
||||
if (!VBaseMapEntry->second.hasVtorDisp())
|
||||
return;
|
||||
|
||||
const CXXRecordDecl *OverriderRD = Overrider.Method->getParent();
|
||||
const CXXRecordDecl *OverriderVBase = 0;
|
||||
if (OverriderRD != MostDerivedClass) {
|
||||
OverriderVBase =
|
||||
ComputeBaseOffset(Context, OverriderRD, MostDerivedClass).VirtualBase;
|
||||
}
|
||||
|
||||
// If the final overrider is defined in the same vbase as the initial
|
||||
// declaration, we don't need a vtordisp thunk at all.
|
||||
if (OverriderVBase == WhichVFPtr.getVBaseWithVPtr())
|
||||
// If there's no vtordisp or the final overrider is defined in the same vbase
|
||||
// as the initial declaration, we don't need any vtordisp adjustment.
|
||||
if (!VBaseMapEntry->second.hasVtorDisp() ||
|
||||
Overrider.VirtualBase == WhichVFPtr.getVBaseWithVPtr())
|
||||
return;
|
||||
|
||||
// OK, now we know we need to use a vtordisp thunk.
|
||||
|
@ -2740,7 +2735,8 @@ void VFTableBuilder::CalculateVtordispAdjustment(
|
|||
|
||||
// A simple vtordisp thunk will suffice if the final overrider is defined
|
||||
// in either the most derived class or its non-virtual base.
|
||||
if (OverriderRD == MostDerivedClass || !OverriderVBase)
|
||||
if (Overrider.Method->getParent() == MostDerivedClass ||
|
||||
!Overrider.VirtualBase)
|
||||
return;
|
||||
|
||||
// Otherwise, we need to do use the dynamic offset of the final overrider
|
||||
|
@ -2750,7 +2746,7 @@ void VFTableBuilder::CalculateVtordispAdjustment(
|
|||
MostDerivedClassLayout.getVBPtrOffset()).getQuantity();
|
||||
TA.Virtual.Microsoft.VBOffsetOffset =
|
||||
Context.getTypeSizeInChars(Context.IntTy).getQuantity() *
|
||||
VTables.getVBTableIndex(MostDerivedClass, OverriderVBase);
|
||||
VTables.getVBTableIndex(MostDerivedClass, Overrider.VirtualBase);
|
||||
|
||||
TA.NonVirtual = (ThisOffset - Overrider.Offset).getQuantity();
|
||||
}
|
||||
|
|
|
@ -480,3 +480,58 @@ struct C : virtual B {
|
|||
|
||||
C c;
|
||||
}
|
||||
|
||||
namespace pr19505 {
|
||||
struct A {
|
||||
virtual void f();
|
||||
virtual void z();
|
||||
};
|
||||
|
||||
struct B : A {
|
||||
virtual void f();
|
||||
};
|
||||
|
||||
struct C : A, B {
|
||||
virtual void g();
|
||||
};
|
||||
|
||||
struct X : B, virtual C {
|
||||
X() {}
|
||||
virtual void g();
|
||||
|
||||
// CHECK-LABEL: VFTable for 'pr19505::A' in 'pr19505::B' in 'pr19505::C' in 'pr19505::X' (2 entries).
|
||||
// CHECK-NEXT: 0 | void pr19505::B::f()
|
||||
// CHECK-NEXT: 1 | void pr19505::A::z()
|
||||
|
||||
// MANGLING-DAG: @"\01??_7X@pr19505@@6BB@1@@" = {{.*}}@"\01?f@B@pr19505@@UAEXXZ"
|
||||
} x;
|
||||
|
||||
void build_vftable(X *obj) { obj->g(); }
|
||||
}
|
||||
|
||||
namespace pr19506 {
|
||||
struct A {
|
||||
virtual void f();
|
||||
virtual void g();
|
||||
};
|
||||
|
||||
struct B : A {
|
||||
virtual void f();
|
||||
};
|
||||
|
||||
struct C : B {};
|
||||
|
||||
struct X : C, virtual B {
|
||||
virtual void g();
|
||||
X() {}
|
||||
|
||||
// CHECK-LABEL: VFTable for 'pr19506::A' in 'pr19506::B' in 'pr19506::X' (2 entries).
|
||||
// CHECK-NEXT: 0 | void pr19506::B::f()
|
||||
// CHECK-NEXT: 1 | void pr19506::X::g()
|
||||
// CHECK-NEXT: [this adjustment: vtordisp at -4, -12 non-virtual]
|
||||
|
||||
// MANGLING-DAG: @"\01??_7X@pr19506@@6BB@1@@" = {{.*}}@"\01?f@B@pr19506@@UAEXXZ"
|
||||
} x;
|
||||
|
||||
void build_vftable(X *obj) { obj->g(); }
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue