diff options
-rw-r--r-- | lib/CodeGen/CGVTables.cpp | 14 | ||||
-rw-r--r-- | test/CodeGenCXX/vtable-layout.cpp | 56 |
2 files changed, 65 insertions, 5 deletions
diff --git a/lib/CodeGen/CGVTables.cpp b/lib/CodeGen/CGVTables.cpp index c3bd229cc3..462384f82f 100644 --- a/lib/CodeGen/CGVTables.cpp +++ b/lib/CodeGen/CGVTables.cpp @@ -1247,9 +1247,13 @@ private: /// LayoutPrimaryAndSecondaryVTables - Layout the primary vtable for the /// given base subobject, as well as all its secondary vtables. /// + /// \param BaseIsMorallyVirtual whether the base subobject is a virtual base + /// or a direct or indirect base of a virtual base. + /// /// \param BaseIsVirtualInLayoutClass - Whether the base subobject is virtual /// in the layout class. void LayoutPrimaryAndSecondaryVTables(BaseSubobject Base, + bool BaseIsMorallyVirtual, bool BaseIsVirtualInLayoutClass, uint64_t OffsetInLayoutClass); @@ -1839,6 +1843,7 @@ VTableBuilder::AddMethods(BaseSubobject Base, uint64_t BaseOffsetInLayoutClass, void VTableBuilder::LayoutVTable() { LayoutPrimaryAndSecondaryVTables(BaseSubobject(MostDerivedClass, 0), + /*BaseIsMorallyVirtual=*/false, MostDerivedClassIsVirtual, MostDerivedClassOffset); @@ -1854,6 +1859,7 @@ void VTableBuilder::LayoutVTable() { void VTableBuilder::LayoutPrimaryAndSecondaryVTables(BaseSubobject Base, + bool BaseIsMorallyVirtual, bool BaseIsVirtualInLayoutClass, uint64_t OffsetInLayoutClass) { assert(Base.getBase()->isDynamicClass() && "class does not have a vtable!"); @@ -1924,10 +1930,6 @@ VTableBuilder::LayoutPrimaryAndSecondaryVTables(BaseSubobject Base, RD = PrimaryBase; } - bool BaseIsMorallyVirtual = BaseIsVirtualInLayoutClass; - if (isBuildingConstructorVTable() && Base.getBase() == MostDerivedClass) - BaseIsMorallyVirtual = false; - // Layout secondary vtables. LayoutSecondaryVTables(Base, BaseIsMorallyVirtual, OffsetInLayoutClass); } @@ -1983,6 +1985,7 @@ void VTableBuilder::LayoutSecondaryVTables(BaseSubobject Base, // Layout the primary vtable (and any secondary vtables) for this base. LayoutPrimaryAndSecondaryVTables(BaseSubobject(BaseDecl, BaseOffset), + BaseIsMorallyVirtual, /*BaseIsVirtualInLayoutClass=*/false, BaseOffsetInLayoutClass); } @@ -2073,7 +2076,8 @@ VTableBuilder::LayoutVTablesForVirtualBases(const CXXRecordDecl *RD, LayoutClassLayout.getVBaseClassOffset(BaseDecl); LayoutPrimaryAndSecondaryVTables(BaseSubobject(BaseDecl, BaseOffset), - /*BaseIsVirtual=*/true, + /*BaseIsMorallyVirtual=*/true, + /*BaseIsVirtualInLayoutClass=*/true, BaseOffsetInLayoutClass); } diff --git a/test/CodeGenCXX/vtable-layout.cpp b/test/CodeGenCXX/vtable-layout.cpp index a8c767ede0..b535af26eb 100644 --- a/test/CodeGenCXX/vtable-layout.cpp +++ b/test/CodeGenCXX/vtable-layout.cpp @@ -1455,3 +1455,59 @@ struct F : virtual E, A { void F::f() { } } + +namespace Test34 { + +// Test that we lay out the construction vtable for 'Test34::E' in 'Test34:::F' correctly. + +struct A { + virtual void a(); +}; +struct B : virtual A { }; + +struct C : B, A { + virtual void c(); +}; + +struct D : A, C { }; + +struct E : virtual D { + virtual void e(); +}; + +// CHECK: Construction vtable for ('Test34::E', 0) in 'Test34::F' (22 entries). +// CHECK-NEXT: 0 | vbase_offset (0) +// CHECK-NEXT: 1 | vbase_offset (8) +// CHECK-NEXT: 2 | vcall_offset (0) +// CHECK-NEXT: 3 | offset_to_top (0) +// CHECK-NEXT: 4 | Test34::E RTTI +// CHECK-NEXT: -- (Test34::A, 0) vtable address -- +// CHECK-NEXT: -- (Test34::E, 0) vtable address -- +// CHECK-NEXT: 5 | void Test34::A::a() +// CHECK-NEXT: 6 | void Test34::E::e() +// CHECK-NEXT: 7 | vcall_offset (8) +// CHECK-NEXT: 8 | vcall_offset (0) +// CHECK-NEXT: 9 | vbase_offset (-8) +// CHECK-NEXT: 10 | offset_to_top (-8) +// CHECK-NEXT: 11 | Test34::E RTTI +// CHECK-NEXT: -- (Test34::A, 8) vtable address -- +// CHECK-NEXT: -- (Test34::D, 8) vtable address -- +// CHECK-NEXT: 12 | void Test34::A::a() +// CHECK-NEXT: 13 | vbase_offset (-16) +// CHECK-NEXT: 14 | vcall_offset (-16) +// CHECK-NEXT: 15 | offset_to_top (-16) +// CHECK-NEXT: 16 | Test34::E RTTI +// CHECK-NEXT: -- (Test34::B, 16) vtable address -- +// CHECK-NEXT: -- (Test34::C, 16) vtable address -- +// CHECK-NEXT: 17 | [unused] void Test34::A::a() +// CHECK-NEXT: 18 | void Test34::C::c() +// CHECK-NEXT: 19 | offset_to_top (-24) +// CHECK-NEXT: 20 | Test34::E RTTI +// CHECK-NEXT: -- (Test34::A, 24) vtable address -- +// CHECK-NEXT: 21 | void Test34::A::a() +struct F : E { + virtual void f(); +}; +void F::f() { } + +} |