diff --git a/toolchain/check/cpp/thunk.cpp b/toolchain/check/cpp/thunk.cpp index 251af0483a52..6a53e3b592f6 100644 --- a/toolchain/check/cpp/thunk.cpp +++ b/toolchain/check/cpp/thunk.cpp @@ -669,9 +669,25 @@ auto PerformCppThunkCall(Context& context, SemIR::LocId loc_id, context.insts().Get(return_slot_id).type_id())), .lvalue_id = return_slot_id}); thunk_arg_ids.push_back(arg_id); + } else if (return_slot_id.has_value()) { + thunk_arg_ids.push_back(return_slot_id); } - auto result_id = PerformCall(context, loc_id, thunk_callee_id, thunk_arg_ids); + // Compute the return type of the call to the thunk. + auto thunk_return_type_id = + thunk_function.GetDeclaredReturnType(context.sem_ir()); + if (!thunk_return_type_id.has_value()) { + CARBON_CHECK(thunk_takes_return_address || !return_type_id.has_value()); + thunk_return_type_id = GetTupleType(context, {}); + } else { + CARBON_CHECK(thunk_return_type_id == return_type_id); + } + + auto result_id = GetOrAddInst( + context, loc_id, + {.type_id = thunk_return_type_id, + .callee_id = thunk_callee_id, + .args_id = context.inst_blocks().Add(thunk_arg_ids)}); // Produce the result of the call, taking the value from the return storage. if (thunk_takes_return_address) { diff --git a/toolchain/check/testdata/interop/cpp/function/pointer.carbon b/toolchain/check/testdata/interop/cpp/function/pointer.carbon index dc844d5ec832..af7024e80931 100644 --- a/toolchain/check/testdata/interop/cpp/function/pointer.carbon +++ b/toolchain/check/testdata/interop/cpp/function/pointer.carbon @@ -1036,9 +1036,8 @@ fn F() { // CHECK:STDOUT: %.loc11_14.2: init %Optional.143 = converted %addr.loc11_14.1, %T.binding.as_type.as.ImplicitAs.impl.Convert.call // CHECK:STDOUT: %.loc11_14.3: ref %Optional.143 = temporary %.loc11_14.1, %.loc11_14.2 // CHECK:STDOUT: %.loc11_14.4: %Optional.143 = bind_value %.loc11_14.3 -// CHECK:STDOUT: %.loc11_16.2: ref %Optional.143 = temporary_storage -// CHECK:STDOUT: %Direct__carbon_thunk.call: init %Optional.143 = call imports.%Direct__carbon_thunk.decl(%.loc11_14.4) to %.loc11_16.2 -// CHECK:STDOUT: %.loc11_16.3: ref %Optional.143 = temporary %.loc11_16.2, %Direct__carbon_thunk.call +// CHECK:STDOUT: %Direct__carbon_thunk.call: init %Optional.143 = call imports.%Direct__carbon_thunk.decl(%.loc11_14.4) to %.loc11_16.1 +// CHECK:STDOUT: %.loc11_16.2: ref %Optional.143 = temporary %.loc11_16.1, %Direct__carbon_thunk.call // CHECK:STDOUT: name_binding_decl { // CHECK:STDOUT: %a.patt: %pattern_type.aa5 = value_binding_pattern a [concrete] // CHECK:STDOUT: } @@ -1055,8 +1054,7 @@ fn F() { // CHECK:STDOUT: %.loc13_50.2: %S = bind_value %.loc13_50.1 // CHECK:STDOUT: %.loc13_50.3: ref %S = value_as_ref %.loc13_50.2 // CHECK:STDOUT: %addr.loc13_58.1: %ptr.5c7 = addr_of %.loc13_50.3 -// CHECK:STDOUT: %.loc13_58.2: ref %Optional.143 = temporary_storage -// CHECK:STDOUT: %Indirect__carbon_thunk.call: init %Optional.143 = call imports.%Indirect__carbon_thunk.decl(%addr.loc13_58.1) to %.loc13_58.2 +// CHECK:STDOUT: %Indirect__carbon_thunk.call: init %Optional.143 = call imports.%Indirect__carbon_thunk.decl(%addr.loc13_58.1) to %.loc13_58.1 // CHECK:STDOUT: %.loc13_30.1: type = splice_block %Optional [concrete = constants.%Optional.143] { // CHECK:STDOUT: %Core.ref: = name_ref Core, imports.%Core [concrete = imports.%Core] // CHECK:STDOUT: %Optional.ref: %Optional.type = name_ref Optional, imports.%Core.Optional [concrete = constants.%Optional.generic] @@ -1067,23 +1065,23 @@ fn F() { // CHECK:STDOUT: %.loc13_30.2: %OptionalStorage.type = converted %ptr, %OptionalStorage.facet [concrete = constants.%OptionalStorage.facet] // CHECK:STDOUT: %Optional: type = class_type @Optional, @Optional(constants.%OptionalStorage.facet) [concrete = constants.%Optional.143] // CHECK:STDOUT: } -// CHECK:STDOUT: %.loc13_58.3: ref %Optional.143 = temporary %.loc13_58.2, %Indirect__carbon_thunk.call -// CHECK:STDOUT: %.loc13_58.4: %Optional.143 = bind_value %.loc13_58.3 -// CHECK:STDOUT: %a: %Optional.143 = value_binding a, %.loc13_58.4 -// CHECK:STDOUT: %DestroyT.binding.as_type.as.Destroy.impl.Op.bound.loc13_58: = bound_method %.loc13_58.3, constants.%DestroyT.binding.as_type.as.Destroy.impl.Op.465 +// CHECK:STDOUT: %.loc13_58.2: ref %Optional.143 = temporary %.loc13_58.1, %Indirect__carbon_thunk.call +// CHECK:STDOUT: %.loc13_58.3: %Optional.143 = bind_value %.loc13_58.2 +// CHECK:STDOUT: %a: %Optional.143 = value_binding a, %.loc13_58.3 +// CHECK:STDOUT: %DestroyT.binding.as_type.as.Destroy.impl.Op.bound.loc13_58: = bound_method %.loc13_58.2, constants.%DestroyT.binding.as_type.as.Destroy.impl.Op.465 // CHECK:STDOUT: -// CHECK:STDOUT: %bound_method.loc13_58: = bound_method %.loc13_58.3, %DestroyT.binding.as_type.as.Destroy.impl.Op.specific_fn.1 -// CHECK:STDOUT: %addr.loc13_58.2: %ptr.451 = addr_of %.loc13_58.3 +// CHECK:STDOUT: %bound_method.loc13_58: = bound_method %.loc13_58.2, %DestroyT.binding.as_type.as.Destroy.impl.Op.specific_fn.1 +// CHECK:STDOUT: %addr.loc13_58.2: %ptr.451 = addr_of %.loc13_58.2 // CHECK:STDOUT: %DestroyT.binding.as_type.as.Destroy.impl.Op.call.loc13_58: init %empty_tuple.type = call %bound_method.loc13_58(%addr.loc13_58.2) // CHECK:STDOUT: %DestroyT.binding.as_type.as.Destroy.impl.Op.bound.loc13_48: = bound_method %.loc13_48.4, constants.%DestroyT.binding.as_type.as.Destroy.impl.Op.016 // CHECK:STDOUT: // CHECK:STDOUT: %bound_method.loc13_48: = bound_method %.loc13_48.4, %DestroyT.binding.as_type.as.Destroy.impl.Op.specific_fn.2 // CHECK:STDOUT: %addr.loc13_48: %ptr.5c7 = addr_of %.loc13_48.4 // CHECK:STDOUT: %DestroyT.binding.as_type.as.Destroy.impl.Op.call.loc13_48: init %empty_tuple.type = call %bound_method.loc13_48(%addr.loc13_48) -// CHECK:STDOUT: %DestroyT.binding.as_type.as.Destroy.impl.Op.bound.loc11_16: = bound_method %.loc11_16.3, constants.%DestroyT.binding.as_type.as.Destroy.impl.Op.465 +// CHECK:STDOUT: %DestroyT.binding.as_type.as.Destroy.impl.Op.bound.loc11_16: = bound_method %.loc11_16.2, constants.%DestroyT.binding.as_type.as.Destroy.impl.Op.465 // CHECK:STDOUT: -// CHECK:STDOUT: %bound_method.loc11_16: = bound_method %.loc11_16.3, %DestroyT.binding.as_type.as.Destroy.impl.Op.specific_fn.3 -// CHECK:STDOUT: %addr.loc11_16: %ptr.451 = addr_of %.loc11_16.3 +// CHECK:STDOUT: %bound_method.loc11_16: = bound_method %.loc11_16.2, %DestroyT.binding.as_type.as.Destroy.impl.Op.specific_fn.3 +// CHECK:STDOUT: %addr.loc11_16: %ptr.451 = addr_of %.loc11_16.2 // CHECK:STDOUT: %DestroyT.binding.as_type.as.Destroy.impl.Op.call.loc11_16: init %empty_tuple.type = call %bound_method.loc11_16(%addr.loc11_16) // CHECK:STDOUT: %DestroyT.binding.as_type.as.Destroy.impl.Op.bound.loc11_14: = bound_method %.loc11_14.3, constants.%DestroyT.binding.as_type.as.Destroy.impl.Op.465 // CHECK:STDOUT: