Add PerformCallToCppFunction() which calls simplified version of PerformCppOverloadResolution() before calling PerformCallToFunction() (#6122)

Instead of calling `PerformCppOverloadResolution()` and use the complex
return value to call `PerformCallToFunction()`, we call
`PerformCallToCppFunction()` which will call both
`PerformCppOverloadResolution()` and `PerformCallToFunction()`.

Followup of #6112.
Part of #5995.
This commit is contained in:
Boaz Brickner
2025-09-29 14:26:23 +00:00
committed by GitHub
parent 3b6d202730
commit 5705b94da8
9 changed files with 135 additions and 107 deletions
+6 -59
View File
@@ -10,6 +10,7 @@
#include "toolchain/base/kind_switch.h"
#include "toolchain/check/cpp/import.h"
#include "toolchain/check/cpp/location.h"
#include "toolchain/check/cpp/operators.h"
#include "toolchain/check/cpp/type_mapping.h"
#include "toolchain/check/member_access.h"
#include "toolchain/check/name_lookup.h"
@@ -116,18 +117,10 @@ static auto CheckOverloadAccess(Context& context, SemIR::LocId loc_id,
.highest_allowed_access = allowed_access_kind});
}
// Returns whether the decl is an operator member function.
static auto IsOperatorMethodDecl(clang::Decl* decl) -> bool {
auto* clang_method_decl = dyn_cast<clang::CXXMethodDecl>(decl);
return clang_method_decl && clang_method_decl->isOverloadedOperator();
}
// Resolve which function to call, or returns an error instruction if overload
// resolution failed.
static auto ResolveCalleeId(Context& context, SemIR::LocId loc_id,
SemIR::CppOverloadSetId overload_set_id,
SemIR::InstId self_id,
llvm::ArrayRef<SemIR::InstId> arg_ids)
auto PerformCppOverloadResolution(Context& context, SemIR::LocId loc_id,
SemIR::CppOverloadSetId overload_set_id,
SemIR::InstId self_id,
llvm::ArrayRef<SemIR::InstId> arg_ids)
-> SemIR::InstId {
// Register an annotation scope to flush any Clang diagnostics when we return.
// This is important to ensure that Clang diagnostics are properly interleaved
@@ -177,7 +170,7 @@ static auto ResolveCalleeId(Context& context, SemIR::LocId loc_id,
context, loc_id, best_viable_fn->Function,
// If this is an operator method, the first arg will be used as self.
arg_exprs.size() -
(IsOperatorMethodDecl(best_viable_fn->Function) ? 1 : 0));
(IsCppOperatorMethodDecl(best_viable_fn->Function) ? 1 : 0));
CheckOverloadAccess(context, loc_id, overload_set,
best_viable_fn->FoundDecl, result_id);
return result_id;
@@ -208,50 +201,4 @@ static auto ResolveCalleeId(Context& context, SemIR::LocId loc_id,
}
}
// Returns whether the function is an imported C++ operator member function.
static auto IsCppOperatorMethod(Context& context, SemIR::FunctionId function_id)
-> bool {
SemIR::ClangDeclId clang_decl_id =
context.functions().Get(function_id).clang_decl_id;
return clang_decl_id.has_value() &&
IsOperatorMethodDecl(
context.clang_decls().Get(clang_decl_id).key.decl);
}
auto PerformCppOverloadResolution(Context& context, SemIR::LocId loc_id,
SemIR::CppOverloadSetId overload_set_id,
SemIR::InstId self_id,
llvm::ArrayRef<SemIR::InstId> arg_ids)
-> CppOverloadResolutionResult {
CppOverloadResolutionResult result = {
.callee_id =
ResolveCalleeId(context, loc_id, overload_set_id, self_id, arg_ids),
.arg_ids = arg_ids};
SemIR::Callee callee = GetCallee(context.sem_ir(), result.callee_id);
CARBON_KIND_SWITCH(callee) {
case CARBON_KIND(SemIR::CalleeError _): {
result.callee_id = SemIR::ErrorInst::InstId;
return result;
}
case CARBON_KIND(SemIR::CalleeFunction fn): {
CARBON_CHECK(!fn.self_id.has_value());
if (self_id.has_value()) {
// Preserve the `self` argument from the original callee.
fn.self_id = self_id;
} else if (IsCppOperatorMethod(context, fn.function_id)) {
// Adjust `self` and args for C++ overloaded operator methods.
fn.self_id = result.arg_ids.consume_front();
}
result.callee_function = fn;
return result;
}
case CARBON_KIND(SemIR::CalleeCppOverloadSet _): {
CARBON_FATAL("overloads can't be recursive");
}
case CARBON_KIND(SemIR::CalleeNonFunction _): {
CARBON_FATAL("overloads should produce functions");
}
}
}
} // namespace Carbon::Check