diff options
-rw-r--r-- | lib/CodeGen/CGVTables.cpp | 11 | ||||
-rw-r--r-- | test/CodeGenCXX/thunks.cpp | 49 |
2 files changed, 54 insertions, 6 deletions
diff --git a/lib/CodeGen/CGVTables.cpp b/lib/CodeGen/CGVTables.cpp index 368e2483c8..3c9b45ba8c 100644 --- a/lib/CodeGen/CGVTables.cpp +++ b/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/test/CodeGenCXX/thunks.cpp b/test/CodeGenCXX/thunks.cpp index 7d2edaa745..8144770763 100644 --- a/test/CodeGenCXX/thunks.cpp +++ b/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( |