From 8166f9a7cf2027233032e07ba901b4d1201bfbb3 Mon Sep 17 00:00:00 2001 From: Jon Ross-Perkins Date: Wed, 5 Nov 2025 09:21:41 -0800 Subject: [PATCH] Formalize Cpp as a PackageNameId (#6306) This turns `Cpp` into a keyword, and makes it map to `NameId::Cpp` and `PackageNameId::Cpp`. Per discussion with zygoloid, the keyword versus identifier question is deliberately kept open by #4846. This PR switches to a keyword because mapping to a specific `PackageNameId` works best with a special `NameId` not backed by an `IdentifierId`. We could in theory make it work using `IdentifierId` or a runtime-tracked `PackageNameId` for `Cpp` (e.g. stored on `SemIR::File`), but this approach is consistent with `Core` and so seemed like a good starting point. --------- Co-authored-by: Dana Jansens --- toolchain/base/value_ids.h | 17 +++++- toolchain/check/check.cpp | 18 +++--- toolchain/check/handle_import_and_package.cpp | 5 ++ toolchain/check/handle_name.cpp | 8 +++ toolchain/check/node_stack.h | 1 + .../basics/raw_sem_ir/cpp_interop.carbon | 58 +++++++++---------- .../testdata/interop/cpp/class/access.carbon | 10 ---- .../testdata/interop/cpp/class/class.carbon | 1 - .../testdata/interop/cpp/cpp_namespace.carbon | 42 ++++++-------- .../packages/restricted_package_names.carbon | 11 ++-- toolchain/lex/token_kind.def | 1 + toolchain/lex/token_kind_test.cpp | 2 +- toolchain/parse/handle_expr.cpp | 5 ++ toolchain/parse/handle_import_and_package.cpp | 6 +- toolchain/parse/node_kind.def | 2 + .../packages/import/cpp_inline.carbon | 12 ++-- .../testdata/packages/keyword_names.carbon | 40 +++++++++++++ toolchain/parse/typed_nodes.h | 12 ++-- toolchain/sem_ir/formatter.cpp | 5 +- toolchain/sem_ir/ids.cpp | 2 + toolchain/sem_ir/ids.h | 2 + toolchain/sem_ir/name.cpp | 2 + 22 files changed, 162 insertions(+), 100 deletions(-) create mode 100644 toolchain/parse/testdata/packages/keyword_names.carbon diff --git a/toolchain/base/value_ids.h b/toolchain/base/value_ids.h index 5806caac617a..e3c90a60df58 100644 --- a/toolchain/base/value_ids.h +++ b/toolchain/base/value_ids.h @@ -83,7 +83,7 @@ struct PackageNameId : public IdBase { static constexpr llvm::StringLiteral Label = "package"; static const PackageNameId None; static const PackageNameId Core; - static constexpr llvm::StringLiteral CppName = "Cpp"; + static const PackageNameId Cpp; // Returns the PackageNameId corresponding to a particular IdentifierId. static auto ForIdentifier(IdentifierId id) -> PackageNameId { @@ -101,17 +101,30 @@ struct PackageNameId : public IdBase { // Returns the special package name corresponding to this PackageNameId. // Requires that this name is not an identifier name. auto AsSpecialName() const -> llvm::StringLiteral { + CARBON_CHECK(index <= NoneIndex); if (*this == None) { return "Main"; } if (*this == Core) { return "Core"; } - CARBON_FATAL("Unknown special package name kind {0}", *this); + if (*this == Cpp) { + return "Cpp"; + } + CARBON_FATAL("Unknown special package name kind {0}", index); + } + + auto Print(llvm::raw_ostream& out) const -> void { + if (index <= NoneIndex) { + out << Label << AsSpecialName(); + } else { + IdBase::Print(out); + } } }; constexpr PackageNameId PackageNameId::None(PackageNameId::NoneIndex); constexpr PackageNameId PackageNameId::Core(PackageNameId::NoneIndex - 1); +constexpr PackageNameId PackageNameId::Cpp(PackageNameId::NoneIndex - 2); // Corresponds to StringRefs for string literals. struct StringLiteralValueId : public IdBase { diff --git a/toolchain/check/check.cpp b/toolchain/check/check.cpp index 435db878278d..a22299660ae5 100644 --- a/toolchain/check/check.cpp +++ b/toolchain/check/check.cpp @@ -73,14 +73,7 @@ static auto TrackImport(Map& api_map, UnitAndImports& unit_info, Parse::Tree::PackagingNames import, bool fuzzing) -> void { - const auto& packaging = unit_info.parse_tree().packaging_decl(); - - PackageNameId file_package_id = - packaging ? packaging->names.package_id : PackageNameId::None; - const auto import_key = GetImportKey(unit_info, file_package_id, import); - const auto& [import_package_name, import_library_name] = import_key; - - if (import_package_name == PackageNameId::CppName) { + if (import.package_id == PackageNameId::Cpp) { if (!explicit_import_map) { // Don't diagnose the implicit import in `impl package Cpp`, because we'll // have diagnosed the use of `Cpp` in the declaration. @@ -108,9 +101,14 @@ static auto TrackImport(Map& api_map, return; } + const auto& packaging = unit_info.parse_tree().packaging_decl(); + PackageNameId file_package_id = + packaging ? packaging->names.package_id : PackageNameId::None; + const auto import_key = GetImportKey(unit_info, file_package_id, import); + // True if the import has `Main` as the package name, even if it comes from // the file's packaging (diagnostics may differentiate). - bool is_explicit_main = import_package_name == MainPackageName; + bool is_explicit_main = import_key.first == MainPackageName; // Explicit imports need more validation than implicit ones. We try to do // these in an order of imports that should be removed, followed by imports @@ -265,7 +263,7 @@ static auto BuildApiMapAndDiagnosePackaging( : ExplicitMainLibrary); continue; } - if (import_key.first == PackageNameId::CppName) { + if (packaging && packaging->names.package_id == PackageNameId::Cpp) { CARBON_DIAGNOSTIC(CppPackageDeclaration, Error, "`Cpp` cannot be used by a `package` declaration"); unit_info.emitter.Emit(packaging->names.node_id, CppPackageDeclaration); diff --git a/toolchain/check/handle_import_and_package.cpp b/toolchain/check/handle_import_and_package.cpp index 71e6bbcc02ee..ac5465c712a3 100644 --- a/toolchain/check/handle_import_and_package.cpp +++ b/toolchain/check/handle_import_and_package.cpp @@ -73,6 +73,11 @@ auto HandleParseNode(Context& /*context*/, Parse::CorePackageNameId /*node_id*/) return true; } +auto HandleParseNode(Context& /*context*/, Parse::CppPackageNameId /*node_id*/) + -> bool { + return true; +} + auto HandleParseNode(Context& context, Parse::LibraryNameId node_id) -> bool { // This is discarded in this file's uses, but is used by modifiers for `extern // library`. diff --git a/toolchain/check/handle_name.cpp b/toolchain/check/handle_name.cpp index dda49800a941..8a86ce9f9074 100644 --- a/toolchain/check/handle_name.cpp +++ b/toolchain/check/handle_name.cpp @@ -240,4 +240,12 @@ auto HandleParseNode(Context& context, Parse::CoreNameExprId node_id) -> bool { return true; } +auto HandleParseNode(Context& context, Parse::CppNameExprId node_id) -> bool { + // TODO: Unqualified lookup will never find anything; perform lookup directly + // into file scope. + context.node_stack().Push( + node_id, HandleNameAsExpr(context, node_id, SemIR::NameId::Cpp)); + return true; +} + } // namespace Carbon::Check diff --git a/toolchain/check/node_stack.h b/toolchain/check/node_stack.h index 56e60d7f2dc9..1f98eb14f009 100644 --- a/toolchain/check/node_stack.h +++ b/toolchain/check/node_stack.h @@ -491,6 +491,7 @@ class NodeStack { case Parse::NodeKind::CompileTimeBindingPatternStart: case Parse::NodeKind::ContinueStatementStart: case Parse::NodeKind::CorePackageName: + case Parse::NodeKind::CppPackageName: case Parse::NodeKind::ExportIntroducer: case Parse::NodeKind::FileEnd: case Parse::NodeKind::FileStart: diff --git a/toolchain/check/testdata/basics/raw_sem_ir/cpp_interop.carbon b/toolchain/check/testdata/basics/raw_sem_ir/cpp_interop.carbon index a3113793ada8..a21c8e375e5d 100644 --- a/toolchain/check/testdata/basics/raw_sem_ir/cpp_interop.carbon +++ b/toolchain/check/testdata/basics/raw_sem_ir/cpp_interop.carbon @@ -52,32 +52,32 @@ fn G(x: Cpp.X) { // CHECK:STDOUT: clang_decl_id60000006: {key: {decl: "extern void f__carbon_thunk(X * _Nonnull x)", num_params: 1}, inst_id: inst60000042} // CHECK:STDOUT: clang_decl_id60000007: {key: "X * _Nonnull global", inst_id: inst6000004B} // CHECK:STDOUT: name_scopes: -// CHECK:STDOUT: name_scope00000000: {inst: inst0000000E, parent_scope: name_scope, has_error: false, extended_scopes: [], names: {name00000000: inst60000010, name00000001: inst6000001C}} -// CHECK:STDOUT: name_scope60000001: {inst: inst60000010, parent_scope: name_scope00000000, has_error: false, extended_scopes: [], names: {name00000003: inst60000013, name00000004: inst60000029, name00000005: inst6000004B}} +// CHECK:STDOUT: name_scope00000000: {inst: inst0000000E, parent_scope: name_scope, has_error: false, extended_scopes: [], names: {name(Cpp): inst60000010, name00000000: inst6000001C}} +// CHECK:STDOUT: name_scope60000001: {inst: inst60000010, parent_scope: name_scope00000000, has_error: false, extended_scopes: [], names: {name00000002: inst60000013, name00000003: inst60000029, name00000004: inst6000004B}} // CHECK:STDOUT: name_scope60000002: {inst: inst60000013, parent_scope: name_scope60000001, has_error: false, extended_scopes: [], names: {}} // CHECK:STDOUT: entity_names: -// CHECK:STDOUT: entity_name60000000: {name: name00000002, parent_scope: name_scope, index: -1, is_template: 0} -// CHECK:STDOUT: entity_name60000001: {name: name00000002, parent_scope: name_scope, index: -1, is_template: 0} -// CHECK:STDOUT: entity_name60000002: {name: name00000002, parent_scope: name_scope, index: -1, is_template: 0} -// CHECK:STDOUT: entity_name60000003: {name: name00000005, parent_scope: name_scope60000001, index: -1, is_template: 0} +// CHECK:STDOUT: entity_name60000000: {name: name00000001, parent_scope: name_scope, index: -1, is_template: 0} +// CHECK:STDOUT: entity_name60000001: {name: name00000001, parent_scope: name_scope, index: -1, is_template: 0} +// CHECK:STDOUT: entity_name60000002: {name: name00000001, parent_scope: name_scope, index: -1, is_template: 0} +// CHECK:STDOUT: entity_name60000003: {name: name00000004, parent_scope: name_scope60000001, index: -1, is_template: 0} // CHECK:STDOUT: cpp_global_vars: // CHECK:STDOUT: cpp_global_var60000000: {key: {entity_name_id: entity_name60000003}, clang_decl_id: clang_decl_id60000007} // CHECK:STDOUT: functions: -// CHECK:STDOUT: function60000000: {name: name00000001, parent_scope: name_scope00000000, call_params_id: inst_block60000006, body: [inst_block60000009]} -// CHECK:STDOUT: function60000001: {name: name00000004, parent_scope: name_scope60000001, call_params_id: inst_block_empty} -// CHECK:STDOUT: function60000002: {name: name00000007, parent_scope: name_scope60000001, call_params_id: inst_block_empty} -// CHECK:STDOUT: function60000003: {name: name00000004, parent_scope: name_scope60000001, call_params_id: inst_block6000000D} -// CHECK:STDOUT: function60000004: {name: name00000007, parent_scope: name_scope60000001, call_params_id: inst_block60000012} +// CHECK:STDOUT: function60000000: {name: name00000000, parent_scope: name_scope00000000, call_params_id: inst_block60000006, body: [inst_block60000009]} +// CHECK:STDOUT: function60000001: {name: name00000003, parent_scope: name_scope60000001, call_params_id: inst_block_empty} +// CHECK:STDOUT: function60000002: {name: name00000006, parent_scope: name_scope60000001, call_params_id: inst_block_empty} +// CHECK:STDOUT: function60000003: {name: name00000003, parent_scope: name_scope60000001, call_params_id: inst_block6000000D} +// CHECK:STDOUT: function60000004: {name: name00000006, parent_scope: name_scope60000001, call_params_id: inst_block60000012} // CHECK:STDOUT: classes: -// CHECK:STDOUT: class60000000: {name: name00000003, parent_scope: name_scope60000001, self_type_id: type(inst60000014), inheritance_kind: Base, is_dynamic: 0, scope_id: name_scope60000002, body_block_id: inst_block6000000A, adapt_id: inst, base_id: inst, complete_type_witness_id: inst60000024, vtable_decl_id: inst}} +// CHECK:STDOUT: class60000000: {name: name00000002, parent_scope: name_scope60000001, self_type_id: type(inst60000014), inheritance_kind: Base, is_dynamic: 0, scope_id: name_scope60000002, body_block_id: inst_block6000000A, adapt_id: inst, base_id: inst, complete_type_witness_id: inst60000024, vtable_decl_id: inst}} // CHECK:STDOUT: generics: {} // CHECK:STDOUT: specifics: {} // CHECK:STDOUT: struct_type_fields: // CHECK:STDOUT: struct_type_fields00000000: {} // CHECK:STDOUT: struct_type_fields60000001: -// CHECK:STDOUT: 0: {name_id: name00000006, type_inst_id: inst6000001F} +// CHECK:STDOUT: 0: {name_id: name00000005, type_inst_id: inst6000001F} // CHECK:STDOUT: struct_type_fields60000002: -// CHECK:STDOUT: 0: {name_id: name00000006, type_inst_id: inst6000001F} +// CHECK:STDOUT: 0: {name_id: name00000005, type_inst_id: inst6000001F} // CHECK:STDOUT: types: // CHECK:STDOUT: 'type(TypeType)': // CHECK:STDOUT: value_repr: {kind: copy, type: type(TypeType)} @@ -129,33 +129,33 @@ fn G(x: Cpp.X) { // CHECK:STDOUT: inst0000000E: {kind: Namespace, arg0: name_scope00000000, arg1: inst, type: type(inst(NamespaceType))} // CHECK:STDOUT: inst6000000F: {kind: ImportCppDecl} // CHECK:STDOUT: inst60000010: {kind: Namespace, arg0: name_scope60000001, arg1: inst6000000F, type: type(inst(NamespaceType))} -// CHECK:STDOUT: inst60000011: {kind: NameRef, arg0: name00000000, arg1: inst60000010, type: type(inst(NamespaceType))} +// CHECK:STDOUT: inst60000011: {kind: NameRef, arg0: name(Cpp), arg1: inst60000010, type: type(inst(NamespaceType))} // CHECK:STDOUT: inst60000012: {kind: TupleType, arg0: inst_block_empty, type: type(TypeType)} // CHECK:STDOUT: inst60000013: {kind: ClassDecl, arg0: class60000000, arg1: inst_block, type: type(TypeType)} // CHECK:STDOUT: inst60000014: {kind: ClassType, arg0: class60000000, arg1: specific, type: type(TypeType)} -// CHECK:STDOUT: inst60000015: {kind: NameRef, arg0: name00000003, arg1: inst60000013, type: type(TypeType)} +// CHECK:STDOUT: inst60000015: {kind: NameRef, arg0: name00000002, arg1: inst60000013, type: type(TypeType)} // CHECK:STDOUT: inst60000016: {kind: ValueBinding, arg0: entity_name60000000, arg1: inst6000001A, type: type(inst60000014)} // CHECK:STDOUT: inst60000017: {kind: PatternType, arg0: inst60000014, type: type(TypeType)} // CHECK:STDOUT: inst60000018: {kind: ValueBindingPattern, arg0: entity_name60000000, type: type(inst60000017)} // CHECK:STDOUT: inst60000019: {kind: ValueParamPattern, arg0: inst60000018, arg1: call_param0, type: type(inst60000017)} -// CHECK:STDOUT: inst6000001A: {kind: ValueParam, arg0: call_param0, arg1: name00000002, type: type(inst60000014)} +// CHECK:STDOUT: inst6000001A: {kind: ValueParam, arg0: call_param0, arg1: name00000001, type: type(inst60000014)} // CHECK:STDOUT: inst6000001B: {kind: SpliceBlock, arg0: inst_block60000004, arg1: inst60000015, type: type(TypeType)} // CHECK:STDOUT: inst6000001C: {kind: FunctionDecl, arg0: function60000000, arg1: inst_block60000008, type: type(inst6000001D)} // CHECK:STDOUT: inst6000001D: {kind: FunctionType, arg0: function60000000, arg1: specific, type: type(TypeType)} // CHECK:STDOUT: inst6000001E: {kind: StructValue, arg0: inst_block_empty, type: type(inst6000001D)} // CHECK:STDOUT: inst6000001F: {kind: PointerType, arg0: inst60000014, type: type(TypeType)} // CHECK:STDOUT: inst60000020: {kind: UnboundElementType, arg0: inst60000014, arg1: inst6000001F, type: type(TypeType)} -// CHECK:STDOUT: inst60000021: {kind: FieldDecl, arg0: name00000006, arg1: element0, type: type(inst60000020)} +// CHECK:STDOUT: inst60000021: {kind: FieldDecl, arg0: name00000005, arg1: element0, type: type(inst60000020)} // CHECK:STDOUT: inst60000022: {kind: CustomLayoutType, arg0: struct_type_fields60000001, arg1: custom_layout60000001, type: type(TypeType)} // CHECK:STDOUT: inst60000023: {kind: CustomLayoutType, arg0: struct_type_fields60000002, arg1: custom_layout60000001, type: type(TypeType)} // CHECK:STDOUT: inst60000024: {kind: CompleteTypeWitness, arg0: inst60000022, type: type(inst(WitnessType))} // CHECK:STDOUT: inst60000025: {kind: CompleteTypeWitness, arg0: inst60000023, type: type(inst(WitnessType))} // CHECK:STDOUT: inst60000026: {kind: PointerType, arg0: inst60000023, type: type(TypeType)} -// CHECK:STDOUT: inst60000027: {kind: NameRef, arg0: name00000000, arg1: inst60000010, type: type(inst(NamespaceType))} +// CHECK:STDOUT: inst60000027: {kind: NameRef, arg0: name(Cpp), arg1: inst60000010, type: type(inst(NamespaceType))} // CHECK:STDOUT: inst60000028: {kind: CppOverloadSetType, arg0: cpp_overload_set60000000, arg1: specific, type: type(TypeType)} // CHECK:STDOUT: inst60000029: {kind: CppOverloadSetValue, arg0: cpp_overload_set60000000, type: type(inst60000028)} // CHECK:STDOUT: inst6000002A: {kind: CppOverloadSetValue, arg0: cpp_overload_set60000000, type: type(inst60000028)} -// CHECK:STDOUT: inst6000002B: {kind: NameRef, arg0: name00000004, arg1: inst60000029, type: type(inst60000028)} +// CHECK:STDOUT: inst6000002B: {kind: NameRef, arg0: name00000003, arg1: inst60000029, type: type(inst60000028)} // CHECK:STDOUT: inst6000002C: {kind: FunctionDecl, arg0: function60000001, arg1: inst_block_empty, type: type(inst6000002D)} // CHECK:STDOUT: inst6000002D: {kind: FunctionType, arg0: function60000001, arg1: specific, type: type(TypeType)} // CHECK:STDOUT: inst6000002E: {kind: StructValue, arg0: inst_block_empty, type: type(inst6000002D)} @@ -163,13 +163,13 @@ fn G(x: Cpp.X) { // CHECK:STDOUT: inst60000030: {kind: FunctionType, arg0: function60000002, arg1: specific, type: type(TypeType)} // CHECK:STDOUT: inst60000031: {kind: StructValue, arg0: inst_block_empty, type: type(inst60000030)} // CHECK:STDOUT: inst60000032: {kind: Call, arg0: inst6000002F, arg1: inst_block_empty, type: type(inst60000012)} -// CHECK:STDOUT: inst60000033: {kind: NameRef, arg0: name00000000, arg1: inst60000010, type: type(inst(NamespaceType))} -// CHECK:STDOUT: inst60000034: {kind: NameRef, arg0: name00000004, arg1: inst60000029, type: type(inst60000028)} -// CHECK:STDOUT: inst60000035: {kind: NameRef, arg0: name00000002, arg1: inst60000016, type: type(inst60000014)} +// CHECK:STDOUT: inst60000033: {kind: NameRef, arg0: name(Cpp), arg1: inst60000010, type: type(inst(NamespaceType))} +// CHECK:STDOUT: inst60000034: {kind: NameRef, arg0: name00000003, arg1: inst60000029, type: type(inst60000028)} +// CHECK:STDOUT: inst60000035: {kind: NameRef, arg0: name00000001, arg1: inst60000016, type: type(inst60000014)} // CHECK:STDOUT: inst60000036: {kind: ValueBinding, arg0: entity_name60000001, arg1: inst60000039, type: type(inst60000014)} // CHECK:STDOUT: inst60000037: {kind: ValueBindingPattern, arg0: entity_name60000001, type: type(inst60000017)} // CHECK:STDOUT: inst60000038: {kind: ValueParamPattern, arg0: inst60000037, arg1: call_param0, type: type(inst60000017)} -// CHECK:STDOUT: inst60000039: {kind: ValueParam, arg0: call_param0, arg1: name00000002, type: type(inst60000014)} +// CHECK:STDOUT: inst60000039: {kind: ValueParam, arg0: call_param0, arg1: name00000001, type: type(inst60000014)} // CHECK:STDOUT: inst6000003A: {kind: FunctionDecl, arg0: function60000003, arg1: inst_block6000000F, type: type(inst6000003B)} // CHECK:STDOUT: inst6000003B: {kind: FunctionType, arg0: function60000003, arg1: specific, type: type(TypeType)} // CHECK:STDOUT: inst6000003C: {kind: StructValue, arg0: inst_block_empty, type: type(inst6000003B)} @@ -177,21 +177,21 @@ fn G(x: Cpp.X) { // CHECK:STDOUT: inst6000003E: {kind: PatternType, arg0: inst6000001F, type: type(TypeType)} // CHECK:STDOUT: inst6000003F: {kind: ValueBindingPattern, arg0: entity_name60000002, type: type(inst6000003E)} // CHECK:STDOUT: inst60000040: {kind: ValueParamPattern, arg0: inst6000003F, arg1: call_param0, type: type(inst6000003E)} -// CHECK:STDOUT: inst60000041: {kind: ValueParam, arg0: call_param0, arg1: name00000002, type: type(inst6000001F)} +// CHECK:STDOUT: inst60000041: {kind: ValueParam, arg0: call_param0, arg1: name00000001, type: type(inst6000001F)} // CHECK:STDOUT: inst60000042: {kind: FunctionDecl, arg0: function60000004, arg1: inst_block60000014, type: type(inst60000043)} // CHECK:STDOUT: inst60000043: {kind: FunctionType, arg0: function60000004, arg1: specific, type: type(TypeType)} // CHECK:STDOUT: inst60000044: {kind: StructValue, arg0: inst_block_empty, type: type(inst60000043)} // CHECK:STDOUT: inst60000045: {kind: ValueAsRef, arg0: inst60000035, type: type(inst60000014)} // CHECK:STDOUT: inst60000046: {kind: AddrOf, arg0: inst60000045, type: type(inst6000001F)} // CHECK:STDOUT: inst60000047: {kind: Call, arg0: inst60000042, arg1: inst_block60000016, type: type(inst60000012)} -// CHECK:STDOUT: inst60000048: {kind: NameRef, arg0: name00000000, arg1: inst60000010, type: type(inst(NamespaceType))} -// CHECK:STDOUT: inst60000049: {kind: NameRef, arg0: name00000004, arg1: inst60000029, type: type(inst60000028)} -// CHECK:STDOUT: inst6000004A: {kind: NameRef, arg0: name00000000, arg1: inst60000010, type: type(inst(NamespaceType))} +// CHECK:STDOUT: inst60000048: {kind: NameRef, arg0: name(Cpp), arg1: inst60000010, type: type(inst(NamespaceType))} +// CHECK:STDOUT: inst60000049: {kind: NameRef, arg0: name00000003, arg1: inst60000029, type: type(inst60000028)} +// CHECK:STDOUT: inst6000004A: {kind: NameRef, arg0: name(Cpp), arg1: inst60000010, type: type(inst(NamespaceType))} // CHECK:STDOUT: inst6000004B: {kind: VarStorage, arg0: inst6000004D, type: type(inst6000001F)} // CHECK:STDOUT: inst6000004C: {kind: RefBindingPattern, arg0: entity_name60000003, type: type(inst6000003E)} // CHECK:STDOUT: inst6000004D: {kind: VarPattern, arg0: inst6000004C, type: type(inst6000003E)} // CHECK:STDOUT: inst6000004E: {kind: NameBindingDecl, arg0: inst_block60000017} -// CHECK:STDOUT: inst6000004F: {kind: NameRef, arg0: name00000005, arg1: inst6000004B, type: type(inst6000001F)} +// CHECK:STDOUT: inst6000004F: {kind: NameRef, arg0: name00000004, arg1: inst6000004B, type: type(inst6000001F)} // CHECK:STDOUT: inst60000050: {kind: AcquireValue, arg0: inst6000004F, type: type(inst6000001F)} // CHECK:STDOUT: inst60000051: {kind: Deref, arg0: inst60000050, type: type(inst60000014)} // CHECK:STDOUT: inst60000052: {kind: AcquireValue, arg0: inst60000051, type: type(inst60000014)} diff --git a/toolchain/check/testdata/interop/cpp/class/access.carbon b/toolchain/check/testdata/interop/cpp/class/access.carbon index c1bcbcd70593..f979bd301003 100644 --- a/toolchain/check/testdata/interop/cpp/class/access.carbon +++ b/toolchain/check/testdata/interop/cpp/class/access.carbon @@ -1687,7 +1687,6 @@ fn Call(var instance: Cpp.PublicPrivate) { // CHECK:STDOUT: // CHECK:STDOUT: !members: // CHECK:STDOUT: .Self = constants.%Derived -// CHECK:STDOUT: .Cpp = // CHECK:STDOUT: .base = %.loc7 // CHECK:STDOUT: .F = %Derived.F.decl // CHECK:STDOUT: .instance_data = @@ -1819,7 +1818,6 @@ fn Call(var instance: Cpp.PublicPrivate) { // CHECK:STDOUT: // CHECK:STDOUT: !members: // CHECK:STDOUT: .Self = constants.%Derived -// CHECK:STDOUT: .Cpp = // CHECK:STDOUT: .base = %.loc7 // CHECK:STDOUT: .F = %Derived.F.decl // CHECK:STDOUT: .instance_fn = @@ -1862,7 +1860,6 @@ fn Call(var instance: Cpp.PublicPrivate) { // CHECK:STDOUT: // CHECK:STDOUT: !members: // CHECK:STDOUT: .Self = constants.%Derived -// CHECK:STDOUT: .Cpp = // CHECK:STDOUT: .base = %.loc7 // CHECK:STDOUT: .F = %Derived.F.decl // CHECK:STDOUT: .static_fn = @@ -2088,7 +2085,6 @@ fn Call(var instance: Cpp.PublicPrivate) { // CHECK:STDOUT: // CHECK:STDOUT: !members: // CHECK:STDOUT: .Self = constants.%D -// CHECK:STDOUT: .Cpp = // CHECK:STDOUT: .base = %.loc7 // CHECK:STDOUT: .D = // CHECK:STDOUT: .MakePublic = %D.MakePublic.decl @@ -2346,7 +2342,6 @@ fn Call(var instance: Cpp.PublicPrivate) { // CHECK:STDOUT: // CHECK:STDOUT: !members: // CHECK:STDOUT: .Self = constants.%Derived -// CHECK:STDOUT: .Cpp = // CHECK:STDOUT: .base = %.loc7 // CHECK:STDOUT: .F = %Derived.F.decl // CHECK:STDOUT: .Overload = @@ -2468,7 +2463,6 @@ fn Call(var instance: Cpp.PublicPrivate) { // CHECK:STDOUT: // CHECK:STDOUT: !members: // CHECK:STDOUT: .Self = constants.%Derived -// CHECK:STDOUT: .Cpp = // CHECK:STDOUT: .base = %.loc7 // CHECK:STDOUT: .F = %Derived.F.decl // CHECK:STDOUT: .Overload = @@ -2581,7 +2575,6 @@ fn Call(var instance: Cpp.PublicPrivate) { // CHECK:STDOUT: // CHECK:STDOUT: !members: // CHECK:STDOUT: .Self = constants.%Derived -// CHECK:STDOUT: .Cpp = // CHECK:STDOUT: .base = %.loc7 // CHECK:STDOUT: .CallStatic = %Derived.CallStatic.decl // CHECK:STDOUT: .CallInstance = %Derived.CallInstance.decl @@ -2678,7 +2671,6 @@ fn Call(var instance: Cpp.PublicPrivate) { // CHECK:STDOUT: // CHECK:STDOUT: !members: // CHECK:STDOUT: .Self = constants.%Derived -// CHECK:STDOUT: .Cpp = // CHECK:STDOUT: .base = %.loc7 // CHECK:STDOUT: .CallStatic = %Derived.CallStatic.decl // CHECK:STDOUT: .CallInstance = %Derived.CallInstance.decl @@ -2759,7 +2751,6 @@ fn Call(var instance: Cpp.PublicPrivate) { // CHECK:STDOUT: // CHECK:STDOUT: !members: // CHECK:STDOUT: .Self = constants.%Derived -// CHECK:STDOUT: .Cpp = // CHECK:STDOUT: .base = %.loc7 // CHECK:STDOUT: .CallStatic = %Derived.CallStatic.decl // CHECK:STDOUT: .CallInstance = %Derived.CallInstance.decl @@ -2876,7 +2867,6 @@ fn Call(var instance: Cpp.PublicPrivate) { // CHECK:STDOUT: // CHECK:STDOUT: !members: // CHECK:STDOUT: .Self = constants.%Derived -// CHECK:STDOUT: .Cpp = // CHECK:STDOUT: .base = %.loc7 // CHECK:STDOUT: .CallStatic = %Derived.CallStatic.decl // CHECK:STDOUT: .CallInstance = %Derived.CallInstance.decl diff --git a/toolchain/check/testdata/interop/cpp/class/class.carbon b/toolchain/check/testdata/interop/cpp/class/class.carbon index b07b1e71ea3a..ab451b35b172 100644 --- a/toolchain/check/testdata/interop/cpp/class/class.carbon +++ b/toolchain/check/testdata/interop/cpp/class/class.carbon @@ -553,7 +553,6 @@ fn MyF(bar: Cpp.Bar*); // CHECK:STDOUT: // CHECK:STDOUT: !members: // CHECK:STDOUT: .Self = constants.%Derived -// CHECK:STDOUT: .Cpp = // CHECK:STDOUT: .base = %.loc8 // CHECK:STDOUT: .foo = // CHECK:STDOUT: extend %Bar.ref diff --git a/toolchain/check/testdata/interop/cpp/cpp_namespace.carbon b/toolchain/check/testdata/interop/cpp/cpp_namespace.carbon index 7b37efed1422..c32ef165ca66 100644 --- a/toolchain/check/testdata/interop/cpp/cpp_namespace.carbon +++ b/toolchain/check/testdata/interop/cpp/cpp_namespace.carbon @@ -18,25 +18,32 @@ library "[[@TEST_NAME]]"; import Cpp library "header.h"; -// CHECK:STDERR: fail_duplicate_cpp_name.carbon:[[@LINE+7]]:11: error: duplicate name `Cpp` being declared in the same scope [NameDeclDuplicate] +// CHECK:STDERR: fail_duplicate_cpp_name.carbon:[[@LINE+8]]:11: error: `namespace` introducer should be followed by a name [ExpectedDeclName] +// CHECK:STDERR: namespace Cpp; +// CHECK:STDERR: ^~~ +// CHECK:STDERR: +// CHECK:STDERR: fail_duplicate_cpp_name.carbon:[[@LINE+4]]:11: error: semantics TODO: `handle invalid parse trees in `check`` [SemanticsTodo] // CHECK:STDERR: namespace Cpp; // CHECK:STDERR: ^~~ -// CHECK:STDERR: fail_duplicate_cpp_name.carbon:[[@LINE-5]]:1: note: name is previously declared here [NameDeclPrevious] -// CHECK:STDERR: import Cpp library "header.h"; -// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // CHECK:STDERR: namespace Cpp; -// --- cpp_in_inner_namespace.carbon +// --- fail_cpp_in_inner_namespace.carbon library "[[@TEST_NAME]]"; import Cpp library "header.h"; -//@dump-sem-ir-begin namespace N; +// CHECK:STDERR: fail_cpp_in_inner_namespace.carbon:[[@LINE+8]]:13: error: `.` should be followed by a name [ExpectedDeclNameAfterPeriod] +// CHECK:STDERR: namespace N.Cpp; +// CHECK:STDERR: ^~~ +// CHECK:STDERR: +// CHECK:STDERR: fail_cpp_in_inner_namespace.carbon:[[@LINE+4]]:13: error: semantics TODO: `handle invalid parse trees in `check`` [SemanticsTodo] +// CHECK:STDERR: namespace N.Cpp; +// CHECK:STDERR: ^~~ +// CHECK:STDERR: namespace N.Cpp; -//@dump-sem-ir-end // --- alias.carbon @@ -54,12 +61,13 @@ library "[[@TEST_NAME]]"; import Cpp library "header.h"; -// CHECK:STDERR: fail_add_name_to_cpp_namespace.carbon:[[@LINE+7]]:7: error: imported packages cannot be used for declarations [QualifiedDeclOutsidePackage] +// CHECK:STDERR: fail_add_name_to_cpp_namespace.carbon:[[@LINE+8]]:7: error: `class` introducer should be followed by a name [ExpectedDeclName] +// CHECK:STDERR: class Cpp.C {}; +// CHECK:STDERR: ^~~ +// CHECK:STDERR: +// CHECK:STDERR: fail_add_name_to_cpp_namespace.carbon:[[@LINE+4]]:7: error: semantics TODO: `handle invalid parse trees in `check`` [SemanticsTodo] // CHECK:STDERR: class Cpp.C {}; // CHECK:STDERR: ^~~ -// CHECK:STDERR: fail_add_name_to_cpp_namespace.carbon:[[@LINE-5]]:1: note: package imported here [QualifiedDeclOutsidePackageSource] -// CHECK:STDERR: import Cpp library "header.h"; -// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // CHECK:STDERR: class Cpp.C {}; @@ -98,18 +106,6 @@ fn F() { //@dump-sem-ir-end } -// CHECK:STDOUT: --- cpp_in_inner_namespace.carbon -// CHECK:STDOUT: -// CHECK:STDOUT: imports { -// CHECK:STDOUT: } -// CHECK:STDOUT: -// CHECK:STDOUT: file { -// CHECK:STDOUT: %N: = namespace [concrete] { -// CHECK:STDOUT: .Cpp = %Cpp -// CHECK:STDOUT: } -// CHECK:STDOUT: %Cpp: = namespace [concrete] {} -// CHECK:STDOUT: } -// CHECK:STDOUT: // CHECK:STDOUT: --- alias.carbon // CHECK:STDOUT: // CHECK:STDOUT: imports { diff --git a/toolchain/check/testdata/packages/restricted_package_names.carbon b/toolchain/check/testdata/packages/restricted_package_names.carbon index af3f80e876fa..3106413b9c69 100644 --- a/toolchain/check/testdata/packages/restricted_package_names.carbon +++ b/toolchain/check/testdata/packages/restricted_package_names.carbon @@ -71,13 +71,8 @@ package Cpp; // CHECK:STDERR: impl package Cpp; -// --- fail_raw_cpp.carbon +// --- raw_cpp.carbon -// `cpp` isn't a keyword, so this fails the same way. -// CHECK:STDERR: fail_raw_cpp.carbon:[[@LINE+4]]:1: error: `Cpp` cannot be used by a `package` declaration [CppPackageDeclaration] -// CHECK:STDERR: package r#Cpp; -// CHECK:STDERR: ^~~~~~~~~~~~~~ -// CHECK:STDERR: package r#Cpp; // --- fail_cpp_lib.carbon @@ -134,9 +129,11 @@ package Cpp library "[[@TEST_NAME]]"; // CHECK:STDOUT: // CHECK:STDOUT: file { // CHECK:STDOUT: package: = namespace [concrete] {} +// CHECK:STDOUT: %Cpp.import = import Cpp +// CHECK:STDOUT: %default.import = import // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: --- fail_raw_cpp.carbon +// CHECK:STDOUT: --- raw_cpp.carbon // CHECK:STDOUT: // CHECK:STDOUT: file { // CHECK:STDOUT: package: = namespace [concrete] {} diff --git a/toolchain/lex/token_kind.def b/toolchain/lex/token_kind.def index ddd9636e23ac..fe8b98b31e71 100644 --- a/toolchain/lex/token_kind.def +++ b/toolchain/lex/token_kind.def @@ -181,6 +181,7 @@ CARBON_KEYWORD_TOKEN(Char, "char") CARBON_KEYWORD_TOKEN(Const, "const") CARBON_KEYWORD_TOKEN(Continue, "continue") CARBON_KEYWORD_TOKEN(Core, "Core") +CARBON_KEYWORD_TOKEN(Cpp, "Cpp") CARBON_KEYWORD_TOKEN(Default, "default") CARBON_KEYWORD_TOKEN(Else, "else") CARBON_KEYWORD_TOKEN(Extend, "extend") diff --git a/toolchain/lex/token_kind_test.cpp b/toolchain/lex/token_kind_test.cpp index 92a89368c3d0..bf1211010fea 100644 --- a/toolchain/lex/token_kind_test.cpp +++ b/toolchain/lex/token_kind_test.cpp @@ -21,7 +21,7 @@ constexpr llvm::StringLiteral SymbolRegex = // We restrict keywords to be lowercase ASCII letters and underscores with a few // specific exceptions. -constexpr llvm::StringLiteral KeywordRegex = "[a-z_]+|Core|Self|String"; +constexpr llvm::StringLiteral KeywordRegex = "[a-z_]+|Core|Cpp|Self"; #define CARBON_TOKEN(TokenName) \ TEST(TokenKindTest, TokenName) { \ diff --git a/toolchain/parse/handle_expr.cpp b/toolchain/parse/handle_expr.cpp index 035d3789329d..eef12852b8d4 100644 --- a/toolchain/parse/handle_expr.cpp +++ b/toolchain/parse/handle_expr.cpp @@ -180,6 +180,11 @@ auto HandleExprInPostfix(Context& context) -> void { context.PushState(state); break; } + case Lex::TokenKind::Cpp: { + context.AddLeafNode(NodeKind::CppNameExpr, context.Consume()); + context.PushState(state); + break; + } case Lex::TokenKind::SelfValueIdentifier: { context.AddLeafNode(NodeKind::SelfValueNameExpr, context.Consume()); context.PushState(state); diff --git a/toolchain/parse/handle_import_and_package.cpp b/toolchain/parse/handle_import_and_package.cpp index 92cc47099ec6..7dfccd3664da 100644 --- a/toolchain/parse/handle_import_and_package.cpp +++ b/toolchain/parse/handle_import_and_package.cpp @@ -48,7 +48,7 @@ static auto HandleDeclContent(Context& context, Context::State state, // This is either `library ...` or `import library ...`, so no package name // is expected. } else { - // We require a package name. This is either an identifier or the `Core` + // We require a package name. This is either an identifier or package name // keyword. auto package_name_position = *context.position(); if (auto ident = context.ConsumeIf(Lex::TokenKind::Identifier)) { @@ -56,9 +56,11 @@ static auto HandleDeclContent(Context& context, Context::State state, PackageNameId::ForIdentifier(context.tokens().GetIdentifier(*ident)); context.AddLeafNode(NodeKind::IdentifierPackageName, *ident); } else if (auto core = context.ConsumeIf(Lex::TokenKind::Core)) { - // TODO: Model `Cpp` as a keyword too. names.package_id = PackageNameId::Core; context.AddLeafNode(NodeKind::CorePackageName, *core); + } else if (auto cpp = context.ConsumeIf(Lex::TokenKind::Cpp)) { + names.package_id = PackageNameId::Cpp; + context.AddLeafNode(NodeKind::CppPackageName, *cpp); } else { CARBON_DIAGNOSTIC(ExpectedIdentifierAfterPackage, Error, "expected identifier after `package`"); diff --git a/toolchain/parse/node_kind.def b/toolchain/parse/node_kind.def index db86dbe92082..5d98c973c194 100644 --- a/toolchain/parse/node_kind.def +++ b/toolchain/parse/node_kind.def @@ -109,8 +109,10 @@ CARBON_PARSE_NODE_KIND(UnderscoreName) CARBON_PARSE_NODE_KIND(BaseName) CARBON_PARSE_NODE_KIND(PackageExpr) CARBON_PARSE_NODE_KIND(CoreNameExpr) +CARBON_PARSE_NODE_KIND(CppNameExpr) CARBON_PARSE_NODE_KIND(IdentifierPackageName) CARBON_PARSE_NODE_KIND(CorePackageName) +CARBON_PARSE_NODE_KIND(CppPackageName) CARBON_PARSE_NODE_KIND(LibraryName) CARBON_PARSE_NODE_KIND(PackageIntroducer) diff --git a/toolchain/parse/testdata/packages/import/cpp_inline.carbon b/toolchain/parse/testdata/packages/import/cpp_inline.carbon index e4974e85c60f..93e7b25f9ad3 100644 --- a/toolchain/parse/testdata/packages/import/cpp_inline.carbon +++ b/toolchain/parse/testdata/packages/import/cpp_inline.carbon @@ -76,17 +76,17 @@ int n; // CHECK:STDOUT: parse_tree: [ // CHECK:STDOUT: {kind: 'FileStart', text: ''}, // CHECK:STDOUT: {kind: 'ImportIntroducer', text: 'import'}, -// CHECK:STDOUT: {kind: 'IdentifierPackageName', text: 'Cpp'}, +// CHECK:STDOUT: {kind: 'CppPackageName', text: 'Cpp'}, // CHECK:STDOUT: {kind: 'InlineImportBody', text: ';', has_error: yes}, // CHECK:STDOUT: {kind: 'InlineImportSpecifier', text: 'inline', subtree_size: 2}, // CHECK:STDOUT: {kind: 'ImportDecl', text: ';', has_error: yes, subtree_size: 5}, // CHECK:STDOUT: {kind: 'ImportIntroducer', text: 'import'}, -// CHECK:STDOUT: {kind: 'IdentifierPackageName', text: 'Cpp'}, +// CHECK:STDOUT: {kind: 'CppPackageName', text: 'Cpp'}, // CHECK:STDOUT: {kind: 'InlineImportBody', text: 'library', has_error: yes}, // CHECK:STDOUT: {kind: 'InlineImportSpecifier', text: 'inline', subtree_size: 2}, // CHECK:STDOUT: {kind: 'ImportDecl', text: ';', has_error: yes, subtree_size: 5}, // CHECK:STDOUT: {kind: 'ImportIntroducer', text: 'import'}, -// CHECK:STDOUT: {kind: 'IdentifierPackageName', text: 'Cpp'}, +// CHECK:STDOUT: {kind: 'CppPackageName', text: 'Cpp'}, // CHECK:STDOUT: {kind: 'LibraryName', text: '"foo.h"'}, // CHECK:STDOUT: {kind: 'LibrarySpecifier', text: 'library', subtree_size: 2}, // CHECK:STDOUT: {kind: 'ImportDecl', text: ';', has_error: yes, subtree_size: 5}, @@ -100,7 +100,7 @@ int n; // CHECK:STDOUT: parse_tree: [ // CHECK:STDOUT: {kind: 'FileStart', text: ''}, // CHECK:STDOUT: {kind: 'ImportIntroducer', text: 'import'}, -// CHECK:STDOUT: {kind: 'IdentifierPackageName', text: 'Cpp'}, +// CHECK:STDOUT: {kind: 'CppPackageName', text: 'Cpp'}, // CHECK:STDOUT: {kind: 'InlineImportBody', text: '', has_error: yes}, // CHECK:STDOUT: {kind: 'InlineImportSpecifier', text: 'inline', subtree_size: 2}, // CHECK:STDOUT: {kind: 'ImportDecl', text: 'inline', has_error: yes, subtree_size: 5}, @@ -136,12 +136,12 @@ int n; // CHECK:STDOUT: parse_tree: [ // CHECK:STDOUT: {kind: 'FileStart', text: ''}, // CHECK:STDOUT: {kind: 'ImportIntroducer', text: 'import'}, -// CHECK:STDOUT: {kind: 'IdentifierPackageName', text: 'Cpp'}, +// CHECK:STDOUT: {kind: 'CppPackageName', text: 'Cpp'}, // CHECK:STDOUT: {kind: 'InlineImportBody', text: '"int m;"'}, // CHECK:STDOUT: {kind: 'InlineImportSpecifier', text: 'inline', subtree_size: 2}, // CHECK:STDOUT: {kind: 'ImportDecl', text: ';', subtree_size: 5}, // CHECK:STDOUT: {kind: 'ImportIntroducer', text: 'import'}, -// CHECK:STDOUT: {kind: 'IdentifierPackageName', text: 'Cpp'}, +// CHECK:STDOUT: {kind: 'CppPackageName', text: 'Cpp'}, // CHECK:STDOUT: {kind: 'InlineImportBody', text: '''' // CHECK:STDOUT: // C++ comment. // CHECK:STDOUT: int n; diff --git a/toolchain/parse/testdata/packages/keyword_names.carbon b/toolchain/parse/testdata/packages/keyword_names.carbon new file mode 100644 index 000000000000..3f58eda2c105 --- /dev/null +++ b/toolchain/parse/testdata/packages/keyword_names.carbon @@ -0,0 +1,40 @@ +// 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 +// +// AUTOUPDATE +// TIP: To test this file alone, run: +// TIP: bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/parse/testdata/packages/keyword_names.carbon +// TIP: To dump output, run: +// TIP: bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/parse/testdata/packages/keyword_names.carbon + +// --- core.carbon + +var x: Core; + +// --- cpp.carbon + +var x: Cpp; + +// CHECK:STDOUT: - filename: core.carbon +// CHECK:STDOUT: parse_tree: [ +// CHECK:STDOUT: {kind: 'FileStart', text: ''}, +// CHECK:STDOUT: {kind: 'VariableIntroducer', text: 'var'}, +// CHECK:STDOUT: {kind: 'IdentifierNameNotBeforeParams', text: 'x'}, +// CHECK:STDOUT: {kind: 'CoreNameExpr', text: 'Core'}, +// CHECK:STDOUT: {kind: 'VarBindingPattern', text: ':', subtree_size: 3}, +// CHECK:STDOUT: {kind: 'VariablePattern', text: 'var', subtree_size: 4}, +// CHECK:STDOUT: {kind: 'VariableDecl', text: ';', subtree_size: 6}, +// CHECK:STDOUT: {kind: 'FileEnd', text: ''}, +// CHECK:STDOUT: ] +// CHECK:STDOUT: - filename: cpp.carbon +// CHECK:STDOUT: parse_tree: [ +// CHECK:STDOUT: {kind: 'FileStart', text: ''}, +// CHECK:STDOUT: {kind: 'VariableIntroducer', text: 'var'}, +// CHECK:STDOUT: {kind: 'IdentifierNameNotBeforeParams', text: 'x'}, +// CHECK:STDOUT: {kind: 'CppNameExpr', text: 'Cpp'}, +// CHECK:STDOUT: {kind: 'VarBindingPattern', text: ':', subtree_size: 3}, +// CHECK:STDOUT: {kind: 'VariablePattern', text: 'var', subtree_size: 4}, +// CHECK:STDOUT: {kind: 'VariableDecl', text: ';', subtree_size: 6}, +// CHECK:STDOUT: {kind: 'FileEnd', text: ''}, +// CHECK:STDOUT: ] diff --git a/toolchain/parse/typed_nodes.h b/toolchain/parse/typed_nodes.h index fa125cba22f1..cd5a18102012 100644 --- a/toolchain/parse/typed_nodes.h +++ b/toolchain/parse/typed_nodes.h @@ -203,13 +203,13 @@ struct DeclName { // Library, package, import, export // -------------------------------- -// The `package` keyword in an expression. -using PackageExpr = - LeafNode; - -// The `Core` keyword in an expression. +// Various keywords in an expression. using CoreNameExpr = LeafNode; +using CppNameExpr = + LeafNode; +using PackageExpr = + LeafNode; // The name of a package or library for `package`, `import`, and `library`. using IdentifierPackageName = @@ -217,6 +217,8 @@ using IdentifierPackageName = NodeCategory::PackageName>; using CorePackageName = LeafNode; +using CppPackageName = LeafNode; using LibraryName = LeafNode; using DefaultLibrary = diff --git a/toolchain/sem_ir/formatter.cpp b/toolchain/sem_ir/formatter.cpp index d791d86db316..7ab977ed9cab 100644 --- a/toolchain/sem_ir/formatter.cpp +++ b/toolchain/sem_ir/formatter.cpp @@ -1255,10 +1255,7 @@ auto Formatter::FormatImportCppDeclRhs() -> void { OpenBrace(); for (const Parse::Tree::PackagingNames& import : sem_ir_->parse_tree().imports()) { - if (auto package_ident_id = import.package_id.AsIdentifierId(); - !package_ident_id.has_value() || - sem_ir_->identifiers().Get(package_ident_id) != - PackageNameId::CppName) { + if (import.package_id != PackageNameId::Cpp) { continue; } diff --git a/toolchain/sem_ir/ids.cpp b/toolchain/sem_ir/ids.cpp index 93f54fdbc9bc..ca0a318858dd 100644 --- a/toolchain/sem_ir/ids.cpp +++ b/toolchain/sem_ir/ids.cpp @@ -162,6 +162,8 @@ auto NameId::ForPackageName(PackageNameId id) -> NameId { return ForIdentifier(identifier_id); } else if (id == PackageNameId::Core) { return NameId::Core; + } else if (id == PackageNameId::Cpp) { + return NameId::Cpp; } else if (!id.has_value()) { return NameId::None; } else { diff --git a/toolchain/sem_ir/ids.h b/toolchain/sem_ir/ids.h index 91a75cebb17c..96020e2604d2 100644 --- a/toolchain/sem_ir/ids.h +++ b/toolchain/sem_ir/ids.h @@ -582,6 +582,8 @@ constexpr FloatKind FloatKind::PPCFloat128 = FloatKind(6); X(ChoiceDiscriminant) \ /* The name of the package `Core`. */ \ X(Core) \ + /* The name of the package `Cpp`. */ \ + X(Cpp) \ /* The name of `package`. */ \ X(PackageNamespace) \ /* The name of `.Self`. */ \ diff --git a/toolchain/sem_ir/name.cpp b/toolchain/sem_ir/name.cpp index 37bb66fd96b4..07bafecf7951 100644 --- a/toolchain/sem_ir/name.cpp +++ b/toolchain/sem_ir/name.cpp @@ -23,6 +23,8 @@ static auto GetSpecialName(NameId name_id, bool for_ir) -> llvm::StringRef { return "discriminant"; case NameId::SpecialNameId::Core: return "Core"; + case NameId::SpecialNameId::Cpp: + return "Cpp"; case NameId::SpecialNameId::PackageNamespace: return "package"; case NameId::SpecialNameId::PeriodSelf: