mirror of
https://github.com/carbon-language/carbon-lang.git
synced 2026-10-05 21:41:27 +01:00
teaches arithmetic interfaces about C++ operators (#7123)
This commit is contained in:
@@ -6,8 +6,10 @@
|
||||
|
||||
#include "clang/Sema/Sema.h"
|
||||
#include "toolchain/base/kind_switch.h"
|
||||
#include "toolchain/check/core_identifier.h"
|
||||
#include "toolchain/check/cpp/import.h"
|
||||
#include "toolchain/check/cpp/location.h"
|
||||
#include "toolchain/check/cpp/operators.h"
|
||||
#include "toolchain/check/cpp/overload_resolution.h"
|
||||
#include "toolchain/check/custom_witness.h"
|
||||
#include "toolchain/check/impl.h"
|
||||
@@ -231,6 +233,74 @@ static auto BuildDestroyWitness(
|
||||
query_specific_interface_id, {fn_id});
|
||||
}
|
||||
|
||||
// Attempts to build a witness table entry for a C++ unary operator.
|
||||
static auto BuildCppUnaryOperatorWitness(
|
||||
Context& context, SemIR::LocId loc_id, SemIR::CoreInterface core_interface,
|
||||
bool has_associated_result_type, SemIR::ConstantId query_self_const_id,
|
||||
SemIR::SpecificInterfaceId query_specific_interface_id) -> SemIR::InstId {
|
||||
auto self_type_id =
|
||||
context.types().GetTypeIdForTypeConstantId(query_self_const_id);
|
||||
auto fn_id = LookupCppOperator(
|
||||
context, loc_id, {.interface_name = AsCoreIdentifier(core_interface)},
|
||||
{self_type_id});
|
||||
if (fn_id == SemIR::ErrorInst::InstId || fn_id == SemIR::InstId::None) {
|
||||
return fn_id;
|
||||
}
|
||||
|
||||
if (has_associated_result_type) {
|
||||
auto result_type_id =
|
||||
context.functions()
|
||||
.Get(context.insts().GetAs<SemIR::FunctionDecl>(fn_id).function_id)
|
||||
.return_type_inst_id;
|
||||
if (result_type_id == SemIR::ErrorInst::InstId) {
|
||||
return SemIR::ErrorInst::InstId;
|
||||
}
|
||||
|
||||
return BuildCustomWitness(context, loc_id, query_self_const_id,
|
||||
query_specific_interface_id,
|
||||
{result_type_id, fn_id});
|
||||
}
|
||||
return BuildCustomWitness(context, loc_id, query_self_const_id,
|
||||
query_specific_interface_id, {fn_id});
|
||||
}
|
||||
|
||||
// Attempts to build a witness table entry for a C++ binary operator.
|
||||
static auto BuildCppBinaryOperatorWitness(
|
||||
Context& context, SemIR::LocId loc_id, SemIR::CoreInterface core_interface,
|
||||
bool has_associated_result_type, SemIR::ConstantId query_self_const_id,
|
||||
SemIR::SpecificInterfaceId query_specific_interface_id) -> SemIR::InstId {
|
||||
auto self_type_id =
|
||||
context.types().GetTypeIdForTypeConstantId(query_self_const_id);
|
||||
auto args =
|
||||
context.inst_blocks().Get(context.specifics()
|
||||
.Get(context.specific_interfaces()
|
||||
.Get(query_specific_interface_id)
|
||||
.specific_id)
|
||||
.args_id);
|
||||
CARBON_CHECK(args.size() == 1, "Binary operator missing an argument");
|
||||
auto arg_type_id = context.types().GetTypeIdForTypeInstId(args.front());
|
||||
auto fn_id = LookupCppOperator(
|
||||
context, loc_id, {.interface_name = AsCoreIdentifier(core_interface)},
|
||||
{self_type_id, arg_type_id});
|
||||
if (fn_id == SemIR::ErrorInst::InstId || fn_id == SemIR::InstId::None) {
|
||||
return fn_id;
|
||||
}
|
||||
if (has_associated_result_type) {
|
||||
auto result_type_id =
|
||||
context.functions()
|
||||
.Get(context.insts().GetAs<SemIR::FunctionDecl>(fn_id).function_id)
|
||||
.return_type_inst_id;
|
||||
if (result_type_id == SemIR::ErrorInst::InstId) {
|
||||
return SemIR::ErrorInst::InstId;
|
||||
}
|
||||
return BuildCustomWitness(context, loc_id, query_self_const_id,
|
||||
query_specific_interface_id,
|
||||
{result_type_id, fn_id});
|
||||
}
|
||||
return BuildCustomWitness(context, loc_id, query_self_const_id,
|
||||
query_specific_interface_id, {fn_id});
|
||||
}
|
||||
|
||||
auto LookupCppImpl(Context& context, SemIR::LocId loc_id,
|
||||
SemIR::CoreInterface core_interface,
|
||||
SemIR::ConstantId query_self_const_id,
|
||||
@@ -243,6 +313,34 @@ auto LookupCppImpl(Context& context, SemIR::LocId loc_id,
|
||||
static_cast<void>(best_impl_loc_id);
|
||||
|
||||
switch (core_interface) {
|
||||
case SemIR::CoreInterface::Inc:
|
||||
case SemIR::CoreInterface::Dec:
|
||||
return BuildCppUnaryOperatorWitness(context, loc_id, core_interface,
|
||||
/*has_associated_result_type=*/false,
|
||||
query_self_const_id,
|
||||
query_specific_interface_id);
|
||||
case SemIR::CoreInterface::Negate:
|
||||
return BuildCppUnaryOperatorWitness(
|
||||
context, loc_id, core_interface, /*has_associated_result_type=*/true,
|
||||
query_self_const_id, query_specific_interface_id);
|
||||
case SemIR::CoreInterface::AddWith:
|
||||
case SemIR::CoreInterface::SubWith:
|
||||
case SemIR::CoreInterface::MulWith:
|
||||
case SemIR::CoreInterface::DivWith:
|
||||
case SemIR::CoreInterface::ModWith:
|
||||
return BuildCppBinaryOperatorWitness(context, loc_id, core_interface,
|
||||
/*has_associated_result_type=*/true,
|
||||
query_self_const_id,
|
||||
query_specific_interface_id);
|
||||
case SemIR::CoreInterface::AddAssignWith:
|
||||
case SemIR::CoreInterface::SubAssignWith:
|
||||
case SemIR::CoreInterface::MulAssignWith:
|
||||
case SemIR::CoreInterface::DivAssignWith:
|
||||
case SemIR::CoreInterface::ModAssignWith:
|
||||
return BuildCppBinaryOperatorWitness(context, loc_id, core_interface,
|
||||
/*has_associated_result_type=*/false,
|
||||
query_self_const_id,
|
||||
query_specific_interface_id);
|
||||
case SemIR::CoreInterface::Copy:
|
||||
return BuildCopyWitness(context, loc_id, query_self_const_id,
|
||||
query_specific_interface_id);
|
||||
|
||||
Reference in New Issue
Block a user