diff options
-rw-r--r-- | lib/CodeGen/CGVTables.cpp | 11 | ||||
-rw-r--r-- | test/CodeGenCXX/thunks.cpp | 19 |
2 files changed, 29 insertions, 1 deletions
diff --git a/lib/CodeGen/CGVTables.cpp b/lib/CodeGen/CGVTables.cpp index 70fdf12967..066b20c837 100644 --- a/lib/CodeGen/CGVTables.cpp +++ b/lib/CodeGen/CGVTables.cpp @@ -1664,9 +1664,18 @@ VTableBuilder::AddMethods(BaseSubobject Base, uint64_t BaseOffsetInLayoutClass, if (ThisAdjustment.VCallOffsetOffset && Overrider.Method->getParent() == MostDerivedClass) { + + // There's no return adjustment from OverriddenMD and MD, + // but that doesn't mean there isn't one between MD and + // the final overrider. + BaseOffset ReturnAdjustmentOffset = + ComputeReturnAdjustmentBaseOffset(Context, Overrider.Method, MD); + ReturnAdjustment ReturnAdjustment = + ComputeReturnAdjustment(ReturnAdjustmentOffset); + // This is a virtual thunk for the most derived class, add it. AddThunk(Overrider.Method, - ThunkInfo(ThisAdjustment, ReturnAdjustment())); + ThunkInfo(ThisAdjustment, ReturnAdjustment)); } } diff --git a/test/CodeGenCXX/thunks.cpp b/test/CodeGenCXX/thunks.cpp index ba60385ab6..238032cc6d 100644 --- a/test/CodeGenCXX/thunks.cpp +++ b/test/CodeGenCXX/thunks.cpp @@ -260,6 +260,25 @@ namespace Test10 { } } +// PR7611 +namespace Test11 { + struct A { virtual A* f(); }; + struct B : virtual A { virtual A* f(); }; + struct C : B { virtual C* f(); }; + C* C::f() { return 0; } + + // The this-adjustment and return-adjustment thunk required when + // C::f appears in a vtable where A is at a nonzero offset from C. + // CHECK: define {{.*}} @_ZTcv0_n24_v0_n32_N6Test111C1fEv( + + // C::f itself. + // CHECK: define {{.*}} @_ZN6Test111C1fEv( + + // The return-adjustment thunk required when C::f appears in a vtable + // where A is at a zero offset from C. + // CHECK: define {{.*}} @_ZTch0_v0_n32_N6Test111C1fEv( +} + /**** The following has to go at the end of the file ****/ // This is from Test5: |