summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHans Wennborg <hans@hanshq.net>2018-12-07 08:17:26 +0000
committerHans Wennborg <hans@hanshq.net>2018-12-07 08:17:26 +0000
commitacd10ee101f16b46741d81f3f84ded7078c150bc (patch)
treece000e08648bc45216a6ffb40ecd82fb5129d091
parentf2ec0bebe9ad40eb8c1e818fa95c78deafc1bc04 (diff)
Fix thunks returning memptrs via sret by emitting also scalar return values directly in sret slot (PR39901)
Thunks that return member pointers via sret are broken due to using temporary storage for the return value on the stack and then passing that pointer to a tail call, violating the rule that a tail call can't access allocas in the caller (see bug). Since r90526, we put aggregate return values directly in the sret slot, but this doesn't apply to member pointers which are considered scalar. Unless I'm missing something subtle, we should be able to always use the sret slot directly for indirect return values. Differential revision: https://reviews.llvm.org/D55371
-rw-r--r--clang/lib/CodeGen/CGVTables.cpp3
-rw-r--r--clang/lib/CodeGen/CodeGenFunction.cpp5
-rw-r--r--clang/test/CodeGenCXX/thunk-returning-memptr.cpp27
3 files changed, 30 insertions, 5 deletions
diff --git a/clang/lib/CodeGen/CGVTables.cpp b/clang/lib/CodeGen/CGVTables.cpp
index c04d0360b39..83466f7f0f0 100644
--- a/clang/lib/CodeGen/CGVTables.cpp
+++ b/clang/lib/CodeGen/CGVTables.cpp
@@ -350,8 +350,7 @@ void CodeGenFunction::EmitCallAndReturnForThunk(llvm::Constant *CalleePtr,
: FPT->getReturnType();
ReturnValueSlot Slot;
if (!ResultType->isVoidType() &&
- CurFnInfo->getReturnInfo().getKind() == ABIArgInfo::Indirect &&
- !hasScalarEvaluationKind(CurFnInfo->getReturnType()))
+ CurFnInfo->getReturnInfo().getKind() == ABIArgInfo::Indirect)
Slot = ReturnValueSlot(ReturnValue, ResultType.isVolatileQualified());
// Now emit our call.
diff --git a/clang/lib/CodeGen/CodeGenFunction.cpp b/clang/lib/CodeGen/CodeGenFunction.cpp
index 7c7ba9d0c12..da8f327efa7 100644
--- a/clang/lib/CodeGen/CodeGenFunction.cpp
+++ b/clang/lib/CodeGen/CodeGenFunction.cpp
@@ -1073,9 +1073,8 @@ void CodeGenFunction::StartFunction(GlobalDecl GD,
// Count the implicit return.
if (!endsWithReturn(D))
++NumReturnExprs;
- } else if (CurFnInfo->getReturnInfo().getKind() == ABIArgInfo::Indirect &&
- !hasScalarEvaluationKind(CurFnInfo->getReturnType())) {
- // Indirect aggregate return; emit returned value directly into sret slot.
+ } else if (CurFnInfo->getReturnInfo().getKind() == ABIArgInfo::Indirect) {
+ // Indirect return; emit returned value directly into sret slot.
// This reduces code size, and affects correctness in C++.
auto AI = CurFn->arg_begin();
if (CurFnInfo->getReturnInfo().isSRetAfterThis())
diff --git a/clang/test/CodeGenCXX/thunk-returning-memptr.cpp b/clang/test/CodeGenCXX/thunk-returning-memptr.cpp
new file mode 100644
index 00000000000..0b7870c6d65
--- /dev/null
+++ b/clang/test/CodeGenCXX/thunk-returning-memptr.cpp
@@ -0,0 +1,27 @@
+// RUN: %clang_cc1 -triple=i686 -emit-llvm -o - %s | FileCheck %s
+
+
+struct X;
+typedef void (X::*memptr)();
+
+struct A {
+ virtual memptr f();
+};
+
+struct B {
+ virtual memptr f();
+};
+
+struct C : A, B {
+ C();
+ memptr f() override __attribute__((noinline)) { return nullptr; };
+};
+
+C::C() {}
+
+// Make sure the member pointer is returned from the thunk via the return slot.
+// Because of the tail call, the return value cannot be copied into a local
+// alloca. (PR39901)
+
+// CHECK-LABEL: define linkonce_odr void @_ZThn4_N1C1fEv({ i32, i32 }* noalias sret %agg.result, %struct.C* %this)
+// CHECK: tail call void @_ZN1C1fEv({ i32, i32 }* sret %agg.result