]> granicus.if.org Git - clang/commitdiff
When creating a this-adjustment thunk where the return value is of C++
authorDouglas Gregor <dgregor@apple.com>
Thu, 20 May 2010 05:54:35 +0000 (05:54 +0000)
committerDouglas Gregor <dgregor@apple.com>
Thu, 20 May 2010 05:54:35 +0000 (05:54 +0000)
class type (that uses a return slot), pass the return slot to the
callee directly rather than allocating new storage and trying to copy
the object. This appears to have been the cause of the remaining two
Boost.Interprocess failures.

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

lib/CodeGen/CGVTables.cpp
test/CodeGenCXX/thunks.cpp

index 368e2483c862ff17404086592ad8d5d715a924f1..3c9b45ba8c1c2c0a39c7b5201a40e37af4f2e846 100644 (file)
@@ -2657,8 +2657,15 @@ void CodeGenFunction::GenerateThunk(llvm::Function *Fn, GlobalDecl GD,
     CGM.getTypes().getFunctionInfo(ResultType, CallArgs,
                                    FPT->getExtInfo());
   
+  // Determine whether we have a return value slot to use.
+  ReturnValueSlot Slot;
+  if (!ResultType->isVoidType() &&
+      FnInfo.getReturnInfo().getKind() == ABIArgInfo::Indirect &&
+      hasAggregateLLVMType(CurFnInfo->getReturnType()))
+    Slot = ReturnValueSlot(ReturnValue, ResultType.isVolatileQualified());
+  
   // Now emit our call.
-  RValue RV = EmitCall(FnInfo, Callee, ReturnValueSlot(), CallArgs, MD);
+  RValue RV = EmitCall(FnInfo, Callee, Slot, CallArgs, MD);
   
   if (!Thunk.Return.isEmpty()) {
     // Emit the return adjustment.
@@ -2701,7 +2708,7 @@ void CodeGenFunction::GenerateThunk(llvm::Function *Fn, GlobalDecl GD,
     RV = RValue::get(ReturnValue);
   }
 
-  if (!ResultType->isVoidType())
+  if (!ResultType->isVoidType() && Slot.isNull())
     EmitReturnOfRValue(RV, ResultType);
 
   FinishFunction();
index 7d2edaa7457b4b7d3fd99aeac6be9940a143e21f..8144770763dd9ab3f217f8ead7c4f66fb0f2dfa1 100644 (file)
@@ -86,10 +86,6 @@ void C::f() { }
 
 }
 
-// This is from Test5:
-// CHECK: define linkonce_odr void @_ZTv0_n24_N5Test51B1fEv
-// CHECK: define internal void @_ZThn8_N12_GLOBAL__N_11C1fEv(
-
 // Check that the thunk gets internal linkage.
 namespace {
 
@@ -134,4 +130,49 @@ void f(B b) {
 }
 }
 
+namespace Test6 {
+  struct X {
+    X();
+    X(const X&);
+    X &operator=(const X&);
+    ~X();
+  };
+
+  struct P {
+    P();
+    P(const P&);
+    ~P();
+    X first;
+    X second;
+  };
+
+  P getP();
+
+  struct Base1 {
+    int i;
+
+    virtual X f() { return X(); }
+  };
+
+  struct Base2 {
+    float real;
 
+    virtual X f() { return X(); }
+  };
+
+  struct Thunks : Base1, Base2 {
+    long l;
+
+    virtual X f();
+  };
+
+  // CHECK: define void @_ZThn16_N5Test66Thunks1fEv
+  // CHECK-NOT: memcpy
+  // CHECK: {{call void @_ZN5Test66Thunks1fEv.*sret}}
+  // CHECK: ret void
+  X Thunks::f() { return X(); }
+}
+
+// This is from Test5:
+// CHECK: define linkonce_odr void @_ZTv0_n24_N5Test51B1fEv
+// CHECK: define internal void @_ZThn8_N12_GLOBAL__N_11C1fEv(