From aa2ac80eaaaea7d99e1efecf52abb4b167dc11c8 Mon Sep 17 00:00:00 2001 From: Douglas Gregor Date: Thu, 20 May 2010 05:54:35 +0000 Subject: [PATCH] When creating a this-adjustment thunk where the return value is of C++ 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. llvm-svn: 104215 --- clang/lib/CodeGen/CGVTables.cpp | 11 +++++-- clang/test/CodeGenCXX/thunks.cpp | 49 +++++++++++++++++++++++++++++--- 2 files changed, 54 insertions(+), 6 deletions(-) diff --git a/clang/lib/CodeGen/CGVTables.cpp b/clang/lib/CodeGen/CGVTables.cpp index 368e2483c862..3c9b45ba8c1c 100644 --- a/clang/lib/CodeGen/CGVTables.cpp +++ b/clang/lib/CodeGen/CGVTables.cpp @@ -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(); diff --git a/clang/test/CodeGenCXX/thunks.cpp b/clang/test/CodeGenCXX/thunks.cpp index 7d2edaa7457b..8144770763dd 100644 --- a/clang/test/CodeGenCXX/thunks.cpp +++ b/clang/test/CodeGenCXX/thunks.cpp @@ -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(