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 <danakj@orodu.net>
This commit is contained in:
Jon Ross-Perkins
2025-11-05 17:21:41 +00:00
committed by GitHub
co-authored by Dana Jansens
parent ae50e0f623
commit 8166f9a7cf
22 changed files with 162 additions and 100 deletions
+15 -2
View File
@@ -83,7 +83,7 @@ struct PackageNameId : public IdBase<PackageNameId> {
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<PackageNameId> {
// 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<StringLiteralValueId> {
+8 -10
View File
@@ -73,14 +73,7 @@ static auto TrackImport(Map<ImportKey, UnitAndImports*>& 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<ImportKey, UnitAndImports*>& 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);
@@ -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`.
+8
View File
@@ -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
+1
View File
@@ -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:
+29 -29
View File
@@ -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<none>, 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<none>, 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<none>, index: -1, is_template: 0}
// CHECK:STDOUT: entity_name60000001: {name: name00000002, parent_scope: name_scope<none>, index: -1, is_template: 0}
// CHECK:STDOUT: entity_name60000002: {name: name00000002, parent_scope: name_scope<none>, 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<none>, index: -1, is_template: 0}
// CHECK:STDOUT: entity_name60000001: {name: name00000001, parent_scope: name_scope<none>, index: -1, is_template: 0}
// CHECK:STDOUT: entity_name60000002: {name: name00000001, parent_scope: name_scope<none>, 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<none>, base_id: inst<none>, complete_type_witness_id: inst60000024, vtable_decl_id: inst<none>}}
// 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<none>, base_id: inst<none>, complete_type_witness_id: inst60000024, vtable_decl_id: inst<none>}}
// 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<none>, 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<none>, type: type(TypeType)}
// CHECK:STDOUT: inst60000014: {kind: ClassType, arg0: class60000000, arg1: specific<none>, 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<none>, 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<none>, 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<none>, 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<none>, 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<none>, 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<none>, 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)}
@@ -1687,7 +1687,6 @@ fn Call(var instance: Cpp.PublicPrivate) {
// CHECK:STDOUT:
// CHECK:STDOUT: !members:
// CHECK:STDOUT: .Self = constants.%Derived
// CHECK:STDOUT: .Cpp = <poisoned>
// CHECK:STDOUT: .base = %.loc7
// CHECK:STDOUT: .F = %Derived.F.decl
// CHECK:STDOUT: .instance_data = <poisoned>
@@ -1819,7 +1818,6 @@ fn Call(var instance: Cpp.PublicPrivate) {
// CHECK:STDOUT:
// CHECK:STDOUT: !members:
// CHECK:STDOUT: .Self = constants.%Derived
// CHECK:STDOUT: .Cpp = <poisoned>
// CHECK:STDOUT: .base = %.loc7
// CHECK:STDOUT: .F = %Derived.F.decl
// CHECK:STDOUT: .instance_fn = <poisoned>
@@ -1862,7 +1860,6 @@ fn Call(var instance: Cpp.PublicPrivate) {
// CHECK:STDOUT:
// CHECK:STDOUT: !members:
// CHECK:STDOUT: .Self = constants.%Derived
// CHECK:STDOUT: .Cpp = <poisoned>
// CHECK:STDOUT: .base = %.loc7
// CHECK:STDOUT: .F = %Derived.F.decl
// CHECK:STDOUT: .static_fn = <poisoned>
@@ -2088,7 +2085,6 @@ fn Call(var instance: Cpp.PublicPrivate) {
// CHECK:STDOUT:
// CHECK:STDOUT: !members:
// CHECK:STDOUT: .Self = constants.%D
// CHECK:STDOUT: .Cpp = <poisoned>
// CHECK:STDOUT: .base = %.loc7
// CHECK:STDOUT: .D = <poisoned>
// 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 = <poisoned>
// CHECK:STDOUT: .base = %.loc7
// CHECK:STDOUT: .F = %Derived.F.decl
// CHECK:STDOUT: .Overload = <poisoned>
@@ -2468,7 +2463,6 @@ fn Call(var instance: Cpp.PublicPrivate) {
// CHECK:STDOUT:
// CHECK:STDOUT: !members:
// CHECK:STDOUT: .Self = constants.%Derived
// CHECK:STDOUT: .Cpp = <poisoned>
// CHECK:STDOUT: .base = %.loc7
// CHECK:STDOUT: .F = %Derived.F.decl
// CHECK:STDOUT: .Overload = <poisoned>
@@ -2581,7 +2575,6 @@ fn Call(var instance: Cpp.PublicPrivate) {
// CHECK:STDOUT:
// CHECK:STDOUT: !members:
// CHECK:STDOUT: .Self = constants.%Derived
// CHECK:STDOUT: .Cpp = <poisoned>
// 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 = <poisoned>
// 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 = <poisoned>
// 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 = <poisoned>
// CHECK:STDOUT: .base = %.loc7
// CHECK:STDOUT: .CallStatic = %Derived.CallStatic.decl
// CHECK:STDOUT: .CallInstance = %Derived.CallInstance.decl
@@ -553,7 +553,6 @@ fn MyF(bar: Cpp.Bar*);
// CHECK:STDOUT:
// CHECK:STDOUT: !members:
// CHECK:STDOUT: .Self = constants.%Derived
// CHECK:STDOUT: .Cpp = <poisoned>
// CHECK:STDOUT: .base = %.loc8
// CHECK:STDOUT: .foo = <poisoned>
// CHECK:STDOUT: extend %Bar.ref
+19 -23
View File
@@ -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> = namespace [concrete] {
// CHECK:STDOUT: .Cpp = %Cpp
// CHECK:STDOUT: }
// CHECK:STDOUT: %Cpp: <namespace> = namespace [concrete] {}
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: --- alias.carbon
// CHECK:STDOUT:
// CHECK:STDOUT: imports {
@@ -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> = namespace [concrete] {}
// CHECK:STDOUT: %Cpp.import = import Cpp
// CHECK:STDOUT: %default.import = import <none>
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: --- fail_raw_cpp.carbon
// CHECK:STDOUT: --- raw_cpp.carbon
// CHECK:STDOUT:
// CHECK:STDOUT: file {
// CHECK:STDOUT: package: <namespace> = namespace [concrete] {}
+1
View File
@@ -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")
+1 -1
View File
@@ -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) { \
+5
View File
@@ -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);
@@ -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`");
+2
View File
@@ -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)
+6 -6
View File
@@ -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;
+40
View File
@@ -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: ]
+7 -5
View File
@@ -203,13 +203,13 @@ struct DeclName {
// Library, package, import, export
// --------------------------------
// The `package` keyword in an expression.
using PackageExpr =
LeafNode<NodeKind::PackageExpr, Lex::PackageTokenIndex, NodeCategory::Expr>;
// The `Core` keyword in an expression.
// Various keywords in an expression.
using CoreNameExpr =
LeafNode<NodeKind::CoreNameExpr, Lex::CoreTokenIndex, NodeCategory::Expr>;
using CppNameExpr =
LeafNode<NodeKind::CppNameExpr, Lex::CppTokenIndex, NodeCategory::Expr>;
using PackageExpr =
LeafNode<NodeKind::PackageExpr, Lex::PackageTokenIndex, NodeCategory::Expr>;
// 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<NodeKind::CorePackageName, Lex::CoreTokenIndex,
NodeCategory::PackageName>;
using CppPackageName = LeafNode<NodeKind::CppPackageName, Lex::CppTokenIndex,
NodeCategory::PackageName>;
using LibraryName =
LeafNode<NodeKind::LibraryName, Lex::StringLiteralTokenIndex>;
using DefaultLibrary =
+1 -4
View File
@@ -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;
}
+2
View File
@@ -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 {
+2
View File
@@ -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`. */ \
+2
View File
@@ -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: