mirror of
https://github.com/carbon-language/carbon-lang.git
synced 2026-10-05 22:02:55 +01:00
Perform overload resolution immediately in C++ operator lookup. (#6416)
Don't attempt to defer overload resolution by creating a `CppOverloadSet`; this was incorrect as we weren't saving the complete clang::OverloadCandidateSet, resulting in template candidates not being found. Moreover, saving the overload candidate set would be expensive, as the representation is surprisingly large, and is unnecessary since we're about to build a call. In passing, improve the diagnostics for overload resolution failure to use Clang's operator overload resolution messages rather than its call overload resolution messages. This fixes calls to templated operator overloads, which is the final piece needed for us to successfully compile an iostream-based "Hello world" program. --------- Co-authored-by: Jon Ross-Perkins <jperkins@google.com>
This commit is contained in:
co-authored by
Jon Ross-Perkins
parent
167b45ca35
commit
054dfca685
@@ -8,6 +8,7 @@
|
||||
|
||||
#include "toolchain/check/call.h"
|
||||
#include "toolchain/check/context.h"
|
||||
#include "toolchain/check/cpp/call.h"
|
||||
#include "toolchain/check/cpp/operators.h"
|
||||
#include "toolchain/check/generic.h"
|
||||
#include "toolchain/check/member_access.h"
|
||||
@@ -67,27 +68,30 @@ auto BuildUnaryOperator(Context& context, SemIR::LocId loc_id, Operator op,
|
||||
// Operator operands don't require `ref` tags.
|
||||
context.ref_tags().Insert(operand_id, Context::RefTag::NotRequired);
|
||||
|
||||
SemIR::InstId op_fn_id = SemIR::InstId::None;
|
||||
|
||||
// For unary operators with a C++ class as the operand, try to import and call
|
||||
// the C++ operator.
|
||||
// TODO: Change impl lookup instead. See
|
||||
// https://github.com/carbon-language/carbon-lang/blob/db0a00d713015436844c55e7ac190a0f95556499/toolchain/check/operator.cpp#L76
|
||||
if (IsCppClassType(context, operand_id)) {
|
||||
SemIR::InstId cpp_inst_id =
|
||||
LookupCppOperator(context, loc_id, op, {operand_id});
|
||||
if (cpp_inst_id.has_value()) {
|
||||
if (cpp_inst_id == SemIR::ErrorInst::InstId) {
|
||||
return SemIR::ErrorInst::InstId;
|
||||
}
|
||||
return PerformCall(context, loc_id, cpp_inst_id, {operand_id});
|
||||
op_fn_id = LookupCppOperator(context, loc_id, op, {operand_id});
|
||||
|
||||
// If C++ operator lookup found a non-method operator, call it with one call
|
||||
// argument. Otherwise fall through to call it with a self argument.
|
||||
if (op_fn_id.has_value() && !IsCppOperatorMethod(context, op_fn_id)) {
|
||||
return PerformCall(context, loc_id, op_fn_id, {operand_id});
|
||||
}
|
||||
}
|
||||
|
||||
// Look up the operator function.
|
||||
auto op_fn = GetOperatorOpFunction(context, loc_id, op);
|
||||
if (!op_fn_id.has_value()) {
|
||||
// Look up the operator function.
|
||||
op_fn_id = GetOperatorOpFunction(context, loc_id, op);
|
||||
}
|
||||
|
||||
// Form `operand.(Op)`.
|
||||
auto bound_op_id = PerformCompoundMemberAccess(context, loc_id, operand_id,
|
||||
op_fn, missing_impl_diagnoser);
|
||||
auto bound_op_id = PerformCompoundMemberAccess(
|
||||
context, loc_id, operand_id, op_fn_id, missing_impl_diagnoser);
|
||||
if (bound_op_id == SemIR::ErrorInst::InstId) {
|
||||
return SemIR::ErrorInst::InstId;
|
||||
}
|
||||
@@ -109,6 +113,8 @@ auto BuildBinaryOperator(Context& context, SemIR::LocId loc_id, Operator op,
|
||||
context.ref_tags().Insert(lhs_id, Context::RefTag::NotRequired);
|
||||
context.ref_tags().Insert(rhs_id, Context::RefTag::NotRequired);
|
||||
|
||||
SemIR::InstId op_fn_id = SemIR::InstId::None;
|
||||
|
||||
// For binary operators with a C++ class as at least one of the operands, try
|
||||
// to import and call the C++ operator.
|
||||
// TODO: Instead of hooking this here, change impl lookup, so that a generic
|
||||
@@ -118,22 +124,24 @@ auto BuildBinaryOperator(Context& context, SemIR::LocId loc_id, Operator op,
|
||||
// and
|
||||
// https://github.com/carbon-language/carbon-lang/pull/5996/files/5d01fa69511b76f87efbc0387f5e40abcf4c911a#r2308664536
|
||||
if (IsCppClassType(context, lhs_id) || IsCppClassType(context, rhs_id)) {
|
||||
SemIR::InstId cpp_inst_id =
|
||||
LookupCppOperator(context, loc_id, op, {lhs_id, rhs_id});
|
||||
if (cpp_inst_id.has_value()) {
|
||||
if (cpp_inst_id == SemIR::ErrorInst::InstId) {
|
||||
return SemIR::ErrorInst::InstId;
|
||||
}
|
||||
return PerformCall(context, loc_id, cpp_inst_id, {lhs_id, rhs_id});
|
||||
op_fn_id = LookupCppOperator(context, loc_id, op, {lhs_id, rhs_id});
|
||||
|
||||
// If C++ operator lookup found a non-method operator, call it with two call
|
||||
// arguments. Otherwise fall through to call it with a self argument and one
|
||||
// call argument.
|
||||
if (op_fn_id.has_value() && !IsCppOperatorMethod(context, op_fn_id)) {
|
||||
return PerformCall(context, loc_id, op_fn_id, {lhs_id, rhs_id});
|
||||
}
|
||||
}
|
||||
|
||||
// Look up the operator function.
|
||||
auto op_fn = GetOperatorOpFunction(context, loc_id, op);
|
||||
if (!op_fn_id.has_value()) {
|
||||
// Look up the operator function.
|
||||
op_fn_id = GetOperatorOpFunction(context, loc_id, op);
|
||||
}
|
||||
|
||||
// Form `lhs.(Op)`.
|
||||
auto bound_op_id = PerformCompoundMemberAccess(context, loc_id, lhs_id, op_fn,
|
||||
missing_impl_diagnoser);
|
||||
auto bound_op_id = PerformCompoundMemberAccess(
|
||||
context, loc_id, lhs_id, op_fn_id, missing_impl_diagnoser);
|
||||
if (bound_op_id == SemIR::ErrorInst::InstId) {
|
||||
return SemIR::ErrorInst::InstId;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user