aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/CodeGen/CGVTables.cpp11
-rw-r--r--test/CodeGenCXX/thunks.cpp19
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: