Support C++ calling Carbon functions with ref parameters (#7107)

When creating the C++ thunk, make the parameters references if the
corresponding callee parameters are `ref`s.

When creating the Carbon thunk, tag the call arguments as `ref` if the
corresponding callee parameters are `ref`s.
This commit is contained in:
Nicholas Bishop
2026-04-23 23:45:26 +00:00
committed by GitHub
parent 709776ad1c
commit 3f63cf4b10
4 changed files with 151 additions and 30 deletions
+28 -12
View File
@@ -168,6 +168,14 @@ auto ExportClassToCpp(Context& context, SemIR::LocId loc_id,
namespace {
struct FunctionInfo {
struct Param {
// Type of the parameter's scrutinee.
SemIR::TypeId type_id;
// Whether this is a `ref` param.
bool is_ref;
};
explicit FunctionInfo(Context& context, SemIR::FunctionId function_id,
const SemIR::Function& function,
clang::DeclContext* decl_context)
@@ -188,15 +196,17 @@ struct FunctionInfo {
self_type_id = scrutinee_type_id;
}
// Get the function's explicit parameter types.
// Get the function's explicit parameters.
function_params =
function_params.drop_front(function.call_param_ranges.implicit_size());
function_params =
function_params.drop_back(function.call_param_ranges.return_size());
for (auto param_inst_id : function_params) {
auto scrutinee_type_id = ExtractScrutineeType(
context.sem_ir(), context.insts().Get(param_inst_id).type_id());
param_type_ids.push_back(scrutinee_type_id);
explicit_params.push_back(
{.type_id = ExtractScrutineeType(
context.sem_ir(), context.insts().Get(param_inst_id).type_id()),
.is_ref =
context.insts().Is<SemIR::RefParamPattern>(param_inst_id)});
}
}
@@ -220,9 +230,9 @@ struct FunctionInfo {
// `CXXRecordDecl`.
clang::DeclContext* decl_context;
// Types of the function's explicit parameters (excludes implicit
// parameters and return parameters).
llvm::SmallVector<SemIR::TypeId> param_type_ids;
// For each of the function's explicit parameters, the scrutinee type
// and whether the parameter is a reference.
llvm::SmallVector<Param> explicit_params;
// Type of the function's `self` parameter, or `None` if the function
// is not a method.
@@ -256,8 +266,8 @@ static auto BuildCppFunctionDeclForCarbonFn(Context& context,
cpp_type = context.ast_context().getLValueReferenceType(cpp_type);
cpp_param_types.push_back(cpp_type);
}
for (auto param_type_id : callee.param_type_ids) {
auto cpp_type = MapToCppType(context, param_type_id);
for (auto param : callee.explicit_params) {
auto cpp_type = MapToCppType(context, param.type_id);
if (cpp_type.isNull()) {
context.TODO(loc_id, "failed to map Carbon type to C++");
return nullptr;
@@ -471,12 +481,15 @@ static auto BuildCppToCarbonThunk(Context& context, SemIR::LocId loc_id,
auto& thunk_ident = context.ast_context().Idents.get(thunk_name);
llvm::SmallVector<clang::QualType> param_types;
for (auto type_id : target.param_type_ids) {
auto cpp_type = MapToCppType(context, type_id);
for (auto param : target.explicit_params) {
auto cpp_type = MapToCppType(context, param.type_id);
if (cpp_type.isNull()) {
context.TODO(loc_id, "failed to map C++ type to Carbon");
return nullptr;
}
if (param.is_ref) {
cpp_type = context.ast_context().getLValueReferenceType(cpp_type);
}
param_types.push_back(cpp_type);
}
@@ -513,7 +526,10 @@ static auto BuildCarbonToCarbonThunk(Context& context, SemIR::LocId loc_id,
// Get the thunk's parameters. These match the callee parameters, with
// the addition of an output parameter for the callee's return value
// (if it has one).
llvm::SmallVector<SemIR::TypeId> thunk_param_type_ids(target.param_type_ids);
llvm::SmallVector<SemIR::TypeId> thunk_param_type_ids;
for (const auto& param : target.explicit_params) {
thunk_param_type_ids.push_back(param.type_id);
}
auto callee_return_type_id =
target.function.GetDeclaredReturnType(context.sem_ir());
if (callee_return_type_id != SemIR::TypeId::None) {