diff options
author | Anders Carlsson <andersca@mac.com> | 2010-03-29 15:08:41 +0000 |
---|---|---|
committer | Anders Carlsson <andersca@mac.com> | 2010-03-29 15:08:41 +0000 |
commit | adb507df13aeb2334eddef64e6bbdf41a44dc5b1 (patch) | |
tree | 290da18d2e3c1be553f1766c233226c8b172b34b | |
parent | 0b4c9b5834a0a5520d2cd32227a53cf7f73fedca (diff) |
Another vtable layout fix, making us match gcc better.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@99812 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | lib/CodeGen/CGVtable.cpp | 11 | ||||
-rw-r--r-- | test/CodeGenCXX/vtable-layout.cpp | 30 |
2 files changed, 39 insertions, 2 deletions
diff --git a/lib/CodeGen/CGVtable.cpp b/lib/CodeGen/CGVtable.cpp index 1283c69d97..e79e91a446 100644 --- a/lib/CodeGen/CGVtable.cpp +++ b/lib/CodeGen/CGVtable.cpp @@ -1401,8 +1401,15 @@ void VtableBuilder::ComputeThisAdjustments() { MethodInfo.BaseOffset), MD); // Check if we need an adjustment at all. - if (MethodInfo.BaseOffsetInLayoutClass == Overrider.Offset) - continue; + if (MethodInfo.BaseOffsetInLayoutClass == Overrider.Offset) { + // When a return thunk is needed by a derived class that overrides a + // virtual base, gcc uses a virtual 'this' adjustment as well. + // While the thunk itself might be needed by vtables in subclasses or + // in construction vtables, there doesn't seem to be a reason for using + // the thunk in this vtable. Still, we do so to match gcc. + if (VTableThunks.lookup(VtableIndex).Return.isEmpty()) + continue; + } ThisAdjustment ThisAdjustment = ComputeThisAdjustment(MD, MethodInfo.BaseOffsetInLayoutClass, Overrider); diff --git a/test/CodeGenCXX/vtable-layout.cpp b/test/CodeGenCXX/vtable-layout.cpp index 335816e544..3a0dae41c3 100644 --- a/test/CodeGenCXX/vtable-layout.cpp +++ b/test/CodeGenCXX/vtable-layout.cpp @@ -1273,3 +1273,33 @@ struct E : D { void E::e() { } } + +namespace Test29 { + +// Test that the covariant return thunk for B::f will have a virtual 'this' adjustment, +// matching gcc. + +struct V1 { }; +struct V2 : virtual V1 { }; + +struct A { + virtual V1 *f(); +}; + +// CHECK: Vtable for 'Test29::B' (6 entries). +// CHECK-NEXT: 0 | vbase_offset (0) +// CHECK-NEXT: 1 | vcall_offset (0) +// CHECK-NEXT: 2 | offset_to_top (0) +// CHECK-NEXT: 3 | Test29::B RTTI +// CHECK-NEXT: -- (Test29::A, 0) vtable address -- +// CHECK-NEXT: -- (Test29::B, 0) vtable address -- +// CHECK-NEXT: 4 | Test29::V2 *Test29::B::f() +// CHECK-NEXT: [return adjustment: 0 non-virtual, -24 vbase offset offset] +// CHECK-NEXT: [this adjustment: 0 non-virtual, -24 vcall offset offset] +// CHECK-NEXT: 5 | Test29::V2 *Test29::B::f() +struct B : virtual A { + virtual V2 *f(); +}; +V2 *B::f() { return 0; } + +} |