diff --git a/toolchain/check/BUILD b/toolchain/check/BUILD index 5919dbcc1b7f..ac80f5f3200d 100644 --- a/toolchain/check/BUILD +++ b/toolchain/check/BUILD @@ -134,6 +134,7 @@ cc_library( "type_structure.h", ], deps = [ + ":core_identifier", ":node_stack", "//common:array_stack", "//common:check", @@ -217,6 +218,7 @@ cc_library( hdrs = ["check.h"], deps = [ ":context", + ":core_identifier", ":diagnostic_emitter", ":dump", ":scope_stack", @@ -322,6 +324,19 @@ cc_library( ], ) +cc_library( + name = "core_identifier", + srcs = ["core_identifier.cpp"], + hdrs = ["core_identifier.h"], + textual_hdrs = ["core_identifier.def"], + deps = [ + "//common:enum_base", + "//toolchain/base:shared_value_stores", + "//toolchain/base:value_ids", + "//toolchain/sem_ir:typed_insts", + ], +) + cc_library( name = "diagnostic_emitter", srcs = ["diagnostic_emitter.cpp"], diff --git a/toolchain/check/context.cpp b/toolchain/check/context.cpp index e3edaccb3452..7b55d8a9c68f 100644 --- a/toolchain/check/context.cpp +++ b/toolchain/check/context.cpp @@ -38,7 +38,8 @@ Context::Context(DiagnosticEmitterBase* emitter, global_init_(this), region_stack_([this](SemIR::LocId loc_id, std::string label) { TODO(loc_id, label); - }) { + }), + core_identifiers_(&identifiers()) { // Prepare fields which relate to the number of IRs available for import. import_irs().Reserve(imported_ir_count); import_ir_constant_values_.reserve(imported_ir_count); diff --git a/toolchain/check/context.h b/toolchain/check/context.h index 13f551e77870..cca5f7c011b0 100644 --- a/toolchain/check/context.h +++ b/toolchain/check/context.h @@ -12,6 +12,7 @@ #include "llvm/ADT/SmallVector.h" #include "toolchain/base/canonical_value_store.h" #include "toolchain/base/value_store.h" +#include "toolchain/check/core_identifier.h" #include "toolchain/check/cpp/context.h" #include "toolchain/check/decl_introducer_state.h" #include "toolchain/check/decl_name_stack.h" @@ -279,6 +280,8 @@ class Context { return *std::exchange(return_type_inst_id_, std::nullopt); } + auto core_identifiers() -> CoreIdentifierCache& { return core_identifiers_; } + // -------------------------------------------------------------------------- // Directly expose SemIR::File data accessors for brevity in calls. // -------------------------------------------------------------------------- @@ -517,6 +520,9 @@ class Context { // Declared return type for the in-progress function declaration, if any. std::optional return_type_inst_id_; + + // See `CoreIdentifierCache` for details. + CoreIdentifierCache core_identifiers_; }; } // namespace Carbon::Check diff --git a/toolchain/check/control_flow.cpp b/toolchain/check/control_flow.cpp index 8b47f97c8863..6dc56baf3ea4 100644 --- a/toolchain/check/control_flow.cpp +++ b/toolchain/check/control_flow.cpp @@ -162,7 +162,7 @@ static auto AddCleanupBlock(Context& context) -> void { // cleanup blocks, so we'll want to avoid this in the future. BuildUnaryOperator(context, context.insts().GetLocIdForDesugaring(destroy_id), - {.interface_name = "Destroy"}, destroy_id); + {.interface_name = CoreIdentifier::Destroy}, destroy_id); } } diff --git a/toolchain/check/convert.cpp b/toolchain/check/convert.cpp index 4abcffc3da07..7df808ab1441 100644 --- a/toolchain/check/convert.cpp +++ b/toolchain/check/convert.cpp @@ -15,6 +15,7 @@ #include "toolchain/check/action.h" #include "toolchain/check/context.h" #include "toolchain/check/control_flow.h" +#include "toolchain/check/core_identifier.h" #include "toolchain/check/diagnostic_helpers.h" #include "toolchain/check/eval.h" #include "toolchain/check/impl_lookup.h" @@ -1367,7 +1368,8 @@ static auto PerformCopy(Context& context, SemIR::InstId expr_id, } auto copy_id = BuildUnaryOperator( - context, SemIR::LocId(expr_id), {"Copy"}, expr_id, [&] { + context, SemIR::LocId(expr_id), {.interface_name = CoreIdentifier::Copy}, + expr_id, [&] { if (!target.diagnose) { return context.emitter().BuildSuppressed(); } @@ -1407,14 +1409,14 @@ static auto ConvertValueForCppThunkRef(Context& context, SemIR::InstId expr_id) // Returns the Core interface name to use for a given kind of conversion. static auto GetConversionInterfaceName(ConversionTarget::Kind kind) - -> llvm::StringLiteral { + -> CoreIdentifier { switch (kind) { case ConversionTarget::ExplicitAs: - return "As"; + return CoreIdentifier::As; case ConversionTarget::ExplicitUnsafeAs: - return "UnsafeAs"; + return CoreIdentifier::UnsafeAs; default: - return "ImplicitAs"; + return CoreIdentifier::ImplicitAs; } } @@ -1559,7 +1561,7 @@ auto Convert(Context& context, SemIR::LocId loc_id, SemIR::InstId expr_id, Operator op = { .interface_name = GetConversionInterfaceName(target.kind), .interface_args_ref = interface_args, - .op_name = "Convert", + .op_name = CoreIdentifier::Convert, }; expr_id = BuildUnaryOperator(context, loc_id, op, expr_id, [&] { if (!target.diagnose) { diff --git a/toolchain/check/core_identifier.cpp b/toolchain/check/core_identifier.cpp new file mode 100644 index 000000000000..8234131b9ded --- /dev/null +++ b/toolchain/check/core_identifier.cpp @@ -0,0 +1,14 @@ +// Part of the Carbon Language project, under the Apache License v2.0 with LLVM +// Exceptions. See /LICENSE for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +#include "toolchain/check/core_identifier.h" + +namespace Carbon::Check { + +CARBON_DEFINE_ENUM_CLASS_NAMES(CoreIdentifier) { +#define CARBON_CORE_IDENTIFIER(Name) CARBON_ENUM_CLASS_NAME_STRING(Name) +#include "toolchain/check/core_identifier.def" +}; + +} // namespace Carbon::Check diff --git a/toolchain/check/core_identifier.def b/toolchain/check/core_identifier.def new file mode 100644 index 000000000000..28f3cbbdc83b --- /dev/null +++ b/toolchain/check/core_identifier.def @@ -0,0 +1,81 @@ +// Part of the Carbon Language project, under the Apache License v2.0 with LLVM +// Exceptions. See /LICENSE for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +// This is an X-macro header. It does not use `#include` guards, and instead is +// designed to be `#include`ed after the x-macro is defined in order for its +// inclusion to expand to the desired output. Macro definitions are cleaned up +// at the end of this file. +// +// This macro should be defined before including this header: +// - CARBON_CORE_IDENTIFIER(Name) +// Invoked for each `Core` identifier. + +#ifndef CARBON_CORE_IDENTIFIER +#error "Must define the x-macro to use this file." +#define CARBON_CORE_IDENTIFIER(Name) +#endif + +CARBON_CORE_IDENTIFIER(AddAssignWith) +CARBON_CORE_IDENTIFIER(AddWith) +CARBON_CORE_IDENTIFIER(As) +CARBON_CORE_IDENTIFIER(AssignWith) +CARBON_CORE_IDENTIFIER(At) +CARBON_CORE_IDENTIFIER(BitAndAssignWith) +CARBON_CORE_IDENTIFIER(BitAndWith) +CARBON_CORE_IDENTIFIER(BitComplement) +CARBON_CORE_IDENTIFIER(BitOrAssignWith) +CARBON_CORE_IDENTIFIER(BitOrWith) +CARBON_CORE_IDENTIFIER(BitXorAssignWith) +CARBON_CORE_IDENTIFIER(BitXorWith) +CARBON_CORE_IDENTIFIER(Bool) +CARBON_CORE_IDENTIFIER(Char) +CARBON_CORE_IDENTIFIER(Convert) +CARBON_CORE_IDENTIFIER(Copy) +CARBON_CORE_IDENTIFIER(CppCompat) +CARBON_CORE_IDENTIFIER(Dec) +CARBON_CORE_IDENTIFIER(Destroy) +CARBON_CORE_IDENTIFIER(DivAssignWith) +CARBON_CORE_IDENTIFIER(DivWith) +CARBON_CORE_IDENTIFIER(EqWith) +CARBON_CORE_IDENTIFIER(Equal) +CARBON_CORE_IDENTIFIER(Float) +CARBON_CORE_IDENTIFIER(Get) +CARBON_CORE_IDENTIFIER(Greater) +CARBON_CORE_IDENTIFIER(GreaterOrEquivalent) +CARBON_CORE_IDENTIFIER(HasValue) +CARBON_CORE_IDENTIFIER(ImplicitAs) +CARBON_CORE_IDENTIFIER(Inc) +CARBON_CORE_IDENTIFIER(IndexWith) +CARBON_CORE_IDENTIFIER(Int) +CARBON_CORE_IDENTIFIER(Iterate) +CARBON_CORE_IDENTIFIER(LeftShiftAssignWith) +CARBON_CORE_IDENTIFIER(LeftShiftWith) +CARBON_CORE_IDENTIFIER(Less) +CARBON_CORE_IDENTIFIER(LessOrEquivalent) +CARBON_CORE_IDENTIFIER(Long32) +CARBON_CORE_IDENTIFIER(LongLong64) +CARBON_CORE_IDENTIFIER(ModAssignWith) +CARBON_CORE_IDENTIFIER(ModWith) +CARBON_CORE_IDENTIFIER(MulAssignWith) +CARBON_CORE_IDENTIFIER(MulWith) +CARBON_CORE_IDENTIFIER(Negate) +CARBON_CORE_IDENTIFIER(NewCursor) +CARBON_CORE_IDENTIFIER(Next) +CARBON_CORE_IDENTIFIER(NotEqual) +CARBON_CORE_IDENTIFIER(NullptrT) +CARBON_CORE_IDENTIFIER(Op) +CARBON_CORE_IDENTIFIER(Optional) +CARBON_CORE_IDENTIFIER(OrderedWith) +CARBON_CORE_IDENTIFIER(RightShiftAssignWith) +CARBON_CORE_IDENTIFIER(RightShiftWith) +CARBON_CORE_IDENTIFIER(String) +CARBON_CORE_IDENTIFIER(SubAssignWith) +CARBON_CORE_IDENTIFIER(SubWith) +CARBON_CORE_IDENTIFIER(UInt) +CARBON_CORE_IDENTIFIER(ULong32) +CARBON_CORE_IDENTIFIER(ULongLong64) +CARBON_CORE_IDENTIFIER(UnsafeAs) +CARBON_CORE_IDENTIFIER(VoidBase) + +#undef CARBON_CORE_IDENTIFIER diff --git a/toolchain/check/core_identifier.h b/toolchain/check/core_identifier.h new file mode 100644 index 000000000000..d78df3f7d51c --- /dev/null +++ b/toolchain/check/core_identifier.h @@ -0,0 +1,74 @@ +// Part of the Carbon Language project, under the Apache License v2.0 with LLVM +// Exceptions. See /LICENSE for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +#ifndef CARBON_TOOLCHAIN_CHECK_CORE_IDENTIFIER_H_ +#define CARBON_TOOLCHAIN_CHECK_CORE_IDENTIFIER_H_ + +#include "common/enum_base.h" +#include "toolchain/base/shared_value_stores.h" +#include "toolchain/base/value_ids.h" +#include "toolchain/sem_ir/ids.h" + +namespace Carbon::Check { + +CARBON_DEFINE_RAW_ENUM_CLASS(CoreIdentifier, uint8_t) { +#define CARBON_CORE_IDENTIFIER(Name) CARBON_RAW_ENUM_ENUMERATOR(Name) +#include "toolchain/check/core_identifier.def" +}; + +// An identifier in `Core` that's significant for the language (typically used +// by desugaring) but not a builtin or keyword. Note this includes non-top-level +// identifiers, such as both `AddWith` and `Op` in `Core.AddWith.Op`. +class CoreIdentifier : public CARBON_ENUM_BASE(CoreIdentifier) { + public: +#define CARBON_CORE_IDENTIFIER(Name) CARBON_ENUM_CONSTANT_DECL(Name) +#include "toolchain/check/core_identifier.def" + + private: + // Exposes `AsInt`. + friend class CoreIdentifierCache; +}; + +#define CARBON_CORE_IDENTIFIER(Name) \ + CARBON_ENUM_CONSTANT_DEFINITION(CoreIdentifier, Name) +#include "toolchain/check/core_identifier.def" + +// A cache of added `Core` identifiers. These are added to the identifier +// store on first use. +class CoreIdentifierCache { + public: + explicit CoreIdentifierCache(SharedValueStores::IdentifierStore* identifiers) + : identifiers_(identifiers) {} + + // Returns the `NameId` for a `CoreIdentifier`. + auto AddNameId(CoreIdentifier identifier) -> SemIR::NameId { + auto& value = cache_[identifier.AsInt()]; + if (!value.has_value()) { + value = + SemIR::NameId::ForIdentifier(identifiers_->Add(identifier.name())); + } + return value; + } + + private: + // The number of cache entries. + static constexpr int CacheSize = 0 +#define CARBON_CORE_IDENTIFIER(Name) +1 +#include "toolchain/check/core_identifier.def" + ; + + // A pointer for adding identifiers. + SharedValueStores::IdentifierStore* identifiers_; + + // The cache of added identifiers. These are stored as a `NameId` because the + // `IdentifierId` isn't directly used. + SemIR::NameId cache_[CacheSize] = { +#define CARBON_CORE_IDENTIFIER(Name) SemIR::NameId::None, +#include "toolchain/check/core_identifier.def" + }; +}; + +} // namespace Carbon::Check + +#endif // CARBON_TOOLCHAIN_CHECK_CORE_IDENTIFIER_H_ diff --git a/toolchain/check/cpp/import.cpp b/toolchain/check/cpp/import.cpp index 9b62232877c8..5e7d975edc2d 100644 --- a/toolchain/check/cpp/import.cpp +++ b/toolchain/check/cpp/import.cpp @@ -32,6 +32,7 @@ #include "toolchain/check/context.h" #include "toolchain/check/control_flow.h" #include "toolchain/check/convert.h" +#include "toolchain/check/core_identifier.h" #include "toolchain/check/cpp/access.h" #include "toolchain/check/cpp/custom_type_mapping.h" #include "toolchain/check/cpp/generate_ast.h" @@ -730,16 +731,17 @@ static auto MakeIntType(Context& context, IntId size_id, bool is_signed) } static auto MakeCppCompatType(Context& context, SemIR::LocId loc_id, - llvm::StringRef name) -> TypeExpr { - return ExprAsType(context, loc_id, - LookupNameInCore(context, loc_id, {"CppCompat", name})); + CoreIdentifier name) -> TypeExpr { + return ExprAsType( + context, loc_id, + LookupNameInCore(context, loc_id, {CoreIdentifier::CppCompat, name})); } // Maps a C++ builtin integer type to a Carbon `Core.CppCompat` type. static auto MapBuiltinCppCompatIntegerType(Context& context, unsigned int cpp_width, unsigned int carbon_width, - llvm::StringRef cpp_compat_name) + CoreIdentifier cpp_compat_name) -> TypeExpr { if (cpp_width != carbon_width) { return TypeExpr::None; @@ -775,23 +777,27 @@ static auto MapBuiltinIntegerType(Context& context, SemIR::LocId loc_id, MakeCharTypeLiteral(context, Parse::NodeId::None)); } if (clang::ASTContext::hasSameType(qual_type, ast_context.LongTy)) { - return MapBuiltinCppCompatIntegerType(context, width, 32, "Long32"); + return MapBuiltinCppCompatIntegerType(context, width, 32, + CoreIdentifier::Long32); } if (clang::ASTContext::hasSameType(qual_type, ast_context.UnsignedLongTy)) { - return MapBuiltinCppCompatIntegerType(context, width, 32, "ULong32"); + return MapBuiltinCppCompatIntegerType(context, width, 32, + CoreIdentifier::ULong32); } if (clang::ASTContext::hasSameType(qual_type, ast_context.LongLongTy)) { - return MapBuiltinCppCompatIntegerType(context, width, 64, "LongLong64"); + return MapBuiltinCppCompatIntegerType(context, width, 64, + CoreIdentifier::LongLong64); } if (clang::ASTContext::hasSameType(qual_type, ast_context.UnsignedLongLongTy)) { - return MapBuiltinCppCompatIntegerType(context, width, 64, "ULongLong64"); + return MapBuiltinCppCompatIntegerType(context, width, 64, + CoreIdentifier::ULongLong64); } return TypeExpr::None; } static auto MapNullptrType(Context& context, SemIR::LocId loc_id) -> TypeExpr { - return MakeCppCompatType(context, loc_id, "NullptrT"); + return MakeCppCompatType(context, loc_id, CoreIdentifier::NullptrT); } // Maps a C++ builtin type to a Carbon type. @@ -820,7 +826,7 @@ static auto MapBuiltinType(Context& context, SemIR::LocId loc_id, } // TODO: Handle floating-point types that map to named aliases. } else if (type.isVoidType()) { - return MakeCppCompatType(context, loc_id, "VoidBase"); + return MakeCppCompatType(context, loc_id, CoreIdentifier::VoidBase); } else if (type.isNullPtrType()) { return MapNullptrType(context, loc_id); } @@ -937,7 +943,7 @@ static auto ClangGetUnqualifiedTypePreserveNonNull( // `inner_type_inst_id`. static auto MakeOptionalType(Context& context, SemIR::LocId loc_id, SemIR::InstId inner_type_inst_id) -> TypeExpr { - auto fn_inst_id = LookupNameInCore(context, loc_id, "Optional"); + auto fn_inst_id = LookupNameInCore(context, loc_id, CoreIdentifier::Optional); auto call_id = PerformCall(context, loc_id, fn_inst_id, {inner_type_inst_id}); return ExprAsType(context, loc_id, call_id); } diff --git a/toolchain/check/cpp/operators.cpp b/toolchain/check/cpp/operators.cpp index 97db0a7b2257..9b30b4b1c454 100644 --- a/toolchain/check/cpp/operators.cpp +++ b/toolchain/check/cpp/operators.cpp @@ -6,6 +6,7 @@ #include "clang/Sema/Overload.h" #include "clang/Sema/Sema.h" +#include "toolchain/check/core_identifier.h" #include "toolchain/check/cpp/import.h" #include "toolchain/check/cpp/location.h" #include "toolchain/check/cpp/overload_resolution.h" @@ -20,147 +21,153 @@ namespace Carbon::Check { // Maps Carbon operator interface and operator names to Clang operator kinds. static auto GetClangOperatorKind(Context& context, SemIR::LocId loc_id, - llvm::StringLiteral interface_name, - llvm::StringLiteral op_name) + CoreIdentifier interface_name, + CoreIdentifier op_name) -> std::optional { - // Unary operators. - if (interface_name == "Destroy" || interface_name == "As" || - interface_name == "ImplicitAs" || interface_name == "Copy") { - // TODO: Support destructors and conversions. - return std::nullopt; - } - - // Increment and Decrement. - if (interface_name == "Inc") { - CARBON_CHECK(op_name == "Op"); - return clang::OO_PlusPlus; - } - if (interface_name == "Dec") { - CARBON_CHECK(op_name == "Op"); - return clang::OO_MinusMinus; - } - - // Arithmetic. - if (interface_name == "Negate") { - CARBON_CHECK(op_name == "Op"); - return clang::OO_Minus; - } - - // Binary operators. - - // Arithmetic Operators. - if (interface_name == "AddWith") { - CARBON_CHECK(op_name == "Op"); - return clang::OO_Plus; - } - if (interface_name == "SubWith") { - CARBON_CHECK(op_name == "Op"); - return clang::OO_Minus; - } - if (interface_name == "MulWith") { - CARBON_CHECK(op_name == "Op"); - return clang::OO_Star; - } - if (interface_name == "DivWith") { - CARBON_CHECK(op_name == "Op"); - return clang::OO_Slash; - } - if (interface_name == "ModWith") { - CARBON_CHECK(op_name == "Op"); - return clang::OO_Percent; - } - - // Bitwise Operators. - if (interface_name == "BitAndWith") { - CARBON_CHECK(op_name == "Op"); - return clang::OO_Amp; - } - if (interface_name == "BitOrWith") { - CARBON_CHECK(op_name == "Op"); - return clang::OO_Pipe; - } - if (interface_name == "BitXorWith") { - CARBON_CHECK(op_name == "Op"); - return clang::OO_Caret; - } - if (interface_name == "LeftShiftWith") { - CARBON_CHECK(op_name == "Op"); - return clang::OO_LessLess; - } - if (interface_name == "RightShiftWith") { - CARBON_CHECK(op_name == "Op"); - return clang::OO_GreaterGreater; - } - - // Compound Assignment Arithmetic Operators. - if (interface_name == "AddAssignWith") { - CARBON_CHECK(op_name == "Op"); - return clang::OO_PlusEqual; - } - if (interface_name == "SubAssignWith") { - CARBON_CHECK(op_name == "Op"); - return clang::OO_MinusEqual; - } - if (interface_name == "MulAssignWith") { - CARBON_CHECK(op_name == "Op"); - return clang::OO_StarEqual; - } - if (interface_name == "DivAssignWith") { - CARBON_CHECK(op_name == "Op"); - return clang::OO_SlashEqual; - } - if (interface_name == "ModAssignWith") { - CARBON_CHECK(op_name == "Op"); - return clang::OO_PercentEqual; - } - - // Compound Assignment Bitwise Operators. - if (interface_name == "BitAndAssignWith") { - CARBON_CHECK(op_name == "Op"); - return clang::OO_AmpEqual; - } - if (interface_name == "BitOrAssignWith") { - CARBON_CHECK(op_name == "Op"); - return clang::OO_PipeEqual; - } - if (interface_name == "BitXorAssignWith") { - CARBON_CHECK(op_name == "Op"); - return clang::OO_CaretEqual; - } - if (interface_name == "LeftShiftAssignWith") { - CARBON_CHECK(op_name == "Op"); - return clang::OO_LessLessEqual; - } - if (interface_name == "RightShiftAssignWith") { - CARBON_CHECK(op_name == "Op"); - return clang::OO_GreaterGreaterEqual; - } - - // Relational Operators. - if (interface_name == "EqWith") { - if (op_name == "Equal") { - return clang::OO_EqualEqual; + switch (interface_name) { + // Unary operators. + case CoreIdentifier::Destroy: + case CoreIdentifier::As: + case CoreIdentifier::ImplicitAs: + case CoreIdentifier::Copy: { + // TODO: Support destructors and conversions. + return std::nullopt; } - CARBON_CHECK(op_name == "NotEqual"); - return clang::OO_ExclaimEqual; - } - if (interface_name == "OrderedWith") { - if (op_name == "Less") { - return clang::OO_Less; - } - if (op_name == "Greater") { - return clang::OO_Greater; - } - if (op_name == "LessOrEquivalent") { - return clang::OO_LessEqual; - } - CARBON_CHECK(op_name == "GreaterOrEquivalent"); - return clang::OO_GreaterEqual; - } - context.TODO(loc_id, llvm::formatv("Unsupported operator interface `{0}`", - interface_name)); - return std::nullopt; + // Increment and decrement. + case CoreIdentifier::Inc: { + CARBON_CHECK(op_name == CoreIdentifier::Op); + return clang::OO_PlusPlus; + } + case CoreIdentifier::Dec: { + CARBON_CHECK(op_name == CoreIdentifier::Op); + return clang::OO_MinusMinus; + } + + // Arithmetic. + case CoreIdentifier::Negate: { + CARBON_CHECK(op_name == CoreIdentifier::Op); + return clang::OO_Minus; + } + + // Binary operators. + + // Arithmetic operators. + case CoreIdentifier::AddWith: { + CARBON_CHECK(op_name == CoreIdentifier::Op); + return clang::OO_Plus; + } + case CoreIdentifier::SubWith: { + CARBON_CHECK(op_name == CoreIdentifier::Op); + return clang::OO_Minus; + } + case CoreIdentifier::MulWith: { + CARBON_CHECK(op_name == CoreIdentifier::Op); + return clang::OO_Star; + } + case CoreIdentifier::DivWith: { + CARBON_CHECK(op_name == CoreIdentifier::Op); + return clang::OO_Slash; + } + case CoreIdentifier::ModWith: { + CARBON_CHECK(op_name == CoreIdentifier::Op); + return clang::OO_Percent; + } + + // Bitwise operators. + case CoreIdentifier::BitAndWith: { + CARBON_CHECK(op_name == CoreIdentifier::Op); + return clang::OO_Amp; + } + case CoreIdentifier::BitOrWith: { + CARBON_CHECK(op_name == CoreIdentifier::Op); + return clang::OO_Pipe; + } + case CoreIdentifier::BitXorWith: { + CARBON_CHECK(op_name == CoreIdentifier::Op); + return clang::OO_Caret; + } + case CoreIdentifier::LeftShiftWith: { + CARBON_CHECK(op_name == CoreIdentifier::Op); + return clang::OO_LessLess; + } + case CoreIdentifier::RightShiftWith: { + CARBON_CHECK(op_name == CoreIdentifier::Op); + return clang::OO_GreaterGreater; + } + + // Compound assignment arithmetic operators. + case CoreIdentifier::AddAssignWith: { + CARBON_CHECK(op_name == CoreIdentifier::Op); + return clang::OO_PlusEqual; + } + case CoreIdentifier::SubAssignWith: { + CARBON_CHECK(op_name == CoreIdentifier::Op); + return clang::OO_MinusEqual; + } + case CoreIdentifier::MulAssignWith: { + CARBON_CHECK(op_name == CoreIdentifier::Op); + return clang::OO_StarEqual; + } + case CoreIdentifier::DivAssignWith: { + CARBON_CHECK(op_name == CoreIdentifier::Op); + return clang::OO_SlashEqual; + } + case CoreIdentifier::ModAssignWith: { + CARBON_CHECK(op_name == CoreIdentifier::Op); + return clang::OO_PercentEqual; + } + + // Compound assignment bitwise operators. + case CoreIdentifier::BitAndAssignWith: { + CARBON_CHECK(op_name == CoreIdentifier::Op); + return clang::OO_AmpEqual; + } + case CoreIdentifier::BitOrAssignWith: { + CARBON_CHECK(op_name == CoreIdentifier::Op); + return clang::OO_PipeEqual; + } + case CoreIdentifier::BitXorAssignWith: { + CARBON_CHECK(op_name == CoreIdentifier::Op); + return clang::OO_CaretEqual; + } + case CoreIdentifier::LeftShiftAssignWith: { + CARBON_CHECK(op_name == CoreIdentifier::Op); + return clang::OO_LessLessEqual; + } + case CoreIdentifier::RightShiftAssignWith: { + CARBON_CHECK(op_name == CoreIdentifier::Op); + return clang::OO_GreaterGreaterEqual; + } + + // Relational operators. + case CoreIdentifier::EqWith: { + if (op_name == CoreIdentifier::Equal) { + return clang::OO_EqualEqual; + } + CARBON_CHECK(op_name == CoreIdentifier::NotEqual); + return clang::OO_ExclaimEqual; + } + case CoreIdentifier::OrderedWith: { + switch (op_name) { + case CoreIdentifier::Less: + return clang::OO_Less; + case CoreIdentifier::Greater: + return clang::OO_Greater; + case CoreIdentifier::LessOrEquivalent: + return clang::OO_LessEqual; + case CoreIdentifier::GreaterOrEquivalent: + return clang::OO_GreaterEqual; + default: + CARBON_FATAL("Unexpected OrderedWith op `{0}`", op_name); + } + } + + default: + context.TODO(loc_id, llvm::formatv("Unsupported operator interface `{0}`", + interface_name)); + return std::nullopt; + } } auto LookupCppOperator(Context& context, SemIR::LocId loc_id, Operator op, diff --git a/toolchain/check/handle_index.cpp b/toolchain/check/handle_index.cpp index 17a502403c6d..501764769210 100644 --- a/toolchain/check/handle_index.cpp +++ b/toolchain/check/handle_index.cpp @@ -35,9 +35,9 @@ static auto PerformIndexWith(Context& context, Parse::NodeId node_id, SemIR::InstId index_inst_id) -> SemIR::InstId { SemIR::InstId args[] = { context.types().GetInstId(context.insts().Get(index_inst_id).type_id())}; - Operator op{.interface_name = "IndexWith", + Operator op{.interface_name = CoreIdentifier::IndexWith, .interface_args_ref = args, - .op_name = "At"}; + .op_name = CoreIdentifier::At}; return BuildBinaryOperator(context, node_id, op, operand_inst_id, index_inst_id); } diff --git a/toolchain/check/handle_literal.cpp b/toolchain/check/handle_literal.cpp index 11536140cd5a..de6be1320272 100644 --- a/toolchain/check/handle_literal.cpp +++ b/toolchain/check/handle_literal.cpp @@ -77,7 +77,7 @@ auto HandleParseNode(Context& context, Parse::StringLiteralId node_id) -> bool { auto HandleParseNode(Context& context, Parse::BoolTypeLiteralId node_id) -> bool { - auto fn_inst_id = LookupNameInCore(context, node_id, "Bool"); + auto fn_inst_id = LookupNameInCore(context, node_id, CoreIdentifier::Bool); auto type_inst_id = PerformCall(context, node_id, fn_inst_id, {}); context.node_stack().Push(node_id, type_inst_id); return true; diff --git a/toolchain/check/handle_loop_statement.cpp b/toolchain/check/handle_loop_statement.cpp index 5eacab4658c5..5a16714d0b52 100644 --- a/toolchain/check/handle_loop_statement.cpp +++ b/toolchain/check/handle_loop_statement.cpp @@ -6,6 +6,7 @@ #include "toolchain/check/context.h" #include "toolchain/check/control_flow.h" #include "toolchain/check/convert.h" +#include "toolchain/check/core_identifier.h" #include "toolchain/check/full_pattern_stack.h" #include "toolchain/check/handle.h" #include "toolchain/check/inst.h" @@ -135,10 +136,9 @@ auto HandleParseNode(Context& context, Parse::ForInId node_id) -> bool { // For a value or reference of type `Optional(T)`, call the given accessor. static auto CallOptionalAccessor(Context& context, Parse::NodeId node_id, SemIR::InstId optional_id, - llvm::StringLiteral accessor_name) + CoreIdentifier accessor_name) -> SemIR::InstId { - auto accessor_name_id = - SemIR::NameId::ForIdentifier(context.identifiers().Add(accessor_name)); + auto accessor_name_id = context.core_identifiers().AddNameId(accessor_name); auto accessor_id = PerformMemberAccess(context, node_id, optional_id, accessor_name_id); return PerformCall(context, node_id, accessor_id, {}); @@ -160,9 +160,11 @@ auto HandleParseNode(Context& context, Parse::ForHeaderId node_id) -> bool { // Create the cursor variable. // TODO: Produce a custom diagnostic if the range operand can't be used as a // range. - auto cursor_id = BuildUnaryOperator( - context, node_id, {.interface_name = "Iterate", .op_name = "NewCursor"}, - range_id); + auto cursor_id = + BuildUnaryOperator(context, node_id, + {.interface_name = CoreIdentifier::Iterate, + .op_name = CoreIdentifier::NewCursor}, + range_id); auto cursor_type_id = context.insts().Get(cursor_id).type_id(); auto cursor_var_id = AddInstWithCleanup( context, node_id, @@ -180,9 +182,11 @@ auto HandleParseNode(Context& context, Parse::ForHeaderId node_id) -> bool { context, node_id, {.type_id = GetPointerType(context, cursor_type_inst_id), .lvalue_id = cursor_var_id}); - auto element_id = BuildBinaryOperator( - context, node_id, {.interface_name = "Iterate", .op_name = "Next"}, - range_id, cursor_addr_id); + auto element_id = + BuildBinaryOperator(context, node_id, + {.interface_name = CoreIdentifier::Iterate, + .op_name = CoreIdentifier::Next}, + range_id, cursor_addr_id); // We need to convert away from an initializing expression in order to call // `HasValue` and then separately pattern-match against the element. // TODO: Instead, form a `.Some(pattern_id)` pattern and pattern-match against @@ -190,8 +194,8 @@ auto HandleParseNode(Context& context, Parse::ForHeaderId node_id) -> bool { element_id = ConvertToValueOrRefExpr(context, element_id); // Branch to the loop body if the optional element has a value. - auto cond_value_id = - CallOptionalAccessor(context, node_id, element_id, "HasValue"); + auto cond_value_id = CallOptionalAccessor(context, node_id, element_id, + CoreIdentifier::HasValue); BranchAndStartLoopBody(context, node_id, loop_header_id, cond_value_id); // The loop pattern's initializer is now complete, and any bindings in it @@ -204,7 +208,7 @@ auto HandleParseNode(Context& context, Parse::ForHeaderId node_id) -> bool { // Initialize the pattern from `.Get()`. auto element_value_id = - CallOptionalAccessor(context, node_id, element_id, "Get"); + CallOptionalAccessor(context, node_id, element_id, CoreIdentifier::Get); LocalPatternMatch(context, pattern_id, element_value_id); return true; } diff --git a/toolchain/check/handle_operator.cpp b/toolchain/check/handle_operator.cpp index 7af8661bbb38..251f59bdb00c 100644 --- a/toolchain/check/handle_operator.cpp +++ b/toolchain/check/handle_operator.cpp @@ -5,6 +5,7 @@ #include "toolchain/check/context.h" #include "toolchain/check/control_flow.h" #include "toolchain/check/convert.h" +#include "toolchain/check/core_identifier.h" #include "toolchain/check/handle.h" #include "toolchain/check/inst.h" #include "toolchain/check/operator.h" @@ -18,16 +19,19 @@ namespace Carbon::Check { // Common logic for unary operator handlers. static auto HandleUnaryOperator(Context& context, Parse::AnyExprId expr_node_id, - Operator op) -> bool { + CoreIdentifier interface_name) -> bool { auto operand_id = context.node_stack().PopExpr(); - auto result_id = BuildUnaryOperator(context, expr_node_id, op, operand_id); + auto result_id = BuildUnaryOperator( + context, expr_node_id, {.interface_name = interface_name}, operand_id); context.node_stack().Push(expr_node_id, result_id); return true; } // Common logic for binary operator handlers. static auto HandleBinaryOperator(Context& context, - Parse::AnyExprId expr_node_id, Operator op) + Parse::AnyExprId expr_node_id, + CoreIdentifier interface_name, + CoreIdentifier op_name = CoreIdentifier::Op) -> bool { auto rhs_id = context.node_stack().PopExpr(); auto lhs_id = context.node_stack().PopExpr(); @@ -36,9 +40,11 @@ static auto HandleBinaryOperator(Context& context, // this function for it. SemIR::InstId args[] = { context.types().GetInstId(context.insts().Get(rhs_id).type_id())}; - op.interface_args_ref = args; - auto result_id = - BuildBinaryOperator(context, expr_node_id, op, lhs_id, rhs_id); + auto result_id = BuildBinaryOperator(context, expr_node_id, + {.interface_name = interface_name, + .interface_args_ref = args, + .op_name = op_name}, + lhs_id, rhs_id); context.node_stack().Push(expr_node_id, result_id); return true; } @@ -46,12 +52,13 @@ static auto HandleBinaryOperator(Context& context, auto HandleParseNode(Context& context, Parse::InfixOperatorAmpId node_id) -> bool { // TODO: Facet type intersection may need to be handled directly. - return HandleBinaryOperator(context, node_id, {"BitAndWith"}); + return HandleBinaryOperator(context, node_id, CoreIdentifier::BitAndWith); } auto HandleParseNode(Context& context, Parse::InfixOperatorAmpEqualId node_id) -> bool { - return HandleBinaryOperator(context, node_id, {"BitAndAssignWith"}); + return HandleBinaryOperator(context, node_id, + CoreIdentifier::BitAndAssignWith); } auto HandleParseNode(Context& context, Parse::UnsafeModifierId node_id) @@ -78,12 +85,13 @@ auto HandleParseNode(Context& context, Parse::InfixOperatorAsId node_id) auto HandleParseNode(Context& context, Parse::InfixOperatorCaretId node_id) -> bool { - return HandleBinaryOperator(context, node_id, {"BitXorWith"}); + return HandleBinaryOperator(context, node_id, CoreIdentifier::BitXorWith); } auto HandleParseNode(Context& context, Parse::InfixOperatorCaretEqualId node_id) -> bool { - return HandleBinaryOperator(context, node_id, {"BitXorAssignWith"}); + return HandleBinaryOperator(context, node_id, + CoreIdentifier::BitXorAssignWith); } auto HandleParseNode(Context& context, Parse::InfixOperatorEqualId node_id) @@ -91,7 +99,8 @@ auto HandleParseNode(Context& context, Parse::InfixOperatorEqualId node_id) // TODO: Switch to using assignment interface for most assignment. Some cases // may need to be handled directly. // - // return HandleBinaryOperator(context, node_id, {"AssignWith"}); + // return HandleBinaryOperator(context, node_id, + // CoreIdentifier::AssignWith); auto [rhs_node, rhs_id] = context.node_stack().PopExprWithNodeId(); auto [lhs_node, lhs_id] = context.node_stack().PopExprWithNodeId(); @@ -117,45 +126,50 @@ auto HandleParseNode(Context& context, Parse::InfixOperatorEqualId node_id) auto HandleParseNode(Context& context, Parse::InfixOperatorEqualEqualId node_id) -> bool { - return HandleBinaryOperator(context, node_id, {"EqWith", {}, "Equal"}); + return HandleBinaryOperator(context, node_id, CoreIdentifier::EqWith, + CoreIdentifier::Equal); } auto HandleParseNode(Context& context, Parse::InfixOperatorExclaimEqualId node_id) -> bool { - return HandleBinaryOperator(context, node_id, {"EqWith", {}, "NotEqual"}); + return HandleBinaryOperator(context, node_id, CoreIdentifier::EqWith, + CoreIdentifier::NotEqual); } auto HandleParseNode(Context& context, Parse::InfixOperatorGreaterId node_id) -> bool { - return HandleBinaryOperator(context, node_id, {"OrderedWith", {}, "Greater"}); + return HandleBinaryOperator(context, node_id, CoreIdentifier::OrderedWith, + CoreIdentifier::Greater); } auto HandleParseNode(Context& context, Parse::InfixOperatorGreaterEqualId node_id) -> bool { - return HandleBinaryOperator(context, node_id, - {"OrderedWith", {}, "GreaterOrEquivalent"}); + return HandleBinaryOperator(context, node_id, CoreIdentifier::OrderedWith, + CoreIdentifier::GreaterOrEquivalent); } auto HandleParseNode(Context& context, Parse::InfixOperatorGreaterGreaterId node_id) -> bool { - return HandleBinaryOperator(context, node_id, {"RightShiftWith"}); + return HandleBinaryOperator(context, node_id, CoreIdentifier::RightShiftWith); } auto HandleParseNode(Context& context, Parse::InfixOperatorGreaterGreaterEqualId node_id) -> bool { - return HandleBinaryOperator(context, node_id, {"RightShiftAssignWith"}); + return HandleBinaryOperator(context, node_id, + CoreIdentifier::RightShiftAssignWith); } auto HandleParseNode(Context& context, Parse::InfixOperatorLessId node_id) -> bool { - return HandleBinaryOperator(context, node_id, {"OrderedWith", {}, "Less"}); + return HandleBinaryOperator(context, node_id, CoreIdentifier::OrderedWith, + CoreIdentifier::Less); } auto HandleParseNode(Context& context, Parse::InfixOperatorLessEqualId node_id) -> bool { - return HandleBinaryOperator(context, node_id, - {"OrderedWith", {}, "LessOrEquivalent"}); + return HandleBinaryOperator(context, node_id, CoreIdentifier::OrderedWith, + CoreIdentifier::LessOrEquivalent); } auto HandleParseNode(Context& context, @@ -165,72 +179,74 @@ auto HandleParseNode(Context& context, auto HandleParseNode(Context& context, Parse::InfixOperatorLessLessId node_id) -> bool { - return HandleBinaryOperator(context, node_id, {"LeftShiftWith"}); + return HandleBinaryOperator(context, node_id, CoreIdentifier::LeftShiftWith); } auto HandleParseNode(Context& context, Parse::InfixOperatorLessLessEqualId node_id) -> bool { - return HandleBinaryOperator(context, node_id, {"LeftShiftAssignWith"}); + return HandleBinaryOperator(context, node_id, + CoreIdentifier::LeftShiftAssignWith); } auto HandleParseNode(Context& context, Parse::InfixOperatorMinusId node_id) -> bool { - return HandleBinaryOperator(context, node_id, {"SubWith"}); + return HandleBinaryOperator(context, node_id, CoreIdentifier::SubWith); } auto HandleParseNode(Context& context, Parse::InfixOperatorMinusEqualId node_id) -> bool { - return HandleBinaryOperator(context, node_id, {"SubAssignWith"}); + return HandleBinaryOperator(context, node_id, CoreIdentifier::SubAssignWith); } auto HandleParseNode(Context& context, Parse::InfixOperatorPercentId node_id) -> bool { - return HandleBinaryOperator(context, node_id, {"ModWith"}); + return HandleBinaryOperator(context, node_id, CoreIdentifier::ModWith); } auto HandleParseNode(Context& context, Parse::InfixOperatorPercentEqualId node_id) -> bool { - return HandleBinaryOperator(context, node_id, {"ModAssignWith"}); + return HandleBinaryOperator(context, node_id, CoreIdentifier::ModAssignWith); } auto HandleParseNode(Context& context, Parse::InfixOperatorPipeId node_id) -> bool { - return HandleBinaryOperator(context, node_id, {"BitOrWith"}); + return HandleBinaryOperator(context, node_id, CoreIdentifier::BitOrWith); } auto HandleParseNode(Context& context, Parse::InfixOperatorPipeEqualId node_id) -> bool { - return HandleBinaryOperator(context, node_id, {"BitOrAssignWith"}); + return HandleBinaryOperator(context, node_id, + CoreIdentifier::BitOrAssignWith); } auto HandleParseNode(Context& context, Parse::InfixOperatorPlusId node_id) -> bool { - return HandleBinaryOperator(context, node_id, {"AddWith"}); + return HandleBinaryOperator(context, node_id, CoreIdentifier::AddWith); } auto HandleParseNode(Context& context, Parse::InfixOperatorPlusEqualId node_id) -> bool { - return HandleBinaryOperator(context, node_id, {"AddAssignWith"}); + return HandleBinaryOperator(context, node_id, CoreIdentifier::AddAssignWith); } auto HandleParseNode(Context& context, Parse::InfixOperatorSlashId node_id) -> bool { - return HandleBinaryOperator(context, node_id, {"DivWith"}); + return HandleBinaryOperator(context, node_id, CoreIdentifier::DivWith); } auto HandleParseNode(Context& context, Parse::InfixOperatorSlashEqualId node_id) -> bool { - return HandleBinaryOperator(context, node_id, {"DivAssignWith"}); + return HandleBinaryOperator(context, node_id, CoreIdentifier::DivAssignWith); } auto HandleParseNode(Context& context, Parse::InfixOperatorStarId node_id) -> bool { - return HandleBinaryOperator(context, node_id, {"MulWith"}); + return HandleBinaryOperator(context, node_id, CoreIdentifier::MulWith); } auto HandleParseNode(Context& context, Parse::InfixOperatorStarEqualId node_id) -> bool { - return HandleBinaryOperator(context, node_id, {"MulAssignWith"}); + return HandleBinaryOperator(context, node_id, CoreIdentifier::MulAssignWith); } auto HandleParseNode(Context& context, Parse::PostfixOperatorStarId node_id) @@ -271,7 +287,7 @@ auto HandleParseNode(Context& context, Parse::PrefixOperatorAmpId node_id) auto HandleParseNode(Context& context, Parse::PrefixOperatorCaretId node_id) -> bool { - return HandleUnaryOperator(context, node_id, {"BitComplement"}); + return HandleUnaryOperator(context, node_id, CoreIdentifier::BitComplement); } auto HandleParseNode(Context& context, Parse::PrefixOperatorConstId node_id) @@ -296,12 +312,12 @@ auto HandleParseNode(Context& context, Parse::PrefixOperatorConstId node_id) auto HandleParseNode(Context& context, Parse::PrefixOperatorMinusId node_id) -> bool { - return HandleUnaryOperator(context, node_id, {"Negate"}); + return HandleUnaryOperator(context, node_id, CoreIdentifier::Negate); } auto HandleParseNode(Context& context, Parse::PrefixOperatorMinusMinusId node_id) -> bool { - return HandleUnaryOperator(context, node_id, {"Dec"}); + return HandleUnaryOperator(context, node_id, CoreIdentifier::Dec); } auto HandleParseNode(Context& context, Parse::PrefixOperatorNotId node_id) @@ -338,7 +354,7 @@ auto HandleParseNode(Context& context, Parse::PrefixOperatorPartialId node_id) auto HandleParseNode(Context& context, Parse::PrefixOperatorPlusPlusId node_id) -> bool { - return HandleUnaryOperator(context, node_id, {"Inc"}); + return HandleUnaryOperator(context, node_id, CoreIdentifier::Inc); } auto HandleParseNode(Context& context, Parse::PrefixOperatorStarId node_id) diff --git a/toolchain/check/literal.cpp b/toolchain/check/literal.cpp index c2ace0e3f986..9c0b8a267b86 100644 --- a/toolchain/check/literal.cpp +++ b/toolchain/check/literal.cpp @@ -27,15 +27,17 @@ auto MakeIntLiteral(Context& context, Parse::NodeId node_id, IntId int_id) auto MakeCharTypeLiteral(Context& context, Parse::NodeId node_id) -> SemIR::InstId { - return LookupNameInCore(context, node_id, "Char"); + return LookupNameInCore(context, node_id, CoreIdentifier::Char); } auto MakeIntTypeLiteral(Context& context, Parse::NodeId node_id, SemIR::IntKind int_kind, IntId size_id) -> SemIR::InstId { auto width_id = MakeIntLiteral(context, node_id, size_id); - auto fn_inst_id = LookupNameInCore( - context, node_id, int_kind == SemIR::IntKind::Signed ? "Int" : "UInt"); + auto fn_inst_id = LookupNameInCore(context, node_id, + int_kind == SemIR::IntKind::Signed + ? CoreIdentifier::Int + : CoreIdentifier::UInt); return PerformCall(context, node_id, fn_inst_id, {width_id}); } @@ -48,7 +50,7 @@ auto MakeIntType(Context& context, Parse::NodeId node_id, auto MakeFloatTypeLiteral(Context& context, Parse::NodeId node_id, IntId size_id) -> SemIR::InstId { auto width_id = MakeIntLiteral(context, node_id, size_id); - auto fn_inst_id = LookupNameInCore(context, node_id, "Float"); + auto fn_inst_id = LookupNameInCore(context, node_id, CoreIdentifier::Float); return PerformCall(context, node_id, fn_inst_id, {width_id}); } @@ -169,7 +171,7 @@ auto MakeStringLiteral(Context& context, Parse::StringLiteralId node_id, auto MakeStringTypeLiteral(Context& context, SemIR::LocId loc_id) -> SemIR::InstId { - return LookupNameInCore(context, loc_id, "String"); + return LookupNameInCore(context, loc_id, CoreIdentifier::String); } auto MakeStringType(Context& context, SemIR::LocId loc_id) -> TypeExpr { diff --git a/toolchain/check/name_lookup.cpp b/toolchain/check/name_lookup.cpp index 66f07db4eea3..e9ce89ea5c0b 100644 --- a/toolchain/check/name_lookup.cpp +++ b/toolchain/check/name_lookup.cpp @@ -6,6 +6,7 @@ #include +#include "common/raw_string_ostream.h" #include "toolchain/check/cpp/import.h" #include "toolchain/check/generic.h" #include "toolchain/check/import.h" @@ -492,12 +493,23 @@ auto LookupQualifiedName(Context& context, SemIR::LocId loc_id, return result; } +// Returns a `Core.` name for diagnostics. +static auto GetCoreQualifiedName(llvm::ArrayRef qualifiers) + -> std::string { + RawStringOstream str; + str << "Core"; + for (auto qualifier : qualifiers) { + str << "." << qualifier; + } + return str.TakeStr(); +} + // Returns the scope of the Core package, or `None` if it's not found. // // TODO: Consider tracking the Core package in SemIR so we don't need to use // name lookup to find it. static auto GetCorePackage(Context& context, SemIR::LocId loc_id, - llvm::ArrayRef names) + llvm::ArrayRef qualifiers) -> SemIR::NameScopeId { auto packaging = context.parse_tree().packaging_decl(); if (packaging && packaging->names.package_id == PackageNameId::Core) { @@ -520,25 +532,26 @@ static auto GetCorePackage(Context& context, SemIR::LocId loc_id, CARBON_DIAGNOSTIC( CoreNotFound, Error, - "`Core.{0}` implicitly referenced here, but package `Core` not found", + "`{0}` implicitly referenced here, but package `Core` not found", std::string); - context.emitter().Emit(loc_id, CoreNotFound, llvm::join(names, ".")); + context.emitter().Emit(loc_id, CoreNotFound, + GetCoreQualifiedName(qualifiers)); return SemIR::NameScopeId::None; } auto LookupNameInCore(Context& context, SemIR::LocId loc_id, - llvm::ArrayRef names) -> SemIR::InstId { - CARBON_CHECK(!names.empty()); + llvm::ArrayRef qualifiers) + -> SemIR::InstId { + CARBON_CHECK(!qualifiers.empty()); - auto core_package_id = GetCorePackage(context, loc_id, names); + auto core_package_id = GetCorePackage(context, loc_id, qualifiers); if (!core_package_id.has_value()) { return SemIR::ErrorInst::InstId; } auto inst_id = SemIR::InstId::None; - for (auto name : names) { - auto name_id = - SemIR::NameId::ForIdentifier(context.identifiers().Add(name)); + for (auto qualifier : qualifiers) { + auto name_id = context.core_identifiers().AddNameId(qualifier); auto scope_id = SemIR::NameScopeId::None; if (inst_id.has_value()) { @@ -556,11 +569,11 @@ auto LookupNameInCore(Context& context, SemIR::LocId loc_id, context.name_scopes().Get(scope_id)) : SemIR::ScopeLookupResult::MakeNotFound(); if (!scope_result.is_found()) { - CARBON_DIAGNOSTIC( - CoreNameNotFound, Error, - "name `Core.{0}` implicitly referenced here, but not found", - std::string); - context.emitter().Emit(loc_id, CoreNameNotFound, llvm::join(names, ".")); + CARBON_DIAGNOSTIC(CoreNameNotFound, Error, + "name `{0}` implicitly referenced here, but not found", + std::string); + context.emitter().Emit(loc_id, CoreNameNotFound, + GetCoreQualifiedName(qualifiers)); return SemIR::ErrorInst::InstId; } diff --git a/toolchain/check/name_lookup.h b/toolchain/check/name_lookup.h index 0122ce6ace3e..46bca49f9b15 100644 --- a/toolchain/check/name_lookup.h +++ b/toolchain/check/name_lookup.h @@ -8,6 +8,7 @@ #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/StringRef.h" #include "toolchain/check/context.h" +#include "toolchain/check/core_identifier.h" #include "toolchain/sem_ir/ids.h" namespace Carbon::Check { @@ -94,16 +95,17 @@ auto LookupQualifiedName(Context& context, SemIR::LocId loc_id, std::optional access_info = std::nullopt) -> LookupResult; -// Returns the `InstId` corresponding to a qualified name in the core package, +// Returns the `InstId` corresponding to a qualified name in the `Core` package, // or BuiltinErrorInst if not found. auto LookupNameInCore(Context& context, SemIR::LocId loc_id, - llvm::ArrayRef names) -> SemIR::InstId; + llvm::ArrayRef qualifiers) + -> SemIR::InstId; -// Returns the `InstId` corresponding to a name in the core package, or +// Returns the `InstId` corresponding to a name in the `Core`, or // BuiltinErrorInst if not found. inline auto LookupNameInCore(Context& context, SemIR::LocId loc_id, - llvm::StringRef name) -> SemIR::InstId { - return LookupNameInCore(context, loc_id, llvm::ArrayRef{name}); + CoreIdentifier identifier) -> SemIR::InstId { + return LookupNameInCore(context, loc_id, llvm::ArrayRef{identifier}); } // Checks whether a name is accessible in the given access context. Produces a diff --git a/toolchain/check/operator.cpp b/toolchain/check/operator.cpp index 184d32401b5a..317611cd9f96 100644 --- a/toolchain/check/operator.cpp +++ b/toolchain/check/operator.cpp @@ -35,8 +35,7 @@ static auto GetOperatorOpFunction(Context& context, SemIR::LocId loc_id, } // Look up the interface member. - auto op_name_id = - SemIR::NameId::ForIdentifier(context.identifiers().Add(op.op_name)); + auto op_name_id = context.core_identifiers().AddNameId(op.op_name); return PerformMemberAccess(context, implicit_loc_id, interface_id, op_name_id); } diff --git a/toolchain/check/operator.h b/toolchain/check/operator.h index 5b3a7fb9aa5a..498089ff9d68 100644 --- a/toolchain/check/operator.h +++ b/toolchain/check/operator.h @@ -6,15 +6,16 @@ #define CARBON_TOOLCHAIN_CHECK_OPERATOR_H_ #include "toolchain/check/context.h" +#include "toolchain/check/core_identifier.h" #include "toolchain/parse/node_ids.h" #include "toolchain/sem_ir/ids.h" namespace Carbon::Check { struct Operator { - llvm::StringLiteral interface_name; + CoreIdentifier interface_name; llvm::ArrayRef interface_args_ref = {}; - llvm::StringLiteral op_name = "Op"; + CoreIdentifier op_name = CoreIdentifier::Op; }; // Checks and builds SemIR for a unary operator expression. For example,