зеркало из https://github.com/microsoft/clang.git
We were mistakenly marking morally virtual bases as being uninteresting. Fix this.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@98180 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Родитель
f2c98ce981
Коммит
a96a2e961a
|
@ -1235,7 +1235,11 @@ private:
|
|||
|
||||
/// LayoutSecondaryVtables - Layout the secondary vtables for the given base
|
||||
/// subobject.
|
||||
void LayoutSecondaryVtables(BaseSubobject Base, uint64_t OffsetInLayoutClass);
|
||||
///
|
||||
/// \param BaseIsMorallyVirtual whether the base subobject is a virtual base
|
||||
/// or a direct or indirect base of a virtual base.
|
||||
void LayoutSecondaryVtables(BaseSubobject Base, bool BaseIsMorallyVirtual,
|
||||
uint64_t OffsetInLayoutClass);
|
||||
|
||||
/// DeterminePrimaryVirtualBases - Determine the primary virtual bases in this
|
||||
/// class hierarchy.
|
||||
|
@ -1772,11 +1776,16 @@ VtableBuilder::LayoutPrimaryAndSecondaryVtables(BaseSubobject Base,
|
|||
AddressPoints.insert(std::make_pair(PrimaryBase, AddressPoint));
|
||||
}
|
||||
|
||||
bool BaseIsMorallyVirtual = BaseIsVirtual;
|
||||
if (isBuildingConstructorVtable() && Base.getBase() == MostDerivedClass)
|
||||
BaseIsMorallyVirtual = false;
|
||||
|
||||
// Layout secondary vtables.
|
||||
LayoutSecondaryVtables(Base, OffsetInLayoutClass);
|
||||
LayoutSecondaryVtables(Base, BaseIsMorallyVirtual, OffsetInLayoutClass);
|
||||
}
|
||||
|
||||
void VtableBuilder::LayoutSecondaryVtables(BaseSubobject Base,
|
||||
bool BaseIsMorallyVirtual,
|
||||
uint64_t OffsetInLayoutClass) {
|
||||
// Itanium C++ ABI 2.5.2:
|
||||
// Following the primary virtual table of a derived class are secondary
|
||||
|
@ -1806,9 +1815,8 @@ void VtableBuilder::LayoutSecondaryVtables(BaseSubobject Base,
|
|||
// tables, which will therefore not be present in the construction
|
||||
// virtual table group, even though the subobject virtual tables are
|
||||
// present in the main virtual table group for the complete object.
|
||||
if (!BaseDecl->getNumVBases()) {
|
||||
if (!BaseIsMorallyVirtual && !BaseDecl->getNumVBases())
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// Get the base offset of this base.
|
||||
|
@ -1821,7 +1829,7 @@ void VtableBuilder::LayoutSecondaryVtables(BaseSubobject Base,
|
|||
// to emit secondary vtables for other bases of this base.
|
||||
if (BaseDecl == PrimaryBase) {
|
||||
LayoutSecondaryVtables(BaseSubobject(BaseDecl, BaseOffset),
|
||||
BaseOffsetInLayoutClass);
|
||||
BaseIsMorallyVirtual, BaseOffsetInLayoutClass);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
|
@ -1150,4 +1150,71 @@ struct E : D {
|
|||
virtual void e();
|
||||
};
|
||||
void E::e() { }
|
||||
|
||||
}
|
||||
|
||||
namespace Test28 {
|
||||
|
||||
// Check that we do include the vtable for B in the D-in-E construction vtable, since
|
||||
// B is a base class of a virtual base (C).
|
||||
|
||||
struct A {
|
||||
virtual void a();
|
||||
};
|
||||
|
||||
struct B {
|
||||
virtual void b();
|
||||
};
|
||||
|
||||
struct C : A, B {
|
||||
virtual void c();
|
||||
};
|
||||
|
||||
struct D : virtual C {
|
||||
};
|
||||
|
||||
// CHECK: Vtable for 'Test28::E' (14 entries).
|
||||
// CHECK-NEXT: 0 | vbase_offset (8)
|
||||
// CHECK-NEXT: 1 | offset_to_top (0)
|
||||
// CHECK-NEXT: 2 | Test28::E RTTI
|
||||
// CHECK-NEXT: -- (Test28::D, 0) vtable address --
|
||||
// CHECK-NEXT: -- (Test28::E, 0) vtable address --
|
||||
// CHECK-NEXT: 3 | void Test28::E::e()
|
||||
// CHECK-NEXT: 4 | vcall_offset (8)
|
||||
// CHECK-NEXT: 5 | vcall_offset (0)
|
||||
// CHECK-NEXT: 6 | vcall_offset (0)
|
||||
// CHECK-NEXT: 7 | offset_to_top (-8)
|
||||
// CHECK-NEXT: 8 | Test28::E RTTI
|
||||
// CHECK-NEXT: -- (Test28::A, 8) vtable address --
|
||||
// CHECK-NEXT: -- (Test28::C, 8) vtable address --
|
||||
// CHECK-NEXT: 9 | void Test28::A::a()
|
||||
// CHECK-NEXT: 10 | void Test28::C::c()
|
||||
// CHECK-NEXT: 11 | offset_to_top (-16)
|
||||
// CHECK-NEXT: 12 | Test28::E RTTI
|
||||
// CHECK-NEXT: -- (Test28::B, 16) vtable address --
|
||||
// CHECK-NEXT: 13 | void Test28::B::b()
|
||||
|
||||
// CHECK: Construction vtable for ('Test28::D', 0) in 'Test28::E' (13 entries).
|
||||
// CHECK-NEXT: 0 | vbase_offset (8)
|
||||
// CHECK-NEXT: 1 | offset_to_top (0)
|
||||
// CHECK-NEXT: 2 | Test28::D RTTI
|
||||
// CHECK-NEXT: -- (Test28::D, 0) vtable address --
|
||||
// CHECK-NEXT: 3 | vcall_offset (8)
|
||||
// CHECK-NEXT: 4 | vcall_offset (0)
|
||||
// CHECK-NEXT: 5 | vcall_offset (0)
|
||||
// CHECK-NEXT: 6 | offset_to_top (-8)
|
||||
// CHECK-NEXT: 7 | Test28::D RTTI
|
||||
// CHECK-NEXT: -- (Test28::A, 8) vtable address --
|
||||
// CHECK-NEXT: -- (Test28::C, 8) vtable address --
|
||||
// CHECK-NEXT: 8 | void Test28::A::a()
|
||||
// CHECK-NEXT: 9 | void Test28::C::c()
|
||||
// CHECK-NEXT: 10 | offset_to_top (-16)
|
||||
// CHECK-NEXT: 11 | Test28::D RTTI
|
||||
// CHECK-NEXT: -- (Test28::B, 16) vtable address --
|
||||
// CHECK-NEXT: 12 | void Test28::B::b()
|
||||
struct E : D {
|
||||
virtual void e();
|
||||
};
|
||||
void E::e() { }
|
||||
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче