From: Anders Carlsson Date: Wed, 10 Mar 2010 21:25:37 +0000 (+0000) Subject: Fix calculation of whether a member function needs a thunk in construction vtables. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=2bc1d3a3b71564dc2909420abdd58aaf35191de2;p=clang Fix calculation of whether a member function needs a thunk in construction vtables. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@98191 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/CodeGen/CGVtable.cpp b/lib/CodeGen/CGVtable.cpp index 37dd23c0b5..5b9c976d38 100644 --- a/lib/CodeGen/CGVtable.cpp +++ b/lib/CodeGen/CGVtable.cpp @@ -1127,14 +1127,21 @@ private: /// BaseOffset - The base offset of this method. const uint64_t BaseOffset; + /// BaseOffsetInLayoutClass - The base offset in the layout class of this + /// method. + const uint64_t BaseOffsetInLayoutClass; + /// VtableIndex - The index in the vtable that this method has. /// (For destructors, this is the index of the complete destructor). const uint64_t VtableIndex; - MethodInfo(uint64_t BaseOffset, uint64_t VtableIndex) - : BaseOffset(BaseOffset), VtableIndex(VtableIndex) { } + MethodInfo(uint64_t BaseOffset, uint64_t BaseOffsetInLayoutClass, + uint64_t VtableIndex) + : BaseOffset(BaseOffset), + BaseOffsetInLayoutClass(BaseOffsetInLayoutClass), + VtableIndex(VtableIndex) { } - MethodInfo() : BaseOffset(0), VtableIndex(0) { } + MethodInfo() : BaseOffset(0), BaseOffsetInLayoutClass(0), VtableIndex(0) { } }; typedef llvm::DenseMap MethodInfoMapTy; @@ -1305,15 +1312,13 @@ void VtableBuilder::ComputeThisAdjustments() { const CXXMethodDecl *MD = I->first; const MethodInfo &MethodInfo = I->second; - BaseSubobject OverriddenBaseSubobject(MD->getParent(), - MethodInfo.BaseOffset); - // Get the final overrider for this method. FinalOverriders::OverriderInfo Overrider = - Overriders.getOverrider(OverriddenBaseSubobject, MD); + Overriders.getOverrider(BaseSubobject(MD->getParent(), + MethodInfo.BaseOffset), MD); // Check if we need an adjustment. - if (Overrider.OldOffset == (int64_t)MethodInfo.BaseOffset) + if (Overrider.Offset == MethodInfo.BaseOffsetInLayoutClass) continue; uint64_t VtableIndex = MethodInfo.VtableIndex; @@ -1327,8 +1332,11 @@ void VtableBuilder::ComputeThisAdjustments() { VtableComponent::CK_UnusedFunctionPointer) continue; + BaseSubobject OverriddenBaseSubobject(MD->getParent(), + MethodInfo.BaseOffsetInLayoutClass); + BaseSubobject OverriderBaseSubobject(Overrider.Method->getParent(), - Overrider.OldOffset); + Overrider.Offset); // Compute the adjustment offset. BaseOffset ThisAdjustmentOffset = @@ -1406,13 +1414,13 @@ VtableBuilder::ComputeThisAdjustmentBaseOffset(BaseSubobject Base, if (Offset.VirtualBase) { // If we have a virtual base class, the non-virtual offset is relative // to the virtual base class offset. - const ASTRecordLayout &MostDerivedClassLayout = - Context.getASTRecordLayout(MostDerivedClass); + const ASTRecordLayout &LayoutClassLayout = + Context.getASTRecordLayout(LayoutClass); /// Get the virtual base offset, relative to the most derived class /// layout. OffsetToBaseSubobject += - MostDerivedClassLayout.getVBaseClassOffset(Offset.VirtualBase); + LayoutClassLayout.getVBaseClassOffset(Offset.VirtualBase); } else { // Otherwise, the non-virtual offset is relative to the derived class // offset. @@ -1669,6 +1677,7 @@ VtableBuilder::AddMethods(BaseSubobject Base, uint64_t BaseOffsetInLayoutClass, MethodInfo &OverriddenMethodInfo = MethodInfoMap[OverriddenMD]; MethodInfo MethodInfo(Base.getBaseOffset(), + BaseOffsetInLayoutClass, OverriddenMethodInfo.VtableIndex); assert(!MethodInfoMap.count(MD) && @@ -1681,7 +1690,8 @@ VtableBuilder::AddMethods(BaseSubobject Base, uint64_t BaseOffsetInLayoutClass, } // Insert the method info for this method. - MethodInfo MethodInfo(Base.getBaseOffset(), Components.size()); + MethodInfo MethodInfo(Base.getBaseOffset(), BaseOffsetInLayoutClass, + Components.size()); assert(!MethodInfoMap.count(MD) && "Should not have method info for this method yet!"); diff --git a/test/CodeGenCXX/vtable-layout.cpp b/test/CodeGenCXX/vtable-layout.cpp index 2e08df9ed9..92544a6543 100644 --- a/test/CodeGenCXX/vtable-layout.cpp +++ b/test/CodeGenCXX/vtable-layout.cpp @@ -698,6 +698,65 @@ struct C : A, B { // CHECK-NEXT: 22 | void Test18::D::f() // CHECK-NEXT: [this adjustment: -8 non-virtual, -32 vcall offset offset] // CHECK-NEXT: 23 | [unused] void Test18::C::g() + +// CHECK: Construction vtable for ('Test18::B', 0) in 'Test18::D' (7 entries). +// CHECK-NEXT: 0 | vbase_offset (0) +// CHECK-NEXT: 1 | vcall_offset (0) +// CHECK-NEXT: 2 | vcall_offset (0) +// CHECK-NEXT: 3 | offset_to_top (0) +// CHECK-NEXT: 4 | Test18::B RTTI +// CHECK-NEXT: -- (Test18::A, 0) vtable address -- +// CHECK-NEXT: -- (Test18::B, 0) vtable address -- +// CHECK-NEXT: 5 | void Test18::B::f() +// CHECK-NEXT: 6 | void Test18::A::g() + +// CHECK: Construction vtable for ('Test18::C', 8) in 'Test18::D' (20 entries). +// CHECK-NEXT: 0 | vcall_offset (0) +// CHECK-NEXT: 1 | vcall_offset (0) +// CHECK-NEXT: 2 | vbase_offset (-8) +// CHECK-NEXT: 3 | offset_to_top (0) +// CHECK-NEXT: 4 | Test18::C RTTI +// CHECK-NEXT: -- (Test18::A, 8) vtable address -- +// CHECK-NEXT: -- (Test18::C, 8) vtable address -- +// CHECK-NEXT: 5 | void Test18::A::f() +// CHECK-NEXT: 6 | void Test18::C::g() +// CHECK-NEXT: 7 | vbase_offset (-16) +// CHECK-NEXT: 8 | vcall_offset (-8) +// 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() +// CHECK-NEXT: 14 | vcall_offset (8) +// CHECK-NEXT: 15 | vcall_offset (16) +// CHECK-NEXT: 16 | offset_to_top (8) +// CHECK-NEXT: 17 | Test18::C RTTI +// CHECK-NEXT: -- (Test18::A, 0) vtable address -- +// CHECK-NEXT: 18 | void Test18::B::f() +// CHECK-NEXT: [this adjustment: 0 non-virtual, -24 vcall offset offset] +// CHECK-NEXT: 19 | void Test18::C::g() +// CHECK-NEXT: [this adjustment: 0 non-virtual, -32 vcall offset offset] + +// CHECK: Construction vtable for ('Test18::B', 16) in 'Test18::D' (13 entries). +// CHECK-NEXT: 0 | vbase_offset (-16) +// CHECK-NEXT: 1 | vcall_offset (-16) +// 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() +// CHECK-NEXT: 7 | vcall_offset (0) +// CHECK-NEXT: 8 | vcall_offset (16) +// CHECK-NEXT: 9 | offset_to_top (16) +// CHECK-NEXT: 10 | Test18::B RTTI +// CHECK-NEXT: -- (Test18::A, 0) vtable address -- +// CHECK-NEXT: 11 | void Test18::B::f() +// CHECK-NEXT: [this adjustment: 0 non-virtual, -24 vcall offset offset] +// CHECK-NEXT: 12 | void Test18::A::g() struct D : virtual B, virtual C, virtual A { virtual void f();