From 807a3f1370780f701cea6a3fce324bc944eb55b6 Mon Sep 17 00:00:00 2001 From: Jon Ross-Perkins Date: Wed, 5 Jun 2024 17:19:56 -0700 Subject: [PATCH] Add namespace-scoped private keyword support. (#4026) Adds access to the name lookup table in name scopes. This is so that we can quickly check access during name lookup without resolving the entity itself. Does this for names in general, but does not implement handling for entity-scoped names, only namespace-scoped names (where they're essentially just not exported). Excludes `private` names from exports. Although names should be accessible to `impl` files, that's not implemented here because we'll probably want to do it by directly copying name lookup tables. --- toolchain/check/BUILD | 1 + toolchain/check/context.cpp | 21 +- toolchain/check/decl_name_stack.cpp | 22 +- toolchain/check/decl_name_stack.h | 10 +- toolchain/check/handle_alias.cpp | 7 +- toolchain/check/handle_class.cpp | 25 +- toolchain/check/handle_export.cpp | 4 +- toolchain/check/handle_function.cpp | 9 +- toolchain/check/handle_interface.cpp | 13 +- toolchain/check/handle_let.cpp | 23 +- toolchain/check/handle_namespace.cpp | 5 +- toolchain/check/handle_variable.cpp | 50 +- toolchain/check/import.cpp | 28 +- toolchain/check/import_ref.cpp | 8 +- toolchain/check/keyword_modifier_set.h | 12 + toolchain/check/merge.cpp | 2 +- .../alias/no_prelude/fail_todo_private.carbon | 38 -- .../alias/no_prelude/import_access.carbon | 153 ++++++ .../testdata/class/fail_modifiers.carbon | 12 +- .../testdata/class/fail_todo_modifiers.carbon | 42 +- .../class/no_prelude/import_access.carbon | 448 ++++++++++++++++ .../no_prelude/fail_modifiers.carbon | 6 +- .../no_prelude/fail_todo_modifiers.carbon | 32 -- .../function/definition/import_access.carbon | 479 ++++++++++++++++++ .../no_prelude/fail_todo_modifiers.carbon | 29 +- .../interface/no_prelude/import_access.carbon | 463 +++++++++++++++++ .../testdata/let/fail_todo_modifiers.carbon | 39 -- .../let/no_prelude/import_access.carbon | 120 +++++ .../var/no_prelude/fail_modifiers.carbon | 18 +- .../var/no_prelude/fail_todo_modifiers.carbon | 31 -- .../var/no_prelude/import_access.carbon | 155 ++++++ toolchain/sem_ir/formatter.cpp | 26 +- toolchain/sem_ir/name_scope.h | 26 +- 33 files changed, 2022 insertions(+), 335 deletions(-) delete mode 100644 toolchain/check/testdata/alias/no_prelude/fail_todo_private.carbon create mode 100644 toolchain/check/testdata/alias/no_prelude/import_access.carbon create mode 100644 toolchain/check/testdata/class/no_prelude/import_access.carbon delete mode 100644 toolchain/check/testdata/function/declaration/no_prelude/fail_todo_modifiers.carbon create mode 100644 toolchain/check/testdata/function/definition/import_access.carbon create mode 100644 toolchain/check/testdata/interface/no_prelude/import_access.carbon delete mode 100644 toolchain/check/testdata/let/fail_todo_modifiers.carbon create mode 100644 toolchain/check/testdata/let/no_prelude/import_access.carbon delete mode 100644 toolchain/check/testdata/var/no_prelude/fail_todo_modifiers.carbon create mode 100644 toolchain/check/testdata/var/no_prelude/import_access.carbon diff --git a/toolchain/check/BUILD b/toolchain/check/BUILD index cfc315d75bdf..5ed3672e2953 100644 --- a/toolchain/check/BUILD +++ b/toolchain/check/BUILD @@ -133,6 +133,7 @@ cc_library( "//toolchain/base:pretty_stack_trace_function", "//toolchain/base:value_store", "//toolchain/diagnostics:diagnostic_emitter", + "//toolchain/lex:token_index", "//toolchain/lex:token_kind", "//toolchain/lex:tokenized_buffer", "//toolchain/parse:node_kind", diff --git a/toolchain/check/context.cpp b/toolchain/check/context.cpp index d9d8cffec204..5ffdeed0bffd 100644 --- a/toolchain/check/context.cpp +++ b/toolchain/check/context.cpp @@ -26,6 +26,7 @@ #include "toolchain/sem_ir/import_ir.h" #include "toolchain/sem_ir/inst.h" #include "toolchain/sem_ir/inst_kind.h" +#include "toolchain/sem_ir/name_scope.h" #include "toolchain/sem_ir/typed_insts.h" namespace Carbon::Check { @@ -321,12 +322,18 @@ static auto LookupInImportIRScopes(Context& context, SemIRLoc loc, // Name doesn't exist in the import scope. continue; } - if (import_ir.sem_ir->insts().Is(it->second)) { + auto import_inst = import_ir.sem_ir->insts().Get(it->second.inst_id); + if (import_inst.Is()) { // This entity was added to name lookup by using an import, and is not // exported. continue; } + if (it->second.access_kind != SemIR::AccessKind::Public) { + // Ignore cross-package non-public names. + continue; + } + if (result_id.is_valid()) { // On a conflict, we verify the canonical instruction is the same. if (!canonical_result_inst) { @@ -335,16 +342,16 @@ static auto LookupInImportIRScopes(Context& context, SemIRLoc loc, } VerifySameCanonicalImportIRInst(context, result_id, *canonical_result_inst, import_ir_id, - import_ir.sem_ir, it->second); + import_ir.sem_ir, it->second.inst_id); } else { // Add the first result found. auto bind_name_id = context.bind_names().Add( {.name_id = name_id, .parent_scope_id = scope_id, .bind_index = SemIR::CompileTimeBindIndex::Invalid}); - result_id = - AddImportRef(context, {.ir_id = import_ir_id, .inst_id = it->second}, - bind_name_id); + result_id = AddImportRef( + context, {.ir_id = import_ir_id, .inst_id = it->second.inst_id}, + bind_name_id); LoadImportRef(context, result_id); } } @@ -357,8 +364,8 @@ auto Context::LookupNameInExactScope(SemIRLoc loc, SemIR::NameId name_id, const SemIR::NameScope& scope) -> SemIR::InstId { if (auto it = scope.names.find(name_id); it != scope.names.end()) { - LoadImportRef(*this, it->second); - return it->second; + LoadImportRef(*this, it->second.inst_id); + return it->second.inst_id; } if (!scope.import_ir_scopes.empty()) { return LookupInImportIRScopes(*this, loc, name_id, scope_id, scope); diff --git a/toolchain/check/decl_name_stack.cpp b/toolchain/check/decl_name_stack.cpp index 1648d6588235..9c2b69edefdf 100644 --- a/toolchain/check/decl_name_stack.cpp +++ b/toolchain/check/decl_name_stack.cpp @@ -11,6 +11,7 @@ #include "toolchain/check/name_component.h" #include "toolchain/diagnostics/diagnostic.h" #include "toolchain/sem_ir/ids.h" +#include "toolchain/sem_ir/name_scope.h" namespace Carbon::Check { @@ -114,8 +115,8 @@ auto DeclNameStack::Restore(SuspendedName sus) -> void { } } -auto DeclNameStack::AddName(NameContext name_context, SemIR::InstId target_id) - -> void { +auto DeclNameStack::AddName(NameContext name_context, SemIR::InstId target_id, + SemIR::AccessKind access_kind) -> void { switch (name_context.state) { case NameContext::State::Error: return; @@ -141,12 +142,14 @@ auto DeclNameStack::AddName(NameContext name_context, SemIR::InstId target_id) // Exports are only tracked when the declaration is at the file-level // scope. Otherwise, it's in some other entity, such as a class. - if (name_context.initial_scope_index == ScopeIndex::Package) { + if (access_kind == SemIR::AccessKind::Public && + name_context.initial_scope_index == ScopeIndex::Package) { context_->AddExport(target_id); } auto [_, success] = name_scope.names.insert( - {name_context.unresolved_name_id, target_id}); + {name_context.unresolved_name_id, + {.inst_id = target_id, .access_kind = access_kind}}); CARBON_CHECK(success) << "Duplicate names should have been resolved previously: " << name_context.unresolved_name_id << " in " @@ -161,21 +164,24 @@ auto DeclNameStack::AddName(NameContext name_context, SemIR::InstId target_id) } auto DeclNameStack::AddNameOrDiagnoseDuplicate(NameContext name_context, - SemIR::InstId target_id) + SemIR::InstId target_id, + SemIR::AccessKind access_kind) -> void { if (auto id = name_context.prev_inst_id(); id.is_valid()) { context_->DiagnoseDuplicateName(target_id, id); } else { - AddName(name_context, target_id); + AddName(name_context, target_id, access_kind); } } auto DeclNameStack::LookupOrAddName(NameContext name_context, - SemIR::InstId target_id) -> SemIR::InstId { + SemIR::InstId target_id, + SemIR::AccessKind access_kind) + -> SemIR::InstId { if (auto id = name_context.prev_inst_id(); id.is_valid()) { return id; } - AddName(name_context, target_id); + AddName(name_context, target_id, access_kind); return SemIR::InstId::Invalid; } diff --git a/toolchain/check/decl_name_stack.h b/toolchain/check/decl_name_stack.h index 8daef64e361a..eaa8da479605 100644 --- a/toolchain/check/decl_name_stack.h +++ b/toolchain/check/decl_name_stack.h @@ -207,16 +207,18 @@ class DeclNameStack { auto Restore(SuspendedName sus) -> void; // Adds a name to name lookup. Assumes duplicates are already handled. - auto AddName(NameContext name_context, SemIR::InstId target_id) -> void; + auto AddName(NameContext name_context, SemIR::InstId target_id, + SemIR::AccessKind access_kind) -> void; // Adds a name to name lookup. Prints a diagnostic for name conflicts. auto AddNameOrDiagnoseDuplicate(NameContext name_context, - SemIR::InstId target_id) -> void; + SemIR::InstId target_id, + SemIR::AccessKind access_kind) -> void; // Adds a name to name lookup, or returns the existing instruction if this // name has already been declared in this scope. - auto LookupOrAddName(NameContext name_context, SemIR::InstId target_id) - -> SemIR::InstId; + auto LookupOrAddName(NameContext name_context, SemIR::InstId target_id, + SemIR::AccessKind access_kind) -> SemIR::InstId; private: // Returns a name context corresponding to an empty name. diff --git a/toolchain/check/handle_alias.cpp b/toolchain/check/handle_alias.cpp index 51c699c45910..95ab8c29afcb 100644 --- a/toolchain/check/handle_alias.cpp +++ b/toolchain/check/handle_alias.cpp @@ -33,10 +33,6 @@ auto HandleAlias(Context& context, Parse::AliasId /*node_id*/) -> bool { auto introducer = context.decl_introducer_state_stack().Pop(); LimitModifiersOnDecl(context, introducer, KeywordModifierSet::Access); - if (introducer.modifier_set.HasAnyOf(KeywordModifierSet::Access)) { - context.TODO(introducer.modifier_node_id(ModifierOrder::Access), - "access modifier"); - } auto bind_name_id = context.bind_names().Add( {.name_id = name_context.name_id_for_new_inst(), @@ -70,7 +66,8 @@ auto HandleAlias(Context& context, Parse::AliasId /*node_id*/) -> bool { // Add the name of the binding to the current scope. context.decl_name_stack().PopScope(); - context.decl_name_stack().AddNameOrDiagnoseDuplicate(name_context, alias_id); + context.decl_name_stack().AddNameOrDiagnoseDuplicate( + name_context, alias_id, introducer.modifier_set.GetAccessKind()); return true; } diff --git a/toolchain/check/handle_class.cpp b/toolchain/check/handle_class.cpp index a1c440bec4d6..8f1fefd7be15 100644 --- a/toolchain/check/handle_class.cpp +++ b/toolchain/check/handle_class.cpp @@ -117,9 +117,10 @@ static auto MergeOrAddName(Context& context, Parse::AnyClassDeclId node_id, SemIR::InstId class_decl_id, SemIR::ClassDecl& class_decl, SemIR::Class& class_info, bool is_definition, - bool is_extern) -> void { - auto prev_id = - context.decl_name_stack().LookupOrAddName(name_context, class_decl_id); + bool is_extern, SemIR::AccessKind access_kind) + -> void { + auto prev_id = context.decl_name_stack().LookupOrAddName( + name_context, class_decl_id, access_kind); if (!prev_id.is_valid()) { return; } @@ -173,6 +174,7 @@ static auto MergeOrAddName(Context& context, Parse::AnyClassDeclId node_id, prev_import_ir_id)) { // When merging, use the existing entity rather than adding a new one. class_decl.class_id = prev_class_id; + // TODO: Validate that the redeclaration doesn't set an access modifier. } } @@ -196,11 +198,6 @@ static auto BuildClassDecl(Context& context, Parse::AnyClassDeclId node_id, RestrictExternModifierOnDecl(context, introducer, parent_scope_inst, is_definition); - if (introducer.modifier_set.HasAnyOf(KeywordModifierSet::Access)) { - context.TODO(introducer.modifier_node_id(ModifierOrder::Access), - "access modifier"); - } - bool is_extern = introducer.modifier_set.HasAnyOf(KeywordModifierSet::Extern); auto inheritance_kind = introducer.modifier_set.HasAnyOf(KeywordModifierSet::Abstract) @@ -230,7 +227,8 @@ static auto BuildClassDecl(Context& context, Parse::AnyClassDeclId node_id, .inheritance_kind = inheritance_kind}; MergeOrAddName(context, node_id, name_context, class_decl_id, class_decl, - class_info, is_definition, is_extern); + class_info, is_definition, is_extern, + introducer.modifier_set.GetAccessKind()); // Create a new class if this isn't a valid redeclaration. bool is_new_class = !class_decl.class_id.is_valid(); @@ -289,10 +287,9 @@ auto HandleClassDefinitionStart(Context& context, context.scope_stack().Push(class_decl_id, class_info.scope_id); // Introduce `Self`. - context.name_scopes() - .Get(class_info.scope_id) - .names.insert({SemIR::NameId::SelfType, - context.types().GetInstId(class_info.self_type_id)}); + context.name_scopes().AddRequiredName( + class_info.scope_id, SemIR::NameId::SelfType, + context.types().GetInstId(class_info.self_type_id)); context.inst_block_stack().Push(); context.node_stack().Push(node_id, class_id); @@ -541,7 +538,7 @@ auto HandleBaseDecl(Context& context, Parse::BaseDeclId node_id) -> bool { context.decl_name_stack().AddNameOrDiagnoseDuplicate( context.decl_name_stack().MakeUnqualifiedName(node_id, SemIR::NameId::Base), - class_info.base_id); + class_info.base_id, introducer.modifier_set.GetAccessKind()); // Extend the class scope with the base class. if (introducer.modifier_set.HasAnyOf(KeywordModifierSet::Extend)) { diff --git a/toolchain/check/handle_export.cpp b/toolchain/check/handle_export.cpp index d583554415fb..cbedfa3f9159 100644 --- a/toolchain/check/handle_export.cpp +++ b/toolchain/check/handle_export.cpp @@ -79,8 +79,8 @@ auto HandleExportDecl(Context& context, Parse::ExportDeclId node_id) -> bool { auto bind_name = context.bind_names().Get(import_ref->bind_name_id); auto& names = context.name_scopes().Get(bind_name.parent_scope_id).names; auto it = names.find(bind_name.name_id); - CARBON_CHECK(it->second == inst_id); - it->second = export_id; + CARBON_CHECK(it->second.inst_id == inst_id); + it->second.inst_id = export_id; return true; } diff --git a/toolchain/check/handle_function.cpp b/toolchain/check/handle_function.cpp index 8d1d1a1e546f..c680006db464 100644 --- a/toolchain/check/handle_function.cpp +++ b/toolchain/check/handle_function.cpp @@ -228,10 +228,6 @@ static auto BuildFunctionDecl(Context& context, context.decl_introducer_state_stack().Pop(); DiagnoseModifiers(context, introducer, is_definition, parent_scope_inst_id, parent_scope_inst); - if (introducer.modifier_set.HasAnyOf(KeywordModifierSet::Access)) { - context.TODO(introducer.modifier_node_id(ModifierOrder::Access), - "access modifier"); - } bool is_extern = introducer.modifier_set.HasAnyOf(KeywordModifierSet::Extern); if (introducer.modifier_set.HasAnyOf(KeywordModifierSet::Method)) { context.TODO(introducer.modifier_node_id(ModifierOrder::Decl), @@ -268,6 +264,8 @@ static auto BuildFunctionDecl(Context& context, // Create a new function if this isn't a valid redeclaration. if (!function_decl.function_id.is_valid()) { function_decl.function_id = context.functions().Add(function_info); + } else { + // TODO: Validate that the redeclaration doesn't set an access modifier. } function_decl.type_id = context.GetFunctionType(function_decl.function_id); @@ -288,7 +286,8 @@ static auto BuildFunctionDecl(Context& context, } } - context.decl_name_stack().AddName(name_context, lookup_result_id); + context.decl_name_stack().AddName(name_context, lookup_result_id, + introducer.modifier_set.GetAccessKind()); } if (SemIR::IsEntryPoint(context.sem_ir(), function_decl.function_id)) { diff --git a/toolchain/check/handle_interface.cpp b/toolchain/check/handle_interface.cpp index a1a8581111c7..0b38e1a52d24 100644 --- a/toolchain/check/handle_interface.cpp +++ b/toolchain/check/handle_interface.cpp @@ -41,11 +41,6 @@ static auto BuildInterfaceDecl(Context& context, CheckAccessModifiersOnDecl(context, introducer, parent_scope_inst); LimitModifiersOnDecl(context, introducer, KeywordModifierSet::Access); - if (introducer.modifier_set.HasAnyOf(KeywordModifierSet::Access)) { - context.TODO(introducer.modifier_node_id(ModifierOrder::Access), - "access modifier"); - } - auto decl_block_id = context.inst_block_stack().Pop(); // Add the interface declaration. @@ -56,7 +51,7 @@ static auto BuildInterfaceDecl(Context& context, // Check whether this is a redeclaration. auto existing_id = context.decl_name_stack().LookupOrAddName( - name_context, interface_decl_id); + name_context, interface_decl_id, introducer.modifier_set.GetAccessKind()); if (existing_id.is_valid()) { if (auto existing_interface_decl = context.insts().Get(existing_id).TryAs()) { @@ -160,9 +155,9 @@ auto HandleInterfaceDefinitionStart(Context& context, SemIR::LocId::Invalid, {.type_id = self_type_id, .bind_name_id = bind_name_id, .value_id = SemIR::InstId::Invalid}); - context.name_scopes() - .Get(interface_info.scope_id) - .names.insert({SemIR::NameId::SelfType, interface_info.self_param_id}); + context.name_scopes().AddRequiredName(interface_info.scope_id, + SemIR::NameId::SelfType, + interface_info.self_param_id); } // TODO: Handle the case where there's control flow in the interface body. For diff --git a/toolchain/check/handle_let.cpp b/toolchain/check/handle_let.cpp index f86e5049cf51..647e090ad349 100644 --- a/toolchain/check/handle_let.cpp +++ b/toolchain/check/handle_let.cpp @@ -9,6 +9,7 @@ #include "toolchain/check/modifiers.h" #include "toolchain/diagnostics/diagnostic_emitter.h" #include "toolchain/sem_ir/inst.h" +#include "toolchain/sem_ir/name_scope.h" #include "toolchain/sem_ir/typed_insts.h" namespace Carbon::Check { @@ -27,9 +28,12 @@ auto HandleLetInitializer(Context& context, Parse::LetInitializerId node_id) return true; } -static auto BuildAssociatedConstantDecl( - Context& context, Parse::LetDeclId node_id, SemIR::InstId pattern_id, - SemIR::LocIdAndInst pattern, SemIR::InterfaceId interface_id) -> void { +static auto BuildAssociatedConstantDecl(Context& context, + Parse::LetDeclId node_id, + SemIR::InstId pattern_id, + SemIR::LocIdAndInst pattern, + SemIR::InterfaceId interface_id, + SemIR::AccessKind access_kind) -> void { auto& interface_info = context.interfaces().Get(interface_id); auto binding_pattern = pattern.inst.TryAs(); @@ -58,7 +62,8 @@ static auto BuildAssociatedConstantDecl( auto assoc_id = BuildAssociatedEntity(context, interface_id, decl_id); auto name_context = context.decl_name_stack().MakeUnqualifiedName(pattern.loc_id, name_id); - context.decl_name_stack().AddNameOrDiagnoseDuplicate(name_context, assoc_id); + context.decl_name_stack().AddNameOrDiagnoseDuplicate(name_context, assoc_id, + access_kind); } auto HandleLetDecl(Context& context, Parse::LetDeclId node_id) -> bool { @@ -90,10 +95,6 @@ auto HandleLetDecl(Context& context, Parse::LetDeclId node_id) -> bool { context, introducer, KeywordModifierSet::Access | KeywordModifierSet::Interface); - if (introducer.modifier_set.HasAnyOf(KeywordModifierSet::Access)) { - context.TODO(introducer.modifier_node_id(ModifierOrder::Access), - "access modifier"); - } if (introducer.modifier_set.HasAnyOf(KeywordModifierSet::Interface)) { context.TODO(introducer.modifier_node_id(ModifierOrder::Decl), "interface modifier"); @@ -112,7 +113,8 @@ auto HandleLetDecl(Context& context, Parse::LetDeclId node_id) -> bool { // different rules. if (interface_scope) { BuildAssociatedConstantDecl(context, node_id, pattern_id, pattern, - interface_scope->interface_id); + interface_scope->interface_id, + introducer.modifier_set.GetAccessKind()); return true; } @@ -137,7 +139,8 @@ auto HandleLetDecl(Context& context, Parse::LetDeclId node_id) -> bool { // Add the name of the binding to the current scope. auto name_id = context.bind_names().Get(bind_name.bind_name_id).name_id; context.AddNameToLookup(name_id, pattern_id); - if (parent_scope_inst_id == SemIR::InstId::PackageNamespace) { + if (parent_scope_inst_id == SemIR::InstId::PackageNamespace && + introducer.modifier_set.GetAccessKind() == SemIR::AccessKind::Public) { context.AddExport(pattern_id); } return true; diff --git a/toolchain/check/handle_namespace.cpp b/toolchain/check/handle_namespace.cpp index 45fdb427f750..0d486ee59f6d 100644 --- a/toolchain/check/handle_namespace.cpp +++ b/toolchain/check/handle_namespace.cpp @@ -9,6 +9,7 @@ #include "toolchain/check/name_component.h" #include "toolchain/sem_ir/ids.h" #include "toolchain/sem_ir/inst.h" +#include "toolchain/sem_ir/name_scope.h" namespace Carbon::Check { @@ -38,8 +39,8 @@ auto HandleNamespace(Context& context, Parse::NamespaceId node_id) -> bool { name_context.parent_scope_id_for_new_inst()); context.ReplaceInstBeforeConstantUse(namespace_id, namespace_inst); - auto existing_inst_id = - context.decl_name_stack().LookupOrAddName(name_context, namespace_id); + auto existing_inst_id = context.decl_name_stack().LookupOrAddName( + name_context, namespace_id, SemIR::AccessKind::Public); if (existing_inst_id.is_valid()) { // If there's a name conflict with a namespace, "merge" by using the // previous declaration. Otherwise, diagnose the issue. diff --git a/toolchain/check/handle_variable.cpp b/toolchain/check/handle_variable.cpp index 03791c82daac..007265f40dae 100644 --- a/toolchain/check/handle_variable.cpp +++ b/toolchain/check/handle_variable.cpp @@ -6,6 +6,7 @@ #include "toolchain/check/convert.h" #include "toolchain/check/handle.h" #include "toolchain/check/modifiers.h" +#include "toolchain/lex/token_index.h" namespace Carbon::Check { @@ -50,31 +51,45 @@ auto HandleVariableDecl(Context& context, Parse::VariableDeclId node_id) return context.TODO(node_id, "tuple pattern in var"); } - // Extract the name binding. auto value_id = context.node_stack().PopPattern(); + + // Pop the `returned` specifier if present. + context.node_stack() + .PopAndDiscardSoloNodeIdIf(); + + context.node_stack() + .PopAndDiscardSoloNodeId(); + + // Process declaration modifiers. + // TODO: For a qualified `var` declaration, this should use the target scope + // of the name introduced in the declaration. See #2590. + auto [_, parent_scope_inst] = context.name_scopes().GetInstIfValid( + context.scope_stack().PeekNameScopeId()); + auto introducer = + context.decl_introducer_state_stack().Pop(); + CheckAccessModifiersOnDecl(context, introducer, parent_scope_inst); + LimitModifiersOnDecl(context, introducer, KeywordModifierSet::Access); + + // Extract the name binding. if (auto bind_name = context.insts().TryGetAs(value_id)) { // Form a corresponding name in the current context, and bind the name to // the variable. auto name_context = context.decl_name_stack().MakeUnqualifiedName( context.insts().GetLocId(value_id), context.bind_names().Get(bind_name->bind_name_id).name_id); - context.decl_name_stack().AddNameOrDiagnoseDuplicate(name_context, - value_id); + context.decl_name_stack().AddNameOrDiagnoseDuplicate( + name_context, value_id, introducer.modifier_set.GetAccessKind()); value_id = bind_name->value_id; } else if (auto field_decl = context.insts().TryGetAs(value_id)) { // Introduce the field name into the class. auto name_context = context.decl_name_stack().MakeUnqualifiedName( context.insts().GetLocId(value_id), field_decl->name_id); - context.decl_name_stack().AddNameOrDiagnoseDuplicate(name_context, - value_id); + context.decl_name_stack().AddNameOrDiagnoseDuplicate( + name_context, value_id, introducer.modifier_set.GetAccessKind()); } // TODO: Handle other kinds of pattern. - // Pop the `returned` specifier if present. - context.node_stack() - .PopAndDiscardSoloNodeIdIf(); - // If there was an initializer, assign it to the storage. if (init_id) { if (context.GetCurrentScopeAs()) { @@ -93,23 +108,6 @@ auto HandleVariableDecl(Context& context, Parse::VariableDeclId node_id) } } - context.node_stack() - .PopAndDiscardSoloNodeId(); - - // Process declaration modifiers. - // TODO: For a qualified `var` declaration, this should use the target scope - // of the name introduced in the declaration. See #2590. - auto [_, parent_scope_inst] = context.name_scopes().GetInstIfValid( - context.scope_stack().PeekNameScopeId()); - auto introducer = - context.decl_introducer_state_stack().Pop(); - CheckAccessModifiersOnDecl(context, introducer, parent_scope_inst); - LimitModifiersOnDecl(context, introducer, KeywordModifierSet::Access); - if (introducer.modifier_set.HasAnyOf(KeywordModifierSet::Access)) { - context.TODO(introducer.modifier_node_id(ModifierOrder::Access), - "access modifier"); - } - return true; } diff --git a/toolchain/check/import.cpp b/toolchain/check/import.cpp index b32c0ab3565e..708f96bf3d64 100644 --- a/toolchain/check/import.cpp +++ b/toolchain/check/import.cpp @@ -86,15 +86,17 @@ static auto AddNamespace( -> std::tuple { auto& parent_scope = context.name_scopes().Get(parent_scope_id); auto [it, success] = - parent_scope.names.insert({name_id, SemIR::InstId::Invalid}); + parent_scope.names.insert({name_id, + {.inst_id = SemIR::InstId::Invalid, + .access_kind = SemIR::AccessKind::Public}}); if (!success) { if (auto namespace_inst = - context.insts().TryGetAs(it->second)) { + context.insts().TryGetAs(it->second.inst_id)) { if (diagnose_duplicate_namespace) { - context.DiagnoseDuplicateName(node_id, it->second); + context.DiagnoseDuplicateName(node_id, it->second.inst_id); } return {namespace_inst->name_scope_id, - context.constant_values().Get(it->second), true}; + context.constant_values().Get(it->second.inst_id), true}; } } @@ -112,10 +114,11 @@ static auto AddNamespace( // Diagnose if there's a name conflict, but still produce the namespace to // supersede the name conflict in order to avoid repeat diagnostics. if (!success) { - context.DiagnoseDuplicateName(namespace_id, it->second); + context.DiagnoseDuplicateName(namespace_id, it->second.inst_id); } - it->second = namespace_id; + it->second = {.inst_id = namespace_id, + .access_kind = SemIR::AccessKind::Public}; return {namespace_inst.name_scope_id, context.constant_values().Get(namespace_id), false}; } @@ -222,21 +225,24 @@ static auto AddImportRefOrMerge(Context& context, SemIR::ImportIRId ir_id, SemIR::NameId name_id) -> void { // Leave a placeholder that the inst comes from the other IR. auto& names = context.name_scopes().Get(parent_scope_id).names; - auto [it, success] = names.insert({name_id, SemIR::InstId::Invalid}); + auto [it, success] = + names.insert({name_id, + {.inst_id = SemIR::InstId::Invalid, + .access_kind = SemIR::AccessKind::Public}}); if (success) { auto bind_name_id = context.bind_names().Add( {.name_id = name_id, .parent_scope_id = parent_scope_id, .bind_index = SemIR::CompileTimeBindIndex::Invalid}); - it->second = AddImportRef( + it->second.inst_id = AddImportRef( context, {.ir_id = ir_id, .inst_id = import_inst_id}, bind_name_id); return; } auto prev_ir_inst = - GetCanonicalImportIRInst(context, &context.sem_ir(), it->second); - VerifySameCanonicalImportIRInst(context, it->second, prev_ir_inst, ir_id, - &import_sem_ir, import_inst_id); + GetCanonicalImportIRInst(context, &context.sem_ir(), it->second.inst_id); + VerifySameCanonicalImportIRInst(context, it->second.inst_id, prev_ir_inst, + ir_id, &import_sem_ir, import_inst_id); } auto ImportLibrariesFromCurrentPackage( diff --git a/toolchain/check/import_ref.cpp b/toolchain/check/import_ref.cpp index b6d8670ec65a..d97907ac726d 100644 --- a/toolchain/check/import_ref.cpp +++ b/toolchain/check/import_ref.cpp @@ -536,12 +536,14 @@ class ImportRefResolver { // lookup. auto AddNameScopeImportRefs(const SemIR::NameScope& import_scope, SemIR::NameScope& new_scope) -> void { - for (auto [entry_name_id, entry_inst_id] : import_scope.names) { + for (auto [entry_name_id, entry] : import_scope.names) { auto ref_id = AddImportRef( - context_, {.ir_id = import_ir_id_, .inst_id = entry_inst_id}, + context_, {.ir_id = import_ir_id_, .inst_id = entry.inst_id}, SemIR::BindNameId::Invalid); CARBON_CHECK( - new_scope.names.insert({GetLocalNameId(entry_name_id), ref_id}) + new_scope.names + .insert({GetLocalNameId(entry_name_id), + {.inst_id = ref_id, .access_kind = entry.access_kind}}) .second); } } diff --git a/toolchain/check/keyword_modifier_set.h b/toolchain/check/keyword_modifier_set.h index de00dca33391..8a77c7784c95 100644 --- a/toolchain/check/keyword_modifier_set.h +++ b/toolchain/check/keyword_modifier_set.h @@ -6,6 +6,7 @@ #define CARBON_TOOLCHAIN_CHECK_KEYWORD_MODIFIER_SET_H_ #include "llvm/ADT/BitmaskEnum.h" +#include "toolchain/sem_ir/name_scope.h" namespace Carbon::Check { @@ -73,6 +74,17 @@ class KeywordModifierSet { return set_ & other.set_; } + // Returns the access kind from modifiers. + auto GetAccessKind() -> SemIR::AccessKind { + if (HasAnyOf(KeywordModifierSet::Protected)) { + return SemIR::AccessKind::Protected; + } + if (HasAnyOf(KeywordModifierSet::Private)) { + return SemIR::AccessKind::Private; + } + return SemIR::AccessKind::Public; + } + // Returns true if empty. constexpr auto empty() -> bool { return !set_; } diff --git a/toolchain/check/merge.cpp b/toolchain/check/merge.cpp index 9df43ebfb7bf..117111b04403 100644 --- a/toolchain/check/merge.cpp +++ b/toolchain/check/merge.cpp @@ -126,7 +126,7 @@ auto ReplacePrevInstForMerge(Context& context, SemIR::NameScopeId scope_id, auto& names = context.name_scopes().Get(scope_id).names; auto it = names.find(name_id); if (it != names.end()) { - it->second = new_inst_id; + it->second.inst_id = new_inst_id; } } diff --git a/toolchain/check/testdata/alias/no_prelude/fail_todo_private.carbon b/toolchain/check/testdata/alias/no_prelude/fail_todo_private.carbon deleted file mode 100644 index 996306802f70..000000000000 --- a/toolchain/check/testdata/alias/no_prelude/fail_todo_private.carbon +++ /dev/null @@ -1,38 +0,0 @@ -// 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/check/testdata/alias/no_prelude/fail_todo_private.carbon -// TIP: To dump output, run: -// TIP: bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/alias/no_prelude/fail_todo_private.carbon - -class C {} -// CHECK:STDERR: fail_todo_private.carbon:[[@LINE+3]]:1: ERROR: Semantics TODO: `access modifier`. -// CHECK:STDERR: private alias A = C; -// CHECK:STDERR: ^~~~~~~ -private alias A = C; - -// CHECK:STDOUT: --- fail_todo_private.carbon -// CHECK:STDOUT: -// CHECK:STDOUT: constants { -// CHECK:STDOUT: %C: type = class_type @C [template] -// CHECK:STDOUT: %.1: type = struct_type {} [template] -// CHECK:STDOUT: } -// CHECK:STDOUT: -// CHECK:STDOUT: file { -// CHECK:STDOUT: package: = namespace [template] { -// CHECK:STDOUT: .C = %C.decl -// CHECK:STDOUT: .A = %A -// CHECK:STDOUT: } -// CHECK:STDOUT: %C.decl: type = class_decl @C [template = constants.%C] {} -// CHECK:STDOUT: %C.ref: type = name_ref C, %C.decl [template = constants.%C] -// CHECK:STDOUT: %A: type = bind_alias A, %C.decl [template = constants.%C] -// CHECK:STDOUT: } -// CHECK:STDOUT: -// CHECK:STDOUT: class @C { -// CHECK:STDOUT: !members: -// CHECK:STDOUT: .Self = constants.%C -// CHECK:STDOUT: } -// CHECK:STDOUT: diff --git a/toolchain/check/testdata/alias/no_prelude/import_access.carbon b/toolchain/check/testdata/alias/no_prelude/import_access.carbon new file mode 100644 index 000000000000..1eb1c2152d4f --- /dev/null +++ b/toolchain/check/testdata/alias/no_prelude/import_access.carbon @@ -0,0 +1,153 @@ +// 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/check/testdata/alias/no_prelude/import_access.carbon +// TIP: To dump output, run: +// TIP: bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/alias/no_prelude/import_access.carbon + +// ============================================================================ +// Setup files +// ============================================================================ + +// --- def.carbon + +package Test library "def"; + +class C {} +private alias A = C; + +// ============================================================================ +// Test files +// ============================================================================ + +// --- fail_todo_def.impl.carbon + +impl package Test library "def"; + +// CHECK:STDERR: fail_todo_def.impl.carbon:[[@LINE+4]]:11: ERROR: Name `A` not found. +// CHECK:STDERR: var inst: A = {}; +// CHECK:STDERR: ^ +// CHECK:STDERR: +var inst: A = {}; + +// --- fail_local_def.carbon + +package Test library "fail_local_def"; + +import library "def"; + +// CHECK:STDERR: fail_local_def.carbon:[[@LINE+4]]:11: ERROR: Name `A` not found. +// CHECK:STDERR: var inst: A = {}; +// CHECK:STDERR: ^ +// CHECK:STDERR: +var inst: A = {}; + +// --- fail_other_def.carbon + +package Other library "fail_other_def"; + +import Test library "def"; + +// CHECK:STDERR: fail_other_def.carbon:[[@LINE+3]]:11: ERROR: Name `A` not found. +// CHECK:STDERR: var inst: Test.A = {}; +// CHECK:STDERR: ^~~~~~ +var inst: Test.A = {}; + +// CHECK:STDOUT: --- def.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %C: type = class_type @C [template] +// CHECK:STDOUT: %.1: type = struct_type {} [template] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .C = %C.decl +// CHECK:STDOUT: .A [private] = %A +// CHECK:STDOUT: } +// CHECK:STDOUT: %C.decl: type = class_decl @C [template = constants.%C] {} +// CHECK:STDOUT: %C.ref: type = name_ref C, %C.decl [template = constants.%C] +// CHECK:STDOUT: %A: type = bind_alias A, %C.decl [template = constants.%C] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: class @C { +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = constants.%C +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: --- fail_todo_def.impl.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %.1: type = struct_type {} [template] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .C = %import_ref +// CHECK:STDOUT: .inst = %inst +// CHECK:STDOUT: } +// CHECK:STDOUT: %import_ref = import_ref ir0, inst+1, unloaded +// CHECK:STDOUT: %A.ref: = name_ref A, [template = ] +// CHECK:STDOUT: %inst.var: ref = var inst +// CHECK:STDOUT: %inst: ref = bind_name inst, %inst.var +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @__global_init() { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %.loc8: {} = struct_literal () +// CHECK:STDOUT: assign file.%inst.var, +// CHECK:STDOUT: return +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: --- fail_local_def.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %.1: type = struct_type {} [template] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .C = %import_ref +// CHECK:STDOUT: .inst = %inst +// CHECK:STDOUT: } +// CHECK:STDOUT: %import_ref = import_ref ir1, inst+1, unloaded +// CHECK:STDOUT: %A.ref: = name_ref A, [template = ] +// CHECK:STDOUT: %inst.var: ref = var inst +// CHECK:STDOUT: %inst: ref = bind_name inst, %inst.var +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @__global_init() { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %.loc10: {} = struct_literal () +// CHECK:STDOUT: assign file.%inst.var, +// CHECK:STDOUT: return +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: --- fail_other_def.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %.1: type = struct_type {} [template] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .Test = %Test +// CHECK:STDOUT: .inst = %inst +// CHECK:STDOUT: } +// CHECK:STDOUT: %Test: = namespace [template] {} +// CHECK:STDOUT: %Test.ref: = name_ref Test, %Test [template = %Test] +// CHECK:STDOUT: %A.ref: = name_ref A, [template = ] +// CHECK:STDOUT: %inst.var: ref = var inst +// CHECK:STDOUT: %inst: ref = bind_name inst, %inst.var +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @__global_init() { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %.loc9: {} = struct_literal () +// CHECK:STDOUT: assign file.%inst.var, +// CHECK:STDOUT: return +// CHECK:STDOUT: } +// CHECK:STDOUT: diff --git a/toolchain/check/testdata/class/fail_modifiers.carbon b/toolchain/check/testdata/class/fail_modifiers.carbon index b4d4bafc1468..79500e00e2a5 100644 --- a/toolchain/check/testdata/class/fail_modifiers.carbon +++ b/toolchain/check/testdata/class/fail_modifiers.carbon @@ -8,10 +8,6 @@ // TIP: To dump output, run: // TIP: bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/class/fail_modifiers.carbon -// CHECK:STDERR: fail_modifiers.carbon:[[@LINE+11]]:1: ERROR: Semantics TODO: `access modifier`. -// CHECK:STDERR: private abstract private class DuplicatePrivate; -// CHECK:STDERR: ^~~~~~~ -// CHECK:STDERR: // CHECK:STDERR: fail_modifiers.carbon:[[@LINE+7]]:18: ERROR: `private` repeated on declaration. // CHECK:STDERR: private abstract private class DuplicatePrivate; // CHECK:STDERR: ^~~~~~~ @@ -21,10 +17,6 @@ // CHECK:STDERR: private abstract private class DuplicatePrivate; -// CHECK:STDERR: fail_modifiers.carbon:[[@LINE+11]]:1: ERROR: Semantics TODO: `access modifier`. -// CHECK:STDERR: private base protected class TwoAccess {} -// CHECK:STDERR: ^~~~~~~ -// CHECK:STDERR: // CHECK:STDERR: fail_modifiers.carbon:[[@LINE+7]]:14: ERROR: `protected` not allowed on declaration with `private`. // CHECK:STDERR: private base protected class TwoAccess {} // CHECK:STDERR: ^~~~~~~~~ @@ -99,8 +91,8 @@ extern class ExternDefined {} // CHECK:STDOUT: file { // CHECK:STDOUT: package: = namespace [template] { // CHECK:STDOUT: .Core = %Core -// CHECK:STDOUT: .DuplicatePrivate = %DuplicatePrivate.decl -// CHECK:STDOUT: .TwoAccess = %TwoAccess.decl +// CHECK:STDOUT: .DuplicatePrivate [private] = %DuplicatePrivate.decl +// CHECK:STDOUT: .TwoAccess [private] = %TwoAccess.decl // CHECK:STDOUT: .TwoAbstract = %TwoAbstract.decl // CHECK:STDOUT: .Virtual = %Virtual.decl // CHECK:STDOUT: .WrongOrder = %WrongOrder.decl diff --git a/toolchain/check/testdata/class/fail_todo_modifiers.carbon b/toolchain/check/testdata/class/fail_todo_modifiers.carbon index da57f89a9935..235fd31418d5 100644 --- a/toolchain/check/testdata/class/fail_todo_modifiers.carbon +++ b/toolchain/check/testdata/class/fail_todo_modifiers.carbon @@ -8,30 +8,14 @@ // TIP: To dump output, run: // TIP: bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/class/fail_todo_modifiers.carbon +// TODO: Test calls to these (member access control is not yet implemented). class Access { - - // CHECK:STDERR: fail_todo_modifiers.carbon:[[@LINE+4]]:3: ERROR: Semantics TODO: `access modifier`. - // CHECK:STDERR: private fn F(); - // CHECK:STDERR: ^~~~~~~ - // CHECK:STDERR: private fn F(); - // CHECK:STDERR: fail_todo_modifiers.carbon:[[@LINE+4]]:3: ERROR: Semantics TODO: `access modifier`. - // CHECK:STDERR: protected fn G(); - // CHECK:STDERR: ^~~~~~~~~ - // CHECK:STDERR: protected fn G(); - // CHECK:STDERR: fail_todo_modifiers.carbon:[[@LINE+4]]:3: ERROR: Semantics TODO: `access modifier`. - // CHECK:STDERR: private var k: i32; - // CHECK:STDERR: ^~~~~~~ - // CHECK:STDERR: private var k: i32; - // CHECK:STDERR: fail_todo_modifiers.carbon:[[@LINE+4]]:3: ERROR: Semantics TODO: `access modifier`. - // CHECK:STDERR: protected var l: i32; - // CHECK:STDERR: ^~~~~~~~~ - // CHECK:STDERR: protected var l: i32; } @@ -116,21 +100,21 @@ abstract class Abstract { // CHECK:STDOUT: class @Access { // CHECK:STDOUT: %F.decl: F = fn_decl @F [template = constants.%struct.1] {} // CHECK:STDOUT: %G.decl: G = fn_decl @G [template = constants.%struct.2] {} -// CHECK:STDOUT: %int.make_type_32.loc29: init type = call constants.%struct.3() [template = i32] -// CHECK:STDOUT: %.loc29_18.1: type = value_of_initializer %int.make_type_32.loc29 [template = i32] -// CHECK:STDOUT: %.loc29_18.2: type = converted %int.make_type_32.loc29, %.loc29_18.1 [template = i32] -// CHECK:STDOUT: %.loc29_16: = field_decl k, element0 [template] -// CHECK:STDOUT: %int.make_type_32.loc35: init type = call constants.%struct.3() [template = i32] -// CHECK:STDOUT: %.loc35_20.1: type = value_of_initializer %int.make_type_32.loc35 [template = i32] -// CHECK:STDOUT: %.loc35_20.2: type = converted %int.make_type_32.loc35, %.loc35_20.1 [template = i32] -// CHECK:STDOUT: %.loc35_18: = field_decl l, element1 [template] +// CHECK:STDOUT: %int.make_type_32.loc17: init type = call constants.%struct.3() [template = i32] +// CHECK:STDOUT: %.loc17_18.1: type = value_of_initializer %int.make_type_32.loc17 [template = i32] +// CHECK:STDOUT: %.loc17_18.2: type = converted %int.make_type_32.loc17, %.loc17_18.1 [template = i32] +// CHECK:STDOUT: %.loc17_16: = field_decl k, element0 [template] +// CHECK:STDOUT: %int.make_type_32.loc19: init type = call constants.%struct.3() [template = i32] +// CHECK:STDOUT: %.loc19_20.1: type = value_of_initializer %int.make_type_32.loc19 [template = i32] +// CHECK:STDOUT: %.loc19_20.2: type = converted %int.make_type_32.loc19, %.loc19_20.1 [template = i32] +// CHECK:STDOUT: %.loc19_18: = field_decl l, element1 [template] // CHECK:STDOUT: // CHECK:STDOUT: !members: // CHECK:STDOUT: .Self = constants.%Access -// CHECK:STDOUT: .F = %F.decl -// CHECK:STDOUT: .G = %G.decl -// CHECK:STDOUT: .k = %.loc29_16 -// CHECK:STDOUT: .l = %.loc35_18 +// CHECK:STDOUT: .F [private] = %F.decl +// CHECK:STDOUT: .G [protected] = %G.decl +// CHECK:STDOUT: .k [private] = %.loc17_16 +// CHECK:STDOUT: .l [protected] = %.loc19_18 // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: class @Base { diff --git a/toolchain/check/testdata/class/no_prelude/import_access.carbon b/toolchain/check/testdata/class/no_prelude/import_access.carbon new file mode 100644 index 000000000000..12a85e13c424 --- /dev/null +++ b/toolchain/check/testdata/class/no_prelude/import_access.carbon @@ -0,0 +1,448 @@ +// 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/check/testdata/class/no_prelude/import_access.carbon +// TIP: To dump output, run: +// TIP: bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/class/no_prelude/import_access.carbon + +// ============================================================================ +// Setup files +// ============================================================================ + +// --- def.carbon + +package Test library "def"; + +private class Def {} + +// --- forward_with_def.carbon + +package Test library "forward_with_def"; + +private class ForwardWithDef; + +class ForwardWithDef {} + +// --- forward.carbon + +package Test library "forward"; + +private class Forward; + +// ============================================================================ +// Test files +// ============================================================================ + +// --- fail_todo_def.impl.carbon + +impl package Test library "def"; + +// CHECK:STDERR: fail_todo_def.impl.carbon:[[@LINE+4]]:8: ERROR: Name `Def` not found. +// CHECK:STDERR: var c: Def = {}; +// CHECK:STDERR: ^~~ +// CHECK:STDERR: +var c: Def = {}; + +// --- fail_local_def.carbon + +package Test library "fail_local_def"; + +import library "def"; + +// CHECK:STDERR: fail_local_def.carbon:[[@LINE+4]]:8: ERROR: Name `Def` not found. +// CHECK:STDERR: var c: Def = {}; +// CHECK:STDERR: ^~~ +// CHECK:STDERR: +var c: Def = {}; + +// --- fail_other_def.carbon + +package Other library "fail_other_def"; + +import Test library "def"; + +// CHECK:STDERR: fail_other_def.carbon:[[@LINE+4]]:8: ERROR: Name `Def` not found. +// CHECK:STDERR: var c: Test.Def = {}; +// CHECK:STDERR: ^~~~~~~~ +// CHECK:STDERR: +var c: Test.Def = {}; + +// --- fail_todo_forward_with_def.impl.carbon + +impl package Test library "forward_with_def"; + +// CHECK:STDERR: fail_todo_forward_with_def.impl.carbon:[[@LINE+4]]:8: ERROR: Name `ForwardWithDef` not found. +// CHECK:STDERR: var c: ForwardWithDef = {}; +// CHECK:STDERR: ^~~~~~~~~~~~~~ +// CHECK:STDERR: +var c: ForwardWithDef = {}; + +// --- fail_local_forward_with_def.carbon + +package Test library "fail_local_forward_with_def"; + +import library "forward_with_def"; + +// CHECK:STDERR: fail_local_forward_with_def.carbon:[[@LINE+4]]:8: ERROR: Name `ForwardWithDef` not found. +// CHECK:STDERR: var c: ForwardWithDef = {}; +// CHECK:STDERR: ^~~~~~~~~~~~~~ +// CHECK:STDERR: +var c: ForwardWithDef = {}; + +// --- fail_other_forward_with_def.carbon + +package Other library "fail_other_forward_with_def"; + +import Test library "forward_with_def"; + +// CHECK:STDERR: fail_other_forward_with_def.carbon:[[@LINE+4]]:8: ERROR: Name `ForwardWithDef` not found. +// CHECK:STDERR: var c: Test.ForwardWithDef = {}; +// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~ +// CHECK:STDERR: +var c: Test.ForwardWithDef = {}; + +// --- fail_todo_forward.impl.carbon + +impl package Test library "forward"; + +// CHECK:STDERR: fail_todo_forward.impl.carbon:[[@LINE+4]]:9: ERROR: Name `Forward` not found. +// CHECK:STDERR: fn F(c: Forward*) {} +// CHECK:STDERR: ^~~~~~~ +// CHECK:STDERR: +fn F(c: Forward*) {} + +class Forward {} + +// --- fail_local_forward.carbon + +package Test library "fail_local_forward"; + +import library "forward"; + +// CHECK:STDERR: fail_local_forward.carbon:[[@LINE+4]]:9: ERROR: Name `Forward` not found. +// CHECK:STDERR: fn F(c: Forward*) {} +// CHECK:STDERR: ^~~~~~~ +// CHECK:STDERR: +fn F(c: Forward*) {} + +// --- fail_other_forward.carbon + +package Other library "fail_other_forward"; + +import Test library "forward"; + +// CHECK:STDERR: fail_other_forward.carbon:[[@LINE+3]]:9: ERROR: Name `Forward` not found. +// CHECK:STDERR: fn F(c: Test.Forward*) {} +// CHECK:STDERR: ^~~~~~~~~~~~ +fn F(c: Test.Forward*) {} + +// --- todo_fail_private_on_redecl.carbon + +library "fail_private_on_redecl"; + +private class Redecl; + +private class Redecl {} + +// CHECK:STDOUT: --- def.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %Def: type = class_type @Def [template] +// CHECK:STDOUT: %.1: type = struct_type {} [template] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .Def [private] = %Def.decl +// CHECK:STDOUT: } +// CHECK:STDOUT: %Def.decl: type = class_decl @Def [template = constants.%Def] {} +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: class @Def { +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = constants.%Def +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: --- forward_with_def.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %ForwardWithDef: type = class_type @ForwardWithDef [template] +// CHECK:STDOUT: %.1: type = struct_type {} [template] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .ForwardWithDef [private] = %ForwardWithDef.decl.loc4 +// CHECK:STDOUT: } +// CHECK:STDOUT: %ForwardWithDef.decl.loc4: type = class_decl @ForwardWithDef [template = constants.%ForwardWithDef] {} +// CHECK:STDOUT: %ForwardWithDef.decl.loc6: type = class_decl @ForwardWithDef [template = constants.%ForwardWithDef] {} +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: class @ForwardWithDef { +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = constants.%ForwardWithDef +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: --- forward.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %Forward: type = class_type @Forward [template] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .Forward [private] = %Forward.decl +// CHECK:STDOUT: } +// CHECK:STDOUT: %Forward.decl: type = class_decl @Forward [template = constants.%Forward] {} +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: class @Forward; +// CHECK:STDOUT: +// CHECK:STDOUT: --- fail_todo_def.impl.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %.1: type = struct_type {} [template] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .c = %c +// CHECK:STDOUT: } +// CHECK:STDOUT: %Def.ref: = name_ref Def, [template = ] +// CHECK:STDOUT: %c.var: ref = var c +// CHECK:STDOUT: %c: ref = bind_name c, %c.var +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @__global_init() { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %.loc8: {} = struct_literal () +// CHECK:STDOUT: assign file.%c.var, +// CHECK:STDOUT: return +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: --- fail_local_def.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %.1: type = struct_type {} [template] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .c = %c +// CHECK:STDOUT: } +// CHECK:STDOUT: %Def.ref: = name_ref Def, [template = ] +// CHECK:STDOUT: %c.var: ref = var c +// CHECK:STDOUT: %c: ref = bind_name c, %c.var +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @__global_init() { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %.loc10: {} = struct_literal () +// CHECK:STDOUT: assign file.%c.var, +// CHECK:STDOUT: return +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: --- fail_other_def.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %.1: type = struct_type {} [template] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .Test = %Test +// CHECK:STDOUT: .c = %c +// CHECK:STDOUT: } +// CHECK:STDOUT: %Test: = namespace [template] {} +// CHECK:STDOUT: %Test.ref: = name_ref Test, %Test [template = %Test] +// CHECK:STDOUT: %Def.ref: = name_ref Def, [template = ] +// CHECK:STDOUT: %c.var: ref = var c +// CHECK:STDOUT: %c: ref = bind_name c, %c.var +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @__global_init() { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %.loc10: {} = struct_literal () +// CHECK:STDOUT: assign file.%c.var, +// CHECK:STDOUT: return +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: --- fail_todo_forward_with_def.impl.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %.1: type = struct_type {} [template] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .c = %c +// CHECK:STDOUT: } +// CHECK:STDOUT: %ForwardWithDef.ref: = name_ref ForwardWithDef, [template = ] +// CHECK:STDOUT: %c.var: ref = var c +// CHECK:STDOUT: %c: ref = bind_name c, %c.var +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @__global_init() { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %.loc8: {} = struct_literal () +// CHECK:STDOUT: assign file.%c.var, +// CHECK:STDOUT: return +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: --- fail_local_forward_with_def.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %.1: type = struct_type {} [template] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .c = %c +// CHECK:STDOUT: } +// CHECK:STDOUT: %ForwardWithDef.ref: = name_ref ForwardWithDef, [template = ] +// CHECK:STDOUT: %c.var: ref = var c +// CHECK:STDOUT: %c: ref = bind_name c, %c.var +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @__global_init() { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %.loc10: {} = struct_literal () +// CHECK:STDOUT: assign file.%c.var, +// CHECK:STDOUT: return +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: --- fail_other_forward_with_def.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %.1: type = struct_type {} [template] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .Test = %Test +// CHECK:STDOUT: .c = %c +// CHECK:STDOUT: } +// CHECK:STDOUT: %Test: = namespace [template] {} +// CHECK:STDOUT: %Test.ref: = name_ref Test, %Test [template = %Test] +// CHECK:STDOUT: %ForwardWithDef.ref: = name_ref ForwardWithDef, [template = ] +// CHECK:STDOUT: %c.var: ref = var c +// CHECK:STDOUT: %c: ref = bind_name c, %c.var +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @__global_init() { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %.loc10: {} = struct_literal () +// CHECK:STDOUT: assign file.%c.var, +// CHECK:STDOUT: return +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: --- fail_todo_forward.impl.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %F: type = fn_type @F [template] +// CHECK:STDOUT: %.1: type = tuple_type () [template] +// CHECK:STDOUT: %struct: F = struct_value () [template] +// CHECK:STDOUT: %Forward: type = class_type @Forward [template] +// CHECK:STDOUT: %.2: type = struct_type {} [template] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .F = %F.decl +// CHECK:STDOUT: .Forward = %Forward.decl +// CHECK:STDOUT: } +// CHECK:STDOUT: %F.decl: F = fn_decl @F [template = constants.%struct] { +// CHECK:STDOUT: %Forward.ref: = name_ref Forward, [template = ] +// CHECK:STDOUT: %.loc8: type = ptr_type [template = ] +// CHECK:STDOUT: %c.loc8_6.1: = param c +// CHECK:STDOUT: @F.%c: = bind_name c, %c.loc8_6.1 +// CHECK:STDOUT: } +// CHECK:STDOUT: %Forward.decl: type = class_decl @Forward [template = constants.%Forward] {} +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: class @Forward { +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = constants.%Forward +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @F(%c: ) { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: return +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: --- fail_local_forward.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %F: type = fn_type @F [template] +// CHECK:STDOUT: %.1: type = tuple_type () [template] +// CHECK:STDOUT: %struct: F = struct_value () [template] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .F = %F.decl +// CHECK:STDOUT: } +// CHECK:STDOUT: %F.decl: F = fn_decl @F [template = constants.%struct] { +// CHECK:STDOUT: %Forward.ref: = name_ref Forward, [template = ] +// CHECK:STDOUT: %.loc10: type = ptr_type [template = ] +// CHECK:STDOUT: %c.loc10_6.1: = param c +// CHECK:STDOUT: @F.%c: = bind_name c, %c.loc10_6.1 +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @F(%c: ) { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: return +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: --- fail_other_forward.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %F: type = fn_type @F [template] +// CHECK:STDOUT: %.1: type = tuple_type () [template] +// CHECK:STDOUT: %struct: F = struct_value () [template] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .Test = %Test +// CHECK:STDOUT: .F = %F.decl +// CHECK:STDOUT: } +// CHECK:STDOUT: %Test: = namespace [template] {} +// CHECK:STDOUT: %F.decl: F = fn_decl @F [template = constants.%struct] { +// CHECK:STDOUT: %Test.ref: = name_ref Test, %Test [template = %Test] +// CHECK:STDOUT: %Forward.ref: = name_ref Forward, [template = ] +// CHECK:STDOUT: %.loc9: type = ptr_type [template = ] +// CHECK:STDOUT: %c.loc9_6.1: = param c +// CHECK:STDOUT: @F.%c: = bind_name c, %c.loc9_6.1 +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @F(%c: ) { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: return +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: --- todo_fail_private_on_redecl.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %Redecl: type = class_type @Redecl [template] +// CHECK:STDOUT: %.1: type = struct_type {} [template] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .Redecl [private] = %Redecl.decl.loc4 +// CHECK:STDOUT: } +// CHECK:STDOUT: %Redecl.decl.loc4: type = class_decl @Redecl [template = constants.%Redecl] {} +// CHECK:STDOUT: %Redecl.decl.loc6: type = class_decl @Redecl [template = constants.%Redecl] {} +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: class @Redecl { +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = constants.%Redecl +// CHECK:STDOUT: } +// CHECK:STDOUT: diff --git a/toolchain/check/testdata/function/declaration/no_prelude/fail_modifiers.carbon b/toolchain/check/testdata/function/declaration/no_prelude/fail_modifiers.carbon index 6da805db1d8f..322bd1a13141 100644 --- a/toolchain/check/testdata/function/declaration/no_prelude/fail_modifiers.carbon +++ b/toolchain/check/testdata/function/declaration/no_prelude/fail_modifiers.carbon @@ -34,10 +34,6 @@ default protected fn WrongOrder(); // CHECK:STDERR: virtual virtual fn DuplicateVirtual() {} -// CHECK:STDERR: fail_modifiers.carbon:[[@LINE+11]]:1: ERROR: Semantics TODO: `access modifier`. -// CHECK:STDERR: private protected fn TwoAccess(); -// CHECK:STDERR: ^~~~~~~ -// CHECK:STDERR: // CHECK:STDERR: fail_modifiers.carbon:[[@LINE+7]]:9: ERROR: `protected` not allowed on declaration with `private`. // CHECK:STDERR: private protected fn TwoAccess(); // CHECK:STDERR: ^~~~~~~~~ @@ -122,7 +118,7 @@ extern private fn ExternOrderAndConflict() {} // CHECK:STDOUT: package: = namespace [template] { // CHECK:STDOUT: .WrongOrder = %WrongOrder.decl // CHECK:STDOUT: .DuplicateVirtual = %DuplicateVirtual.decl -// CHECK:STDOUT: .TwoAccess = %TwoAccess.decl +// CHECK:STDOUT: .TwoAccess [private] = %TwoAccess.decl // CHECK:STDOUT: .ModifiersConflict = %ModifiersConflict.decl // CHECK:STDOUT: .InvalidModifier = %InvalidModifier.decl // CHECK:STDOUT: .ModifiersConflict2 = %ModifiersConflict2.decl diff --git a/toolchain/check/testdata/function/declaration/no_prelude/fail_todo_modifiers.carbon b/toolchain/check/testdata/function/declaration/no_prelude/fail_todo_modifiers.carbon deleted file mode 100644 index ec54aadfe4c9..000000000000 --- a/toolchain/check/testdata/function/declaration/no_prelude/fail_todo_modifiers.carbon +++ /dev/null @@ -1,32 +0,0 @@ -// 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/check/testdata/function/declaration/no_prelude/fail_todo_modifiers.carbon -// TIP: To dump output, run: -// TIP: bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/function/declaration/no_prelude/fail_todo_modifiers.carbon - -// CHECK:STDERR: fail_todo_modifiers.carbon:[[@LINE+3]]:1: ERROR: Semantics TODO: `access modifier`. -// CHECK:STDERR: private fn F(); -// CHECK:STDERR: ^~~~~~~ -private fn F(); - -// CHECK:STDOUT: --- fail_todo_modifiers.carbon -// CHECK:STDOUT: -// CHECK:STDOUT: constants { -// CHECK:STDOUT: %F: type = fn_type @F [template] -// CHECK:STDOUT: %.1: type = tuple_type () [template] -// CHECK:STDOUT: %struct: F = struct_value () [template] -// CHECK:STDOUT: } -// CHECK:STDOUT: -// CHECK:STDOUT: file { -// CHECK:STDOUT: package: = namespace [template] { -// CHECK:STDOUT: .F = %F.decl -// CHECK:STDOUT: } -// CHECK:STDOUT: %F.decl: F = fn_decl @F [template = constants.%struct] {} -// CHECK:STDOUT: } -// CHECK:STDOUT: -// CHECK:STDOUT: fn @F(); -// CHECK:STDOUT: diff --git a/toolchain/check/testdata/function/definition/import_access.carbon b/toolchain/check/testdata/function/definition/import_access.carbon new file mode 100644 index 000000000000..a1d662141a20 --- /dev/null +++ b/toolchain/check/testdata/function/definition/import_access.carbon @@ -0,0 +1,479 @@ +// 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/check/testdata/function/definition/import_access.carbon +// TIP: To dump output, run: +// TIP: bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/function/definition/import_access.carbon + +// ============================================================================ +// Setup files +// ============================================================================ + +// --- def.carbon + +package Test library "def"; + +private fn Def() {} + +// --- forward_with_def.carbon + +package Test library "forward_with_def"; + +private fn ForwardWithDef(); + +fn ForwardWithDef() {} + +// --- forward.carbon + +package Test library "forward"; + +private fn Forward(); + +// ============================================================================ +// Test files +// ============================================================================ + +// --- fail_todo_def.impl.carbon + +impl package Test library "def"; + +// CHECK:STDERR: fail_todo_def.impl.carbon:[[@LINE+4]]:13: ERROR: Name `Def` not found. +// CHECK:STDERR: var f: () = Def(); +// CHECK:STDERR: ^~~ +// CHECK:STDERR: +var f: () = Def(); + +// --- fail_local_def.carbon + +package Test library "fail_local_def"; + +import library "def"; + +// CHECK:STDERR: fail_local_def.carbon:[[@LINE+4]]:13: ERROR: Name `Def` not found. +// CHECK:STDERR: var f: () = Def(); +// CHECK:STDERR: ^~~ +// CHECK:STDERR: +var f: () = Def(); + +// --- fail_other_def.carbon + +package Other library "fail_other_def"; + +import Test library "def"; + +// CHECK:STDERR: fail_other_def.carbon:[[@LINE+4]]:13: ERROR: Name `Def` not found. +// CHECK:STDERR: var f: () = Test.Def(); +// CHECK:STDERR: ^~~~~~~~ +// CHECK:STDERR: +var f: () = Test.Def(); + +// --- fail_todo_forward_with_def.impl.carbon + +impl package Test library "forward_with_def"; + +// CHECK:STDERR: fail_todo_forward_with_def.impl.carbon:[[@LINE+4]]:13: ERROR: Name `ForwardWithDef` not found. +// CHECK:STDERR: var f: () = ForwardWithDef(); +// CHECK:STDERR: ^~~~~~~~~~~~~~ +// CHECK:STDERR: +var f: () = ForwardWithDef(); + +// --- fail_local_forward_with_def.carbon + +package Test library "fail_local_forward_with_def"; + +import library "forward_with_def"; + +// CHECK:STDERR: fail_local_forward_with_def.carbon:[[@LINE+4]]:13: ERROR: Name `ForwardWithDef` not found. +// CHECK:STDERR: var f: () = ForwardWithDef(); +// CHECK:STDERR: ^~~~~~~~~~~~~~ +// CHECK:STDERR: +var f: () = ForwardWithDef(); + +// --- fail_other_forward_with_def.carbon + +package Other library "fail_other_forward_with_def"; + +import Test library "forward_with_def"; + +// CHECK:STDERR: fail_other_forward_with_def.carbon:[[@LINE+4]]:13: ERROR: Name `ForwardWithDef` not found. +// CHECK:STDERR: var f: () = Test.ForwardWithDef(); +// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~ +// CHECK:STDERR: +var f: () = Test.ForwardWithDef(); + +// --- fail_todo_forward.impl.carbon + +impl package Test library "forward"; + +// CHECK:STDERR: fail_todo_forward.impl.carbon:[[@LINE+4]]:13: ERROR: Name `Forward` not found. +// CHECK:STDERR: var f: () = Forward(); +// CHECK:STDERR: ^~~~~~~ +// CHECK:STDERR: +var f: () = Forward(); + +fn Forward() {} + +// --- fail_local_forward.carbon + +package Test library "fail_local_forward"; + +import library "forward"; + +// CHECK:STDERR: fail_local_forward.carbon:[[@LINE+4]]:13: ERROR: Name `Forward` not found. +// CHECK:STDERR: var f: () = Forward(); +// CHECK:STDERR: ^~~~~~~ +// CHECK:STDERR: +var f: () = Forward(); + +// --- fail_other_forward.carbon + +package Other library "fail_other_forward"; + +import Test library "forward"; + +// CHECK:STDERR: fail_other_forward.carbon:[[@LINE+3]]:13: ERROR: Name `Forward` not found. +// CHECK:STDERR: var f: () = Test.Forward(); +// CHECK:STDERR: ^~~~~~~~~~~~ +var f: () = Test.Forward(); + +// --- todo_fail_private_on_redecl.carbon + +library "fail_private_on_redecl"; + +private fn Redecl(); + +private fn Redecl() {} + +// CHECK:STDOUT: --- def.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %Def: type = fn_type @Def [template] +// CHECK:STDOUT: %.1: type = tuple_type () [template] +// CHECK:STDOUT: %struct: Def = struct_value () [template] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .Core = %Core +// CHECK:STDOUT: .Def [private] = %Def.decl +// CHECK:STDOUT: } +// CHECK:STDOUT: %Core: = namespace [template] {} +// CHECK:STDOUT: %Def.decl: Def = fn_decl @Def [template = constants.%struct] {} +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @Def() { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: return +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: --- forward_with_def.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %ForwardWithDef: type = fn_type @ForwardWithDef [template] +// CHECK:STDOUT: %.1: type = tuple_type () [template] +// CHECK:STDOUT: %struct: ForwardWithDef = struct_value () [template] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .Core = %Core +// CHECK:STDOUT: .ForwardWithDef [private] = %ForwardWithDef.decl.loc4 +// CHECK:STDOUT: } +// CHECK:STDOUT: %Core: = namespace [template] {} +// CHECK:STDOUT: %ForwardWithDef.decl.loc4: ForwardWithDef = fn_decl @ForwardWithDef [template = constants.%struct] {} +// CHECK:STDOUT: %ForwardWithDef.decl.loc6: ForwardWithDef = fn_decl @ForwardWithDef [template = constants.%struct] {} +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @ForwardWithDef() { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: return +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: --- forward.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %Forward: type = fn_type @Forward [template] +// CHECK:STDOUT: %.1: type = tuple_type () [template] +// CHECK:STDOUT: %struct: Forward = struct_value () [template] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .Core = %Core +// CHECK:STDOUT: .Forward [private] = %Forward.decl +// CHECK:STDOUT: } +// CHECK:STDOUT: %Core: = namespace [template] {} +// CHECK:STDOUT: %Forward.decl: Forward = fn_decl @Forward [template = constants.%struct] {} +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @Forward(); +// CHECK:STDOUT: +// CHECK:STDOUT: --- fail_todo_def.impl.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %.1: type = tuple_type () [template] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .Core = %Core +// CHECK:STDOUT: .f = %f +// CHECK:STDOUT: } +// CHECK:STDOUT: %Core: = namespace [template] {} +// CHECK:STDOUT: %.loc8_9.1: () = tuple_literal () +// CHECK:STDOUT: %.loc8_9.2: type = converted %.loc8_9.1, constants.%.1 [template = constants.%.1] +// CHECK:STDOUT: %f.var: ref () = var f +// CHECK:STDOUT: %f: ref () = bind_name f, %f.var +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @__global_init() { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %Def.ref: = name_ref Def, [template = ] +// CHECK:STDOUT: assign file.%f.var, +// CHECK:STDOUT: return +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: --- fail_local_def.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %.1: type = tuple_type () [template] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .Core = %Core +// CHECK:STDOUT: .f = %f +// CHECK:STDOUT: } +// CHECK:STDOUT: %Core: = namespace [template] {} +// CHECK:STDOUT: %.loc10_9.1: () = tuple_literal () +// CHECK:STDOUT: %.loc10_9.2: type = converted %.loc10_9.1, constants.%.1 [template = constants.%.1] +// CHECK:STDOUT: %f.var: ref () = var f +// CHECK:STDOUT: %f: ref () = bind_name f, %f.var +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @__global_init() { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %Def.ref: = name_ref Def, [template = ] +// CHECK:STDOUT: assign file.%f.var, +// CHECK:STDOUT: return +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: --- fail_other_def.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %.1: type = tuple_type () [template] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .Core = %Core +// CHECK:STDOUT: .Test = %Test +// CHECK:STDOUT: .f = %f +// CHECK:STDOUT: } +// CHECK:STDOUT: %Core: = namespace [template] {} +// CHECK:STDOUT: %Test: = namespace [template] {} +// CHECK:STDOUT: %.loc10_9.1: () = tuple_literal () +// CHECK:STDOUT: %.loc10_9.2: type = converted %.loc10_9.1, constants.%.1 [template = constants.%.1] +// CHECK:STDOUT: %f.var: ref () = var f +// CHECK:STDOUT: %f: ref () = bind_name f, %f.var +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @__global_init() { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %Test.ref: = name_ref Test, file.%Test [template = file.%Test] +// CHECK:STDOUT: %Def.ref: = name_ref Def, [template = ] +// CHECK:STDOUT: assign file.%f.var, +// CHECK:STDOUT: return +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: --- fail_todo_forward_with_def.impl.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %.1: type = tuple_type () [template] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .Core = %Core +// CHECK:STDOUT: .f = %f +// CHECK:STDOUT: } +// CHECK:STDOUT: %Core: = namespace [template] {} +// CHECK:STDOUT: %.loc8_9.1: () = tuple_literal () +// CHECK:STDOUT: %.loc8_9.2: type = converted %.loc8_9.1, constants.%.1 [template = constants.%.1] +// CHECK:STDOUT: %f.var: ref () = var f +// CHECK:STDOUT: %f: ref () = bind_name f, %f.var +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @__global_init() { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %ForwardWithDef.ref: = name_ref ForwardWithDef, [template = ] +// CHECK:STDOUT: assign file.%f.var, +// CHECK:STDOUT: return +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: --- fail_local_forward_with_def.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %.1: type = tuple_type () [template] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .Core = %Core +// CHECK:STDOUT: .f = %f +// CHECK:STDOUT: } +// CHECK:STDOUT: %Core: = namespace [template] {} +// CHECK:STDOUT: %.loc10_9.1: () = tuple_literal () +// CHECK:STDOUT: %.loc10_9.2: type = converted %.loc10_9.1, constants.%.1 [template = constants.%.1] +// CHECK:STDOUT: %f.var: ref () = var f +// CHECK:STDOUT: %f: ref () = bind_name f, %f.var +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @__global_init() { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %ForwardWithDef.ref: = name_ref ForwardWithDef, [template = ] +// CHECK:STDOUT: assign file.%f.var, +// CHECK:STDOUT: return +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: --- fail_other_forward_with_def.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %.1: type = tuple_type () [template] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .Core = %Core +// CHECK:STDOUT: .Test = %Test +// CHECK:STDOUT: .f = %f +// CHECK:STDOUT: } +// CHECK:STDOUT: %Core: = namespace [template] {} +// CHECK:STDOUT: %Test: = namespace [template] {} +// CHECK:STDOUT: %.loc10_9.1: () = tuple_literal () +// CHECK:STDOUT: %.loc10_9.2: type = converted %.loc10_9.1, constants.%.1 [template = constants.%.1] +// CHECK:STDOUT: %f.var: ref () = var f +// CHECK:STDOUT: %f: ref () = bind_name f, %f.var +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @__global_init() { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %Test.ref: = name_ref Test, file.%Test [template = file.%Test] +// CHECK:STDOUT: %ForwardWithDef.ref: = name_ref ForwardWithDef, [template = ] +// CHECK:STDOUT: assign file.%f.var, +// CHECK:STDOUT: return +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: --- fail_todo_forward.impl.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %.1: type = tuple_type () [template] +// CHECK:STDOUT: %Forward: type = fn_type @Forward [template] +// CHECK:STDOUT: %struct: Forward = struct_value () [template] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .Core = %Core +// CHECK:STDOUT: .f = %f +// CHECK:STDOUT: .Forward = %Forward.decl +// CHECK:STDOUT: } +// CHECK:STDOUT: %Core: = namespace [template] {} +// CHECK:STDOUT: %.loc8_9.1: () = tuple_literal () +// CHECK:STDOUT: %.loc8_9.2: type = converted %.loc8_9.1, constants.%.1 [template = constants.%.1] +// CHECK:STDOUT: %f.var: ref () = var f +// CHECK:STDOUT: %f: ref () = bind_name f, %f.var +// CHECK:STDOUT: %Forward.decl: Forward = fn_decl @Forward [template = constants.%struct] {} +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @Forward() { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: return +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @__global_init() { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %Forward.ref: = name_ref Forward, [template = ] +// CHECK:STDOUT: assign file.%f.var, +// CHECK:STDOUT: return +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: --- fail_local_forward.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %.1: type = tuple_type () [template] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .Core = %Core +// CHECK:STDOUT: .f = %f +// CHECK:STDOUT: } +// CHECK:STDOUT: %Core: = namespace [template] {} +// CHECK:STDOUT: %.loc10_9.1: () = tuple_literal () +// CHECK:STDOUT: %.loc10_9.2: type = converted %.loc10_9.1, constants.%.1 [template = constants.%.1] +// CHECK:STDOUT: %f.var: ref () = var f +// CHECK:STDOUT: %f: ref () = bind_name f, %f.var +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @__global_init() { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %Forward.ref: = name_ref Forward, [template = ] +// CHECK:STDOUT: assign file.%f.var, +// CHECK:STDOUT: return +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: --- fail_other_forward.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %.1: type = tuple_type () [template] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .Core = %Core +// CHECK:STDOUT: .Test = %Test +// CHECK:STDOUT: .f = %f +// CHECK:STDOUT: } +// CHECK:STDOUT: %Core: = namespace [template] {} +// CHECK:STDOUT: %Test: = namespace [template] {} +// CHECK:STDOUT: %.loc9_9.1: () = tuple_literal () +// CHECK:STDOUT: %.loc9_9.2: type = converted %.loc9_9.1, constants.%.1 [template = constants.%.1] +// CHECK:STDOUT: %f.var: ref () = var f +// CHECK:STDOUT: %f: ref () = bind_name f, %f.var +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @__global_init() { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %Test.ref: = name_ref Test, file.%Test [template = file.%Test] +// CHECK:STDOUT: %Forward.ref: = name_ref Forward, [template = ] +// CHECK:STDOUT: assign file.%f.var, +// CHECK:STDOUT: return +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: --- todo_fail_private_on_redecl.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %Redecl: type = fn_type @Redecl [template] +// CHECK:STDOUT: %.1: type = tuple_type () [template] +// CHECK:STDOUT: %struct: Redecl = struct_value () [template] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .Core = %Core +// CHECK:STDOUT: .Redecl [private] = %Redecl.decl.loc4 +// CHECK:STDOUT: } +// CHECK:STDOUT: %Core: = namespace [template] {} +// CHECK:STDOUT: %Redecl.decl.loc4: Redecl = fn_decl @Redecl [template = constants.%struct] {} +// CHECK:STDOUT: %Redecl.decl.loc6: Redecl = fn_decl @Redecl [template = constants.%struct] {} +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @Redecl() { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: return +// CHECK:STDOUT: } +// CHECK:STDOUT: diff --git a/toolchain/check/testdata/interface/no_prelude/fail_todo_modifiers.carbon b/toolchain/check/testdata/interface/no_prelude/fail_todo_modifiers.carbon index 5de7abad55a4..872ff04019a2 100644 --- a/toolchain/check/testdata/interface/no_prelude/fail_todo_modifiers.carbon +++ b/toolchain/check/testdata/interface/no_prelude/fail_todo_modifiers.carbon @@ -14,24 +14,17 @@ interface Modifiers { // CHECK:STDERR: ^~~~~ // CHECK:STDERR: final fn Final() { } - // CHECK:STDERR: fail_todo_modifiers.carbon:[[@LINE+4]]:3: ERROR: Semantics TODO: `interface modifier`. + // CHECK:STDERR: fail_todo_modifiers.carbon:[[@LINE+3]]:3: ERROR: Semantics TODO: `interface modifier`. // CHECK:STDERR: default fn Default() { } // CHECK:STDERR: ^~~~~~~ - // CHECK:STDERR: default fn Default() { } } -// CHECK:STDERR: fail_todo_modifiers.carbon:[[@LINE+3]]:1: ERROR: Semantics TODO: `access modifier`. -// CHECK:STDERR: private interface Private { -// CHECK:STDERR: ^~~~~~~ -private interface Private { -} - // CHECK:STDOUT: --- fail_todo_modifiers.carbon // CHECK:STDOUT: // CHECK:STDOUT: constants { // CHECK:STDOUT: %.1: type = interface_type @Modifiers [template] -// CHECK:STDOUT: %Self.1: Modifiers = bind_symbolic_name Self 0 [symbolic] +// CHECK:STDOUT: %Self: Modifiers = bind_symbolic_name Self 0 [symbolic] // CHECK:STDOUT: %Final: type = fn_type @Final [template] // CHECK:STDOUT: %.2: type = tuple_type () [template] // CHECK:STDOUT: %struct.1: Final = struct_value () [template] @@ -41,41 +34,29 @@ private interface Private { // CHECK:STDOUT: %struct.2: Default = struct_value () [template] // CHECK:STDOUT: %.5: type = assoc_entity_type @Modifiers, Default [template] // CHECK:STDOUT: %.6: = assoc_entity element1, @Modifiers.%Default.decl [template] -// CHECK:STDOUT: %.7: type = interface_type @Private [template] -// CHECK:STDOUT: %Self.2: Private = bind_symbolic_name Self 0 [symbolic] // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: file { // CHECK:STDOUT: package: = namespace [template] { // CHECK:STDOUT: .Modifiers = %Modifiers.decl -// CHECK:STDOUT: .Private = %Private.decl // CHECK:STDOUT: } // CHECK:STDOUT: %Modifiers.decl: type = interface_decl @Modifiers [template = constants.%.1] {} -// CHECK:STDOUT: %Private.decl: type = interface_decl @Private [template = constants.%.7] {} // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: interface @Modifiers { -// CHECK:STDOUT: %Self: Modifiers = bind_symbolic_name Self 0 [symbolic = constants.%Self.1] +// CHECK:STDOUT: %Self: Modifiers = bind_symbolic_name Self 0 [symbolic = constants.%Self] // CHECK:STDOUT: %Final.decl: Final = fn_decl @Final [template = constants.%struct.1] {} // CHECK:STDOUT: %.loc16: = assoc_entity element0, %Final.decl [template = constants.%.4] // CHECK:STDOUT: %Default.decl: Default = fn_decl @Default [template = constants.%struct.2] {} -// CHECK:STDOUT: %.loc21: = assoc_entity element1, %Default.decl [template = constants.%.6] +// CHECK:STDOUT: %.loc20: = assoc_entity element1, %Default.decl [template = constants.%.6] // CHECK:STDOUT: // CHECK:STDOUT: !members: // CHECK:STDOUT: .Self = %Self // CHECK:STDOUT: .Final = %.loc16 -// CHECK:STDOUT: .Default = %.loc21 +// CHECK:STDOUT: .Default = %.loc20 // CHECK:STDOUT: witness = (%Final.decl, %Default.decl) // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: interface @Private { -// CHECK:STDOUT: %Self: Private = bind_symbolic_name Self 0 [symbolic = constants.%Self.2] -// CHECK:STDOUT: -// CHECK:STDOUT: !members: -// CHECK:STDOUT: .Self = %Self -// CHECK:STDOUT: witness = () -// CHECK:STDOUT: } -// CHECK:STDOUT: // CHECK:STDOUT: fn @Final() { // CHECK:STDOUT: !entry: // CHECK:STDOUT: return diff --git a/toolchain/check/testdata/interface/no_prelude/import_access.carbon b/toolchain/check/testdata/interface/no_prelude/import_access.carbon new file mode 100644 index 000000000000..03673ddcd810 --- /dev/null +++ b/toolchain/check/testdata/interface/no_prelude/import_access.carbon @@ -0,0 +1,463 @@ +// 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/check/testdata/interface/no_prelude/import_access.carbon +// TIP: To dump output, run: +// TIP: bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/interface/no_prelude/import_access.carbon + +// ============================================================================ +// Setup files +// ============================================================================ + +// --- def.carbon + +package Test library "def"; + +private interface Def {} + +// --- forward_with_def.carbon + +package Test library "forward_with_def"; + +private interface ForwardWithDef; + +interface ForwardWithDef {} + +// --- forward.carbon + +package Test library "forward"; + +// TODO: Import of forward declared interfaces crashes. +// private interface Forward; + +// ============================================================================ +// Test files +// ============================================================================ + +// --- fail_todo_def.impl.carbon + +impl package Test library "def"; + +// CHECK:STDERR: fail_todo_def.impl.carbon:[[@LINE+4]]:9: ERROR: Name `Def` not found. +// CHECK:STDERR: fn F(i: Def) {} +// CHECK:STDERR: ^~~ +// CHECK:STDERR: +fn F(i: Def) {} + +// --- fail_local_def.carbon + +package Test library "fail_local_def"; + +import library "def"; + +// CHECK:STDERR: fail_local_def.carbon:[[@LINE+4]]:9: ERROR: Name `Def` not found. +// CHECK:STDERR: fn F(i: Def) {} +// CHECK:STDERR: ^~~ +// CHECK:STDERR: +fn F(i: Def) {} + +// --- fail_other_def.carbon + +package Other library "fail_other_def"; + +import Test library "def"; + +// CHECK:STDERR: fail_other_def.carbon:[[@LINE+4]]:9: ERROR: Name `Def` not found. +// CHECK:STDERR: fn F(i: Test.Def) {} +// CHECK:STDERR: ^~~~~~~~ +// CHECK:STDERR: +fn F(i: Test.Def) {} + +// --- fail_todo_forward_with_def.impl.carbon + +impl package Test library "forward_with_def"; + +// CHECK:STDERR: fail_todo_forward_with_def.impl.carbon:[[@LINE+4]]:9: ERROR: Name `ForwardWithDef` not found. +// CHECK:STDERR: fn F(i: ForwardWithDef) {} +// CHECK:STDERR: ^~~~~~~~~~~~~~ +// CHECK:STDERR: +fn F(i: ForwardWithDef) {} + +// --- fail_local_forward_with_def.carbon + +package Test library "fail_local_forward_with_def"; + +import library "forward_with_def"; + +// CHECK:STDERR: fail_local_forward_with_def.carbon:[[@LINE+4]]:9: ERROR: Name `ForwardWithDef` not found. +// CHECK:STDERR: fn F(i: ForwardWithDef) {} +// CHECK:STDERR: ^~~~~~~~~~~~~~ +// CHECK:STDERR: +fn F(i: ForwardWithDef) {} + +// --- fail_other_forward_with_def.carbon + +package Other library "fail_other_forward_with_def"; + +import Test library "forward_with_def"; + +// CHECK:STDERR: fail_other_forward_with_def.carbon:[[@LINE+4]]:9: ERROR: Name `ForwardWithDef` not found. +// CHECK:STDERR: fn F(i: Test.ForwardWithDef) {} +// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~ +// CHECK:STDERR: +fn F(i: Test.ForwardWithDef) {} + +// --- fail_todo_forward.impl.carbon + +impl package Test library "forward"; + +// CHECK:STDERR: fail_todo_forward.impl.carbon:[[@LINE+4]]:9: ERROR: Name `Forward` not found. +// CHECK:STDERR: fn F(i: Forward*) {} +// CHECK:STDERR: ^~~~~~~ +// CHECK:STDERR: +fn F(i: Forward*) {} + +interface Forward {} + +// --- fail_local_forward.carbon + +package Test library "fail_local_forward"; + +import library "forward"; + +// CHECK:STDERR: fail_local_forward.carbon:[[@LINE+4]]:9: ERROR: Name `Forward` not found. +// CHECK:STDERR: fn F(i: Forward*) {} +// CHECK:STDERR: ^~~~~~~ +// CHECK:STDERR: +fn F(i: Forward*) {} + +// --- fail_other_forward.carbon + +package Other library "fail_other_forward"; + +import Test library "forward"; + +// CHECK:STDERR: fail_other_forward.carbon:[[@LINE+3]]:9: ERROR: Name `Forward` not found. +// CHECK:STDERR: fn F(i: Forward*) {} +// CHECK:STDERR: ^~~~~~~ +fn F(i: Forward*) {} + +// --- todo_fail_private_on_redecl.carbon + +library "fail_private_on_redecl"; + +private interface Redecl; + +private interface Redecl {} + +// CHECK:STDOUT: --- def.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %.1: type = interface_type @Def [template] +// CHECK:STDOUT: %Self: Def = bind_symbolic_name Self 0 [symbolic] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .Def [private] = %Def.decl +// CHECK:STDOUT: } +// CHECK:STDOUT: %Def.decl: type = interface_decl @Def [template = constants.%.1] {} +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: interface @Def { +// CHECK:STDOUT: %Self: Def = bind_symbolic_name Self 0 [symbolic = constants.%Self] +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = %Self +// CHECK:STDOUT: witness = () +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: --- forward_with_def.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %.1: type = interface_type @ForwardWithDef [template] +// CHECK:STDOUT: %Self: ForwardWithDef = bind_symbolic_name Self 0 [symbolic] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .ForwardWithDef [private] = %ForwardWithDef.decl.loc4 +// CHECK:STDOUT: } +// CHECK:STDOUT: %ForwardWithDef.decl.loc4: type = interface_decl @ForwardWithDef [template = constants.%.1] {} +// CHECK:STDOUT: %ForwardWithDef.decl.loc6: type = interface_decl @ForwardWithDef [template = constants.%.1] {} +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: interface @ForwardWithDef { +// CHECK:STDOUT: %Self: ForwardWithDef = bind_symbolic_name Self 0 [symbolic = constants.%Self] +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = %Self +// CHECK:STDOUT: witness = () +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: --- forward.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] {} +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: --- fail_todo_def.impl.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %F: type = fn_type @F [template] +// CHECK:STDOUT: %.1: type = tuple_type () [template] +// CHECK:STDOUT: %struct: F = struct_value () [template] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .F = %F.decl +// CHECK:STDOUT: } +// CHECK:STDOUT: %F.decl: F = fn_decl @F [template = constants.%struct] { +// CHECK:STDOUT: %Def.ref: = name_ref Def, [template = ] +// CHECK:STDOUT: %i.loc8_6.1: = param i +// CHECK:STDOUT: @F.%i: = bind_name i, %i.loc8_6.1 +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @F(%i: ) { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: return +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: --- fail_local_def.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %F: type = fn_type @F [template] +// CHECK:STDOUT: %.1: type = tuple_type () [template] +// CHECK:STDOUT: %struct: F = struct_value () [template] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .F = %F.decl +// CHECK:STDOUT: } +// CHECK:STDOUT: %F.decl: F = fn_decl @F [template = constants.%struct] { +// CHECK:STDOUT: %Def.ref: = name_ref Def, [template = ] +// CHECK:STDOUT: %i.loc10_6.1: = param i +// CHECK:STDOUT: @F.%i: = bind_name i, %i.loc10_6.1 +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @F(%i: ) { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: return +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: --- fail_other_def.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %F: type = fn_type @F [template] +// CHECK:STDOUT: %.1: type = tuple_type () [template] +// CHECK:STDOUT: %struct: F = struct_value () [template] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .Test = %Test +// CHECK:STDOUT: .F = %F.decl +// CHECK:STDOUT: } +// CHECK:STDOUT: %Test: = namespace [template] {} +// CHECK:STDOUT: %F.decl: F = fn_decl @F [template = constants.%struct] { +// CHECK:STDOUT: %Test.ref: = name_ref Test, %Test [template = %Test] +// CHECK:STDOUT: %Def.ref: = name_ref Def, [template = ] +// CHECK:STDOUT: %i.loc10_6.1: = param i +// CHECK:STDOUT: @F.%i: = bind_name i, %i.loc10_6.1 +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @F(%i: ) { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: return +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: --- fail_todo_forward_with_def.impl.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %F: type = fn_type @F [template] +// CHECK:STDOUT: %.1: type = tuple_type () [template] +// CHECK:STDOUT: %struct: F = struct_value () [template] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .F = %F.decl +// CHECK:STDOUT: } +// CHECK:STDOUT: %F.decl: F = fn_decl @F [template = constants.%struct] { +// CHECK:STDOUT: %ForwardWithDef.ref: = name_ref ForwardWithDef, [template = ] +// CHECK:STDOUT: %i.loc8_6.1: = param i +// CHECK:STDOUT: @F.%i: = bind_name i, %i.loc8_6.1 +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @F(%i: ) { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: return +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: --- fail_local_forward_with_def.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %F: type = fn_type @F [template] +// CHECK:STDOUT: %.1: type = tuple_type () [template] +// CHECK:STDOUT: %struct: F = struct_value () [template] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .F = %F.decl +// CHECK:STDOUT: } +// CHECK:STDOUT: %F.decl: F = fn_decl @F [template = constants.%struct] { +// CHECK:STDOUT: %ForwardWithDef.ref: = name_ref ForwardWithDef, [template = ] +// CHECK:STDOUT: %i.loc10_6.1: = param i +// CHECK:STDOUT: @F.%i: = bind_name i, %i.loc10_6.1 +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @F(%i: ) { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: return +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: --- fail_other_forward_with_def.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %F: type = fn_type @F [template] +// CHECK:STDOUT: %.1: type = tuple_type () [template] +// CHECK:STDOUT: %struct: F = struct_value () [template] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .Test = %Test +// CHECK:STDOUT: .F = %F.decl +// CHECK:STDOUT: } +// CHECK:STDOUT: %Test: = namespace [template] {} +// CHECK:STDOUT: %F.decl: F = fn_decl @F [template = constants.%struct] { +// CHECK:STDOUT: %Test.ref: = name_ref Test, %Test [template = %Test] +// CHECK:STDOUT: %ForwardWithDef.ref: = name_ref ForwardWithDef, [template = ] +// CHECK:STDOUT: %i.loc10_6.1: = param i +// CHECK:STDOUT: @F.%i: = bind_name i, %i.loc10_6.1 +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @F(%i: ) { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: return +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: --- fail_todo_forward.impl.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %F: type = fn_type @F [template] +// CHECK:STDOUT: %.1: type = tuple_type () [template] +// CHECK:STDOUT: %struct: F = struct_value () [template] +// CHECK:STDOUT: %.2: type = interface_type @Forward [template] +// CHECK:STDOUT: %Self: Forward = bind_symbolic_name Self 0 [symbolic] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .F = %F.decl +// CHECK:STDOUT: .Forward = %Forward.decl +// CHECK:STDOUT: } +// CHECK:STDOUT: %F.decl: F = fn_decl @F [template = constants.%struct] { +// CHECK:STDOUT: %Forward.ref: = name_ref Forward, [template = ] +// CHECK:STDOUT: %.loc8: type = ptr_type [template = ] +// CHECK:STDOUT: %i.loc8_6.1: = param i +// CHECK:STDOUT: @F.%i: = bind_name i, %i.loc8_6.1 +// CHECK:STDOUT: } +// CHECK:STDOUT: %Forward.decl: type = interface_decl @Forward [template = constants.%.2] {} +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: interface @Forward { +// CHECK:STDOUT: %Self: Forward = bind_symbolic_name Self 0 [symbolic = constants.%Self] +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = %Self +// CHECK:STDOUT: witness = () +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @F(%i: ) { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: return +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: --- fail_local_forward.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %F: type = fn_type @F [template] +// CHECK:STDOUT: %.1: type = tuple_type () [template] +// CHECK:STDOUT: %struct: F = struct_value () [template] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .F = %F.decl +// CHECK:STDOUT: } +// CHECK:STDOUT: %F.decl: F = fn_decl @F [template = constants.%struct] { +// CHECK:STDOUT: %Forward.ref: = name_ref Forward, [template = ] +// CHECK:STDOUT: %.loc10: type = ptr_type [template = ] +// CHECK:STDOUT: %i.loc10_6.1: = param i +// CHECK:STDOUT: @F.%i: = bind_name i, %i.loc10_6.1 +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @F(%i: ) { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: return +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: --- fail_other_forward.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %F: type = fn_type @F [template] +// CHECK:STDOUT: %.1: type = tuple_type () [template] +// CHECK:STDOUT: %struct: F = struct_value () [template] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .Test = %Test +// CHECK:STDOUT: .F = %F.decl +// CHECK:STDOUT: } +// CHECK:STDOUT: %Test: = namespace [template] {} +// CHECK:STDOUT: %F.decl: F = fn_decl @F [template = constants.%struct] { +// CHECK:STDOUT: %Forward.ref: = name_ref Forward, [template = ] +// CHECK:STDOUT: %.loc9: type = ptr_type [template = ] +// CHECK:STDOUT: %i.loc9_6.1: = param i +// CHECK:STDOUT: @F.%i: = bind_name i, %i.loc9_6.1 +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @F(%i: ) { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: return +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: --- todo_fail_private_on_redecl.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %.1: type = interface_type @Redecl [template] +// CHECK:STDOUT: %Self: Redecl = bind_symbolic_name Self 0 [symbolic] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .Redecl [private] = %Redecl.decl.loc4 +// CHECK:STDOUT: } +// CHECK:STDOUT: %Redecl.decl.loc4: type = interface_decl @Redecl [template = constants.%.1] {} +// CHECK:STDOUT: %Redecl.decl.loc6: type = interface_decl @Redecl [template = constants.%.1] {} +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: interface @Redecl { +// CHECK:STDOUT: %Self: Redecl = bind_symbolic_name Self 0 [symbolic = constants.%Self] +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = %Self +// CHECK:STDOUT: witness = () +// CHECK:STDOUT: } +// CHECK:STDOUT: diff --git a/toolchain/check/testdata/let/fail_todo_modifiers.carbon b/toolchain/check/testdata/let/fail_todo_modifiers.carbon deleted file mode 100644 index 503f3ea5a9ef..000000000000 --- a/toolchain/check/testdata/let/fail_todo_modifiers.carbon +++ /dev/null @@ -1,39 +0,0 @@ -// 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/check/testdata/let/fail_todo_modifiers.carbon -// TIP: To dump output, run: -// TIP: bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/let/fail_todo_modifiers.carbon - -// CHECK:STDERR: fail_todo_modifiers.carbon:[[@LINE+3]]:1: ERROR: Semantics TODO: `access modifier`. -// CHECK:STDERR: private let a: i32 = 1; -// CHECK:STDERR: ^~~~~~~ -private let a: i32 = 1; - -// CHECK:STDOUT: --- fail_todo_modifiers.carbon -// CHECK:STDOUT: -// CHECK:STDOUT: constants { -// CHECK:STDOUT: %Int32: type = fn_type @Int32 [template] -// CHECK:STDOUT: %.1: type = tuple_type () [template] -// CHECK:STDOUT: %struct: Int32 = struct_value () [template] -// CHECK:STDOUT: %.2: i32 = int_literal 1 [template] -// CHECK:STDOUT: } -// CHECK:STDOUT: -// CHECK:STDOUT: file { -// CHECK:STDOUT: package: = namespace [template] { -// CHECK:STDOUT: .Core = %Core -// CHECK:STDOUT: } -// CHECK:STDOUT: %Core: = namespace [template] {} -// CHECK:STDOUT: %import_ref: Int32 = import_ref ir3, inst+3, loaded [template = constants.%struct] -// CHECK:STDOUT: %int.make_type_32: init type = call constants.%struct() [template = i32] -// CHECK:STDOUT: %.loc14_16.1: type = value_of_initializer %int.make_type_32 [template = i32] -// CHECK:STDOUT: %.loc14_16.2: type = converted %int.make_type_32, %.loc14_16.1 [template = i32] -// CHECK:STDOUT: %.loc14_22: i32 = int_literal 1 [template = constants.%.2] -// CHECK:STDOUT: %a: i32 = bind_name a, %.loc14_22 -// CHECK:STDOUT: } -// CHECK:STDOUT: -// CHECK:STDOUT: fn @Int32() -> type = "int.make_type_32"; -// CHECK:STDOUT: diff --git a/toolchain/check/testdata/let/no_prelude/import_access.carbon b/toolchain/check/testdata/let/no_prelude/import_access.carbon new file mode 100644 index 000000000000..a48f77368e85 --- /dev/null +++ b/toolchain/check/testdata/let/no_prelude/import_access.carbon @@ -0,0 +1,120 @@ +// 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/check/testdata/let/no_prelude/import_access.carbon +// TIP: To dump output, run: +// TIP: bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/let/no_prelude/import_access.carbon + +// ============================================================================ +// Setup files +// ============================================================================ + +// --- def.carbon + +package Test library "def"; + +private let v: () = (); + +// ============================================================================ +// Test files +// ============================================================================ + +// --- fail_todo_def.impl.carbon + +impl package Test library "def"; + +// CHECK:STDERR: fail_todo_def.impl.carbon:[[@LINE+4]]:14: ERROR: Name `v` not found. +// CHECK:STDERR: let v2: () = v; +// CHECK:STDERR: ^ +// CHECK:STDERR: +let v2: () = v; + +// --- fail_local_def.carbon + +package Test library "fail_local_def"; + +import library "def"; + +// CHECK:STDERR: fail_local_def.carbon:[[@LINE+4]]:14: ERROR: Name `v` not found. +// CHECK:STDERR: let v2: () = v; +// CHECK:STDERR: ^ +// CHECK:STDERR: +let v2: () = v; + +// --- fail_other_def.carbon + +package Other library "fail_other_def"; + +import Test library "def"; + +// CHECK:STDERR: fail_other_def.carbon:[[@LINE+3]]:14: ERROR: Name `v` not found. +// CHECK:STDERR: let v2: () = Test.v; +// CHECK:STDERR: ^~~~~~ +let v2: () = Test.v; + +// CHECK:STDOUT: --- def.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %.1: type = tuple_type () [template] +// CHECK:STDOUT: %tuple: () = tuple_value () [template] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] {} +// CHECK:STDOUT: %.loc4_17.1: () = tuple_literal () +// CHECK:STDOUT: %.loc4_17.2: type = converted %.loc4_17.1, constants.%.1 [template = constants.%.1] +// CHECK:STDOUT: %.loc4_22: () = tuple_literal () +// CHECK:STDOUT: %tuple: () = tuple_value () [template = constants.%tuple] +// CHECK:STDOUT: %.loc4_23: () = converted %.loc4_22, %tuple [template = constants.%tuple] +// CHECK:STDOUT: %v: () = bind_name v, %.loc4_23 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: --- fail_todo_def.impl.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %.1: type = tuple_type () [template] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] {} +// CHECK:STDOUT: %.loc8_10.1: () = tuple_literal () +// CHECK:STDOUT: %.loc8_10.2: type = converted %.loc8_10.1, constants.%.1 [template = constants.%.1] +// CHECK:STDOUT: %v.ref: = name_ref v, [template = ] +// CHECK:STDOUT: %v2: () = bind_name v2, +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: --- fail_local_def.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %.1: type = tuple_type () [template] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] {} +// CHECK:STDOUT: %.loc10_10.1: () = tuple_literal () +// CHECK:STDOUT: %.loc10_10.2: type = converted %.loc10_10.1, constants.%.1 [template = constants.%.1] +// CHECK:STDOUT: %v.ref: = name_ref v, [template = ] +// CHECK:STDOUT: %v2: () = bind_name v2, +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: --- fail_other_def.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %.1: type = tuple_type () [template] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .Test = %Test +// CHECK:STDOUT: } +// CHECK:STDOUT: %Test: = namespace [template] {} +// CHECK:STDOUT: %.loc9_10.1: () = tuple_literal () +// CHECK:STDOUT: %.loc9_10.2: type = converted %.loc9_10.1, constants.%.1 [template = constants.%.1] +// CHECK:STDOUT: %Test.ref: = name_ref Test, %Test [template = %Test] +// CHECK:STDOUT: %v.ref: = name_ref v, [template = ] +// CHECK:STDOUT: %v2: () = bind_name v2, +// CHECK:STDOUT: } +// CHECK:STDOUT: diff --git a/toolchain/check/testdata/var/no_prelude/fail_modifiers.carbon b/toolchain/check/testdata/var/no_prelude/fail_modifiers.carbon index 5f2df37a41b7..22ceb8b823dc 100644 --- a/toolchain/check/testdata/var/no_prelude/fail_modifiers.carbon +++ b/toolchain/check/testdata/var/no_prelude/fail_modifiers.carbon @@ -14,10 +14,6 @@ // CHECK:STDERR: protected var b: (); -// CHECK:STDERR: fail_modifiers.carbon:[[@LINE+11]]:1: ERROR: Semantics TODO: `access modifier`. -// CHECK:STDERR: private protected var c: (); -// CHECK:STDERR: ^~~~~~~ -// CHECK:STDERR: // CHECK:STDERR: fail_modifiers.carbon:[[@LINE+7]]:9: ERROR: `protected` not allowed on declaration with `private`. // CHECK:STDERR: private protected var c: (); // CHECK:STDERR: ^~~~~~~~~ @@ -54,7 +50,7 @@ abstract var e: (); // CHECK:STDOUT: file { // CHECK:STDOUT: package: = namespace [template] { // CHECK:STDOUT: .b = %b -// CHECK:STDOUT: .c = %c +// CHECK:STDOUT: .c [private] = %c // CHECK:STDOUT: .d = %d // CHECK:STDOUT: .e = %e // CHECK:STDOUT: } @@ -62,16 +58,16 @@ abstract var e: (); // CHECK:STDOUT: %.loc15_19.2: type = converted %.loc15_19.1, constants.%.1 [template = constants.%.1] // CHECK:STDOUT: %b.var: ref () = var b // CHECK:STDOUT: %b: ref () = bind_name b, %b.var -// CHECK:STDOUT: %.loc28_27.1: () = tuple_literal () -// CHECK:STDOUT: %.loc28_27.2: type = converted %.loc28_27.1, constants.%.1 [template = constants.%.1] +// CHECK:STDOUT: %.loc24_27.1: () = tuple_literal () +// CHECK:STDOUT: %.loc24_27.2: type = converted %.loc24_27.1, constants.%.1 [template = constants.%.1] // CHECK:STDOUT: %c.var: ref () = var c // CHECK:STDOUT: %c: ref () = bind_name c, %c.var -// CHECK:STDOUT: %.loc41_29.1: () = tuple_literal () -// CHECK:STDOUT: %.loc41_29.2: type = converted %.loc41_29.1, constants.%.1 [template = constants.%.1] +// CHECK:STDOUT: %.loc37_29.1: () = tuple_literal () +// CHECK:STDOUT: %.loc37_29.2: type = converted %.loc37_29.1, constants.%.1 [template = constants.%.1] // CHECK:STDOUT: %d.var: ref () = var d // CHECK:STDOUT: %d: ref () = bind_name d, %d.var -// CHECK:STDOUT: %.loc46_18.1: () = tuple_literal () -// CHECK:STDOUT: %.loc46_18.2: type = converted %.loc46_18.1, constants.%.1 [template = constants.%.1] +// CHECK:STDOUT: %.loc42_18.1: () = tuple_literal () +// CHECK:STDOUT: %.loc42_18.2: type = converted %.loc42_18.1, constants.%.1 [template = constants.%.1] // CHECK:STDOUT: %e.var: ref () = var e // CHECK:STDOUT: %e: ref () = bind_name e, %e.var // CHECK:STDOUT: } diff --git a/toolchain/check/testdata/var/no_prelude/fail_todo_modifiers.carbon b/toolchain/check/testdata/var/no_prelude/fail_todo_modifiers.carbon deleted file mode 100644 index fe79c589bded..000000000000 --- a/toolchain/check/testdata/var/no_prelude/fail_todo_modifiers.carbon +++ /dev/null @@ -1,31 +0,0 @@ -// 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/check/testdata/var/no_prelude/fail_todo_modifiers.carbon -// TIP: To dump output, run: -// TIP: bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/var/no_prelude/fail_todo_modifiers.carbon - -// CHECK:STDERR: fail_todo_modifiers.carbon:[[@LINE+3]]:1: ERROR: Semantics TODO: `access modifier`. -// CHECK:STDERR: private var a: (); -// CHECK:STDERR: ^~~~~~~ -private var a: (); - -// CHECK:STDOUT: --- fail_todo_modifiers.carbon -// CHECK:STDOUT: -// CHECK:STDOUT: constants { -// CHECK:STDOUT: %.1: type = tuple_type () [template] -// CHECK:STDOUT: } -// CHECK:STDOUT: -// CHECK:STDOUT: file { -// CHECK:STDOUT: package: = namespace [template] { -// CHECK:STDOUT: .a = %a -// CHECK:STDOUT: } -// CHECK:STDOUT: %.loc14_17.1: () = tuple_literal () -// CHECK:STDOUT: %.loc14_17.2: type = converted %.loc14_17.1, constants.%.1 [template = constants.%.1] -// CHECK:STDOUT: %a.var: ref () = var a -// CHECK:STDOUT: %a: ref () = bind_name a, %a.var -// CHECK:STDOUT: } -// CHECK:STDOUT: diff --git a/toolchain/check/testdata/var/no_prelude/import_access.carbon b/toolchain/check/testdata/var/no_prelude/import_access.carbon new file mode 100644 index 000000000000..8542bcad2d34 --- /dev/null +++ b/toolchain/check/testdata/var/no_prelude/import_access.carbon @@ -0,0 +1,155 @@ +// 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/check/testdata/var/no_prelude/import_access.carbon +// TIP: To dump output, run: +// TIP: bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/var/no_prelude/import_access.carbon + +// ============================================================================ +// Setup files +// ============================================================================ + +// --- def.carbon + +package Test library "def"; + +private var v: () = (); + +// ============================================================================ +// Test files +// ============================================================================ + +// --- fail_todo_def.impl.carbon + +impl package Test library "def"; + +// CHECK:STDERR: fail_todo_def.impl.carbon:[[@LINE+4]]:14: ERROR: Name `v` not found. +// CHECK:STDERR: var v2: () = v; +// CHECK:STDERR: ^ +// CHECK:STDERR: +var v2: () = v; + +// --- fail_local_def.carbon + +package Test library "fail_local_def"; + +import library "def"; + +// CHECK:STDERR: fail_local_def.carbon:[[@LINE+4]]:14: ERROR: Name `v` not found. +// CHECK:STDERR: var v2: () = v; +// CHECK:STDERR: ^ +// CHECK:STDERR: +var v2: () = v; + +// --- fail_other_def.carbon + +package Other library "fail_other_def"; + +import Test library "def"; + +// CHECK:STDERR: fail_other_def.carbon:[[@LINE+3]]:14: ERROR: Name `v` not found. +// CHECK:STDERR: var v2: () = Test.v; +// CHECK:STDERR: ^~~~~~ +var v2: () = Test.v; + +// CHECK:STDOUT: --- def.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %.1: type = tuple_type () [template] +// CHECK:STDOUT: %tuple: () = tuple_value () [template] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .v [private] = %v +// CHECK:STDOUT: } +// CHECK:STDOUT: %.loc4_17.1: () = tuple_literal () +// CHECK:STDOUT: %.loc4_17.2: type = converted %.loc4_17.1, constants.%.1 [template = constants.%.1] +// CHECK:STDOUT: %v.var: ref () = var v +// CHECK:STDOUT: %v: ref () = bind_name v, %v.var +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @__global_init() { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %.loc4_22.1: () = tuple_literal () +// CHECK:STDOUT: %.loc4_22.2: init () = tuple_init () to file.%v.var [template = constants.%tuple] +// CHECK:STDOUT: %.loc4_23: init () = converted %.loc4_22.1, %.loc4_22.2 [template = constants.%tuple] +// CHECK:STDOUT: assign file.%v.var, %.loc4_23 +// CHECK:STDOUT: return +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: --- fail_todo_def.impl.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %.1: type = tuple_type () [template] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .v2 = %v2 +// CHECK:STDOUT: } +// CHECK:STDOUT: %.loc8_10.1: () = tuple_literal () +// CHECK:STDOUT: %.loc8_10.2: type = converted %.loc8_10.1, constants.%.1 [template = constants.%.1] +// CHECK:STDOUT: %v2.var: ref () = var v2 +// CHECK:STDOUT: %v2: ref () = bind_name v2, %v2.var +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @__global_init() { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %v.ref: = name_ref v, [template = ] +// CHECK:STDOUT: assign file.%v2.var, +// CHECK:STDOUT: return +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: --- fail_local_def.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %.1: type = tuple_type () [template] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .v2 = %v2 +// CHECK:STDOUT: } +// CHECK:STDOUT: %.loc10_10.1: () = tuple_literal () +// CHECK:STDOUT: %.loc10_10.2: type = converted %.loc10_10.1, constants.%.1 [template = constants.%.1] +// CHECK:STDOUT: %v2.var: ref () = var v2 +// CHECK:STDOUT: %v2: ref () = bind_name v2, %v2.var +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @__global_init() { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %v.ref: = name_ref v, [template = ] +// CHECK:STDOUT: assign file.%v2.var, +// CHECK:STDOUT: return +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: --- fail_other_def.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %.1: type = tuple_type () [template] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .Test = %Test +// CHECK:STDOUT: .v2 = %v2 +// CHECK:STDOUT: } +// CHECK:STDOUT: %Test: = namespace [template] {} +// CHECK:STDOUT: %.loc9_10.1: () = tuple_literal () +// CHECK:STDOUT: %.loc9_10.2: type = converted %.loc9_10.1, constants.%.1 [template = constants.%.1] +// CHECK:STDOUT: %v2.var: ref () = var v2 +// CHECK:STDOUT: %v2: ref () = bind_name v2, %v2.var +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @__global_init() { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %Test.ref: = name_ref Test, file.%Test [template = file.%Test] +// CHECK:STDOUT: %v.ref: = name_ref v, [template = ] +// CHECK:STDOUT: assign file.%v2.var, +// CHECK:STDOUT: return +// CHECK:STDOUT: } +// CHECK:STDOUT: diff --git a/toolchain/sem_ir/formatter.cpp b/toolchain/sem_ir/formatter.cpp index 8084bd1b750a..fcbf24661328 100644 --- a/toolchain/sem_ir/formatter.cpp +++ b/toolchain/sem_ir/formatter.cpp @@ -16,6 +16,7 @@ #include "toolchain/sem_ir/function.h" #include "toolchain/sem_ir/ids.h" #include "toolchain/sem_ir/inst_namer.h" +#include "toolchain/sem_ir/name_scope.h" #include "toolchain/sem_ir/typed_insts.h" namespace Carbon::SemIR { @@ -333,19 +334,30 @@ class Formatter { // Name scopes aren't kept in any particular order. Sort the entries before // we print them for stability and consistency. - llvm::SmallVector> entries; - for (auto [name_id, inst_id] : scope.names) { - entries.push_back({inst_id, name_id}); + llvm::SmallVector> entries; + for (auto [name_id, entry] : scope.names) { + entries.push_back({entry, name_id}); } - llvm::sort(entries, - [](auto a, auto b) { return a.first.index < b.first.index; }); + llvm::sort(entries, [](auto a, auto b) { + return a.first.inst_id.index < b.first.inst_id.index; + }); - for (auto [inst_id, name_id] : entries) { + for (auto [entry, name_id] : entries) { Indent(); out_ << "."; FormatName(name_id); + switch (entry.access_kind) { + case SemIR::AccessKind::Public: + break; + case SemIR::AccessKind::Protected: + out_ << " [protected]"; + break; + case SemIR::AccessKind::Private: + out_ << " [private]"; + break; + } out_ << " = "; - FormatInstName(inst_id); + FormatInstName(entry.inst_id); out_ << "\n"; } diff --git a/toolchain/sem_ir/name_scope.h b/toolchain/sem_ir/name_scope.h index b2e864cb8534..0a1c7944b833 100644 --- a/toolchain/sem_ir/name_scope.h +++ b/toolchain/sem_ir/name_scope.h @@ -10,7 +10,19 @@ namespace Carbon::SemIR { +// Access control for an entity. +enum class AccessKind : int8_t { + Public, + Protected, + Private, +}; + struct NameScope : Printable { + struct Entry { + InstId inst_id; + AccessKind access_kind; + }; + auto Print(llvm::raw_ostream& out) const -> void { out << "{inst: " << inst_id << ", parent_scope: " << parent_scope_id << ", has_error: " << (has_error ? "true" : "false"); @@ -32,7 +44,7 @@ struct NameScope : Printable { [](NameId lhs, NameId rhs) { return lhs.index < rhs.index; }); llvm::ListSeparator key_sep; for (auto key : keys) { - out << key_sep << key << ": " << names.find(key)->second; + out << key_sep << key << ": " << names.find(key)->second.inst_id; } out << "}"; @@ -40,7 +52,7 @@ struct NameScope : Printable { } // Names in the scope. - llvm::DenseMap names = llvm::DenseMap(); + llvm::DenseMap names = llvm::DenseMap(); // Scopes extended by this scope. // @@ -98,6 +110,16 @@ class NameScopeStore { .parent_scope_id = parent_scope_id}); } + // Adds a name that is required to exist in a name scope, such as `Self`. + // These must never conflict. + auto AddRequiredName(NameScopeId scope_id, NameId name_id, InstId inst_id) + -> void { + NameScope::Entry entry = {.inst_id = inst_id, + .access_kind = AccessKind::Public}; + auto success = Get(scope_id).names.insert({name_id, entry}).second; + CARBON_CHECK(success) << "Failed to add required name: " << name_id; + } + // Returns the requested name scope. auto Get(NameScopeId scope_id) -> NameScope& { return values_.Get(scope_id); }