diff --git a/lib/CodeGen/CGVtable.cpp b/lib/CodeGen/CGVtable.cpp index 768e6a7566..23cef42a3c 100644 --- a/lib/CodeGen/CGVtable.cpp +++ b/lib/CodeGen/CGVtable.cpp @@ -1900,20 +1900,32 @@ VtableBuilder::LayoutPrimaryAndSecondaryVtables(BaseSubobject Base, // Compute 'this' pointer adjustments. ComputeThisAdjustments(); - // Record the address point. - AddressPoints.insert(std::make_pair(BaseSubobject(Base.getBase(), - OffsetInLayoutClass), - AddressPoint)); - - // Record the address points for all primary bases. - for (PrimaryBasesSetVectorTy::const_iterator I = PrimaryBases.begin(), - E = PrimaryBases.end(); I != E; ++I) { - const CXXRecordDecl *BaseDecl = *I; + // Add all address points. + const CXXRecordDecl *RD = Base.getBase(); + while (true) { + AddressPoints.insert(std::make_pair(BaseSubobject(RD, OffsetInLayoutClass), + AddressPoint)); + + const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD); + const CXXRecordDecl *PrimaryBase = Layout.getPrimaryBase(); - // We know that all the primary bases have the same offset as the base - // subobject. - BaseSubobject PrimaryBase(BaseDecl, OffsetInLayoutClass); - AddressPoints.insert(std::make_pair(PrimaryBase, AddressPoint)); + if (!PrimaryBase) + break; + + if (Layout.getPrimaryBaseWasVirtual()) { + // Check if this virtual primary base is a primary base in the layout + // class. If it's not, we don't want to add it. + const ASTRecordLayout &LayoutClassLayout = + Context.getASTRecordLayout(LayoutClass); + + if (LayoutClassLayout.getVBaseClassOffset(PrimaryBase) != + OffsetInLayoutClass) { + // We don't want to add this class (or any of its primary bases). + break; + } + } + + RD = PrimaryBase; } bool BaseIsMorallyVirtual = BaseIsVirtual; diff --git a/test/CodeGenCXX/vtable-layout-abi-examples.cpp b/test/CodeGenCXX/vtable-layout-abi-examples.cpp index a82fca736c..c01c5ef72c 100644 --- a/test/CodeGenCXX/vtable-layout-abi-examples.cpp +++ b/test/CodeGenCXX/vtable-layout-abi-examples.cpp @@ -178,7 +178,6 @@ struct C : virtual public A { int j; }; // CHECK-NEXT: 7 | vcall_offset (-16) // CHECK-NEXT: 8 | offset_to_top (-16) // CHECK-NEXT: 9 | Test2::D RTTI -// CHECK-NEXT: -- (Test2::A, 16) vtable address -- // CHECK-NEXT: -- (Test2::C, 16) vtable address -- // CHECK-NEXT: 10 | [unused] void Test2::A::f() struct D : public B, public C { diff --git a/test/CodeGenCXX/vtable-layout.cpp b/test/CodeGenCXX/vtable-layout.cpp index bc3d54b8e4..335816e544 100644 --- a/test/CodeGenCXX/vtable-layout.cpp +++ b/test/CodeGenCXX/vtable-layout.cpp @@ -635,7 +635,6 @@ struct D : virtual B, virtual C { virtual void f(); }; // CHECK-NEXT: 9 | vcall_offset (-8) // CHECK-NEXT: 10 | offset_to_top (-8) // CHECK-NEXT: 11 | Test17::E RTTI -// CHECK-NEXT: -- (Test17::A, 8) vtable address -- // CHECK-NEXT: -- (Test17::C, 8) vtable address -- // CHECK-NEXT: 12 | void Test17::E::f() // CHECK-NEXT: [this adjustment: 0 non-virtual, -24 vcall offset offset] @@ -693,7 +692,6 @@ struct C : A, B { // CHECK-NEXT: 19 | vcall_offset (-16) // CHECK-NEXT: 20 | offset_to_top (-16) // CHECK-NEXT: 21 | Test18::D RTTI -// CHECK-NEXT: -- (Test18::A, 16) vtable address -- // CHECK-NEXT: -- (Test18::B, 16) vtable address -- // CHECK-NEXT: 22 | void Test18::D::f() // CHECK-NEXT: [this adjustment: -8 non-virtual, -32 vcall offset offset] @@ -725,7 +723,6 @@ struct C : A, B { // CHECK-NEXT: 9 | vcall_offset (0) // CHECK-NEXT: 10 | offset_to_top (-8) // CHECK-NEXT: 11 | Test18::C RTTI -// CHECK-NEXT: -- (Test18::A, 16) vtable address -- // CHECK-NEXT: -- (Test18::B, 16) vtable address -- // CHECK-NEXT: 12 | void Test18::B::f() // CHECK-NEXT: 13 | [unused] void Test18::C::g() @@ -745,7 +742,6 @@ struct C : A, B { // CHECK-NEXT: 2 | vcall_offset (0) // CHECK-NEXT: 3 | offset_to_top (0) // CHECK-NEXT: 4 | Test18::B RTTI -// CHECK-NEXT: -- (Test18::A, 16) vtable address -- // CHECK-NEXT: -- (Test18::B, 16) vtable address -- // CHECK-NEXT: 5 | void Test18::B::f() // CHECK-NEXT: 6 | [unused] void Test18::A::g() @@ -881,9 +877,6 @@ class E : virtual C { }; // CHECK-NEXT: 12 | vcall_offset (-8) // CHECK-NEXT: 13 | offset_to_top (-8) // CHECK-NEXT: 14 | Test21::F RTTI -// CHECK-NEXT: -- (Test21::A, 8) vtable address -- -// CHECK-NEXT: -- (Test21::B, 8) vtable address -- -// CHECK-NEXT: -- (Test21::C, 8) vtable address -- // CHECK-NEXT: -- (Test21::E, 8) vtable address -- // CHECK-NEXT: 15 | [unused] void Test21::F::f() // @@ -1012,7 +1005,6 @@ struct C : virtual A { }; // CHECK-NEXT: 6 | vcall_offset (-8) // CHECK-NEXT: 7 | offset_to_top (-8) // CHECK-NEXT: 8 | Test24::D RTTI -// CHECK-NEXT: -- (Test24::A, 8) vtable address -- // CHECK-NEXT: -- (Test24::C, 8) vtable address -- // CHECK-NEXT: 9 | [unused] void Test24::D::f() @@ -1030,14 +1022,13 @@ struct C : virtual A { }; // CHECK-NEXT: 1 | vcall_offset (-8) // CHECK-NEXT: 2 | offset_to_top (0) // CHECK-NEXT: 3 | Test24::C RTTI -// CHECK-NEXT: -- (Test24::A, 8) vtable address -- // CHECK-NEXT: -- (Test24::C, 8) vtable address -- // CHECK-NEXT: 4 | [unused] void Test24::A::f() // CHECK-NEXT: 5 | vcall_offset (0) -// CHECK-NEXT: 6 | offset_to_top (8) -// CHECK-NEXT: 7 | Test24::C RTTI -// CHECK-NEXT: -- (Test24::A, 0) vtable address -- -// CHECK-NEXT: 8 | void Test24::A::f() +// CHECK-NEXT: 6 | offset_to_top (8) +// CHECK-NEXT: 7 | Test24::C RTTI +// CHECK-NEXT: -- (Test24::A, 0) vtable address -- +// CHECK-NEXT: 8 | void Test24::A::f() struct D : B, C { virtual void f(); }; @@ -1071,7 +1062,6 @@ struct B : virtual V { }; // CHECK-NEXT: 8 | offset_to_top (-8) // CHECK-NEXT: 9 | Test25::C RTTI // CHECK-NEXT: -- (Test25::B, 8) vtable address -- -// CHECK-NEXT: -- (Test25::V, 8) vtable address -- // CHECK-NEXT: 10 | [unused] void Test25::V::f() // CHECK: Construction vtable for ('Test25::A', 0) in 'Test25::C' (5 entries). @@ -1089,7 +1079,6 @@ struct B : virtual V { }; // CHECK-NEXT: 2 | offset_to_top (0) // CHECK-NEXT: 3 | Test25::B RTTI // CHECK-NEXT: -- (Test25::B, 8) vtable address -- -// CHECK-NEXT: -- (Test25::V, 8) vtable address -- // CHECK-NEXT: 4 | [unused] void Test25::V::f() // CHECK-NEXT: 5 | vcall_offset (0) // CHECK-NEXT: 6 | offset_to_top (8)