mirror of
https://github.com/carbon-language/carbon-lang.git
synced 2026-10-05 22:02:55 +01:00
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:
co-authored by
Nicholas Bishop
parent
f65572a1e6
commit
12e1afeb15
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user