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); }