]> granicus.if.org Git - clang/commitdiff
Fix thunks returning memptrs via sret by emitting also scalar return values directly...
authorHans Wennborg <hans@hanshq.net>
Fri, 7 Dec 2018 08:17:26 +0000 (08:17 +0000)
committerHans Wennborg <hans@hanshq.net>
Fri, 7 Dec 2018 08:17:26 +0000 (08:17 +0000)
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

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@348569 91177308-0d34-0410-b5e6-96231b3b80d8

lib/CodeGen/CGVTables.cpp
lib/CodeGen/CodeGenFunction.cpp
test/CodeGenCXX/thunk-returning-memptr.cpp [new file with mode: 0644]

index c04d0360b3915cba0603e3c2b7ac07ddbace6379..83466f7f0f097061b978e267d532758be1c247f0 100644 (file)
@@ -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.
index 7c7ba9d0c124aa237b7062edf7195e31908690e0..da8f327efa7ccaec1b1c3e8c9a7e3681765c6897 100644 (file)
@@ -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/test/CodeGenCXX/thunk-returning-memptr.cpp b/test/CodeGenCXX/thunk-returning-memptr.cpp
new file mode 100644 (file)
index 0000000..0b7870c
--- /dev/null
@@ -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