Initial support for C++ function pointers (#7788)

This change introduces a new inst kind `CppFunctionPointerType`, which
represents an imported C++ function pointer that can be invoked from
Carbon (support for forming such a pointer from a Carbon function is in
a follow-up PR). This is implemented by treating the operation of
invoking a function pointer in C++ as if it were a call to an `__invoke`
method on the function pointer type, and extending the existing
function-import logic to support importing this fictitious method.

---------

Co-authored-by: Nicholas Bishop <nbishop@nbishop.net>
This commit is contained in:
Geoff Romer
2026-09-30 00:06:06 +00:00
committed by GitHub
co-authored by Nicholas Bishop
parent f65572a1e6
commit 12e1afeb15
41 changed files with 2030 additions and 200 deletions
+34 -21
View File
@@ -40,6 +40,31 @@ static auto GetExprCategoryImpl(const File* ir, InstId inst_id,
auto untyped_inst = ir->insts().Get(inst_id);
auto category_from_kind = untyped_inst.kind().expr_category();
auto handle_function_return =
[&](SemIR::FunctionId function_id,
SemIR::SpecificId resolved_specific_id) -> ExprCategory {
const auto& function = ir->functions().Get(function_id);
auto return_form_id =
function.GetDeclaredReturnForm(*ir, resolved_specific_id);
if (!return_form_id.has_value()) {
// Treat as equivalent to `-> ()`.
return ExprCategory::ReprInitializing;
}
auto return_form = ir->insts().Get(return_form_id);
CARBON_KIND_SWITCH(return_form) {
case CARBON_KIND(InitForm _):
return ExprCategory::ReprInitializing;
case CARBON_KIND(RefForm _):
return ExprCategory::DurableRef;
case CARBON_KIND(ValueForm _):
return ExprCategory::Value;
case CARBON_KIND(ErrorInst _):
return ExprCategory::Error;
default:
CARBON_FATAL("Unexpected form inst kind: {0}", return_form);
}
};
// Handle any special cases that use
// ComputedExprCategory::DependsOnOperands.
auto handle_special_case =
@@ -69,27 +94,8 @@ static auto GetExprCategoryImpl(const File* ir, InstId inst_id,
return ExprCategory::Error;
}
case CARBON_KIND(SemIR::CalleeFunction callee_function): {
const auto& function =
ir->functions().Get(callee_function.function_id);
auto return_form_id = function.GetDeclaredReturnForm(
*ir, callee_function.resolved_specific_id);
if (!return_form_id.has_value()) {
// Treat as equivalent to `-> ()`.
return ExprCategory::ReprInitializing;
}
auto return_form = ir->insts().Get(return_form_id);
CARBON_KIND_SWITCH(return_form) {
case CARBON_KIND(InitForm _):
return ExprCategory::ReprInitializing;
case CARBON_KIND(RefForm _):
return ExprCategory::DurableRef;
case CARBON_KIND(ValueForm _):
return ExprCategory::Value;
case CARBON_KIND(ErrorInst _):
return ExprCategory::Error;
default:
CARBON_FATAL("Unexpected inst kind: {0}", return_form);
}
return handle_function_return(callee_function.function_id,
callee_function.resolved_specific_id);
}
case CARBON_KIND(SemIR::CalleeNonFunction _): {
return ExprCategory::NotExpr;
@@ -98,6 +104,13 @@ static auto GetExprCategoryImpl(const File* ir, InstId inst_id,
// TODO: support `ref` returns from C++.
return ExprCategory::ReprInitializing;
}
case CARBON_KIND(SemIR::CalleeCppFunctionPointer function_ptr): {
return handle_function_return(
ir->clang_function_pointer_types()
.Get(function_ptr.function_type_id)
.function_id,
SemIR::SpecificId::None);
}
}
} else if constexpr (std::same_as<TypedInstT, SpecificInst>) {
// Switch to looking at the inner instruction and its specific, which is