diff --git a/toolchain/check/decl_introducer_state.h b/toolchain/check/decl_introducer_state.h index ade36dc9310b..193223a5126c 100644 --- a/toolchain/check/decl_introducer_state.h +++ b/toolchain/check/decl_introducer_state.h @@ -35,6 +35,9 @@ struct DeclIntroducerState { // Invariant: contains just the modifiers represented by `saw_*_modifier`. KeywordModifierSet modifier_set = KeywordModifierSet(); + + // If there's an `extern library` in use, the library name. + SemIR::LibraryNameId extern_library = SemIR::LibraryNameId::Invalid; }; // Stack of `DeclIntroducerState` values, representing all the declaration diff --git a/toolchain/check/decl_name_stack.h b/toolchain/check/decl_name_stack.h index f0d87c280e73..fd87dbc4c575 100644 --- a/toolchain/check/decl_name_stack.h +++ b/toolchain/check/decl_name_stack.h @@ -91,7 +91,8 @@ class DeclNameStack { // Combines name information to produce a base struct for entity // construction. auto MakeEntityWithParamsBase(const NameComponent& name, - SemIR::InstId decl_id, bool is_extern) + SemIR::InstId decl_id, bool is_extern, + SemIR::LibraryNameId extern_library) -> SemIR::EntityWithParamsBase { return { .name_id = name_id_for_new_inst(), @@ -102,9 +103,11 @@ class DeclNameStack { .implicit_param_refs_id = name.implicit_params_id, .param_refs_id = name.params_id, .is_extern = is_extern, - .extern_library_id = StringLiteralValueId::Invalid, - .non_owning_decl_id = SemIR::InstId::Invalid, - .first_owning_decl_id = decl_id, + .extern_library_id = extern_library, + .non_owning_decl_id = + extern_library.is_valid() ? decl_id : SemIR::InstId::Invalid, + .first_owning_decl_id = + extern_library.is_valid() ? SemIR::InstId::Invalid : decl_id, }; } diff --git a/toolchain/check/global_init.cpp b/toolchain/check/global_init.cpp index e08a10f2499e..03ce55569318 100644 --- a/toolchain/check/global_init.cpp +++ b/toolchain/check/global_init.cpp @@ -43,7 +43,7 @@ auto GlobalInit::Finalize() -> void { .implicit_param_refs_id = SemIR::InstBlockId::Invalid, .param_refs_id = SemIR::InstBlockId::Empty, .is_extern = false, - .extern_library_id = StringLiteralValueId::Invalid, + .extern_library_id = SemIR::LibraryNameId::Invalid, .non_owning_decl_id = SemIR::InstId::Invalid, .first_owning_decl_id = SemIR::InstId::Invalid}, {.return_storage_id = SemIR::InstId::Invalid, diff --git a/toolchain/check/handle_class.cpp b/toolchain/check/handle_class.cpp index 738192e3758f..ed2dd897482e 100644 --- a/toolchain/check/handle_class.cpp +++ b/toolchain/check/handle_class.cpp @@ -52,8 +52,8 @@ auto HandleParseNode(Context& context, Parse::ClassIntroducerId node_id) // Otherwise, returns false. Prints a diagnostic when appropriate. static auto MergeClassRedecl(Context& context, SemIRLoc new_loc, SemIR::Class& new_class, bool new_is_import, - bool new_is_definition, bool new_is_extern, - SemIR::ClassId prev_class_id, bool prev_is_extern, + bool new_is_definition, + SemIR::ClassId prev_class_id, SemIR::ImportIRId prev_import_ir_id) -> bool { auto& prev_class = context.classes().Get(prev_class_id); SemIRLoc prev_loc = prev_class.latest_decl_id(); @@ -64,14 +64,11 @@ static auto MergeClassRedecl(Context& context, SemIRLoc new_loc, return false; } - CheckIsAllowedRedecl(context, Lex::TokenKind::Class, prev_class.name_id, - {.loc = new_loc, - .is_definition = new_is_definition, - .is_extern = new_is_extern}, - {.loc = prev_loc, - .is_definition = prev_class.is_defined(), - .is_extern = prev_is_extern}, - prev_import_ir_id); + CheckIsAllowedRedecl( + context, Lex::TokenKind::Class, prev_class.name_id, + RedeclInfo(new_class, new_loc, new_is_definition), + RedeclInfo(prev_class, prev_loc, prev_class.is_defined()), + prev_import_ir_id); if (new_is_definition && prev_class.is_defined()) { // Don't attempt to merge multiple definitions. @@ -101,7 +98,7 @@ static auto MergeClassRedecl(Context& context, SemIRLoc new_loc, } if ((prev_import_ir_id.is_valid() && !new_is_import) || - (prev_is_extern && !new_is_extern)) { + (prev_class.is_extern && !new_class.is_extern)) { prev_class.first_owning_decl_id = new_class.first_owning_decl_id; ReplacePrevInstForMerge( context, prev_class.parent_scope_id, prev_class.name_id, @@ -117,8 +114,7 @@ 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, SemIR::AccessKind access_kind) - -> void { + 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()) { @@ -168,10 +164,10 @@ static auto MergeOrAddName(Context& context, Parse::AnyClassDeclId node_id, return; } - // TODO: Fix prev_is_extern logic. + // TODO: Fix `extern` logic. It doesn't work correctly, but doesn't seem worth + // ripping out because existing code may incrementally help. if (MergeClassRedecl(context, node_id, class_info, - /*new_is_import=*/false, is_definition, is_extern, - prev_class_id, /*prev_is_extern=*/false, + /*new_is_import=*/false, is_definition, prev_class_id, prev_import_ir_id)) { // When merging, use the existing entity rather than adding a new one. class_decl.class_id = prev_class_id; @@ -201,6 +197,9 @@ static auto BuildClassDecl(Context& context, Parse::AnyClassDeclId node_id, is_definition); bool is_extern = introducer.modifier_set.HasAnyOf(KeywordModifierSet::Extern); + if (introducer.extern_library.is_valid()) { + context.TODO(node_id, "extern library"); + } auto inheritance_kind = introducer.modifier_set.HasAnyOf(KeywordModifierSet::Abstract) ? SemIR::Class::Abstract @@ -219,7 +218,8 @@ static auto BuildClassDecl(Context& context, Parse::AnyClassDeclId node_id, // TODO: Store state regarding is_extern. SemIR::Class class_info = { - name_context.MakeEntityWithParamsBase(name, class_decl_id, is_extern), + name_context.MakeEntityWithParamsBase(name, class_decl_id, is_extern, + SemIR::LibraryNameId::Invalid), {// `.self_type_id` depends on the ClassType, so is set below. .self_type_id = SemIR::TypeId::Invalid, .inheritance_kind = inheritance_kind}}; @@ -228,7 +228,7 @@ static auto BuildClassDecl(Context& context, Parse::AnyClassDeclId node_id, RequireGenericParams(context, class_info.param_refs_id); MergeOrAddName(context, node_id, name_context, class_decl_id, class_decl, - class_info, is_definition, is_extern, + class_info, is_definition, introducer.modifier_set.GetAccessKind()); // Create a new class if this isn't a valid redeclaration. diff --git a/toolchain/check/handle_function.cpp b/toolchain/check/handle_function.cpp index 9801cf457ce1..f6c370bf4db0 100644 --- a/toolchain/check/handle_function.cpp +++ b/toolchain/check/handle_function.cpp @@ -82,12 +82,9 @@ static auto MergeFunctionRedecl(Context& context, SemIRLoc new_loc, } CheckIsAllowedRedecl(context, Lex::TokenKind::Fn, prev_function.name_id, - {.loc = new_loc, - .is_definition = new_is_definition, - .is_extern = new_function.is_extern}, - {.loc = prev_function.latest_decl_id(), - .is_definition = prev_function.definition_id.is_valid(), - .is_extern = prev_function.is_extern}, + RedeclInfo(new_function, new_loc, new_is_definition), + RedeclInfo(prev_function, prev_function.latest_decl_id(), + prev_function.definition_id.is_valid()), prev_import_ir_id); if (new_is_definition) { @@ -216,9 +213,10 @@ static auto BuildFunctionDecl(Context& context, // Build the function entity. This will be merged into an existing function if // there is one, or otherwise added to the function store. - auto function_info = SemIR::Function{ - {name_context.MakeEntityWithParamsBase(name, decl_id, is_extern)}, - {.return_storage_id = return_storage_id}}; + auto function_info = + SemIR::Function{{name_context.MakeEntityWithParamsBase( + name, decl_id, is_extern, introducer.extern_library)}, + {.return_storage_id = return_storage_id}}; if (is_definition) { function_info.definition_id = decl_id; } diff --git a/toolchain/check/handle_import_and_package.cpp b/toolchain/check/handle_import_and_package.cpp index fc0420eb01a6..e52dc8900e34 100644 --- a/toolchain/check/handle_import_and_package.cpp +++ b/toolchain/check/handle_import_and_package.cpp @@ -20,6 +20,7 @@ auto HandleParseNode(Context& context, Parse::ImportIntroducerId /*node_id*/) auto HandleParseNode(Context& context, Parse::ImportDeclId /*node_id*/) -> bool { + context.node_stack().PopIf(); auto introducer = context.decl_introducer_state_stack().Pop(); LimitModifiersOnDecl(context, introducer, KeywordModifierSet::Export); @@ -34,6 +35,7 @@ auto HandleParseNode(Context& context, Parse::LibraryIntroducerId /*node_id*/) auto HandleParseNode(Context& context, Parse::LibraryDeclId /*node_id*/) -> bool { + context.node_stack().PopIf(); auto introducer = context.decl_introducer_state_stack().Pop(); LimitModifiersOnDecl(context, introducer, KeywordModifierSet::Impl); @@ -48,14 +50,16 @@ auto HandleParseNode(Context& context, Parse::PackageIntroducerId /*node_id*/) auto HandleParseNode(Context& context, Parse::PackageDeclId /*node_id*/) -> bool { + context.node_stack().PopIf(); auto introducer = context.decl_introducer_state_stack().Pop(); LimitModifiersOnDecl(context, introducer, KeywordModifierSet::Impl); return true; } -auto HandleParseNode(Context& /*context*/, - Parse::LibrarySpecifierId /*node_id*/) -> bool { +auto HandleParseNode(Context& context, Parse::LibrarySpecifierId /*node_id*/) + -> bool { + CARBON_CHECK(context.node_stack().PeekIs()); return true; } @@ -64,13 +68,19 @@ auto HandleParseNode(Context& /*context*/, Parse::PackageNameId /*node_id*/) return true; } -auto HandleParseNode(Context& /*context*/, Parse::LibraryNameId /*node_id*/) - -> bool { +auto HandleParseNode(Context& context, Parse::LibraryNameId node_id) -> bool { + // This is discarded in this file's uses, but is used by modifiers for `extern + // library`. + auto literal_id = context.tokens().GetStringLiteralValue( + context.parse_tree().node_token(node_id)); + context.node_stack().Push( + node_id, SemIR::LibraryNameId::ForStringLiteralValueId(literal_id)); return true; } -auto HandleParseNode(Context& /*context*/, Parse::DefaultLibraryId /*node_id*/) +auto HandleParseNode(Context& context, Parse::DefaultLibraryId node_id) -> bool { + context.node_stack().Push(node_id, SemIR::LibraryNameId::Default); return true; } diff --git a/toolchain/check/handle_interface.cpp b/toolchain/check/handle_interface.cpp index 72e95e33826c..dfd6e2019df1 100644 --- a/toolchain/check/handle_interface.cpp +++ b/toolchain/check/handle_interface.cpp @@ -54,7 +54,8 @@ static auto BuildInterfaceDecl(Context& context, context.AddPlaceholderInst(SemIR::LocIdAndInst(node_id, interface_decl)); SemIR::Interface interface_info = {name_context.MakeEntityWithParamsBase( - name, interface_decl_id, /*is_extern=*/false)}; + name, interface_decl_id, /*is_extern=*/false, + SemIR::LibraryNameId::Invalid)}; RequireGenericParams(context, interface_info.implicit_param_refs_id); RequireGenericParams(context, interface_info.param_refs_id); @@ -75,15 +76,12 @@ static auto BuildInterfaceDecl(Context& context, // TODO: This should be refactored a little, particularly for // prev_import_ir_id. See similar logic for classes and functions, which // might also be refactored to merge. - CheckIsAllowedRedecl(context, Lex::TokenKind::Interface, - existing_interface.name_id, - {.loc = node_id, - .is_definition = is_definition, - .is_extern = false}, - {.loc = existing_interface.latest_decl_id(), - .is_definition = existing_interface.is_defined(), - .is_extern = false}, - /*prev_import_ir_id=*/SemIR::ImportIRId::Invalid); + CheckIsAllowedRedecl( + context, Lex::TokenKind::Interface, existing_interface.name_id, + RedeclInfo(interface_info, node_id, is_definition), + RedeclInfo(existing_interface, existing_interface.latest_decl_id(), + existing_interface.is_defined()), + /*prev_import_ir_id=*/SemIR::ImportIRId::Invalid); // Can't merge interface definitions due to the generic requirements. // TODO: Should this also be mirrored to classes/functions for generics? diff --git a/toolchain/check/handle_modifier.cpp b/toolchain/check/handle_modifier.cpp index 3cf89bb312f1..66845a771af6 100644 --- a/toolchain/check/handle_modifier.cpp +++ b/toolchain/check/handle_modifier.cpp @@ -34,6 +34,10 @@ static auto DiagnoseNotAllowedWith(Context& context, Parse::NodeId first_node, .Emit(); } +// Handles the keyword that starts a modifier. This may a standalone keyword, +// such as `private`, or the first in a complex modifier, such as `extern` in +// `extern library ...`. If valid, adds it to the modifier set and returns true. +// Otherwise, diagnoses and returns false. static auto HandleModifier(Context& context, Parse::NodeId node_id, KeywordModifierSet keyword) -> bool { auto& s = context.decl_introducer_state_stack().innermost(); @@ -54,10 +58,14 @@ static auto HandleModifier(Context& context, Parse::NodeId node_id, auto current_modifier_node_id = s.modifier_node_id(order); if (s.modifier_set.HasAnyOf(keyword)) { DiagnoseRepeated(context, current_modifier_node_id, node_id); - } else if (current_modifier_node_id.is_valid()) { + return false; + } + if (current_modifier_node_id.is_valid()) { DiagnoseNotAllowedWith(context, current_modifier_node_id, node_id); - } else if (auto later_modifier_set = s.modifier_set & later_modifiers; - !later_modifier_set.empty()) { + return false; + } + if (auto later_modifier_set = s.modifier_set & later_modifiers; + !later_modifier_set.empty()) { // At least one later modifier is present. Diagnose using the closest. Parse::NodeId closest_later_modifier = Parse::NodeId::Invalid; for (auto later_order = static_cast(order) + 1; @@ -79,10 +87,11 @@ static auto HandleModifier(Context& context, Parse::NodeId node_id, .Note(closest_later_modifier, ModifierPrevious, context.token_kind(closest_later_modifier)) .Emit(); - } else { - s.modifier_set.Add(keyword); - s.set_modifier_node_id(order, node_id); + return false; } + + s.modifier_set.Add(keyword); + s.set_modifier_node_id(order, node_id); return true; } @@ -90,13 +99,19 @@ static auto HandleModifier(Context& context, Parse::NodeId node_id, #define CARBON_PARSE_NODE_KIND_TOKEN_MODIFIER(Name, ...) \ auto HandleParseNode(Context& context, Parse::Name##ModifierId node_id) \ -> bool { \ - return HandleModifier(context, node_id, KeywordModifierSet::Name); \ + HandleModifier(context, node_id, KeywordModifierSet::Name); \ + return true; \ } #include "toolchain/parse/node_kind.def" auto HandleParseNode(Context& context, Parse::ExternModifierWithLibraryId node_id) -> bool { - return context.TODO(node_id, "extern library syntax"); + auto name_literal_id = context.node_stack().Pop(); + if (HandleModifier(context, node_id, KeywordModifierSet::Extern)) { + auto& s = context.decl_introducer_state_stack().innermost(); + s.extern_library = name_literal_id; + } + return true; } auto HandleParseNode(Context& context, Parse::ExternModifierId node_id) diff --git a/toolchain/check/handle_struct.cpp b/toolchain/check/handle_struct.cpp index dde097e5de8e..63788b7e662f 100644 --- a/toolchain/check/handle_struct.cpp +++ b/toolchain/check/handle_struct.cpp @@ -29,7 +29,7 @@ auto HandleParseNode(Context& context, Parse::StructLiteralStartId node_id) auto HandleParseNode(Context& context, Parse::StructFieldDesignatorId /*node_id*/) -> bool { // This leaves the designated name on top because the `.` isn't interesting. - CARBON_CHECK(context.node_stack().PeekIsName()); + CARBON_CHECK(context.node_stack().PeekIs()); return true; } diff --git a/toolchain/check/import_ref.cpp b/toolchain/check/import_ref.cpp index d39978c8b0b5..0dd640f93abd 100644 --- a/toolchain/check/import_ref.cpp +++ b/toolchain/check/import_ref.cpp @@ -844,6 +844,19 @@ class ImportRefResolver { auto GetIncompleteLocalEntityBase( SemIR::InstId decl_id, const SemIR::EntityWithParamsBase& import_base) -> SemIR::EntityWithParamsBase { + // Translate the extern_library_id if present. + auto extern_library_id = SemIR::LibraryNameId::Invalid; + if (import_base.extern_library_id.is_valid()) { + if (import_base.extern_library_id.index >= 0) { + auto val = import_ir_.string_literal_values().Get( + import_base.extern_library_id.AsStringLiteralValueId()); + extern_library_id = SemIR::LibraryNameId::ForStringLiteralValueId( + context_.string_literal_values().Add(val)); + } else { + extern_library_id = import_base.extern_library_id; + } + } + return { .name_id = GetLocalNameId(import_base.name_id), .parent_scope_id = SemIR::NameScopeId::Invalid, @@ -857,9 +870,13 @@ class ImportRefResolver { ? SemIR::InstBlockId::Empty : SemIR::InstBlockId::Invalid, .is_extern = import_base.is_extern, - .extern_library_id = StringLiteralValueId::Invalid, - .non_owning_decl_id = SemIR::InstId::Invalid, - .first_owning_decl_id = decl_id, + .extern_library_id = extern_library_id, + .non_owning_decl_id = import_base.non_owning_decl_id.is_valid() + ? decl_id + : SemIR::InstId::Invalid, + .first_owning_decl_id = import_base.first_owning_decl_id.is_valid() + ? decl_id + : SemIR::InstId::Invalid, }; } @@ -1373,7 +1390,7 @@ class ImportRefResolver { .decl_block_id = SemIR::InstBlockId::Empty}; auto function_decl_id = context_.AddPlaceholderInstInNoBlock(SemIR::LocIdAndInst( - AddImportIRInst(import_function.latest_decl_id()), function_decl)); + AddImportIRInst(import_function.first_decl_id()), function_decl)); // Start with an incomplete function. function_decl.function_id = context_.functions().Add( @@ -1471,7 +1488,7 @@ class ImportRefResolver { auto TryResolveTypedInst(SemIR::FunctionType inst) -> ResolveResult { CARBON_CHECK(inst.type_id == SemIR::TypeId::TypeType); auto fn_val_id = GetLocalConstantInstId( - import_ir_.functions().Get(inst.function_id).first_owning_decl_id); + import_ir_.functions().Get(inst.function_id).first_decl_id()); auto specific_data = GetLocalSpecificData(inst.specific_id); if (HasNewWork()) { return Retry(); diff --git a/toolchain/check/merge.cpp b/toolchain/check/merge.cpp index 3e01c623d647..3a441e257153 100644 --- a/toolchain/check/merge.cpp +++ b/toolchain/check/merge.cpp @@ -44,8 +44,7 @@ static auto DiagnoseExternMismatch(Context& context, Lex::TokenKind decl_kind, SemIR::NameId name_id, SemIRLoc new_loc, SemIRLoc prev_loc) { CARBON_DIAGNOSTIC(RedeclExternMismatch, Error, - "Redeclarations of `{0} {1}` in the same library must " - "match use of `extern`.", + "Redeclarations of `{0} {1}` must match use of `extern`.", Lex::TokenKind, SemIR::NameId); context.emitter() .Build(new_loc, RedeclExternMismatch, decl_kind, name_id) @@ -53,19 +52,36 @@ static auto DiagnoseExternMismatch(Context& context, Lex::TokenKind decl_kind, .Emit(); } -// Diagnoses when multiple non-`extern` declarations are found. -static auto DiagnoseNonExtern(Context& context, Lex::TokenKind decl_kind, - SemIR::NameId name_id, SemIRLoc new_loc, - SemIRLoc prev_loc) { - CARBON_DIAGNOSTIC(RedeclNonExtern, Error, - "Only one library can declare `{0} {1}` without `extern`.", +// Diagnoses `extern library` declared in a library importing the owned entity. +static auto DiagnoseExternLibraryInImporter(Context& context, + Lex::TokenKind decl_kind, + SemIR::NameId name_id, + SemIRLoc new_loc, + SemIRLoc prev_loc) { + CARBON_DIAGNOSTIC(ExternLibraryInImporter, Error, + "Cannot declare imported `{0} {1}` as `extern library`.", Lex::TokenKind, SemIR::NameId); context.emitter() - .Build(new_loc, RedeclNonExtern, decl_kind, name_id) + .Build(new_loc, ExternLibraryInImporter, decl_kind, name_id) .Note(prev_loc, RedeclPrevDecl) .Emit(); } +// Diagnoses `extern library` pointing to the wrong library. +static auto DiagnoseExternLibraryIncorrect(Context& context, SemIRLoc new_loc, + SemIRLoc prev_loc) { + CARBON_DIAGNOSTIC( + ExternLibraryIncorrect, Error, + "Declaration in {0} doesn't match `extern library` declaration.", + SemIR::LibraryNameId); + CARBON_DIAGNOSTIC(ExternLibraryExpected, Note, + "Previously declared with `extern library` here."); + context.emitter() + .Build(new_loc, ExternLibraryIncorrect, context.sem_ir().library_id()) + .Note(prev_loc, ExternLibraryExpected) + .Emit(); +} + // Checks to see if a structurally valid redeclaration is allowed in context. // These all still merge. auto CheckIsAllowedRedecl(Context& context, Lex::TokenKind decl_kind, @@ -83,9 +99,7 @@ auto CheckIsAllowedRedecl(Context& context, Lex::TokenKind decl_kind, DiagnoseRedef(context, decl_kind, name_id, new_decl.loc, prev_decl.loc); return; } - // `extern` definitions are prevented at creation; this is only - // checking for a non-`extern` definition after an `extern` declaration. - if (prev_decl.is_extern) { + if (prev_decl.is_extern != new_decl.is_extern) { DiagnoseExternMismatch(context, decl_kind, name_id, new_decl.loc, prev_decl.loc); return; @@ -114,10 +128,25 @@ auto CheckIsAllowedRedecl(Context& context, Lex::TokenKind decl_kind, } // Check for disallowed redeclarations cross-library. - if (!new_decl.is_extern && !prev_decl.is_extern) { - DiagnoseNonExtern(context, decl_kind, name_id, new_decl.loc, prev_decl.loc); + if (prev_decl.is_extern != new_decl.is_extern) { + DiagnoseExternMismatch(context, decl_kind, name_id, new_decl.loc, + prev_decl.loc); return; } + if (!prev_decl.extern_library_id.is_valid()) { + if (new_decl.extern_library_id.is_valid()) { + DiagnoseExternLibraryInImporter(context, decl_kind, name_id, new_decl.loc, + prev_decl.loc); + } else { + DiagnoseRedundant(context, decl_kind, name_id, new_decl.loc, + prev_decl.loc); + } + return; + } + if (prev_decl.extern_library_id != SemIR::LibraryNameId::Error && + prev_decl.extern_library_id != context.sem_ir().library_id()) { + DiagnoseExternLibraryIncorrect(context, new_decl.loc, prev_decl.loc); + } } auto ReplacePrevInstForMerge(Context& context, SemIR::NameScopeId scope_id, diff --git a/toolchain/check/merge.h b/toolchain/check/merge.h index 88202d687ceb..16468e4ff185 100644 --- a/toolchain/check/merge.h +++ b/toolchain/check/merge.h @@ -13,12 +13,21 @@ namespace Carbon::Check { // Information on new and previous declarations for CheckIsAllowedRedecl. struct RedeclInfo { + explicit RedeclInfo(SemIR::EntityWithParamsBase params, SemIRLoc loc, + bool is_definition) + : loc(loc), + is_definition(is_definition), + is_extern(params.is_extern), + extern_library_id(params.extern_library_id) {} + // The associated diagnostic location. SemIRLoc loc; // True if a definition. bool is_definition; // True if an `extern` declaration. bool is_extern; + // The library name in `extern library`, or invalid if not present. + SemIR::LibraryNameId extern_library_id; }; // Checks if a redeclaration is allowed prior to merging. This may emit a diff --git a/toolchain/check/modifiers.cpp b/toolchain/check/modifiers.cpp index 1caf82995b14..17092bd27164 100644 --- a/toolchain/check/modifiers.cpp +++ b/toolchain/check/modifiers.cpp @@ -120,13 +120,35 @@ auto RestrictExternModifierOnDecl(Context& context, DeclIntroducerState& introducer, std::optional parent_scope_inst, bool is_definition) -> void { - if (is_definition) { - ForbidModifiersOnDecl(context, introducer, KeywordModifierSet::Extern, - " that provides a definition"); + if (!introducer.modifier_set.HasAnyOf(KeywordModifierSet::Extern)) { + return; } + if (parent_scope_inst && !parent_scope_inst->Is()) { ForbidModifiersOnDecl(context, introducer, KeywordModifierSet::Extern, " that is a member"); + // Treat as unset. + introducer.extern_library = SemIR::LibraryNameId::Invalid; + return; + } + + if (introducer.extern_library == context.sem_ir().library_id()) { + // This prints an error for `extern library`, but doesn't drop it because we + // assume there is some other, correct value that we just don't know here. + CARBON_DIAGNOSTIC(ExternLibraryIsCurrentLibrary, Error, + "`extern library` cannot specify the current library."); + context.emitter().Emit(introducer.modifier_node_id(ModifierOrder::Extern), + ExternLibraryIsCurrentLibrary); + introducer.extern_library = SemIR::LibraryNameId::Error; + // Right now this can produce both this and the below diagnostic. + } + + if (is_definition && introducer.extern_library.is_valid()) { + CARBON_DIAGNOSTIC(ExternLibraryOnDefinition, Error, + "A library cannot be provided for an `extern` modifier " + "on a definition."); + context.emitter().Emit(introducer.modifier_node_id(ModifierOrder::Extern), + ExternLibraryOnDefinition); } } diff --git a/toolchain/check/modifiers.h b/toolchain/check/modifiers.h index 002b5f12959b..fef07c00b0fc 100644 --- a/toolchain/check/modifiers.h +++ b/toolchain/check/modifiers.h @@ -47,8 +47,8 @@ inline auto LimitModifiersOnDecl(Context& context, } // Restricts the `extern` modifier to only be used on namespace-scoped -// declarations, diagnosing and removing it on: -// - `extern` on a definition. +// declarations. Diagnoses and cleans up: +// - `extern library` on a definition. // - `extern` on a scoped entity. // // `parent_scope_inst` may be nullopt for a declaration in a block scope. diff --git a/toolchain/check/node_stack.h b/toolchain/check/node_stack.h index 463979cb8105..b4bb8b87dc9d 100644 --- a/toolchain/check/node_stack.h +++ b/toolchain/check/node_stack.h @@ -130,10 +130,12 @@ class NodeStack { return PeekIs(RequiredParseCategory); } - // Returns whether there is a name on top of the stack. - auto PeekIsName() const -> bool { + // Returns whether there is a node with the corresponding ID on top of the + // stack. + template + auto PeekIs() const -> bool { return !stack_.empty() && - NodeKindToIdKind(PeekNodeKind()) == Id::KindFor(); + NodeKindToIdKind(PeekNodeKind()) == Id::KindFor(); } // Returns whether the *next* node on the stack is a given kind. This doesn't @@ -274,6 +276,16 @@ class NodeStack { return std::nullopt; } + // Pops the top of the stack if it has the given category, and returns the ID. + // Otherwise returns std::nullopt. + template + auto PopIf() -> std::optional { + if (PeekIs()) { + return Pop(); + } + return std::nullopt; + } + // Pops the top of the stack and returns the node_id and the ID if it is // of the specified kind. template @@ -436,6 +448,9 @@ class NodeStack { return Id::KindFor(); case Parse::NodeKind::SelfValueName: return Id::KindFor(); + case Parse::NodeKind::DefaultLibrary: + case Parse::NodeKind::LibraryName: + return Id::KindFor(); case Parse::NodeKind::ArrayExprSemi: case Parse::NodeKind::BuiltinName: case Parse::NodeKind::ClassIntroducer: diff --git a/toolchain/check/sem_ir_diagnostic_converter.cpp b/toolchain/check/sem_ir_diagnostic_converter.cpp index 3a062968445a..f85d688adebf 100644 --- a/toolchain/check/sem_ir_diagnostic_converter.cpp +++ b/toolchain/check/sem_ir_diagnostic_converter.cpp @@ -113,6 +113,21 @@ auto SemIRDiagnosticConverter::ConvertLoc(SemIRLoc loc, } auto SemIRDiagnosticConverter::ConvertArg(llvm::Any arg) const -> llvm::Any { + if (auto* library_name_id = llvm::any_cast(&arg)) { + std::string library_name; + if (*library_name_id == SemIR::LibraryNameId::Default) { + library_name = "default library"; + } else if (!library_name_id->is_valid()) { + library_name = "library "; + } else { + llvm::raw_string_ostream stream(library_name); + stream << "library \""; + stream << sem_ir_->string_literal_values().Get( + library_name_id->AsStringLiteralValueId()); + stream << "\""; + } + return library_name; + } if (auto* name_id = llvm::any_cast(&arg)) { return sem_ir_->names().GetFormatted(*name_id).str(); } diff --git a/toolchain/check/testdata/class/fail_import_misuses.carbon b/toolchain/check/testdata/class/fail_import_misuses.carbon index 04ee287d48d4..7efa584bd477 100644 --- a/toolchain/check/testdata/class/fail_import_misuses.carbon +++ b/toolchain/check/testdata/class/fail_import_misuses.carbon @@ -23,7 +23,7 @@ library "b"; import library "a"; -// CHECK:STDERR: fail_b.carbon:[[@LINE+10]]:1: ERROR: Only one library can declare `class Empty` without `extern`. +// CHECK:STDERR: fail_b.carbon:[[@LINE+10]]:1: ERROR: Redeclaration of `class Empty` is redundant. // CHECK:STDERR: class Empty { // CHECK:STDERR: ^~~~~~~~~~~~~ // CHECK:STDERR: fail_b.carbon:[[@LINE-5]]:1: In import. diff --git a/toolchain/check/testdata/class/fail_modifiers.carbon b/toolchain/check/testdata/class/fail_modifiers.carbon index d90888257d32..e14b90cbe81a 100644 --- a/toolchain/check/testdata/class/fail_modifiers.carbon +++ b/toolchain/check/testdata/class/fail_modifiers.carbon @@ -61,20 +61,14 @@ protected virtual base class Virtual {} // CHECK:STDERR: abstract protected class WrongOrder; -// CHECK:STDERR: fail_modifiers.carbon:[[@LINE+7]]:10: ERROR: `base` not allowed on declaration with `abstract`. +// CHECK:STDERR: fail_modifiers.carbon:[[@LINE+6]]:10: ERROR: `base` not allowed on declaration with `abstract`. // CHECK:STDERR: abstract base class AbstractAndBase {} // CHECK:STDERR: ^~~~ -// CHECK:STDERR: fail_modifiers.carbon:[[@LINE+4]]:1: `abstract` previously appeared here. +// CHECK:STDERR: fail_modifiers.carbon:[[@LINE+3]]:1: `abstract` previously appeared here. // CHECK:STDERR: abstract base class AbstractAndBase {} // CHECK:STDERR: ^~~~~~~~ -// CHECK:STDERR: abstract base class AbstractAndBase {} -// CHECK:STDERR: fail_modifiers.carbon:[[@LINE+3]]:1: ERROR: `extern` not allowed on `class` declaration that provides a definition. -// CHECK:STDERR: extern class ExternDefined {} -// CHECK:STDERR: ^~~~~~ -extern class ExternDefined {} - // CHECK:STDOUT: --- fail_modifiers.carbon // CHECK:STDOUT: // CHECK:STDOUT: constants { @@ -85,7 +79,6 @@ extern class ExternDefined {} // CHECK:STDOUT: %Virtual: type = class_type @Virtual [template] // CHECK:STDOUT: %WrongOrder: type = class_type @WrongOrder [template] // CHECK:STDOUT: %AbstractAndBase: type = class_type @AbstractAndBase [template] -// CHECK:STDOUT: %ExternDefined: type = class_type @ExternDefined [template] // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: imports { @@ -109,7 +102,6 @@ extern class ExternDefined {} // CHECK:STDOUT: .Virtual = %Virtual.decl // CHECK:STDOUT: .WrongOrder = %WrongOrder.decl // CHECK:STDOUT: .AbstractAndBase = %AbstractAndBase.decl -// CHECK:STDOUT: .ExternDefined = %ExternDefined.decl // CHECK:STDOUT: } // CHECK:STDOUT: %Core.import = import Core // CHECK:STDOUT: %DuplicatePrivate.decl: type = class_decl @DuplicatePrivate [template = constants.%DuplicatePrivate] {} @@ -118,7 +110,6 @@ extern class ExternDefined {} // CHECK:STDOUT: %Virtual.decl: type = class_decl @Virtual [template = constants.%Virtual] {} // CHECK:STDOUT: %WrongOrder.decl: type = class_decl @WrongOrder [template = constants.%WrongOrder] {} // CHECK:STDOUT: %AbstractAndBase.decl: type = class_decl @AbstractAndBase [template = constants.%AbstractAndBase] {} -// CHECK:STDOUT: %ExternDefined.decl: type = class_decl @ExternDefined [template = constants.%ExternDefined] {} // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: class @DuplicatePrivate; @@ -142,8 +133,3 @@ extern class ExternDefined {} // CHECK:STDOUT: .Self = constants.%AbstractAndBase // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: class @ExternDefined { -// CHECK:STDOUT: !members: -// CHECK:STDOUT: .Self = constants.%ExternDefined -// CHECK:STDOUT: } -// CHECK:STDOUT: diff --git a/toolchain/check/testdata/class/extern.carbon b/toolchain/check/testdata/class/no_prelude/extern.carbon similarity index 56% rename from toolchain/check/testdata/class/extern.carbon rename to toolchain/check/testdata/class/no_prelude/extern.carbon index 7dfc8a5511d3..963cc77971ce 100644 --- a/toolchain/check/testdata/class/extern.carbon +++ b/toolchain/check/testdata/class/no_prelude/extern.carbon @@ -4,9 +4,9 @@ // // AUTOUPDATE // TIP: To test this file alone, run: -// TIP: bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/class/extern.carbon +// TIP: bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/class/no_prelude/extern.carbon // TIP: To dump output, run: -// TIP: bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/class/extern.carbon +// TIP: bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/class/no_prelude/extern.carbon // ============================================================================ // Setup files @@ -54,14 +54,10 @@ extern class C; // CHECK:STDERR: fn C.F(); -// --- fail_extern_def.carbon +// --- extern_def.carbon library "fail_extern_def"; -// CHECK:STDERR: fail_extern_def.carbon:[[@LINE+4]]:1: ERROR: `extern` not allowed on `class` declaration that provides a definition. -// CHECK:STDERR: extern class C {} -// CHECK:STDERR: ^~~~~~ -// CHECK:STDERR: extern class C {} // --- fail_extern_decl_after_extern_decl.carbon @@ -104,11 +100,18 @@ class C { extern class D; } -// --- todo_fail_def_after_extern_decl.carbon +// --- fail_def_after_extern_decl.carbon library "fail_def_after_extern_decl"; extern class C; +// CHECK:STDERR: fail_def_after_extern_decl.carbon:[[@LINE+7]]:1: ERROR: Redeclarations of `class C` must match use of `extern`. +// CHECK:STDERR: class C {} +// CHECK:STDERR: ^~~~~~~~~ +// CHECK:STDERR: fail_def_after_extern_decl.carbon:[[@LINE-4]]:1: Previously declared here. +// CHECK:STDERR: extern class C; +// CHECK:STDERR: ^~~~~~~~~~~~~~~ +// CHECK:STDERR: class C {} // --- fail_extern_decl_after_decl.carbon @@ -125,17 +128,17 @@ class C; // CHECK:STDERR: extern class C; -// --- fail_todo_import_extern_decl_then_decl.carbon +// --- fail_import_extern_decl_then_decl.carbon library "import_extern_decl_then_decl"; -// CHECK:STDERR: fail_todo_import_extern_decl_then_decl.carbon:[[@LINE+13]]:1: In import. +// CHECK:STDERR: fail_import_extern_decl_then_decl.carbon:[[@LINE+13]]:1: In import. // CHECK:STDERR: import library "extern_decl"; // CHECK:STDERR: ^~~~~~ // CHECK:STDERR: decl.carbon:4:1: ERROR: Duplicate name being declared in the same scope. // CHECK:STDERR: class C; // CHECK:STDERR: ^~~~~~~~ -// CHECK:STDERR: fail_todo_import_extern_decl_then_decl.carbon:[[@LINE+7]]:1: In import. +// CHECK:STDERR: fail_import_extern_decl_then_decl.carbon:[[@LINE+7]]:1: In import. // CHECK:STDERR: import library "extern_decl"; // CHECK:STDERR: ^~~~~~ // CHECK:STDERR: extern_decl.carbon:4:1: Name is previously declared here. @@ -145,17 +148,17 @@ library "import_extern_decl_then_decl"; import library "extern_decl"; import library "decl"; -// --- fail_todo_import_decl_then_extern_decl.carbon +// --- fail_import_decl_then_extern_decl.carbon library "import_decl_then_extern_decl"; -// CHECK:STDERR: fail_todo_import_decl_then_extern_decl.carbon:[[@LINE+13]]:1: In import. +// CHECK:STDERR: fail_import_decl_then_extern_decl.carbon:[[@LINE+13]]:1: In import. // CHECK:STDERR: import library "decl"; // CHECK:STDERR: ^~~~~~ // CHECK:STDERR: extern_decl.carbon:4:1: ERROR: Duplicate name being declared in the same scope. // CHECK:STDERR: extern class C; // CHECK:STDERR: ^~~~~~~~~~~~~~~ -// CHECK:STDERR: fail_todo_import_decl_then_extern_decl.carbon:[[@LINE+7]]:1: In import. +// CHECK:STDERR: fail_import_decl_then_extern_decl.carbon:[[@LINE+7]]:1: In import. // CHECK:STDERR: import library "decl"; // CHECK:STDERR: ^~~~~~ // CHECK:STDERR: decl.carbon:4:1: Name is previously declared here. @@ -165,17 +168,17 @@ library "import_decl_then_extern_decl"; import library "decl"; import library "extern_decl"; -// --- fail_todo_import_extern_decl_then_def.carbon +// --- fail_import_extern_decl_then_def.carbon library "import_extern_decl_then_def"; -// CHECK:STDERR: fail_todo_import_extern_decl_then_def.carbon:[[@LINE+13]]:1: In import. +// CHECK:STDERR: fail_import_extern_decl_then_def.carbon:[[@LINE+13]]:1: In import. // CHECK:STDERR: import library "extern_decl"; // CHECK:STDERR: ^~~~~~ // CHECK:STDERR: def.carbon:4:1: ERROR: Duplicate name being declared in the same scope. // CHECK:STDERR: class C {} // CHECK:STDERR: ^~~~~~~~~ -// CHECK:STDERR: fail_todo_import_extern_decl_then_def.carbon:[[@LINE+7]]:1: In import. +// CHECK:STDERR: fail_import_extern_decl_then_def.carbon:[[@LINE+7]]:1: In import. // CHECK:STDERR: import library "extern_decl"; // CHECK:STDERR: ^~~~~~ // CHECK:STDERR: extern_decl.carbon:4:1: Name is previously declared here. @@ -223,51 +226,91 @@ import library "def"; library "import_extern_decl_copy"; -// CHECK:STDERR: fail_todo_import_extern_decl_copy.carbon:[[@LINE+12]]:1: In import. +// CHECK:STDERR: fail_todo_import_extern_decl_copy.carbon:[[@LINE+13]]:1: In import. // CHECK:STDERR: import library "extern_decl"; // CHECK:STDERR: ^~~~~~ // CHECK:STDERR: extern_decl_copy.carbon:4:1: ERROR: Duplicate name being declared in the same scope. // CHECK:STDERR: extern class C; // CHECK:STDERR: ^~~~~~~~~~~~~~~ -// CHECK:STDERR: fail_todo_import_extern_decl_copy.carbon:[[@LINE+6]]:1: In import. +// CHECK:STDERR: fail_todo_import_extern_decl_copy.carbon:[[@LINE+7]]:1: In import. // CHECK:STDERR: import library "extern_decl"; // CHECK:STDERR: ^~~~~~ // CHECK:STDERR: extern_decl.carbon:4:1: Name is previously declared here. // CHECK:STDERR: extern class C; // CHECK:STDERR: ^~~~~~~~~~~~~~~ +// CHECK:STDERR: import library "extern_decl"; import library "extern_decl_copy"; -// --- extern_decl_after_import_extern_decl.carbon +// --- fail_extern_decl_after_import_extern_decl.carbon library "extern_decl_after_import_extern_decl"; import library "extern_decl"; +// CHECK:STDERR: fail_extern_decl_after_import_extern_decl.carbon:[[@LINE+10]]:1: ERROR: Redeclaration of `class C` is redundant. +// CHECK:STDERR: extern class C; +// CHECK:STDERR: ^~~~~~~~~~~~~~~ +// CHECK:STDERR: fail_extern_decl_after_import_extern_decl.carbon:[[@LINE-5]]:1: In import. +// CHECK:STDERR: import library "extern_decl"; +// CHECK:STDERR: ^~~~~~ +// CHECK:STDERR: extern_decl.carbon:4:1: Previously declared here. +// CHECK:STDERR: extern class C; +// CHECK:STDERR: ^~~~~~~~~~~~~~~ +// CHECK:STDERR: extern class C; -// --- decl_after_import_extern_decl.carbon +// --- fail_decl_after_import_extern_decl.carbon library "decl_after_import_extern_decl"; import library "decl"; +// CHECK:STDERR: fail_decl_after_import_extern_decl.carbon:[[@LINE+10]]:1: ERROR: Redeclarations of `class C` must match use of `extern`. +// CHECK:STDERR: extern class C; +// CHECK:STDERR: ^~~~~~~~~~~~~~~ +// CHECK:STDERR: fail_decl_after_import_extern_decl.carbon:[[@LINE-5]]:1: In import. +// CHECK:STDERR: import library "decl"; +// CHECK:STDERR: ^~~~~~ +// CHECK:STDERR: decl.carbon:4:1: Previously declared here. +// CHECK:STDERR: class C; +// CHECK:STDERR: ^~~~~~~~ +// CHECK:STDERR: extern class C; -// --- def_after_import_extern_decl.carbon +// --- fail_def_after_import_extern_decl.carbon library "def_after_import_extern_decl"; import library "def"; +// CHECK:STDERR: fail_def_after_import_extern_decl.carbon:[[@LINE+10]]:1: ERROR: Redeclarations of `class C` must match use of `extern`. +// CHECK:STDERR: extern class C; +// CHECK:STDERR: ^~~~~~~~~~~~~~~ +// CHECK:STDERR: fail_def_after_import_extern_decl.carbon:[[@LINE-5]]:1: In import. +// CHECK:STDERR: import library "def"; +// CHECK:STDERR: ^~~~~~ +// CHECK:STDERR: def.carbon:4:1: Previously declared here. +// CHECK:STDERR: class C {} +// CHECK:STDERR: ^~~~~~~~~ +// CHECK:STDERR: extern class C; -// --- extern_decl_after_import_def.carbon +// --- fail_extern_decl_after_import_def.carbon library "extern_decl_after_import_def"; import library "def"; +// CHECK:STDERR: fail_extern_decl_after_import_def.carbon:[[@LINE+9]]:1: ERROR: Redeclarations of `class C` must match use of `extern`. +// CHECK:STDERR: extern class C; +// CHECK:STDERR: ^~~~~~~~~~~~~~~ +// CHECK:STDERR: fail_extern_decl_after_import_def.carbon:[[@LINE-5]]:1: In import. +// CHECK:STDERR: import library "def"; +// CHECK:STDERR: ^~~~~~ +// CHECK:STDERR: def.carbon:4:1: Previously declared here. +// CHECK:STDERR: class C {} +// CHECK:STDERR: ^~~~~~~~~ extern class C; // CHECK:STDOUT: --- decl.carbon @@ -276,24 +319,10 @@ extern class C; // CHECK:STDOUT: %C: type = class_type @C [template] // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: imports { -// CHECK:STDOUT: %Core: = namespace file.%Core.import, [template] { -// CHECK:STDOUT: import Core//prelude -// CHECK:STDOUT: import Core//prelude/operators -// CHECK:STDOUT: import Core//prelude/types -// CHECK:STDOUT: import Core//prelude/operators/arithmetic -// CHECK:STDOUT: import Core//prelude/operators/bitwise -// CHECK:STDOUT: import Core//prelude/operators/comparison -// CHECK:STDOUT: import Core//prelude/types/bool -// CHECK:STDOUT: } -// CHECK:STDOUT: } -// CHECK:STDOUT: // CHECK:STDOUT: file { // CHECK:STDOUT: package: = namespace [template] { -// CHECK:STDOUT: .Core = imports.%Core // CHECK:STDOUT: .C = %C.decl // CHECK:STDOUT: } -// CHECK:STDOUT: %Core.import = import Core // CHECK:STDOUT: %C.decl: type = class_decl @C [template = constants.%C] {} // CHECK:STDOUT: } // CHECK:STDOUT: @@ -305,24 +334,10 @@ extern class C; // CHECK:STDOUT: %C: type = class_type @C [template] // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: imports { -// CHECK:STDOUT: %Core: = namespace file.%Core.import, [template] { -// CHECK:STDOUT: import Core//prelude -// CHECK:STDOUT: import Core//prelude/operators -// CHECK:STDOUT: import Core//prelude/types -// CHECK:STDOUT: import Core//prelude/operators/arithmetic -// CHECK:STDOUT: import Core//prelude/operators/bitwise -// CHECK:STDOUT: import Core//prelude/operators/comparison -// CHECK:STDOUT: import Core//prelude/types/bool -// CHECK:STDOUT: } -// CHECK:STDOUT: } -// CHECK:STDOUT: // CHECK:STDOUT: file { // CHECK:STDOUT: package: = namespace [template] { -// CHECK:STDOUT: .Core = imports.%Core // CHECK:STDOUT: .C = %C.decl // CHECK:STDOUT: } -// CHECK:STDOUT: %Core.import = import Core // CHECK:STDOUT: %C.decl: type = class_decl @C [template = constants.%C] {} // CHECK:STDOUT: } // CHECK:STDOUT: @@ -334,24 +349,10 @@ extern class C; // CHECK:STDOUT: %C: type = class_type @C [template] // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: imports { -// CHECK:STDOUT: %Core: = namespace file.%Core.import, [template] { -// CHECK:STDOUT: import Core//prelude -// CHECK:STDOUT: import Core//prelude/operators -// CHECK:STDOUT: import Core//prelude/types -// CHECK:STDOUT: import Core//prelude/operators/arithmetic -// CHECK:STDOUT: import Core//prelude/operators/bitwise -// CHECK:STDOUT: import Core//prelude/operators/comparison -// CHECK:STDOUT: import Core//prelude/types/bool -// CHECK:STDOUT: } -// CHECK:STDOUT: } -// CHECK:STDOUT: // CHECK:STDOUT: file { // CHECK:STDOUT: package: = namespace [template] { -// CHECK:STDOUT: .Core = imports.%Core // CHECK:STDOUT: .C = %C.decl // CHECK:STDOUT: } -// CHECK:STDOUT: %Core.import = import Core // CHECK:STDOUT: %C.decl: type = class_decl @C [template = constants.%C] {} // CHECK:STDOUT: } // CHECK:STDOUT: @@ -364,24 +365,10 @@ extern class C; // CHECK:STDOUT: %.1: type = struct_type {} [template] // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: imports { -// CHECK:STDOUT: %Core: = namespace file.%Core.import, [template] { -// CHECK:STDOUT: import Core//prelude -// CHECK:STDOUT: import Core//prelude/operators -// CHECK:STDOUT: import Core//prelude/types -// CHECK:STDOUT: import Core//prelude/operators/arithmetic -// CHECK:STDOUT: import Core//prelude/operators/bitwise -// CHECK:STDOUT: import Core//prelude/operators/comparison -// CHECK:STDOUT: import Core//prelude/types/bool -// CHECK:STDOUT: } -// CHECK:STDOUT: } -// CHECK:STDOUT: // CHECK:STDOUT: file { // CHECK:STDOUT: package: = namespace [template] { -// CHECK:STDOUT: .Core = imports.%Core // CHECK:STDOUT: .C = %C.decl // CHECK:STDOUT: } -// CHECK:STDOUT: %Core.import = import Core // CHECK:STDOUT: %C.decl: type = class_decl @C [template = constants.%C] {} // CHECK:STDOUT: } // CHECK:STDOUT: @@ -399,24 +386,10 @@ extern class C; // CHECK:STDOUT: %.2: %.type = struct_value () [template] // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: imports { -// CHECK:STDOUT: %Core: = namespace file.%Core.import, [template] { -// CHECK:STDOUT: import Core//prelude -// CHECK:STDOUT: import Core//prelude/operators -// CHECK:STDOUT: import Core//prelude/types -// CHECK:STDOUT: import Core//prelude/operators/arithmetic -// CHECK:STDOUT: import Core//prelude/operators/bitwise -// CHECK:STDOUT: import Core//prelude/operators/comparison -// CHECK:STDOUT: import Core//prelude/types/bool -// CHECK:STDOUT: } -// CHECK:STDOUT: } -// CHECK:STDOUT: // CHECK:STDOUT: file { // CHECK:STDOUT: package: = namespace [template] { -// CHECK:STDOUT: .Core = imports.%Core // CHECK:STDOUT: .C = %C.decl // CHECK:STDOUT: } -// CHECK:STDOUT: %Core.import = import Core // CHECK:STDOUT: %C.decl: type = class_decl @C [template = constants.%C] {} // CHECK:STDOUT: %.decl: %.type = fn_decl @.1 [template = constants.%.2] {} // CHECK:STDOUT: } @@ -425,31 +398,17 @@ extern class C; // CHECK:STDOUT: // CHECK:STDOUT: fn @.1(); // CHECK:STDOUT: -// CHECK:STDOUT: --- fail_extern_def.carbon +// CHECK:STDOUT: --- extern_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: imports { -// CHECK:STDOUT: %Core: = namespace file.%Core.import, [template] { -// CHECK:STDOUT: import Core//prelude -// CHECK:STDOUT: import Core//prelude/operators -// CHECK:STDOUT: import Core//prelude/types -// CHECK:STDOUT: import Core//prelude/operators/arithmetic -// CHECK:STDOUT: import Core//prelude/operators/bitwise -// CHECK:STDOUT: import Core//prelude/operators/comparison -// CHECK:STDOUT: import Core//prelude/types/bool -// CHECK:STDOUT: } -// CHECK:STDOUT: } -// CHECK:STDOUT: // CHECK:STDOUT: file { // CHECK:STDOUT: package: = namespace [template] { -// CHECK:STDOUT: .Core = imports.%Core // CHECK:STDOUT: .C = %C.decl // CHECK:STDOUT: } -// CHECK:STDOUT: %Core.import = import Core // CHECK:STDOUT: %C.decl: type = class_decl @C [template = constants.%C] {} // CHECK:STDOUT: } // CHECK:STDOUT: @@ -464,24 +423,10 @@ extern class C; // CHECK:STDOUT: %C: type = class_type @C [template] // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: imports { -// CHECK:STDOUT: %Core: = namespace file.%Core.import, [template] { -// CHECK:STDOUT: import Core//prelude -// CHECK:STDOUT: import Core//prelude/operators -// CHECK:STDOUT: import Core//prelude/types -// CHECK:STDOUT: import Core//prelude/operators/arithmetic -// CHECK:STDOUT: import Core//prelude/operators/bitwise -// CHECK:STDOUT: import Core//prelude/operators/comparison -// CHECK:STDOUT: import Core//prelude/types/bool -// CHECK:STDOUT: } -// CHECK:STDOUT: } -// CHECK:STDOUT: // CHECK:STDOUT: file { // CHECK:STDOUT: package: = namespace [template] { -// CHECK:STDOUT: .Core = imports.%Core // CHECK:STDOUT: .C = %C.decl.loc4 // CHECK:STDOUT: } -// CHECK:STDOUT: %Core.import = import Core // CHECK:STDOUT: %C.decl.loc4: type = class_decl @C [template = constants.%C] {} // CHECK:STDOUT: %C.decl.loc12: type = class_decl @C [template = constants.%C] {} // CHECK:STDOUT: } @@ -494,24 +439,10 @@ extern class C; // CHECK:STDOUT: %C: type = class_type @C [template] // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: imports { -// CHECK:STDOUT: %Core: = namespace file.%Core.import, [template] { -// CHECK:STDOUT: import Core//prelude -// CHECK:STDOUT: import Core//prelude/operators -// CHECK:STDOUT: import Core//prelude/types -// CHECK:STDOUT: import Core//prelude/operators/arithmetic -// CHECK:STDOUT: import Core//prelude/operators/bitwise -// CHECK:STDOUT: import Core//prelude/operators/comparison -// CHECK:STDOUT: import Core//prelude/types/bool -// CHECK:STDOUT: } -// CHECK:STDOUT: } -// CHECK:STDOUT: // CHECK:STDOUT: file { // CHECK:STDOUT: package: = namespace [template] { -// CHECK:STDOUT: .Core = imports.%Core -// CHECK:STDOUT: .C = %C.decl.loc4 +// CHECK:STDOUT: .C = %C.decl.loc12 // CHECK:STDOUT: } -// CHECK:STDOUT: %Core.import = import Core // CHECK:STDOUT: %C.decl.loc4: type = class_decl @C [template = constants.%C] {} // CHECK:STDOUT: %C.decl.loc12: type = class_decl @C [template = constants.%C] {} // CHECK:STDOUT: } @@ -526,24 +457,10 @@ extern class C; // CHECK:STDOUT: %.1: type = struct_type {} [template] // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: imports { -// CHECK:STDOUT: %Core: = namespace file.%Core.import, [template] { -// CHECK:STDOUT: import Core//prelude -// CHECK:STDOUT: import Core//prelude/operators -// CHECK:STDOUT: import Core//prelude/types -// CHECK:STDOUT: import Core//prelude/operators/arithmetic -// CHECK:STDOUT: import Core//prelude/operators/bitwise -// CHECK:STDOUT: import Core//prelude/operators/comparison -// CHECK:STDOUT: import Core//prelude/types/bool -// CHECK:STDOUT: } -// CHECK:STDOUT: } -// CHECK:STDOUT: // CHECK:STDOUT: file { // CHECK:STDOUT: package: = namespace [template] { -// CHECK:STDOUT: .Core = imports.%Core // CHECK:STDOUT: .C = %C.decl // CHECK:STDOUT: } -// CHECK:STDOUT: %Core.import = import Core // CHECK:STDOUT: %C.decl: type = class_decl @C [template = constants.%C] {} // CHECK:STDOUT: } // CHECK:STDOUT: @@ -557,33 +474,19 @@ extern class C; // CHECK:STDOUT: // CHECK:STDOUT: class @D; // CHECK:STDOUT: -// CHECK:STDOUT: --- todo_fail_def_after_extern_decl.carbon +// CHECK:STDOUT: --- fail_def_after_extern_decl.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: imports { -// CHECK:STDOUT: %Core: = namespace file.%Core.import, [template] { -// CHECK:STDOUT: import Core//prelude -// CHECK:STDOUT: import Core//prelude/operators -// CHECK:STDOUT: import Core//prelude/types -// CHECK:STDOUT: import Core//prelude/operators/arithmetic -// CHECK:STDOUT: import Core//prelude/operators/bitwise -// CHECK:STDOUT: import Core//prelude/operators/comparison -// CHECK:STDOUT: import Core//prelude/types/bool -// CHECK:STDOUT: } -// CHECK:STDOUT: } -// CHECK:STDOUT: // CHECK:STDOUT: file { // CHECK:STDOUT: package: = namespace [template] { -// CHECK:STDOUT: .Core = imports.%Core -// CHECK:STDOUT: .C = %C.decl.loc4 +// CHECK:STDOUT: .C = %C.decl.loc12 // CHECK:STDOUT: } -// CHECK:STDOUT: %Core.import = import Core // CHECK:STDOUT: %C.decl.loc4: type = class_decl @C [template = constants.%C] {} -// CHECK:STDOUT: %C.decl.loc5: type = class_decl @C [template = constants.%C] {} +// CHECK:STDOUT: %C.decl.loc12: type = class_decl @C [template = constants.%C] {} // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: class @C { @@ -597,219 +500,128 @@ extern class C; // CHECK:STDOUT: %C: type = class_type @C [template] // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: imports { -// CHECK:STDOUT: %Core: = namespace file.%Core.import, [template] { -// CHECK:STDOUT: import Core//prelude -// CHECK:STDOUT: import Core//prelude/operators -// CHECK:STDOUT: import Core//prelude/types -// CHECK:STDOUT: import Core//prelude/operators/arithmetic -// CHECK:STDOUT: import Core//prelude/operators/bitwise -// CHECK:STDOUT: import Core//prelude/operators/comparison -// CHECK:STDOUT: import Core//prelude/types/bool -// CHECK:STDOUT: } -// CHECK:STDOUT: } -// CHECK:STDOUT: // CHECK:STDOUT: file { // CHECK:STDOUT: package: = namespace [template] { -// CHECK:STDOUT: .Core = imports.%Core // CHECK:STDOUT: .C = %C.decl.loc4 // CHECK:STDOUT: } -// CHECK:STDOUT: %Core.import = import Core // CHECK:STDOUT: %C.decl.loc4: type = class_decl @C [template = constants.%C] {} // CHECK:STDOUT: %C.decl.loc12: type = class_decl @C [template = constants.%C] {} // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: class @C; // CHECK:STDOUT: -// CHECK:STDOUT: --- fail_todo_import_extern_decl_then_decl.carbon +// CHECK:STDOUT: --- fail_import_extern_decl_then_decl.carbon // CHECK:STDOUT: // CHECK:STDOUT: imports { -// CHECK:STDOUT: %import_ref.1 = import_ref Main//extern_decl, inst+3, unloaded -// CHECK:STDOUT: %import_ref.2 = import_ref Main//decl, inst+3, unloaded -// CHECK:STDOUT: %Core: = namespace file.%Core.import, [template] { -// CHECK:STDOUT: import Core//prelude -// CHECK:STDOUT: import Core//prelude/operators -// CHECK:STDOUT: import Core//prelude/types -// CHECK:STDOUT: import Core//prelude/operators/arithmetic -// CHECK:STDOUT: import Core//prelude/operators/bitwise -// CHECK:STDOUT: import Core//prelude/operators/comparison -// CHECK:STDOUT: import Core//prelude/types/bool -// CHECK:STDOUT: } +// CHECK:STDOUT: %import_ref.1 = import_ref Main//extern_decl, inst+1, unloaded +// CHECK:STDOUT: %import_ref.2 = import_ref Main//decl, inst+1, unloaded // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: file { // CHECK:STDOUT: package: = namespace [template] { // CHECK:STDOUT: .C = imports.%import_ref.1 -// CHECK:STDOUT: .Core = imports.%Core // CHECK:STDOUT: } -// CHECK:STDOUT: %Core.import = import Core // CHECK:STDOUT: %default.import = import // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: --- fail_todo_import_decl_then_extern_decl.carbon +// CHECK:STDOUT: --- fail_import_decl_then_extern_decl.carbon // CHECK:STDOUT: // CHECK:STDOUT: imports { -// CHECK:STDOUT: %import_ref.1 = import_ref Main//decl, inst+3, unloaded -// CHECK:STDOUT: %import_ref.2 = import_ref Main//extern_decl, inst+3, unloaded -// CHECK:STDOUT: %Core: = namespace file.%Core.import, [template] { -// CHECK:STDOUT: import Core//prelude -// CHECK:STDOUT: import Core//prelude/operators -// CHECK:STDOUT: import Core//prelude/types -// CHECK:STDOUT: import Core//prelude/operators/arithmetic -// CHECK:STDOUT: import Core//prelude/operators/bitwise -// CHECK:STDOUT: import Core//prelude/operators/comparison -// CHECK:STDOUT: import Core//prelude/types/bool -// CHECK:STDOUT: } +// CHECK:STDOUT: %import_ref.1 = import_ref Main//decl, inst+1, unloaded +// CHECK:STDOUT: %import_ref.2 = import_ref Main//extern_decl, inst+1, unloaded // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: file { // CHECK:STDOUT: package: = namespace [template] { // CHECK:STDOUT: .C = imports.%import_ref.1 -// CHECK:STDOUT: .Core = imports.%Core // CHECK:STDOUT: } -// CHECK:STDOUT: %Core.import = import Core // CHECK:STDOUT: %default.import = import // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: --- fail_todo_import_extern_decl_then_def.carbon +// CHECK:STDOUT: --- fail_import_extern_decl_then_def.carbon // CHECK:STDOUT: // CHECK:STDOUT: imports { -// CHECK:STDOUT: %import_ref.1 = import_ref Main//extern_decl, inst+3, unloaded -// CHECK:STDOUT: %import_ref.2 = import_ref Main//def, inst+3, unloaded -// CHECK:STDOUT: %Core: = namespace file.%Core.import, [template] { -// CHECK:STDOUT: import Core//prelude -// CHECK:STDOUT: import Core//prelude/operators -// CHECK:STDOUT: import Core//prelude/types -// CHECK:STDOUT: import Core//prelude/operators/arithmetic -// CHECK:STDOUT: import Core//prelude/operators/bitwise -// CHECK:STDOUT: import Core//prelude/operators/comparison -// CHECK:STDOUT: import Core//prelude/types/bool -// CHECK:STDOUT: } +// CHECK:STDOUT: %import_ref.1 = import_ref Main//extern_decl, inst+1, unloaded +// CHECK:STDOUT: %import_ref.2 = import_ref Main//def, inst+1, unloaded // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: file { // CHECK:STDOUT: package: = namespace [template] { // CHECK:STDOUT: .C = imports.%import_ref.1 -// CHECK:STDOUT: .Core = imports.%Core // CHECK:STDOUT: } -// CHECK:STDOUT: %Core.import = import Core // CHECK:STDOUT: %default.import = import // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: --- fail_import_ownership_conflict.carbon // CHECK:STDOUT: // CHECK:STDOUT: imports { -// CHECK:STDOUT: %import_ref.1 = import_ref Main//extern_decl, inst+3, unloaded -// CHECK:STDOUT: %import_ref.2 = import_ref Main//decl, inst+3, unloaded -// CHECK:STDOUT: %import_ref.3 = import_ref Main//def, inst+3, unloaded -// CHECK:STDOUT: %Core: = namespace file.%Core.import, [template] { -// CHECK:STDOUT: import Core//prelude -// CHECK:STDOUT: import Core//prelude/operators -// CHECK:STDOUT: import Core//prelude/types -// CHECK:STDOUT: import Core//prelude/operators/arithmetic -// CHECK:STDOUT: import Core//prelude/operators/bitwise -// CHECK:STDOUT: import Core//prelude/operators/comparison -// CHECK:STDOUT: import Core//prelude/types/bool -// CHECK:STDOUT: } +// CHECK:STDOUT: %import_ref.1 = import_ref Main//extern_decl, inst+1, unloaded +// CHECK:STDOUT: %import_ref.2 = import_ref Main//decl, inst+1, unloaded +// CHECK:STDOUT: %import_ref.3 = import_ref Main//def, inst+1, unloaded // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: file { // CHECK:STDOUT: package: = namespace [template] { // CHECK:STDOUT: .C = imports.%import_ref.1 -// CHECK:STDOUT: .Core = imports.%Core // CHECK:STDOUT: } -// CHECK:STDOUT: %Core.import = import Core // CHECK:STDOUT: %default.import = import // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: --- fail_todo_import_extern_decl_copy.carbon // CHECK:STDOUT: // CHECK:STDOUT: imports { -// CHECK:STDOUT: %import_ref.1 = import_ref Main//extern_decl, inst+3, unloaded -// CHECK:STDOUT: %import_ref.2 = import_ref Main//extern_decl_copy, inst+3, unloaded -// CHECK:STDOUT: %Core: = namespace file.%Core.import, [template] { -// CHECK:STDOUT: import Core//prelude -// CHECK:STDOUT: import Core//prelude/operators -// CHECK:STDOUT: import Core//prelude/types -// CHECK:STDOUT: import Core//prelude/operators/arithmetic -// CHECK:STDOUT: import Core//prelude/operators/bitwise -// CHECK:STDOUT: import Core//prelude/operators/comparison -// CHECK:STDOUT: import Core//prelude/types/bool -// CHECK:STDOUT: } +// CHECK:STDOUT: %import_ref.1 = import_ref Main//extern_decl, inst+1, unloaded +// CHECK:STDOUT: %import_ref.2 = import_ref Main//extern_decl_copy, inst+1, unloaded // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: file { // CHECK:STDOUT: package: = namespace [template] { // CHECK:STDOUT: .C = imports.%import_ref.1 -// CHECK:STDOUT: .Core = imports.%Core // CHECK:STDOUT: } -// CHECK:STDOUT: %Core.import = import Core // CHECK:STDOUT: %default.import = import // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: --- extern_decl_after_import_extern_decl.carbon +// CHECK:STDOUT: --- fail_extern_decl_after_import_extern_decl.carbon // CHECK:STDOUT: // CHECK:STDOUT: constants { // CHECK:STDOUT: %C: type = class_type @C [template] // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: imports { -// CHECK:STDOUT: %import_ref: type = import_ref Main//extern_decl, inst+3, loaded [template = constants.%C] -// CHECK:STDOUT: %Core: = namespace file.%Core.import, [template] { -// CHECK:STDOUT: import Core//prelude -// CHECK:STDOUT: import Core//prelude/operators -// CHECK:STDOUT: import Core//prelude/types -// CHECK:STDOUT: import Core//prelude/operators/arithmetic -// CHECK:STDOUT: import Core//prelude/operators/bitwise -// CHECK:STDOUT: import Core//prelude/operators/comparison -// CHECK:STDOUT: import Core//prelude/types/bool -// CHECK:STDOUT: } +// CHECK:STDOUT: %import_ref: type = import_ref Main//extern_decl, inst+1, loaded [template = constants.%C] // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: file { // CHECK:STDOUT: package: = namespace [template] { // CHECK:STDOUT: .C = %C.decl -// CHECK:STDOUT: .Core = imports.%Core // CHECK:STDOUT: } -// CHECK:STDOUT: %Core.import = import Core // CHECK:STDOUT: %default.import = import // CHECK:STDOUT: %C.decl: type = class_decl @C [template = constants.%C] {} // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: class @C; // CHECK:STDOUT: -// CHECK:STDOUT: --- decl_after_import_extern_decl.carbon +// CHECK:STDOUT: --- fail_decl_after_import_extern_decl.carbon // CHECK:STDOUT: // CHECK:STDOUT: constants { // CHECK:STDOUT: %C: type = class_type @C [template] // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: imports { -// CHECK:STDOUT: %import_ref: type = import_ref Main//decl, inst+3, loaded [template = constants.%C] -// CHECK:STDOUT: %Core: = namespace file.%Core.import, [template] { -// CHECK:STDOUT: import Core//prelude -// CHECK:STDOUT: import Core//prelude/operators -// CHECK:STDOUT: import Core//prelude/types -// CHECK:STDOUT: import Core//prelude/operators/arithmetic -// CHECK:STDOUT: import Core//prelude/operators/bitwise -// CHECK:STDOUT: import Core//prelude/operators/comparison -// CHECK:STDOUT: import Core//prelude/types/bool -// CHECK:STDOUT: } +// CHECK:STDOUT: %import_ref: type = import_ref Main//decl, inst+1, loaded [template = constants.%C] // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: file { // CHECK:STDOUT: package: = namespace [template] { // CHECK:STDOUT: .C = %C.decl -// CHECK:STDOUT: .Core = imports.%Core // CHECK:STDOUT: } -// CHECK:STDOUT: %Core.import = import Core // CHECK:STDOUT: %default.import = import // CHECK:STDOUT: %C.decl: type = class_decl @C [template = constants.%C] {} // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: class @C; // CHECK:STDOUT: -// CHECK:STDOUT: --- def_after_import_extern_decl.carbon +// CHECK:STDOUT: --- fail_def_after_import_extern_decl.carbon // CHECK:STDOUT: // CHECK:STDOUT: constants { // CHECK:STDOUT: %C: type = class_type @C [template] @@ -817,25 +629,14 @@ extern class C; // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: imports { -// CHECK:STDOUT: %import_ref.1: type = import_ref Main//def, inst+3, loaded [template = constants.%C] -// CHECK:STDOUT: %Core: = namespace file.%Core.import, [template] { -// CHECK:STDOUT: import Core//prelude -// CHECK:STDOUT: import Core//prelude/operators -// CHECK:STDOUT: import Core//prelude/types -// CHECK:STDOUT: import Core//prelude/operators/arithmetic -// CHECK:STDOUT: import Core//prelude/operators/bitwise -// CHECK:STDOUT: import Core//prelude/operators/comparison -// CHECK:STDOUT: import Core//prelude/types/bool -// CHECK:STDOUT: } -// CHECK:STDOUT: %import_ref.2 = import_ref Main//def, inst+4, unloaded +// CHECK:STDOUT: %import_ref.1: type = import_ref Main//def, inst+1, loaded [template = constants.%C] +// CHECK:STDOUT: %import_ref.2 = import_ref Main//def, inst+2, unloaded // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: file { // CHECK:STDOUT: package: = namespace [template] { // CHECK:STDOUT: .C = %C.decl -// CHECK:STDOUT: .Core = imports.%Core // CHECK:STDOUT: } -// CHECK:STDOUT: %Core.import = import Core // CHECK:STDOUT: %default.import = import // CHECK:STDOUT: %C.decl: type = class_decl @C [template = constants.%C] {} // CHECK:STDOUT: } @@ -845,7 +646,7 @@ extern class C; // CHECK:STDOUT: .Self = imports.%import_ref.2 // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: --- extern_decl_after_import_def.carbon +// CHECK:STDOUT: --- fail_extern_decl_after_import_def.carbon // CHECK:STDOUT: // CHECK:STDOUT: constants { // CHECK:STDOUT: %C: type = class_type @C [template] @@ -853,25 +654,14 @@ extern class C; // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: imports { -// CHECK:STDOUT: %import_ref.1: type = import_ref Main//def, inst+3, loaded [template = constants.%C] -// CHECK:STDOUT: %Core: = namespace file.%Core.import, [template] { -// CHECK:STDOUT: import Core//prelude -// CHECK:STDOUT: import Core//prelude/operators -// CHECK:STDOUT: import Core//prelude/types -// CHECK:STDOUT: import Core//prelude/operators/arithmetic -// CHECK:STDOUT: import Core//prelude/operators/bitwise -// CHECK:STDOUT: import Core//prelude/operators/comparison -// CHECK:STDOUT: import Core//prelude/types/bool -// CHECK:STDOUT: } -// CHECK:STDOUT: %import_ref.2 = import_ref Main//def, inst+4, unloaded +// CHECK:STDOUT: %import_ref.1: type = import_ref Main//def, inst+1, loaded [template = constants.%C] +// CHECK:STDOUT: %import_ref.2 = import_ref Main//def, inst+2, unloaded // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: file { // CHECK:STDOUT: package: = namespace [template] { // CHECK:STDOUT: .C = %C.decl -// CHECK:STDOUT: .Core = imports.%Core // CHECK:STDOUT: } -// CHECK:STDOUT: %Core.import = import Core // CHECK:STDOUT: %default.import = import // CHECK:STDOUT: %C.decl: type = class_decl @C [template = constants.%C] {} // CHECK:STDOUT: } diff --git a/toolchain/check/testdata/class/no_prelude/extern_library.carbon b/toolchain/check/testdata/class/no_prelude/extern_library.carbon new file mode 100644 index 000000000000..7d3c54bd6152 --- /dev/null +++ b/toolchain/check/testdata/class/no_prelude/extern_library.carbon @@ -0,0 +1,32 @@ +// 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/extern_library.carbon +// TIP: To dump output, run: +// TIP: bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/class/no_prelude/extern_library.carbon + +// --- fail_todo.carbon + +// CHECK:STDERR: fail_todo.carbon:[[@LINE+3]]:1: ERROR: Semantics TODO: `extern library`. +// CHECK:STDERR: extern library "foo" class C; +// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +extern library "foo" class C; + +// CHECK:STDOUT: --- fail_todo.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %C: type = class_type @C [template] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .C = %C.decl +// CHECK:STDOUT: } +// CHECK:STDOUT: %C.decl: type = class_decl @C [template = constants.%C] {} +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: class @C; +// CHECK:STDOUT: diff --git a/toolchain/check/testdata/function/declaration/import.carbon b/toolchain/check/testdata/function/declaration/import.carbon index a83174da6636..52a08c11af78 100644 --- a/toolchain/check/testdata/function/declaration/import.carbon +++ b/toolchain/check/testdata/function/declaration/import.carbon @@ -28,13 +28,13 @@ fn NS.E(); library "extern_api"; -extern fn A(); -extern fn B(b: i32) -> i32; -extern fn C(c: (i32,)) -> {.c: i32}; -extern fn D(); +extern library "redecl_extern_api" fn A(); +extern library "redecl_extern_api" fn B(b: i32) -> i32; +extern library "redecl_extern_api" fn C(c: (i32,)) -> {.c: i32}; +extern library "redecl_extern_api" fn D(); namespace NS; -extern fn NS.E(); +extern library "redecl_extern_api" fn NS.E(); // ============================================================================ // Test files @@ -52,16 +52,66 @@ var c: {.c: i32} = C((1,)); var d: () = D(); var e: () = NS.E(); -// --- redecl_api.carbon +// --- fail_redecl_api.carbon library "redecl_api"; import library "api"; +// CHECK:STDERR: fail_redecl_api.carbon:[[@LINE+10]]:1: ERROR: Redeclarations of `fn A` must match use of `extern`. +// CHECK:STDERR: extern fn A(); +// CHECK:STDERR: ^~~~~~~~~~~~~~ +// CHECK:STDERR: fail_redecl_api.carbon:[[@LINE-5]]:1: In import. +// CHECK:STDERR: import library "api"; +// CHECK:STDERR: ^~~~~~ +// CHECK:STDERR: api.carbon:4:1: Previously declared here. +// CHECK:STDERR: fn A(); +// CHECK:STDERR: ^~~~~~~ +// CHECK:STDERR: extern fn A(); +// CHECK:STDERR: fail_redecl_api.carbon:[[@LINE+10]]:1: ERROR: Redeclarations of `fn B` must match use of `extern`. +// CHECK:STDERR: extern fn B(b: i32) -> i32; +// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~ +// CHECK:STDERR: fail_redecl_api.carbon:[[@LINE-16]]:1: In import. +// CHECK:STDERR: import library "api"; +// CHECK:STDERR: ^~~~~~ +// CHECK:STDERR: api.carbon:5:1: Previously declared here. +// CHECK:STDERR: fn B(b: i32) -> i32; +// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~ +// CHECK:STDERR: extern fn B(b: i32) -> i32; +// CHECK:STDERR: fail_redecl_api.carbon:[[@LINE+10]]:1: ERROR: Redeclarations of `fn C` must match use of `extern`. +// CHECK:STDERR: extern fn C(c: (i32,)) -> {.c: i32}; +// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// CHECK:STDERR: fail_redecl_api.carbon:[[@LINE-27]]:1: In import. +// CHECK:STDERR: import library "api"; +// CHECK:STDERR: ^~~~~~ +// CHECK:STDERR: api.carbon:6:1: Previously declared here. +// CHECK:STDERR: fn C(c: (i32,)) -> {.c: i32}; +// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// CHECK:STDERR: extern fn C(c: (i32,)) -> {.c: i32}; +// CHECK:STDERR: fail_redecl_api.carbon:[[@LINE+10]]:1: ERROR: Redeclaration of `fn D` is redundant. +// CHECK:STDERR: extern fn D(); +// CHECK:STDERR: ^~~~~~~~~~~~~~ +// CHECK:STDERR: fail_redecl_api.carbon:[[@LINE-38]]:1: In import. +// CHECK:STDERR: import library "api"; +// CHECK:STDERR: ^~~~~~ +// CHECK:STDERR: api.carbon:7:1: Previously declared here. +// CHECK:STDERR: extern fn D(); +// CHECK:STDERR: ^~~~~~~~~~~~~~ +// CHECK:STDERR: extern fn D(); +// CHECK:STDERR: fail_redecl_api.carbon:[[@LINE+10]]:1: ERROR: Redeclarations of `fn E` must match use of `extern`. +// CHECK:STDERR: extern fn NS.E(); +// CHECK:STDERR: ^~~~~~~~~~~~~~~~~ +// CHECK:STDERR: fail_redecl_api.carbon:[[@LINE-49]]:1: In import. +// CHECK:STDERR: import library "api"; +// CHECK:STDERR: ^~~~~~ +// CHECK:STDERR: api.carbon:10:1: Previously declared here. +// CHECK:STDERR: fn NS.E(); +// CHECK:STDERR: ^~~~~~~~~~ +// CHECK:STDERR: extern fn NS.E(); var a: () = A(); @@ -88,69 +138,69 @@ var c: {.c: i32} = C((1,)); var d: () = D(); var e: () = NS.E(); -// --- fail_todo_merge.carbon +// --- fail_merge.carbon library "merge"; -// CHECK:STDERR: fail_todo_merge.carbon:[[@LINE+65]]:1: In import. +// CHECK:STDERR: fail_merge.carbon:[[@LINE+65]]:1: In import. // CHECK:STDERR: import library "api"; // CHECK:STDERR: ^~~~~~ // CHECK:STDERR: extern_api.carbon:4:1: ERROR: Duplicate name being declared in the same scope. -// CHECK:STDERR: extern fn A(); -// CHECK:STDERR: ^~~~~~~~~~~~~~ -// CHECK:STDERR: fail_todo_merge.carbon:[[@LINE+59]]:1: In import. +// CHECK:STDERR: extern library "redecl_extern_api" fn A(); +// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// CHECK:STDERR: fail_merge.carbon:[[@LINE+59]]:1: In import. // CHECK:STDERR: import library "api"; // CHECK:STDERR: ^~~~~~ // CHECK:STDERR: api.carbon:4:1: Name is previously declared here. // CHECK:STDERR: fn A(); // CHECK:STDERR: ^~~~~~~ // CHECK:STDERR: -// CHECK:STDERR: fail_todo_merge.carbon:[[@LINE+52]]:1: In import. +// CHECK:STDERR: fail_merge.carbon:[[@LINE+52]]:1: In import. // CHECK:STDERR: import library "api"; // CHECK:STDERR: ^~~~~~ // CHECK:STDERR: extern_api.carbon:5:1: ERROR: Duplicate name being declared in the same scope. -// CHECK:STDERR: extern fn B(b: i32) -> i32; -// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~ -// CHECK:STDERR: fail_todo_merge.carbon:[[@LINE+46]]:1: In import. +// CHECK:STDERR: extern library "redecl_extern_api" fn B(b: i32) -> i32; +// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// CHECK:STDERR: fail_merge.carbon:[[@LINE+46]]:1: In import. // CHECK:STDERR: import library "api"; // CHECK:STDERR: ^~~~~~ // CHECK:STDERR: api.carbon:5:1: Name is previously declared here. // CHECK:STDERR: fn B(b: i32) -> i32; // CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~ // CHECK:STDERR: -// CHECK:STDERR: fail_todo_merge.carbon:[[@LINE+39]]:1: In import. +// CHECK:STDERR: fail_merge.carbon:[[@LINE+39]]:1: In import. // CHECK:STDERR: import library "api"; // CHECK:STDERR: ^~~~~~ // CHECK:STDERR: extern_api.carbon:6:1: ERROR: Duplicate name being declared in the same scope. -// CHECK:STDERR: extern fn C(c: (i32,)) -> {.c: i32}; -// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// CHECK:STDERR: fail_todo_merge.carbon:[[@LINE+33]]:1: In import. +// CHECK:STDERR: extern library "redecl_extern_api" fn C(c: (i32,)) -> {.c: i32}; +// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// CHECK:STDERR: fail_merge.carbon:[[@LINE+33]]:1: In import. // CHECK:STDERR: import library "api"; // CHECK:STDERR: ^~~~~~ // CHECK:STDERR: api.carbon:6:1: Name is previously declared here. // CHECK:STDERR: fn C(c: (i32,)) -> {.c: i32}; // CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // CHECK:STDERR: -// CHECK:STDERR: fail_todo_merge.carbon:[[@LINE+26]]:1: In import. +// CHECK:STDERR: fail_merge.carbon:[[@LINE+26]]:1: In import. // CHECK:STDERR: import library "api"; // CHECK:STDERR: ^~~~~~ // CHECK:STDERR: extern_api.carbon:7:1: ERROR: Duplicate name being declared in the same scope. -// CHECK:STDERR: extern fn D(); -// CHECK:STDERR: ^~~~~~~~~~~~~~ -// CHECK:STDERR: fail_todo_merge.carbon:[[@LINE+20]]:1: In import. +// CHECK:STDERR: extern library "redecl_extern_api" fn D(); +// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// CHECK:STDERR: fail_merge.carbon:[[@LINE+20]]:1: In import. // CHECK:STDERR: import library "api"; // CHECK:STDERR: ^~~~~~ // CHECK:STDERR: api.carbon:7:1: Name is previously declared here. // CHECK:STDERR: extern fn D(); // CHECK:STDERR: ^~~~~~~~~~~~~~ // CHECK:STDERR: -// CHECK:STDERR: fail_todo_merge.carbon:[[@LINE+13]]:1: In import. +// CHECK:STDERR: fail_merge.carbon:[[@LINE+13]]:1: In import. // CHECK:STDERR: import library "api"; // CHECK:STDERR: ^~~~~~ // CHECK:STDERR: extern_api.carbon:10:1: ERROR: Duplicate name being declared in the same scope. -// CHECK:STDERR: extern fn NS.E(); -// CHECK:STDERR: ^~~~~~~~~~~~~~~~~ -// CHECK:STDERR: fail_todo_merge.carbon:[[@LINE+7]]:1: In import. +// CHECK:STDERR: extern library "redecl_extern_api" fn NS.E(); +// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// CHECK:STDERR: fail_merge.carbon:[[@LINE+7]]:1: In import. // CHECK:STDERR: import library "api"; // CHECK:STDERR: ^~~~~~ // CHECK:STDERR: api.carbon:10:1: Name is previously declared here. @@ -166,75 +216,74 @@ var c: {.c: i32} = C((1,)); var d: () = D(); var e: () = NS.E(); -// --- fail_todo_merge_reverse.carbon +// --- fail_merge_reverse.carbon library "merge_reverse"; -// CHECK:STDERR: fail_todo_merge_reverse.carbon:[[@LINE+65]]:1: In import. +// CHECK:STDERR: fail_merge_reverse.carbon:[[@LINE+64]]:1: In import. // CHECK:STDERR: import library "extern_api"; // CHECK:STDERR: ^~~~~~ // CHECK:STDERR: api.carbon:4:1: ERROR: Duplicate name being declared in the same scope. // CHECK:STDERR: fn A(); // CHECK:STDERR: ^~~~~~~ -// CHECK:STDERR: fail_todo_merge_reverse.carbon:[[@LINE+59]]:1: In import. +// CHECK:STDERR: fail_merge_reverse.carbon:[[@LINE+58]]:1: In import. // CHECK:STDERR: import library "extern_api"; // CHECK:STDERR: ^~~~~~ // CHECK:STDERR: extern_api.carbon:4:1: Name is previously declared here. -// CHECK:STDERR: extern fn A(); -// CHECK:STDERR: ^~~~~~~~~~~~~~ +// CHECK:STDERR: extern library "redecl_extern_api" fn A(); +// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // CHECK:STDERR: -// CHECK:STDERR: fail_todo_merge_reverse.carbon:[[@LINE+52]]:1: In import. +// CHECK:STDERR: fail_merge_reverse.carbon:[[@LINE+51]]:1: In import. // CHECK:STDERR: import library "extern_api"; // CHECK:STDERR: ^~~~~~ // CHECK:STDERR: api.carbon:5:1: ERROR: Duplicate name being declared in the same scope. // CHECK:STDERR: fn B(b: i32) -> i32; // CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~ -// CHECK:STDERR: fail_todo_merge_reverse.carbon:[[@LINE+46]]:1: In import. +// CHECK:STDERR: fail_merge_reverse.carbon:[[@LINE+45]]:1: In import. // CHECK:STDERR: import library "extern_api"; // CHECK:STDERR: ^~~~~~ // CHECK:STDERR: extern_api.carbon:5:1: Name is previously declared here. -// CHECK:STDERR: extern fn B(b: i32) -> i32; -// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~ +// CHECK:STDERR: extern library "redecl_extern_api" fn B(b: i32) -> i32; +// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // CHECK:STDERR: -// CHECK:STDERR: fail_todo_merge_reverse.carbon:[[@LINE+39]]:1: In import. +// CHECK:STDERR: fail_merge_reverse.carbon:[[@LINE+38]]:1: In import. // CHECK:STDERR: import library "extern_api"; // CHECK:STDERR: ^~~~~~ // CHECK:STDERR: api.carbon:6:1: ERROR: Duplicate name being declared in the same scope. // CHECK:STDERR: fn C(c: (i32,)) -> {.c: i32}; // CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// CHECK:STDERR: fail_todo_merge_reverse.carbon:[[@LINE+33]]:1: In import. +// CHECK:STDERR: fail_merge_reverse.carbon:[[@LINE+32]]:1: In import. // CHECK:STDERR: import library "extern_api"; // CHECK:STDERR: ^~~~~~ // CHECK:STDERR: extern_api.carbon:6:1: Name is previously declared here. -// CHECK:STDERR: extern fn C(c: (i32,)) -> {.c: i32}; -// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// CHECK:STDERR: extern library "redecl_extern_api" fn C(c: (i32,)) -> {.c: i32}; +// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // CHECK:STDERR: -// CHECK:STDERR: fail_todo_merge_reverse.carbon:[[@LINE+26]]:1: In import. +// CHECK:STDERR: fail_merge_reverse.carbon:[[@LINE+25]]:1: In import. // CHECK:STDERR: import library "extern_api"; // CHECK:STDERR: ^~~~~~ // CHECK:STDERR: api.carbon:7:1: ERROR: Duplicate name being declared in the same scope. // CHECK:STDERR: extern fn D(); // CHECK:STDERR: ^~~~~~~~~~~~~~ -// CHECK:STDERR: fail_todo_merge_reverse.carbon:[[@LINE+20]]:1: In import. +// CHECK:STDERR: fail_merge_reverse.carbon:[[@LINE+19]]:1: In import. // CHECK:STDERR: import library "extern_api"; // CHECK:STDERR: ^~~~~~ // CHECK:STDERR: extern_api.carbon:7:1: Name is previously declared here. -// CHECK:STDERR: extern fn D(); -// CHECK:STDERR: ^~~~~~~~~~~~~~ +// CHECK:STDERR: extern library "redecl_extern_api" fn D(); +// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // CHECK:STDERR: -// CHECK:STDERR: fail_todo_merge_reverse.carbon:[[@LINE+13]]:1: In import. +// CHECK:STDERR: fail_merge_reverse.carbon:[[@LINE+12]]:1: In import. // CHECK:STDERR: import library "extern_api"; // CHECK:STDERR: ^~~~~~ // CHECK:STDERR: api.carbon:10:1: ERROR: Duplicate name being declared in the same scope. // CHECK:STDERR: fn NS.E(); // CHECK:STDERR: ^~~~~~~~~~ -// CHECK:STDERR: fail_todo_merge_reverse.carbon:[[@LINE+7]]:1: In import. +// CHECK:STDERR: fail_merge_reverse.carbon:[[@LINE+6]]:1: In import. // CHECK:STDERR: import library "extern_api"; // CHECK:STDERR: ^~~~~~ // CHECK:STDERR: extern_api.carbon:10:1: Name is previously declared here. -// CHECK:STDERR: extern fn NS.E(); -// CHECK:STDERR: ^~~~~~~~~~~~~~~~~ -// CHECK:STDERR: +// CHECK:STDERR: extern library "redecl_extern_api" fn NS.E(); +// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ import library "extern_api"; import library "api"; @@ -244,46 +293,6 @@ var c: {.c: i32} = C((1,)); var d: () = D(); var e: () = NS.E(); -// --- decl_after_use.carbon - -library "decl_after_use"; - -import library "extern_api"; - -var a: () = A(); - -fn A(); - -// --- fail_redecl_mismatch_after_use.carbon - -library "redecl_mismatch_after_use"; - -import library "extern_api"; - -var a: () = A(); - -// CHECK:STDERR: fail_redecl_mismatch_after_use.carbon:[[@LINE+10]]:1: ERROR: Function redeclaration differs because return type is `i32`. -// CHECK:STDERR: fn A() -> i32; -// CHECK:STDERR: ^~~~~~~~~~~~~~ -// CHECK:STDERR: fail_redecl_mismatch_after_use.carbon:[[@LINE-7]]:1: In import. -// CHECK:STDERR: import library "extern_api"; -// CHECK:STDERR: ^~~~~~ -// CHECK:STDERR: extern_api.carbon:4:1: Previously declared with no return type. -// CHECK:STDERR: extern fn A(); -// CHECK:STDERR: ^~~~~~~~~~~~~~ -// CHECK:STDERR: -fn A() -> i32; - -// --- todo_fail_extern_after_use.carbon - -library "extern_after_use"; - -import library "api"; - -var a: () = A(); - -extern fn A(); - // --- unloaded.carbon library "unloaded"; @@ -296,77 +305,6 @@ library "unloaded_extern"; import library "extern_api"; -// --- fail_todo_loaded_merge.carbon - -library "loaded_merge"; - -// CHECK:STDERR: fail_todo_loaded_merge.carbon:[[@LINE+64]]:1: In import. -// CHECK:STDERR: import library "api"; -// CHECK:STDERR: ^~~~~~ -// CHECK:STDERR: extern_api.carbon:4:1: ERROR: Duplicate name being declared in the same scope. -// CHECK:STDERR: extern fn A(); -// CHECK:STDERR: ^~~~~~~~~~~~~~ -// CHECK:STDERR: fail_todo_loaded_merge.carbon:[[@LINE+58]]:1: In import. -// CHECK:STDERR: import library "api"; -// CHECK:STDERR: ^~~~~~ -// CHECK:STDERR: api.carbon:4:1: Name is previously declared here. -// CHECK:STDERR: fn A(); -// CHECK:STDERR: ^~~~~~~ -// CHECK:STDERR: -// CHECK:STDERR: fail_todo_loaded_merge.carbon:[[@LINE+51]]:1: In import. -// CHECK:STDERR: import library "api"; -// CHECK:STDERR: ^~~~~~ -// CHECK:STDERR: extern_api.carbon:5:1: ERROR: Duplicate name being declared in the same scope. -// CHECK:STDERR: extern fn B(b: i32) -> i32; -// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~ -// CHECK:STDERR: fail_todo_loaded_merge.carbon:[[@LINE+45]]:1: In import. -// CHECK:STDERR: import library "api"; -// CHECK:STDERR: ^~~~~~ -// CHECK:STDERR: api.carbon:5:1: Name is previously declared here. -// CHECK:STDERR: fn B(b: i32) -> i32; -// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~ -// CHECK:STDERR: -// CHECK:STDERR: fail_todo_loaded_merge.carbon:[[@LINE+38]]:1: In import. -// CHECK:STDERR: import library "api"; -// CHECK:STDERR: ^~~~~~ -// CHECK:STDERR: extern_api.carbon:6:1: ERROR: Duplicate name being declared in the same scope. -// CHECK:STDERR: extern fn C(c: (i32,)) -> {.c: i32}; -// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// CHECK:STDERR: fail_todo_loaded_merge.carbon:[[@LINE+32]]:1: In import. -// CHECK:STDERR: import library "api"; -// CHECK:STDERR: ^~~~~~ -// CHECK:STDERR: api.carbon:6:1: Name is previously declared here. -// CHECK:STDERR: fn C(c: (i32,)) -> {.c: i32}; -// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// CHECK:STDERR: -// CHECK:STDERR: fail_todo_loaded_merge.carbon:[[@LINE+25]]:1: In import. -// CHECK:STDERR: import library "api"; -// CHECK:STDERR: ^~~~~~ -// CHECK:STDERR: extern_api.carbon:7:1: ERROR: Duplicate name being declared in the same scope. -// CHECK:STDERR: extern fn D(); -// CHECK:STDERR: ^~~~~~~~~~~~~~ -// CHECK:STDERR: fail_todo_loaded_merge.carbon:[[@LINE+19]]:1: In import. -// CHECK:STDERR: import library "api"; -// CHECK:STDERR: ^~~~~~ -// CHECK:STDERR: api.carbon:7:1: Name is previously declared here. -// CHECK:STDERR: extern fn D(); -// CHECK:STDERR: ^~~~~~~~~~~~~~ -// CHECK:STDERR: -// CHECK:STDERR: fail_todo_loaded_merge.carbon:[[@LINE+12]]:1: In import. -// CHECK:STDERR: import library "api"; -// CHECK:STDERR: ^~~~~~ -// CHECK:STDERR: extern_api.carbon:10:1: ERROR: Duplicate name being declared in the same scope. -// CHECK:STDERR: extern fn NS.E(); -// CHECK:STDERR: ^~~~~~~~~~~~~~~~~ -// CHECK:STDERR: fail_todo_loaded_merge.carbon:[[@LINE+6]]:1: In import. -// CHECK:STDERR: import library "api"; -// CHECK:STDERR: ^~~~~~ -// CHECK:STDERR: api.carbon:10:1: Name is previously declared here. -// CHECK:STDERR: fn NS.E(); -// CHECK:STDERR: ^~~~~~~~~~ -import library "api"; -import library "extern_api"; - // CHECK:STDOUT: --- api.carbon // CHECK:STDOUT: // CHECK:STDOUT: constants { @@ -504,28 +442,28 @@ import library "extern_api"; // CHECK:STDOUT: %Core.import = import Core // CHECK:STDOUT: %A.decl: %A.type = fn_decl @A [template = constants.%A] {} // CHECK:STDOUT: %B.decl: %B.type = fn_decl @B [template = constants.%B] { -// CHECK:STDOUT: %int.make_type_32.loc5_16: init type = call constants.%Int32() [template = i32] -// CHECK:STDOUT: %.loc5_16.1: type = value_of_initializer %int.make_type_32.loc5_16 [template = i32] -// CHECK:STDOUT: %.loc5_16.2: type = converted %int.make_type_32.loc5_16, %.loc5_16.1 [template = i32] -// CHECK:STDOUT: %b.loc5_13.1: i32 = param b -// CHECK:STDOUT: @B.%b: i32 = bind_name b, %b.loc5_13.1 -// CHECK:STDOUT: %int.make_type_32.loc5_24: init type = call constants.%Int32() [template = i32] -// CHECK:STDOUT: %.loc5_24.1: type = value_of_initializer %int.make_type_32.loc5_24 [template = i32] -// CHECK:STDOUT: %.loc5_24.2: type = converted %int.make_type_32.loc5_24, %.loc5_24.1 [template = i32] +// CHECK:STDOUT: %int.make_type_32.loc5_44: init type = call constants.%Int32() [template = i32] +// CHECK:STDOUT: %.loc5_44.1: type = value_of_initializer %int.make_type_32.loc5_44 [template = i32] +// CHECK:STDOUT: %.loc5_44.2: type = converted %int.make_type_32.loc5_44, %.loc5_44.1 [template = i32] +// CHECK:STDOUT: %b.loc5_41.1: i32 = param b +// CHECK:STDOUT: @B.%b: i32 = bind_name b, %b.loc5_41.1 +// CHECK:STDOUT: %int.make_type_32.loc5_52: init type = call constants.%Int32() [template = i32] +// CHECK:STDOUT: %.loc5_52.1: type = value_of_initializer %int.make_type_32.loc5_52 [template = i32] +// CHECK:STDOUT: %.loc5_52.2: type = converted %int.make_type_32.loc5_52, %.loc5_52.1 [template = i32] // CHECK:STDOUT: @B.%return: ref i32 = var // CHECK:STDOUT: } // CHECK:STDOUT: %C.decl: %C.type = fn_decl @C [template = constants.%C] { -// CHECK:STDOUT: %int.make_type_32.loc6_17: init type = call constants.%Int32() [template = i32] -// CHECK:STDOUT: %.loc6_21.1: %.2 = tuple_literal (%int.make_type_32.loc6_17) -// CHECK:STDOUT: %.loc6_21.2: type = value_of_initializer %int.make_type_32.loc6_17 [template = i32] -// CHECK:STDOUT: %.loc6_21.3: type = converted %int.make_type_32.loc6_17, %.loc6_21.2 [template = i32] -// CHECK:STDOUT: %.loc6_21.4: type = converted %.loc6_21.1, constants.%.3 [template = constants.%.3] -// CHECK:STDOUT: %c.loc6_13.1: %.3 = param c -// CHECK:STDOUT: @C.%c: %.3 = bind_name c, %c.loc6_13.1 -// CHECK:STDOUT: %int.make_type_32.loc6_32: init type = call constants.%Int32() [template = i32] -// CHECK:STDOUT: %.loc6_32.1: type = value_of_initializer %int.make_type_32.loc6_32 [template = i32] -// CHECK:STDOUT: %.loc6_32.2: type = converted %int.make_type_32.loc6_32, %.loc6_32.1 [template = i32] -// CHECK:STDOUT: %.loc6_35: type = struct_type {.c: i32} [template = constants.%.4] +// CHECK:STDOUT: %int.make_type_32.loc6_45: init type = call constants.%Int32() [template = i32] +// CHECK:STDOUT: %.loc6_49.1: %.2 = tuple_literal (%int.make_type_32.loc6_45) +// CHECK:STDOUT: %.loc6_49.2: type = value_of_initializer %int.make_type_32.loc6_45 [template = i32] +// CHECK:STDOUT: %.loc6_49.3: type = converted %int.make_type_32.loc6_45, %.loc6_49.2 [template = i32] +// CHECK:STDOUT: %.loc6_49.4: type = converted %.loc6_49.1, constants.%.3 [template = constants.%.3] +// CHECK:STDOUT: %c.loc6_41.1: %.3 = param c +// CHECK:STDOUT: @C.%c: %.3 = bind_name c, %c.loc6_41.1 +// CHECK:STDOUT: %int.make_type_32.loc6_60: init type = call constants.%Int32() [template = i32] +// CHECK:STDOUT: %.loc6_60.1: type = value_of_initializer %int.make_type_32.loc6_60 [template = i32] +// CHECK:STDOUT: %.loc6_60.2: type = converted %int.make_type_32.loc6_60, %.loc6_60.1 [template = i32] +// CHECK:STDOUT: %.loc6_63: type = struct_type {.c: i32} [template = constants.%.4] // CHECK:STDOUT: @C.%return: ref %.4 = var // CHECK:STDOUT: } // CHECK:STDOUT: %D.decl: %D.type = fn_decl @D [template = constants.%D] {} @@ -671,7 +609,7 @@ import library "extern_api"; // CHECK:STDOUT: return // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: --- redecl_api.carbon +// CHECK:STDOUT: --- fail_redecl_api.carbon // CHECK:STDOUT: // CHECK:STDOUT: constants { // CHECK:STDOUT: %A.type: type = fn_type @A [template] @@ -726,8 +664,8 @@ import library "extern_api"; // CHECK:STDOUT: .NS = imports.%NS // CHECK:STDOUT: .Core = imports.%Core // CHECK:STDOUT: .a = %a -// CHECK:STDOUT: .b = %b.loc13 -// CHECK:STDOUT: .c = %c.loc14 +// CHECK:STDOUT: .b = %b.loc63 +// CHECK:STDOUT: .c = %c.loc64 // CHECK:STDOUT: .d = %d // CHECK:STDOUT: .e = %e // CHECK:STDOUT: } @@ -735,53 +673,53 @@ import library "extern_api"; // CHECK:STDOUT: %default.import = import // CHECK:STDOUT: %A.decl: %A.type = fn_decl @A [template = constants.%A] {} // CHECK:STDOUT: %B.decl: %B.type = fn_decl @B [template = constants.%B] { -// CHECK:STDOUT: %int.make_type_32.loc7_16: init type = call constants.%Int32() [template = i32] -// CHECK:STDOUT: %.loc7_16.1: type = value_of_initializer %int.make_type_32.loc7_16 [template = i32] -// CHECK:STDOUT: %.loc7_16.2: type = converted %int.make_type_32.loc7_16, %.loc7_16.1 [template = i32] -// CHECK:STDOUT: %b.loc7_13.1: i32 = param b -// CHECK:STDOUT: %b.loc7_13.2: i32 = bind_name b, %b.loc7_13.1 -// CHECK:STDOUT: %int.make_type_32.loc7_24: init type = call constants.%Int32() [template = i32] -// CHECK:STDOUT: %.loc7_24.1: type = value_of_initializer %int.make_type_32.loc7_24 [template = i32] -// CHECK:STDOUT: %.loc7_24.2: type = converted %int.make_type_32.loc7_24, %.loc7_24.1 [template = i32] -// CHECK:STDOUT: %return.var.loc7: ref i32 = var +// CHECK:STDOUT: %int.make_type_32.loc27_16: init type = call constants.%Int32() [template = i32] +// CHECK:STDOUT: %.loc27_16.1: type = value_of_initializer %int.make_type_32.loc27_16 [template = i32] +// CHECK:STDOUT: %.loc27_16.2: type = converted %int.make_type_32.loc27_16, %.loc27_16.1 [template = i32] +// CHECK:STDOUT: %b.loc27_13.1: i32 = param b +// CHECK:STDOUT: %b.loc27_13.2: i32 = bind_name b, %b.loc27_13.1 +// CHECK:STDOUT: %int.make_type_32.loc27_24: init type = call constants.%Int32() [template = i32] +// CHECK:STDOUT: %.loc27_24.1: type = value_of_initializer %int.make_type_32.loc27_24 [template = i32] +// CHECK:STDOUT: %.loc27_24.2: type = converted %int.make_type_32.loc27_24, %.loc27_24.1 [template = i32] +// CHECK:STDOUT: %return.var.loc27: ref i32 = var // CHECK:STDOUT: } // CHECK:STDOUT: %C.decl: %C.type = fn_decl @C [template = constants.%C] { -// CHECK:STDOUT: %int.make_type_32.loc8_17: init type = call constants.%Int32() [template = i32] -// CHECK:STDOUT: %.loc8_21.1: %.2 = tuple_literal (%int.make_type_32.loc8_17) -// CHECK:STDOUT: %.loc8_21.2: type = value_of_initializer %int.make_type_32.loc8_17 [template = i32] -// CHECK:STDOUT: %.loc8_21.3: type = converted %int.make_type_32.loc8_17, %.loc8_21.2 [template = i32] -// CHECK:STDOUT: %.loc8_21.4: type = converted %.loc8_21.1, constants.%.3 [template = constants.%.3] -// CHECK:STDOUT: %c.loc8_13.1: %.3 = param c -// CHECK:STDOUT: %c.loc8_13.2: %.3 = bind_name c, %c.loc8_13.1 -// CHECK:STDOUT: %int.make_type_32.loc8_32: init type = call constants.%Int32() [template = i32] -// CHECK:STDOUT: %.loc8_32.1: type = value_of_initializer %int.make_type_32.loc8_32 [template = i32] -// CHECK:STDOUT: %.loc8_32.2: type = converted %int.make_type_32.loc8_32, %.loc8_32.1 [template = i32] -// CHECK:STDOUT: %.loc8_35: type = struct_type {.c: i32} [template = constants.%.4] -// CHECK:STDOUT: %return.var.loc8: ref %.4 = var +// CHECK:STDOUT: %int.make_type_32.loc38_17: init type = call constants.%Int32() [template = i32] +// CHECK:STDOUT: %.loc38_21.1: %.2 = tuple_literal (%int.make_type_32.loc38_17) +// CHECK:STDOUT: %.loc38_21.2: type = value_of_initializer %int.make_type_32.loc38_17 [template = i32] +// CHECK:STDOUT: %.loc38_21.3: type = converted %int.make_type_32.loc38_17, %.loc38_21.2 [template = i32] +// CHECK:STDOUT: %.loc38_21.4: type = converted %.loc38_21.1, constants.%.3 [template = constants.%.3] +// CHECK:STDOUT: %c.loc38_13.1: %.3 = param c +// CHECK:STDOUT: %c.loc38_13.2: %.3 = bind_name c, %c.loc38_13.1 +// CHECK:STDOUT: %int.make_type_32.loc38_32: init type = call constants.%Int32() [template = i32] +// CHECK:STDOUT: %.loc38_32.1: type = value_of_initializer %int.make_type_32.loc38_32 [template = i32] +// CHECK:STDOUT: %.loc38_32.2: type = converted %int.make_type_32.loc38_32, %.loc38_32.1 [template = i32] +// CHECK:STDOUT: %.loc38_35: type = struct_type {.c: i32} [template = constants.%.4] +// CHECK:STDOUT: %return.var.loc38: ref %.4 = var // CHECK:STDOUT: } // CHECK:STDOUT: %D.decl: %D.type = fn_decl @D [template = constants.%D] {} // CHECK:STDOUT: %E.decl: %E.type = fn_decl @E [template = constants.%E] {} -// CHECK:STDOUT: %.loc12_9.1: %.1 = tuple_literal () -// CHECK:STDOUT: %.loc12_9.2: type = converted %.loc12_9.1, constants.%.1 [template = constants.%.1] +// CHECK:STDOUT: %.loc62_9.1: %.1 = tuple_literal () +// CHECK:STDOUT: %.loc62_9.2: type = converted %.loc62_9.1, constants.%.1 [template = constants.%.1] // CHECK:STDOUT: %a.var: ref %.1 = var a // CHECK:STDOUT: %a: ref %.1 = bind_name a, %a.var -// CHECK:STDOUT: %int.make_type_32.loc13: init type = call constants.%Int32() [template = i32] -// CHECK:STDOUT: %.loc13_8.1: type = value_of_initializer %int.make_type_32.loc13 [template = i32] -// CHECK:STDOUT: %.loc13_8.2: type = converted %int.make_type_32.loc13, %.loc13_8.1 [template = i32] +// CHECK:STDOUT: %int.make_type_32.loc63: init type = call constants.%Int32() [template = i32] +// CHECK:STDOUT: %.loc63_8.1: type = value_of_initializer %int.make_type_32.loc63 [template = i32] +// CHECK:STDOUT: %.loc63_8.2: type = converted %int.make_type_32.loc63, %.loc63_8.1 [template = i32] // CHECK:STDOUT: %b.var: ref i32 = var b -// CHECK:STDOUT: %b.loc13: ref i32 = bind_name b, %b.var -// CHECK:STDOUT: %int.make_type_32.loc14: init type = call constants.%Int32() [template = i32] -// CHECK:STDOUT: %.loc14_13.1: type = value_of_initializer %int.make_type_32.loc14 [template = i32] -// CHECK:STDOUT: %.loc14_13.2: type = converted %int.make_type_32.loc14, %.loc14_13.1 [template = i32] -// CHECK:STDOUT: %.loc14_16: type = struct_type {.c: i32} [template = constants.%.4] +// CHECK:STDOUT: %b.loc63: ref i32 = bind_name b, %b.var +// CHECK:STDOUT: %int.make_type_32.loc64: init type = call constants.%Int32() [template = i32] +// CHECK:STDOUT: %.loc64_13.1: type = value_of_initializer %int.make_type_32.loc64 [template = i32] +// CHECK:STDOUT: %.loc64_13.2: type = converted %int.make_type_32.loc64, %.loc64_13.1 [template = i32] +// CHECK:STDOUT: %.loc64_16: type = struct_type {.c: i32} [template = constants.%.4] // CHECK:STDOUT: %c.var: ref %.4 = var c -// CHECK:STDOUT: %c.loc14: ref %.4 = bind_name c, %c.var -// CHECK:STDOUT: %.loc15_9.1: %.1 = tuple_literal () -// CHECK:STDOUT: %.loc15_9.2: type = converted %.loc15_9.1, constants.%.1 [template = constants.%.1] +// CHECK:STDOUT: %c.loc64: ref %.4 = bind_name c, %c.var +// CHECK:STDOUT: %.loc65_9.1: %.1 = tuple_literal () +// CHECK:STDOUT: %.loc65_9.2: type = converted %.loc65_9.1, constants.%.1 [template = constants.%.1] // CHECK:STDOUT: %d.var: ref %.1 = var d // CHECK:STDOUT: %d: ref %.1 = bind_name d, %d.var -// CHECK:STDOUT: %.loc16_9.1: %.1 = tuple_literal () -// CHECK:STDOUT: %.loc16_9.2: type = converted %.loc16_9.1, constants.%.1 [template = constants.%.1] +// CHECK:STDOUT: %.loc66_9.1: %.1 = tuple_literal () +// CHECK:STDOUT: %.loc66_9.2: type = converted %.loc66_9.1, constants.%.1 [template = constants.%.1] // CHECK:STDOUT: %e.var: ref %.1 = var e // CHECK:STDOUT: %e: ref %.1 = bind_name e, %e.var // CHECK:STDOUT: } @@ -804,15 +742,15 @@ import library "extern_api"; // CHECK:STDOUT: %A.call: init %.1 = call %A.ref() // CHECK:STDOUT: assign file.%a.var, %A.call // CHECK:STDOUT: %B.ref: %B.type = name_ref B, file.%B.decl [template = constants.%B] -// CHECK:STDOUT: %.loc13: i32 = int_literal 1 [template = constants.%.5] -// CHECK:STDOUT: %B.call: init i32 = call %B.ref(%.loc13) +// CHECK:STDOUT: %.loc63: i32 = int_literal 1 [template = constants.%.5] +// CHECK:STDOUT: %B.call: init i32 = call %B.ref(%.loc63) // CHECK:STDOUT: assign file.%b.var, %B.call // CHECK:STDOUT: %C.ref: %C.type = name_ref C, file.%C.decl [template = constants.%C] -// CHECK:STDOUT: %.loc14_23: i32 = int_literal 1 [template = constants.%.5] -// CHECK:STDOUT: %.loc14_25: %.3 = tuple_literal (%.loc14_23) -// CHECK:STDOUT: %tuple: %.3 = tuple_value (%.loc14_23) [template = constants.%tuple] -// CHECK:STDOUT: %.loc14_21: %.3 = converted %.loc14_25, %tuple [template = constants.%tuple] -// CHECK:STDOUT: %C.call: init %.4 = call %C.ref(%.loc14_21) +// CHECK:STDOUT: %.loc64_23: i32 = int_literal 1 [template = constants.%.5] +// CHECK:STDOUT: %.loc64_25: %.3 = tuple_literal (%.loc64_23) +// CHECK:STDOUT: %tuple: %.3 = tuple_value (%.loc64_23) [template = constants.%tuple] +// CHECK:STDOUT: %.loc64_21: %.3 = converted %.loc64_25, %tuple [template = constants.%tuple] +// CHECK:STDOUT: %C.call: init %.4 = call %C.ref(%.loc64_21) // CHECK:STDOUT: assign file.%c.var, %C.call // CHECK:STDOUT: %D.ref: %D.type = name_ref D, file.%D.decl [template = constants.%D] // CHECK:STDOUT: %D.call: init %.1 = call %D.ref() @@ -977,7 +915,7 @@ import library "extern_api"; // CHECK:STDOUT: return // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: --- fail_todo_merge.carbon +// CHECK:STDOUT: --- fail_merge.carbon // CHECK:STDOUT: // CHECK:STDOUT: constants { // CHECK:STDOUT: %.1: type = tuple_type () [template] @@ -1106,7 +1044,7 @@ import library "extern_api"; // CHECK:STDOUT: return // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: --- fail_todo_merge_reverse.carbon +// CHECK:STDOUT: --- fail_merge_reverse.carbon // CHECK:STDOUT: // CHECK:STDOUT: constants { // CHECK:STDOUT: %.1: type = tuple_type () [template] @@ -1172,27 +1110,27 @@ import library "extern_api"; // CHECK:STDOUT: } // CHECK:STDOUT: %Core.import = import Core // CHECK:STDOUT: %default.import = import -// CHECK:STDOUT: %.loc72_9.1: %.1 = tuple_literal () -// CHECK:STDOUT: %.loc72_9.2: type = converted %.loc72_9.1, constants.%.1 [template = constants.%.1] +// CHECK:STDOUT: %.loc71_9.1: %.1 = tuple_literal () +// CHECK:STDOUT: %.loc71_9.2: type = converted %.loc71_9.1, constants.%.1 [template = constants.%.1] // CHECK:STDOUT: %a.var: ref %.1 = var a // CHECK:STDOUT: %a: ref %.1 = bind_name a, %a.var -// CHECK:STDOUT: %int.make_type_32.loc73: init type = call constants.%Int32() [template = i32] -// CHECK:STDOUT: %.loc73_8.1: type = value_of_initializer %int.make_type_32.loc73 [template = i32] -// CHECK:STDOUT: %.loc73_8.2: type = converted %int.make_type_32.loc73, %.loc73_8.1 [template = i32] +// CHECK:STDOUT: %int.make_type_32.loc72: init type = call constants.%Int32() [template = i32] +// CHECK:STDOUT: %.loc72_8.1: type = value_of_initializer %int.make_type_32.loc72 [template = i32] +// CHECK:STDOUT: %.loc72_8.2: type = converted %int.make_type_32.loc72, %.loc72_8.1 [template = i32] // CHECK:STDOUT: %b.var: ref i32 = var b // CHECK:STDOUT: %b: ref i32 = bind_name b, %b.var -// CHECK:STDOUT: %int.make_type_32.loc74: init type = call constants.%Int32() [template = i32] -// CHECK:STDOUT: %.loc74_13.1: type = value_of_initializer %int.make_type_32.loc74 [template = i32] -// CHECK:STDOUT: %.loc74_13.2: type = converted %int.make_type_32.loc74, %.loc74_13.1 [template = i32] -// CHECK:STDOUT: %.loc74_16: type = struct_type {.c: i32} [template = constants.%.3] +// CHECK:STDOUT: %int.make_type_32.loc73: init type = call constants.%Int32() [template = i32] +// CHECK:STDOUT: %.loc73_13.1: type = value_of_initializer %int.make_type_32.loc73 [template = i32] +// CHECK:STDOUT: %.loc73_13.2: type = converted %int.make_type_32.loc73, %.loc73_13.1 [template = i32] +// CHECK:STDOUT: %.loc73_16: type = struct_type {.c: i32} [template = constants.%.3] // CHECK:STDOUT: %c.var: ref %.3 = var c // CHECK:STDOUT: %c: ref %.3 = bind_name c, %c.var -// CHECK:STDOUT: %.loc75_9.1: %.1 = tuple_literal () -// CHECK:STDOUT: %.loc75_9.2: type = converted %.loc75_9.1, constants.%.1 [template = constants.%.1] +// CHECK:STDOUT: %.loc74_9.1: %.1 = tuple_literal () +// CHECK:STDOUT: %.loc74_9.2: type = converted %.loc74_9.1, constants.%.1 [template = constants.%.1] // CHECK:STDOUT: %d.var: ref %.1 = var d // CHECK:STDOUT: %d: ref %.1 = bind_name d, %d.var -// CHECK:STDOUT: %.loc76_9.1: %.1 = tuple_literal () -// CHECK:STDOUT: %.loc76_9.2: type = converted %.loc76_9.1, constants.%.1 [template = constants.%.1] +// CHECK:STDOUT: %.loc75_9.1: %.1 = tuple_literal () +// CHECK:STDOUT: %.loc75_9.2: type = converted %.loc75_9.1, constants.%.1 [template = constants.%.1] // CHECK:STDOUT: %e.var: ref %.1 = var e // CHECK:STDOUT: %e: ref %.1 = bind_name e, %e.var // CHECK:STDOUT: } @@ -1215,15 +1153,15 @@ import library "extern_api"; // CHECK:STDOUT: %A.call: init %.1 = call %A.ref() // CHECK:STDOUT: assign file.%a.var, %A.call // CHECK:STDOUT: %B.ref: %B.type = name_ref B, imports.%import_ref.2 [template = constants.%B] -// CHECK:STDOUT: %.loc73: i32 = int_literal 1 [template = constants.%.2] -// CHECK:STDOUT: %B.call: init i32 = call %B.ref(%.loc73) +// CHECK:STDOUT: %.loc72: i32 = int_literal 1 [template = constants.%.2] +// CHECK:STDOUT: %B.call: init i32 = call %B.ref(%.loc72) // CHECK:STDOUT: assign file.%b.var, %B.call // CHECK:STDOUT: %C.ref: %C.type = name_ref C, imports.%import_ref.3 [template = constants.%C] -// CHECK:STDOUT: %.loc74_23: i32 = int_literal 1 [template = constants.%.2] -// CHECK:STDOUT: %.loc74_25: %.4 = tuple_literal (%.loc74_23) -// CHECK:STDOUT: %tuple: %.4 = tuple_value (%.loc74_23) [template = constants.%tuple] -// CHECK:STDOUT: %.loc74_21: %.4 = converted %.loc74_25, %tuple [template = constants.%tuple] -// CHECK:STDOUT: %C.call: init %.3 = call %C.ref(%.loc74_21) +// CHECK:STDOUT: %.loc73_23: i32 = int_literal 1 [template = constants.%.2] +// CHECK:STDOUT: %.loc73_25: %.4 = tuple_literal (%.loc73_23) +// CHECK:STDOUT: %tuple: %.4 = tuple_value (%.loc73_23) [template = constants.%tuple] +// CHECK:STDOUT: %.loc73_21: %.4 = converted %.loc73_25, %tuple [template = constants.%tuple] +// CHECK:STDOUT: %C.call: init %.3 = call %C.ref(%.loc73_21) // CHECK:STDOUT: assign file.%c.var, %C.call // CHECK:STDOUT: %D.ref: %D.type = name_ref D, imports.%import_ref.4 [template = constants.%D] // CHECK:STDOUT: %D.call: init %.1 = call %D.ref() @@ -1235,195 +1173,6 @@ import library "extern_api"; // CHECK:STDOUT: return // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: --- decl_after_use.carbon -// CHECK:STDOUT: -// CHECK:STDOUT: constants { -// CHECK:STDOUT: %.1: type = tuple_type () [template] -// CHECK:STDOUT: %A.type: type = fn_type @A [template] -// CHECK:STDOUT: %A: %A.type = struct_value () [template] -// CHECK:STDOUT: } -// CHECK:STDOUT: -// CHECK:STDOUT: imports { -// CHECK:STDOUT: %import_ref.1: %A.type = import_ref Main//extern_api, inst+3, loaded [template = constants.%A] -// CHECK:STDOUT: %import_ref.2 = import_ref Main//extern_api, inst+21, unloaded -// CHECK:STDOUT: %import_ref.3 = import_ref Main//extern_api, inst+41, unloaded -// CHECK:STDOUT: %import_ref.4 = import_ref Main//extern_api, inst+44, unloaded -// CHECK:STDOUT: %import_ref.5: = import_ref Main//extern_api, inst+47, loaded -// CHECK:STDOUT: %NS: = namespace %import_ref.5, [template] { -// CHECK:STDOUT: .E = %import_ref.6 -// CHECK:STDOUT: } -// CHECK:STDOUT: %import_ref.6 = import_ref Main//extern_api, inst+48, unloaded -// CHECK:STDOUT: %Core: = namespace file.%Core.import, [template] { -// CHECK:STDOUT: import Core//prelude -// CHECK:STDOUT: import Core//prelude/operators -// CHECK:STDOUT: import Core//prelude/types -// CHECK:STDOUT: import Core//prelude/operators/arithmetic -// CHECK:STDOUT: import Core//prelude/operators/bitwise -// CHECK:STDOUT: import Core//prelude/operators/comparison -// CHECK:STDOUT: import Core//prelude/types/bool -// CHECK:STDOUT: } -// CHECK:STDOUT: } -// CHECK:STDOUT: -// CHECK:STDOUT: file { -// CHECK:STDOUT: package: = namespace [template] { -// CHECK:STDOUT: .A = %A.decl -// CHECK:STDOUT: .B = imports.%import_ref.2 -// CHECK:STDOUT: .C = imports.%import_ref.3 -// CHECK:STDOUT: .D = imports.%import_ref.4 -// CHECK:STDOUT: .NS = imports.%NS -// CHECK:STDOUT: .Core = imports.%Core -// CHECK:STDOUT: .a = %a -// CHECK:STDOUT: } -// CHECK:STDOUT: %Core.import = import Core -// CHECK:STDOUT: %default.import = import -// CHECK:STDOUT: %.loc6_9.1: %.1 = tuple_literal () -// CHECK:STDOUT: %.loc6_9.2: type = converted %.loc6_9.1, constants.%.1 [template = constants.%.1] -// CHECK:STDOUT: %a.var: ref %.1 = var a -// CHECK:STDOUT: %a: ref %.1 = bind_name a, %a.var -// CHECK:STDOUT: %A.decl: %A.type = fn_decl @A [template = constants.%A] {} -// CHECK:STDOUT: } -// CHECK:STDOUT: -// CHECK:STDOUT: fn @A(); -// CHECK:STDOUT: -// CHECK:STDOUT: fn @__global_init() { -// CHECK:STDOUT: !entry: -// CHECK:STDOUT: %A.ref: %A.type = name_ref A, imports.%import_ref.1 [template = constants.%A] -// CHECK:STDOUT: %A.call: init %.1 = call %A.ref() -// CHECK:STDOUT: assign file.%a.var, %A.call -// CHECK:STDOUT: return -// CHECK:STDOUT: } -// CHECK:STDOUT: -// CHECK:STDOUT: --- fail_redecl_mismatch_after_use.carbon -// CHECK:STDOUT: -// CHECK:STDOUT: constants { -// CHECK:STDOUT: %.1: type = tuple_type () [template] -// CHECK:STDOUT: %A.type: type = fn_type @A [template] -// CHECK:STDOUT: %A: %A.type = struct_value () [template] -// CHECK:STDOUT: %Int32.type: type = fn_type @Int32 [template] -// CHECK:STDOUT: %Int32: %Int32.type = struct_value () [template] -// CHECK:STDOUT: %.type: type = fn_type @.1 [template] -// CHECK:STDOUT: %.2: %.type = struct_value () [template] -// CHECK:STDOUT: } -// CHECK:STDOUT: -// CHECK:STDOUT: imports { -// CHECK:STDOUT: %import_ref.1: %A.type = import_ref Main//extern_api, inst+3, loaded [template = constants.%A] -// CHECK:STDOUT: %import_ref.2 = import_ref Main//extern_api, inst+21, unloaded -// CHECK:STDOUT: %import_ref.3 = import_ref Main//extern_api, inst+41, unloaded -// CHECK:STDOUT: %import_ref.4 = import_ref Main//extern_api, inst+44, unloaded -// CHECK:STDOUT: %import_ref.5: = import_ref Main//extern_api, inst+47, loaded -// CHECK:STDOUT: %NS: = namespace %import_ref.5, [template] { -// CHECK:STDOUT: .E = %import_ref.6 -// CHECK:STDOUT: } -// CHECK:STDOUT: %import_ref.6 = import_ref Main//extern_api, inst+48, unloaded -// CHECK:STDOUT: %Core: = namespace file.%Core.import, [template] { -// CHECK:STDOUT: .Int32 = %import_ref.7 -// CHECK:STDOUT: import Core//prelude -// CHECK:STDOUT: import Core//prelude/operators -// CHECK:STDOUT: import Core//prelude/types -// CHECK:STDOUT: import Core//prelude/operators/arithmetic -// CHECK:STDOUT: import Core//prelude/operators/bitwise -// CHECK:STDOUT: import Core//prelude/operators/comparison -// CHECK:STDOUT: import Core//prelude/types/bool -// CHECK:STDOUT: } -// CHECK:STDOUT: %import_ref.7: %Int32.type = import_ref Core//prelude/types, inst+4, loaded [template = constants.%Int32] -// CHECK:STDOUT: } -// CHECK:STDOUT: -// CHECK:STDOUT: file { -// CHECK:STDOUT: package: = namespace [template] { -// CHECK:STDOUT: .A = imports.%import_ref.1 -// CHECK:STDOUT: .B = imports.%import_ref.2 -// CHECK:STDOUT: .C = imports.%import_ref.3 -// CHECK:STDOUT: .D = imports.%import_ref.4 -// CHECK:STDOUT: .NS = imports.%NS -// CHECK:STDOUT: .Core = imports.%Core -// CHECK:STDOUT: .a = %a -// CHECK:STDOUT: } -// CHECK:STDOUT: %Core.import = import Core -// CHECK:STDOUT: %default.import = import -// CHECK:STDOUT: %.loc6_9.1: %.1 = tuple_literal () -// CHECK:STDOUT: %.loc6_9.2: type = converted %.loc6_9.1, constants.%.1 [template = constants.%.1] -// CHECK:STDOUT: %a.var: ref %.1 = var a -// CHECK:STDOUT: %a: ref %.1 = bind_name a, %a.var -// CHECK:STDOUT: %.decl: %.type = fn_decl @.1 [template = constants.%.2] { -// CHECK:STDOUT: %int.make_type_32: init type = call constants.%Int32() [template = i32] -// CHECK:STDOUT: %.loc18_11.1: type = value_of_initializer %int.make_type_32 [template = i32] -// CHECK:STDOUT: %.loc18_11.2: type = converted %int.make_type_32, %.loc18_11.1 [template = i32] -// CHECK:STDOUT: @.1.%return: ref i32 = var -// CHECK:STDOUT: } -// CHECK:STDOUT: } -// CHECK:STDOUT: -// CHECK:STDOUT: extern fn @A(); -// CHECK:STDOUT: -// CHECK:STDOUT: fn @Int32() -> type = "int.make_type_32"; -// CHECK:STDOUT: -// CHECK:STDOUT: fn @.1() -> i32; -// CHECK:STDOUT: -// CHECK:STDOUT: fn @__global_init() { -// CHECK:STDOUT: !entry: -// CHECK:STDOUT: %A.ref: %A.type = name_ref A, imports.%import_ref.1 [template = constants.%A] -// CHECK:STDOUT: %A.call: init %.1 = call %A.ref() -// CHECK:STDOUT: assign file.%a.var, %A.call -// CHECK:STDOUT: return -// CHECK:STDOUT: } -// CHECK:STDOUT: -// CHECK:STDOUT: --- todo_fail_extern_after_use.carbon -// CHECK:STDOUT: -// CHECK:STDOUT: constants { -// CHECK:STDOUT: %.1: type = tuple_type () [template] -// CHECK:STDOUT: %A.type: type = fn_type @A [template] -// CHECK:STDOUT: %A: %A.type = struct_value () [template] -// CHECK:STDOUT: } -// CHECK:STDOUT: -// CHECK:STDOUT: imports { -// CHECK:STDOUT: %import_ref.1: %A.type = import_ref Main//api, inst+3, loaded [template = constants.%A] -// CHECK:STDOUT: %import_ref.2 = import_ref Main//api, inst+21, unloaded -// CHECK:STDOUT: %import_ref.3 = import_ref Main//api, inst+41, unloaded -// CHECK:STDOUT: %import_ref.4 = import_ref Main//api, inst+44, unloaded -// CHECK:STDOUT: %import_ref.5: = import_ref Main//api, inst+47, loaded -// CHECK:STDOUT: %NS: = namespace %import_ref.5, [template] { -// CHECK:STDOUT: .E = %import_ref.6 -// CHECK:STDOUT: } -// CHECK:STDOUT: %import_ref.6 = import_ref Main//api, inst+48, unloaded -// CHECK:STDOUT: %Core: = namespace file.%Core.import, [template] { -// CHECK:STDOUT: import Core//prelude -// CHECK:STDOUT: import Core//prelude/operators -// CHECK:STDOUT: import Core//prelude/types -// CHECK:STDOUT: import Core//prelude/operators/arithmetic -// CHECK:STDOUT: import Core//prelude/operators/bitwise -// CHECK:STDOUT: import Core//prelude/operators/comparison -// CHECK:STDOUT: import Core//prelude/types/bool -// CHECK:STDOUT: } -// CHECK:STDOUT: } -// CHECK:STDOUT: -// CHECK:STDOUT: file { -// CHECK:STDOUT: package: = namespace [template] { -// CHECK:STDOUT: .A = %A.decl -// CHECK:STDOUT: .B = imports.%import_ref.2 -// CHECK:STDOUT: .C = imports.%import_ref.3 -// CHECK:STDOUT: .D = imports.%import_ref.4 -// CHECK:STDOUT: .NS = imports.%NS -// CHECK:STDOUT: .Core = imports.%Core -// CHECK:STDOUT: .a = %a -// CHECK:STDOUT: } -// CHECK:STDOUT: %Core.import = import Core -// CHECK:STDOUT: %default.import = import -// CHECK:STDOUT: %.loc6_9.1: %.1 = tuple_literal () -// CHECK:STDOUT: %.loc6_9.2: type = converted %.loc6_9.1, constants.%.1 [template = constants.%.1] -// CHECK:STDOUT: %a.var: ref %.1 = var a -// CHECK:STDOUT: %a: ref %.1 = bind_name a, %a.var -// CHECK:STDOUT: %A.decl: %A.type = fn_decl @A [template = constants.%A] {} -// CHECK:STDOUT: } -// CHECK:STDOUT: -// CHECK:STDOUT: extern fn @A(); -// CHECK:STDOUT: -// CHECK:STDOUT: fn @__global_init() { -// CHECK:STDOUT: !entry: -// CHECK:STDOUT: %A.ref: %A.type = name_ref A, imports.%import_ref.1 [template = constants.%A] -// CHECK:STDOUT: %A.call: init %.1 = call %A.ref() -// CHECK:STDOUT: assign file.%a.var, %A.call -// CHECK:STDOUT: return -// CHECK:STDOUT: } -// CHECK:STDOUT: // CHECK:STDOUT: --- unloaded.carbon // CHECK:STDOUT: // CHECK:STDOUT: imports { @@ -1496,44 +1245,3 @@ import library "extern_api"; // CHECK:STDOUT: %default.import = import // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: --- fail_todo_loaded_merge.carbon -// CHECK:STDOUT: -// CHECK:STDOUT: imports { -// CHECK:STDOUT: %import_ref.1 = import_ref Main//api, inst+3, unloaded -// CHECK:STDOUT: %import_ref.2 = import_ref Main//api, inst+21, unloaded -// CHECK:STDOUT: %import_ref.3 = import_ref Main//api, inst+41, unloaded -// CHECK:STDOUT: %import_ref.4 = import_ref Main//api, inst+44, unloaded -// CHECK:STDOUT: %import_ref.5: = import_ref Main//api, inst+47, loaded -// CHECK:STDOUT: %NS: = namespace %import_ref.5, [template] { -// CHECK:STDOUT: .E = %import_ref.6 -// CHECK:STDOUT: } -// CHECK:STDOUT: %import_ref.6 = import_ref Main//api, inst+48, unloaded -// CHECK:STDOUT: %import_ref.7 = import_ref Main//extern_api, inst+3, unloaded -// CHECK:STDOUT: %import_ref.8 = import_ref Main//extern_api, inst+21, unloaded -// CHECK:STDOUT: %import_ref.9 = import_ref Main//extern_api, inst+41, unloaded -// CHECK:STDOUT: %import_ref.10 = import_ref Main//extern_api, inst+44, unloaded -// CHECK:STDOUT: %import_ref.11 = import_ref Main//extern_api, inst+48, unloaded -// CHECK:STDOUT: %Core: = namespace file.%Core.import, [template] { -// CHECK:STDOUT: import Core//prelude -// CHECK:STDOUT: import Core//prelude/operators -// CHECK:STDOUT: import Core//prelude/types -// CHECK:STDOUT: import Core//prelude/operators/arithmetic -// CHECK:STDOUT: import Core//prelude/operators/bitwise -// CHECK:STDOUT: import Core//prelude/operators/comparison -// CHECK:STDOUT: import Core//prelude/types/bool -// CHECK:STDOUT: } -// CHECK:STDOUT: } -// CHECK:STDOUT: -// CHECK:STDOUT: file { -// CHECK:STDOUT: package: = namespace [template] { -// CHECK:STDOUT: .A = imports.%import_ref.1 -// CHECK:STDOUT: .B = imports.%import_ref.2 -// CHECK:STDOUT: .C = imports.%import_ref.3 -// CHECK:STDOUT: .D = imports.%import_ref.4 -// CHECK:STDOUT: .NS = imports.%NS -// CHECK:STDOUT: .Core = imports.%Core -// CHECK:STDOUT: } -// CHECK:STDOUT: %Core.import = import Core -// CHECK:STDOUT: %default.import = import -// CHECK:STDOUT: } -// CHECK:STDOUT: diff --git a/toolchain/check/testdata/function/declaration/no_prelude/extern.carbon b/toolchain/check/testdata/function/declaration/no_prelude/extern.carbon index 8c960562acc6..a4d4ca9d9d81 100644 --- a/toolchain/check/testdata/function/declaration/no_prelude/extern.carbon +++ b/toolchain/check/testdata/function/declaration/no_prelude/extern.carbon @@ -14,6 +14,12 @@ library "basic"; extern fn F(); +// --- basic_use.carbon + +import library "basic"; + +var x: () = F(); + // --- fail_redecl.carbon library "redecl"; @@ -52,22 +58,12 @@ class C { // CHECK:STDERR: ^~~~~~ // CHECK:STDERR: extern fn F(); - // CHECK:STDERR: fail_member_extern.carbon:[[@LINE+4]]:3: ERROR: `extern` not allowed on `fn` declaration that is a member. + // CHECK:STDERR: fail_member_extern.carbon:[[@LINE+3]]:3: ERROR: `extern` not allowed on `fn` declaration that is a member. // CHECK:STDERR: extern fn G[self: Self](); // CHECK:STDERR: ^~~~~~ - // CHECK:STDERR: extern fn G[self: Self](); } -// --- fail_todo_extern_library.carbon - -library "extern_library"; - -// CHECK:STDERR: fail_todo_extern_library.carbon:[[@LINE+3]]:1: ERROR: Semantics TODO: `extern library syntax`. -// CHECK:STDERR: extern library "foo" fn F(); -// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~ -extern library "foo" fn F(); - // CHECK:STDOUT: --- basic.carbon // CHECK:STDOUT: // CHECK:STDOUT: constants { @@ -85,6 +81,40 @@ extern library "foo" fn F(); // CHECK:STDOUT: // CHECK:STDOUT: extern fn @F(); // CHECK:STDOUT: +// CHECK:STDOUT: --- basic_use.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %.1: type = tuple_type () [template] +// CHECK:STDOUT: %F.type: type = fn_type @F [template] +// CHECK:STDOUT: %F: %F.type = struct_value () [template] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: imports { +// CHECK:STDOUT: %import_ref: %F.type = import_ref Main//basic, inst+1, loaded [template = constants.%F] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .F = imports.%import_ref +// CHECK:STDOUT: .x = %x +// CHECK:STDOUT: } +// CHECK:STDOUT: %default.import = import +// CHECK:STDOUT: %.loc4_9.1: %.1 = tuple_literal () +// CHECK:STDOUT: %.loc4_9.2: type = converted %.loc4_9.1, constants.%.1 [template = constants.%.1] +// CHECK:STDOUT: %x.var: ref %.1 = var x +// CHECK:STDOUT: %x: ref %.1 = bind_name x, %x.var +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: extern fn @F(); +// CHECK:STDOUT: +// CHECK:STDOUT: fn @__global_init() { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %F.ref: %F.type = name_ref F, imports.%import_ref [template = constants.%F] +// CHECK:STDOUT: %F.call: init %.1 = call %F.ref() +// CHECK:STDOUT: assign file.%x.var, %F.call +// CHECK:STDOUT: return +// CHECK:STDOUT: } +// CHECK:STDOUT: // CHECK:STDOUT: --- fail_redecl.carbon // CHECK:STDOUT: // CHECK:STDOUT: constants { @@ -144,8 +174,8 @@ extern library "foo" fn F(); // CHECK:STDOUT: %F.decl: %F.type = fn_decl @F [template = constants.%F] {} // CHECK:STDOUT: %G.decl: %G.type = fn_decl @G [template = constants.%G] { // CHECK:STDOUT: %Self.ref: type = name_ref Self, constants.%C [template = constants.%C] -// CHECK:STDOUT: %self.loc14_15.1: %C = param self -// CHECK:STDOUT: %self.loc14_15.2: %C = bind_name self, %self.loc14_15.1 +// CHECK:STDOUT: %self.loc13_15.1: %C = param self +// CHECK:STDOUT: %self.loc13_15.2: %C = bind_name self, %self.loc13_15.1 // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: !members: @@ -156,9 +186,5 @@ extern library "foo" fn F(); // CHECK:STDOUT: // CHECK:STDOUT: fn @F(); // CHECK:STDOUT: -// CHECK:STDOUT: fn @G[@C.%self.loc14_15.2: %C](); -// CHECK:STDOUT: -// CHECK:STDOUT: --- fail_todo_extern_library.carbon -// CHECK:STDOUT: -// CHECK:STDOUT: file {} +// CHECK:STDOUT: fn @G[@C.%self.loc13_15.2: %C](); // CHECK:STDOUT: diff --git a/toolchain/check/testdata/function/declaration/no_prelude/extern_library.carbon b/toolchain/check/testdata/function/declaration/no_prelude/extern_library.carbon new file mode 100644 index 000000000000..e25a28d6b81b --- /dev/null +++ b/toolchain/check/testdata/function/declaration/no_prelude/extern_library.carbon @@ -0,0 +1,381 @@ +// 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/extern_library.carbon +// TIP: To dump output, run: +// TIP: bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/function/declaration/no_prelude/extern_library.carbon + +// --- extern_library.carbon + +library "extern_library"; + +extern library "extern_library_owner" fn F(); + +// --- extern_library_owner.carbon + +library "extern_library_owner"; + +import library "extern_library"; + +extern fn F(); + +// --- fail_extern_library_nonowner.carbon + +library "extern_library_nonowner"; + +import library "extern_library"; + +// CHECK:STDERR: fail_extern_library_nonowner.carbon:[[@LINE+10]]:1: ERROR: Declaration in library "extern_library_nonowner" doesn't match `extern library` declaration. +// CHECK:STDERR: extern fn F(); +// CHECK:STDERR: ^~~~~~~~~~~~~~ +// CHECK:STDERR: fail_extern_library_nonowner.carbon:[[@LINE-5]]:1: In import. +// CHECK:STDERR: import library "extern_library"; +// CHECK:STDERR: ^~~~~~ +// CHECK:STDERR: extern_library.carbon:4:1: Previously declared with `extern library` here. +// CHECK:STDERR: extern library "extern_library_owner" fn F(); +// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// CHECK:STDERR: +extern fn F(); + +// --- fail_extern_library_nonextern.carbon + +library "extern_library_nonextern"; + +import library "extern_library"; + +// CHECK:STDERR: fail_extern_library_nonextern.carbon:[[@LINE+10]]:1: ERROR: Redeclarations of `fn F` must match use of `extern`. +// CHECK:STDERR: fn F(); +// CHECK:STDERR: ^~~~~~~ +// CHECK:STDERR: fail_extern_library_nonextern.carbon:[[@LINE-5]]:1: In import. +// CHECK:STDERR: import library "extern_library"; +// CHECK:STDERR: ^~~~~~ +// CHECK:STDERR: extern_library.carbon:4:1: Previously declared here. +// CHECK:STDERR: extern library "extern_library_owner" fn F(); +// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// CHECK:STDERR: +fn F(); + +// --- fail_extern_library_redecl.carbon + +library "fail_extern_library_redecl"; + +import library "extern_library"; + +// CHECK:STDERR: fail_extern_library_redecl.carbon:[[@LINE+10]]:1: ERROR: Declaration in library "fail_extern_library_redecl" doesn't match `extern library` declaration. +// CHECK:STDERR: extern library "extern_library_owner" fn F(); +// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// CHECK:STDERR: fail_extern_library_redecl.carbon:[[@LINE-5]]:1: In import. +// CHECK:STDERR: import library "extern_library"; +// CHECK:STDERR: ^~~~~~ +// CHECK:STDERR: extern_library.carbon:4:1: Previously declared with `extern library` here. +// CHECK:STDERR: extern library "extern_library_owner" fn F(); +// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// CHECK:STDERR: +extern library "extern_library_owner" fn F(); + +// --- extern_library_copy.carbon + +library "extern_library_copy"; + +extern library "extern_library_owner" fn F(); + +// --- fail_extern_library_collision.carbon + +library "extern_library_collision"; + +// CHECK:STDERR: fail_extern_library_collision.carbon:[[@LINE+13]]:1: In import. +// CHECK:STDERR: import library "extern_library"; +// CHECK:STDERR: ^~~~~~ +// CHECK:STDERR: extern_library_copy.carbon:4:1: ERROR: Duplicate name being declared in the same scope. +// CHECK:STDERR: extern library "extern_library_owner" fn F(); +// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// CHECK:STDERR: fail_extern_library_collision.carbon:[[@LINE+7]]:1: In import. +// CHECK:STDERR: import library "extern_library"; +// CHECK:STDERR: ^~~~~~ +// CHECK:STDERR: extern_library.carbon:4:1: Name is previously declared here. +// CHECK:STDERR: extern library "extern_library_owner" fn F(); +// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// CHECK:STDERR: +import library "extern_library"; +import library "extern_library_copy"; + +// --- extern_library_mismatch.carbon + +library "extern_library_mismatch"; + +extern library "extern_library_owner" fn F(); + +// --- fail_extern_library_mismatch_owner.carbon + +library "extern_library_mismatch_owner"; + +import library "extern_library_mismatch" + +// CHECK:STDERR: fail_extern_library_mismatch_owner.carbon:[[@LINE+4]]:1: ERROR: `import` declarations must end with a `;`. +// CHECK:STDERR: extern fn F(); +// CHECK:STDERR: ^~~~~~ +// CHECK:STDERR: +extern fn F(); + +// --- fail_extern_self_library.carbon + +library "extern_self_library"; + +// CHECK:STDERR: fail_extern_self_library.carbon:[[@LINE+4]]:1: ERROR: `extern library` cannot specify the current library. +// CHECK:STDERR: extern library "extern_self_library" fn F(); +// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// CHECK:STDERR: +extern library "extern_self_library" fn F(); + +// --- extern_of_import.carbon + +library "extern_of_import"; + +fn F(); + +// --- fail_extern_of_import_redecl.carbon + +library "extern_of_import_redecl"; + +import library "extern_of_import"; + +// CHECK:STDERR: fail_extern_of_import_redecl.carbon:[[@LINE+9]]:1: ERROR: Redeclarations of `fn F` must match use of `extern`. +// CHECK:STDERR: extern library "extern_of_import" fn F(); +// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// CHECK:STDERR: fail_extern_of_import_redecl.carbon:[[@LINE-5]]:1: In import. +// CHECK:STDERR: import library "extern_of_import"; +// CHECK:STDERR: ^~~~~~ +// CHECK:STDERR: extern_of_import.carbon:4:1: Previously declared here. +// CHECK:STDERR: fn F(); +// CHECK:STDERR: ^~~~~~~ +extern library "extern_of_import" fn F(); + +// CHECK:STDOUT: --- extern_library.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %F.type: type = fn_type @F [template] +// CHECK:STDOUT: %.1: type = tuple_type () [template] +// CHECK:STDOUT: %F: %F.type = 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.type = fn_decl @F [template = constants.%F] {} +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: extern fn @F(); +// CHECK:STDOUT: +// CHECK:STDOUT: --- extern_library_owner.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %F.type: type = fn_type @F [template] +// CHECK:STDOUT: %.1: type = tuple_type () [template] +// CHECK:STDOUT: %F: %F.type = struct_value () [template] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: imports { +// CHECK:STDOUT: %import_ref: %F.type = import_ref Main//extern_library, inst+1, loaded [template = constants.%F] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .F = %F.decl +// CHECK:STDOUT: } +// CHECK:STDOUT: %default.import = import +// CHECK:STDOUT: %F.decl: %F.type = fn_decl @F [template = constants.%F] {} +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: extern fn @F(); +// CHECK:STDOUT: +// CHECK:STDOUT: --- fail_extern_library_nonowner.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %F.type: type = fn_type @F [template] +// CHECK:STDOUT: %.1: type = tuple_type () [template] +// CHECK:STDOUT: %F: %F.type = struct_value () [template] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: imports { +// CHECK:STDOUT: %import_ref: %F.type = import_ref Main//extern_library, inst+1, loaded [template = constants.%F] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .F = %F.decl +// CHECK:STDOUT: } +// CHECK:STDOUT: %default.import = import +// CHECK:STDOUT: %F.decl: %F.type = fn_decl @F [template = constants.%F] {} +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: extern fn @F(); +// CHECK:STDOUT: +// CHECK:STDOUT: --- fail_extern_library_nonextern.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %F.type: type = fn_type @F [template] +// CHECK:STDOUT: %.1: type = tuple_type () [template] +// CHECK:STDOUT: %F: %F.type = struct_value () [template] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: imports { +// CHECK:STDOUT: %import_ref: %F.type = import_ref Main//extern_library, inst+1, loaded [template = constants.%F] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .F = %F.decl +// CHECK:STDOUT: } +// CHECK:STDOUT: %default.import = import +// CHECK:STDOUT: %F.decl: %F.type = fn_decl @F [template = constants.%F] {} +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @F(); +// CHECK:STDOUT: +// CHECK:STDOUT: --- fail_extern_library_redecl.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %F.type: type = fn_type @F [template] +// CHECK:STDOUT: %.1: type = tuple_type () [template] +// CHECK:STDOUT: %F: %F.type = struct_value () [template] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: imports { +// CHECK:STDOUT: %import_ref: %F.type = import_ref Main//extern_library, inst+1, loaded [template = constants.%F] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .F = invalid +// CHECK:STDOUT: } +// CHECK:STDOUT: %default.import = import +// CHECK:STDOUT: %F.decl: %F.type = fn_decl @F [template = constants.%F] {} +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: extern fn @F(); +// CHECK:STDOUT: +// CHECK:STDOUT: --- extern_library_copy.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %F.type: type = fn_type @F [template] +// CHECK:STDOUT: %.1: type = tuple_type () [template] +// CHECK:STDOUT: %F: %F.type = 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.type = fn_decl @F [template = constants.%F] {} +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: extern fn @F(); +// CHECK:STDOUT: +// CHECK:STDOUT: --- fail_extern_library_collision.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: imports { +// CHECK:STDOUT: %import_ref.1 = import_ref Main//extern_library, inst+1, unloaded +// CHECK:STDOUT: %import_ref.2 = import_ref Main//extern_library_copy, inst+1, unloaded +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .F = imports.%import_ref.1 +// CHECK:STDOUT: } +// CHECK:STDOUT: %default.import = import +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: --- extern_library_mismatch.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %F.type: type = fn_type @F [template] +// CHECK:STDOUT: %.1: type = tuple_type () [template] +// CHECK:STDOUT: %F: %F.type = 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.type = fn_decl @F [template = constants.%F] {} +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: extern fn @F(); +// CHECK:STDOUT: +// CHECK:STDOUT: --- fail_extern_library_mismatch_owner.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %F.type: type = fn_type @F [template] +// CHECK:STDOUT: %.1: type = tuple_type () [template] +// CHECK:STDOUT: %F: %F.type = 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.type = fn_decl @F [template = constants.%F] {} +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @F(); +// CHECK:STDOUT: +// CHECK:STDOUT: --- fail_extern_self_library.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %F.type: type = fn_type @F [template] +// CHECK:STDOUT: %.1: type = tuple_type () [template] +// CHECK:STDOUT: %F: %F.type = 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.type = fn_decl @F [template = constants.%F] {} +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: extern fn @F(); +// CHECK:STDOUT: +// CHECK:STDOUT: --- extern_of_import.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %F.type: type = fn_type @F [template] +// CHECK:STDOUT: %.1: type = tuple_type () [template] +// CHECK:STDOUT: %F: %F.type = 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.type = fn_decl @F [template = constants.%F] {} +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @F(); +// CHECK:STDOUT: +// CHECK:STDOUT: --- fail_extern_of_import_redecl.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %F.type: type = fn_type @F [template] +// CHECK:STDOUT: %.1: type = tuple_type () [template] +// CHECK:STDOUT: %F: %F.type = struct_value () [template] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: imports { +// CHECK:STDOUT: %import_ref: %F.type = import_ref Main//extern_of_import, inst+1, loaded [template = constants.%F] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .F = invalid +// CHECK:STDOUT: } +// CHECK:STDOUT: %default.import = import +// CHECK:STDOUT: %F.decl: %F.type = fn_decl @F [template = constants.%F] {} +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: extern fn @F(); +// CHECK:STDOUT: diff --git a/toolchain/check/testdata/function/declaration/no_prelude/extern_library_for_default.carbon b/toolchain/check/testdata/function/declaration/no_prelude/extern_library_for_default.carbon new file mode 100644 index 000000000000..73f0323ad625 --- /dev/null +++ b/toolchain/check/testdata/function/declaration/no_prelude/extern_library_for_default.carbon @@ -0,0 +1,102 @@ +// 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/extern_library_for_default.carbon +// TIP: To dump output, run: +// TIP: bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/function/declaration/no_prelude/extern_library_for_default.carbon + +// --- default.carbon + +package Foo; + +extern library "expected" fn F(); + +// --- expected.carbon + +package Foo library "expected"; + +import library default; + +extern fn F(); + +// --- fail_wrong_library.carbon + +package Foo library "wrong_library"; + +import library default; + +// CHECK:STDERR: fail_wrong_library.carbon:[[@LINE+9]]:1: ERROR: Declaration in library "wrong_library" doesn't match `extern library` declaration. +// CHECK:STDERR: extern fn F(); +// CHECK:STDERR: ^~~~~~~~~~~~~~ +// CHECK:STDERR: fail_wrong_library.carbon:[[@LINE-5]]:1: In import. +// CHECK:STDERR: import library default; +// CHECK:STDERR: ^~~~~~ +// CHECK:STDERR: default.carbon:4:1: Previously declared with `extern library` here. +// CHECK:STDERR: extern library "expected" fn F(); +// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +extern fn F(); + +// CHECK:STDOUT: --- default.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %F.type: type = fn_type @F [template] +// CHECK:STDOUT: %.1: type = tuple_type () [template] +// CHECK:STDOUT: %F: %F.type = 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.type = fn_decl @F [template = constants.%F] {} +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: extern fn @F(); +// CHECK:STDOUT: +// CHECK:STDOUT: --- expected.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %F.type: type = fn_type @F [template] +// CHECK:STDOUT: %.1: type = tuple_type () [template] +// CHECK:STDOUT: %F: %F.type = struct_value () [template] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: imports { +// CHECK:STDOUT: %import_ref: %F.type = import_ref Foo//default, inst+1, loaded [template = constants.%F] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .F = %F.decl +// CHECK:STDOUT: } +// CHECK:STDOUT: %default.import = import +// CHECK:STDOUT: %F.decl: %F.type = fn_decl @F [template = constants.%F] {} +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: extern fn @F(); +// CHECK:STDOUT: +// CHECK:STDOUT: --- fail_wrong_library.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %F.type: type = fn_type @F [template] +// CHECK:STDOUT: %.1: type = tuple_type () [template] +// CHECK:STDOUT: %F: %F.type = struct_value () [template] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: imports { +// CHECK:STDOUT: %import_ref: %F.type = import_ref Foo//default, inst+1, loaded [template = constants.%F] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .F = %F.decl +// CHECK:STDOUT: } +// CHECK:STDOUT: %default.import = import +// CHECK:STDOUT: %F.decl: %F.type = fn_decl @F [template = constants.%F] {} +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: extern fn @F(); +// CHECK:STDOUT: diff --git a/toolchain/check/testdata/function/declaration/no_prelude/extern_library_from_default.carbon b/toolchain/check/testdata/function/declaration/no_prelude/extern_library_from_default.carbon new file mode 100644 index 000000000000..e97fbe574a3d --- /dev/null +++ b/toolchain/check/testdata/function/declaration/no_prelude/extern_library_from_default.carbon @@ -0,0 +1,100 @@ +// 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/extern_library_from_default.carbon +// TIP: To dump output, run: +// TIP: bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/function/declaration/no_prelude/extern_library_from_default.carbon + +// --- extern_library.carbon + +library "extern_library"; + +extern library default fn F(); + +// --- default.carbon + +import library "extern_library"; + +extern fn F(); + +// --- fail_wrong_library.carbon + +library "wrong_library"; + +import library "extern_library"; + +// CHECK:STDERR: fail_wrong_library.carbon:[[@LINE+9]]:1: ERROR: Declaration in library "wrong_library" doesn't match `extern library` declaration. +// CHECK:STDERR: extern fn F(); +// CHECK:STDERR: ^~~~~~~~~~~~~~ +// CHECK:STDERR: fail_wrong_library.carbon:[[@LINE-5]]:1: In import. +// CHECK:STDERR: import library "extern_library"; +// CHECK:STDERR: ^~~~~~ +// CHECK:STDERR: extern_library.carbon:4:1: Previously declared with `extern library` here. +// CHECK:STDERR: extern library default fn F(); +// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +extern fn F(); + +// CHECK:STDOUT: --- extern_library.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %F.type: type = fn_type @F [template] +// CHECK:STDOUT: %.1: type = tuple_type () [template] +// CHECK:STDOUT: %F: %F.type = 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.type = fn_decl @F [template = constants.%F] {} +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: extern fn @F(); +// CHECK:STDOUT: +// CHECK:STDOUT: --- default.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %F.type: type = fn_type @F [template] +// CHECK:STDOUT: %.1: type = tuple_type () [template] +// CHECK:STDOUT: %F: %F.type = struct_value () [template] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: imports { +// CHECK:STDOUT: %import_ref: %F.type = import_ref Main//extern_library, inst+1, loaded [template = constants.%F] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .F = %F.decl +// CHECK:STDOUT: } +// CHECK:STDOUT: %default.import = import +// CHECK:STDOUT: %F.decl: %F.type = fn_decl @F [template = constants.%F] {} +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: extern fn @F(); +// CHECK:STDOUT: +// CHECK:STDOUT: --- fail_wrong_library.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %F.type: type = fn_type @F [template] +// CHECK:STDOUT: %.1: type = tuple_type () [template] +// CHECK:STDOUT: %F: %F.type = struct_value () [template] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: imports { +// CHECK:STDOUT: %import_ref: %F.type = import_ref Main//extern_library, inst+1, loaded [template = constants.%F] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .F = %F.decl +// CHECK:STDOUT: } +// CHECK:STDOUT: %default.import = import +// CHECK:STDOUT: %F.decl: %F.type = fn_decl @F [template = constants.%F] {} +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: extern fn @F(); +// 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 448e4ccde71c..8a770517264c 100644 --- a/toolchain/check/testdata/function/declaration/no_prelude/fail_modifiers.carbon +++ b/toolchain/check/testdata/function/declaration/no_prelude/fail_modifiers.carbon @@ -82,10 +82,6 @@ base fn InvalidModifier(); // CHECK:STDERR: default final virtual fn ModifiersConflict2() {} -// CHECK:STDERR: fail_modifiers.carbon:[[@LINE+10]]:1: ERROR: `extern` not allowed on `fn` declaration that provides a definition. -// CHECK:STDERR: extern private fn ExternOrderAndConflict() {} -// CHECK:STDERR: ^~~~~~ -// CHECK:STDERR: // CHECK:STDERR: fail_modifiers.carbon:[[@LINE+6]]:8: ERROR: `private` must appear before `extern`. // CHECK:STDERR: extern private fn ExternOrderAndConflict() {} // CHECK:STDERR: ^~~~~~~ @@ -154,7 +150,7 @@ extern private fn ExternOrderAndConflict() {} // CHECK:STDOUT: return // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: fn @ExternOrderAndConflict() { +// CHECK:STDOUT: extern fn @ExternOrderAndConflict() { // CHECK:STDOUT: !entry: // CHECK:STDOUT: return // CHECK:STDOUT: } diff --git a/toolchain/check/testdata/function/declaration/no_prelude/implicit_import.carbon b/toolchain/check/testdata/function/declaration/no_prelude/implicit_import.carbon index e6d69b607d03..9b9f0458b657 100644 --- a/toolchain/check/testdata/function/declaration/no_prelude/implicit_import.carbon +++ b/toolchain/check/testdata/function/declaration/no_prelude/implicit_import.carbon @@ -30,7 +30,7 @@ extern fn A(); impl library "extern_api"; -// CHECK:STDERR: fail_extern_api.impl.carbon:[[@LINE+14]]:1: ERROR: Redeclarations of `fn A` in the same library must match use of `extern`. +// CHECK:STDERR: fail_extern_api.impl.carbon:[[@LINE+14]]:1: ERROR: Redeclarations of `fn A` must match use of `extern`. // CHECK:STDERR: fn A(); // CHECK:STDERR: ^~~~~~~ // CHECK:STDERR: fail_extern_api.impl.carbon:[[@LINE-5]]:6: In import. @@ -56,7 +56,7 @@ fn A(); impl library "extern_impl"; -// CHECK:STDERR: fail_extern_impl.impl.carbon:[[@LINE+9]]:1: ERROR: Redeclarations of `fn A` in the same library must match use of `extern`. +// CHECK:STDERR: fail_extern_impl.impl.carbon:[[@LINE+9]]:1: ERROR: Redeclarations of `fn A` must match use of `extern`. // CHECK:STDERR: extern fn A(); // CHECK:STDERR: ^~~~~~~~~~~~~~ // CHECK:STDERR: fail_extern_impl.impl.carbon:[[@LINE-5]]:6: In import. diff --git a/toolchain/check/testdata/function/definition/import.carbon b/toolchain/check/testdata/function/definition/import.carbon index db0fa849e6fc..f55d4d8895e1 100644 --- a/toolchain/check/testdata/function/definition/import.carbon +++ b/toolchain/check/testdata/function/definition/import.carbon @@ -47,7 +47,7 @@ library "def_ownership"; import library "fns"; -// CHECK:STDERR: fail_def_ownership.carbon:[[@LINE+10]]:1: ERROR: Only one library can declare `fn A` without `extern`. +// CHECK:STDERR: fail_def_ownership.carbon:[[@LINE+10]]:1: ERROR: Redeclaration of `fn A` is redundant. // CHECK:STDERR: fn A() {}; // CHECK:STDERR: ^~~~~~~~ // CHECK:STDERR: fail_def_ownership.carbon:[[@LINE-5]]:1: In import. @@ -58,7 +58,7 @@ import library "fns"; // CHECK:STDERR: ^~~~~~~~ // CHECK:STDERR: fn A() {}; -// CHECK:STDERR: fail_def_ownership.carbon:[[@LINE+10]]:1: ERROR: Only one library can declare `fn B` without `extern`. +// CHECK:STDERR: fail_def_ownership.carbon:[[@LINE+10]]:1: ERROR: Redeclaration of `fn B` is redundant. // CHECK:STDERR: fn B(b: i32) -> i32; // CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~ // CHECK:STDERR: fail_def_ownership.carbon:[[@LINE-16]]:1: In import. @@ -70,13 +70,24 @@ fn A() {}; // CHECK:STDERR: fn B(b: i32) -> i32; -// --- redecl_then_def.carbon +// --- fail_redecl_then_def.carbon library "redecl_then_def"; import library "extern"; +// CHECK:STDERR: fail_redecl_then_def.carbon:[[@LINE+10]]:1: ERROR: Redeclarations of `fn A` must match use of `extern`. +// CHECK:STDERR: fn A(); +// CHECK:STDERR: ^~~~~~~ +// CHECK:STDERR: fail_redecl_then_def.carbon:[[@LINE-5]]:1: In import. +// CHECK:STDERR: import library "extern"; +// CHECK:STDERR: ^~~~~~ +// CHECK:STDERR: extern.carbon:4:1: Previously declared here. +// CHECK:STDERR: extern fn A(); +// CHECK:STDERR: ^~~~~~~~~~~~~~ +// CHECK:STDERR: fn A(); + fn A() {} // --- fail_mix_extern_decl.carbon @@ -85,11 +96,22 @@ library "mix_extern_decl"; import library "fns"; +// CHECK:STDERR: fail_mix_extern_decl.carbon:[[@LINE+10]]:1: ERROR: Redeclarations of `fn D` must match use of `extern`. +// CHECK:STDERR: extern fn D(); +// CHECK:STDERR: ^~~~~~~~~~~~~~ +// CHECK:STDERR: fail_mix_extern_decl.carbon:[[@LINE-5]]:1: In import. +// CHECK:STDERR: import library "fns"; +// CHECK:STDERR: ^~~~~~ +// CHECK:STDERR: fns.carbon:7:1: Previously declared here. +// CHECK:STDERR: fn D(); +// CHECK:STDERR: ^~~~~~~ +// CHECK:STDERR: extern fn D(); -// CHECK:STDERR: fail_mix_extern_decl.carbon:[[@LINE+6]]:1: ERROR: Redeclarations of `fn D` in the same library must match use of `extern`. + +// CHECK:STDERR: fail_mix_extern_decl.carbon:[[@LINE+6]]:1: ERROR: Redeclarations of `fn D` must match use of `extern`. // CHECK:STDERR: fn D() {} // CHECK:STDERR: ^~~~~~~~ -// CHECK:STDERR: fail_mix_extern_decl.carbon:[[@LINE-4]]:1: Previously declared here. +// CHECK:STDERR: fail_mix_extern_decl.carbon:[[@LINE-5]]:1: Previously declared here. // CHECK:STDERR: extern fn D(); // CHECK:STDERR: ^~~~~~~~~~~~~~ fn D() {} @@ -379,7 +401,7 @@ fn D() {} // CHECK:STDOUT: // CHECK:STDOUT: fn @B(%b: i32) -> i32; // CHECK:STDOUT: -// CHECK:STDOUT: --- redecl_then_def.carbon +// CHECK:STDOUT: --- fail_redecl_then_def.carbon // CHECK:STDOUT: // CHECK:STDOUT: constants { // CHECK:STDOUT: %A.type: type = fn_type @A [template] @@ -402,13 +424,13 @@ fn D() {} // CHECK:STDOUT: // CHECK:STDOUT: file { // CHECK:STDOUT: package: = namespace [template] { -// CHECK:STDOUT: .A = %A.decl.loc6 +// CHECK:STDOUT: .A = %A.decl.loc16 // CHECK:STDOUT: .Core = imports.%Core // CHECK:STDOUT: } // CHECK:STDOUT: %Core.import = import Core // CHECK:STDOUT: %default.import = import -// CHECK:STDOUT: %A.decl.loc6: %A.type = fn_decl @A [template = constants.%A] {} -// CHECK:STDOUT: %A.decl.loc7: %A.type = fn_decl @A [template = constants.%A] {} +// CHECK:STDOUT: %A.decl.loc16: %A.type = fn_decl @A [template = constants.%A] {} +// CHECK:STDOUT: %A.decl.loc18: %A.type = fn_decl @A [template = constants.%A] {} // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: fn @A() { @@ -445,13 +467,13 @@ fn D() {} // CHECK:STDOUT: .A = imports.%import_ref.1 // CHECK:STDOUT: .B = imports.%import_ref.2 // CHECK:STDOUT: .C = imports.%import_ref.3 -// CHECK:STDOUT: .D = %D.decl.loc13 +// CHECK:STDOUT: .D = %D.decl.loc24 // CHECK:STDOUT: .Core = imports.%Core // CHECK:STDOUT: } // CHECK:STDOUT: %Core.import = import Core // CHECK:STDOUT: %default.import = import -// CHECK:STDOUT: %D.decl.loc6: %D.type = fn_decl @D [template = constants.%D] {} -// CHECK:STDOUT: %D.decl.loc13: %D.type = fn_decl @D [template = constants.%D] {} +// CHECK:STDOUT: %D.decl.loc16: %D.type = fn_decl @D [template = constants.%D] {} +// CHECK:STDOUT: %D.decl.loc24: %D.type = fn_decl @D [template = constants.%D] {} // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: fn @D() { diff --git a/toolchain/check/testdata/function/definition/no_prelude/extern.carbon b/toolchain/check/testdata/function/definition/no_prelude/extern.carbon index b814f08e31ec..61d36a3048db 100644 --- a/toolchain/check/testdata/function/definition/no_prelude/extern.carbon +++ b/toolchain/check/testdata/function/definition/no_prelude/extern.carbon @@ -8,30 +8,59 @@ // TIP: To dump output, run: // TIP: bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/function/definition/no_prelude/extern.carbon -// --- fail_extern_def.carbon +// --- extern_def.carbon library "extern_def"; -// CHECK:STDERR: fail_extern_def.carbon:[[@LINE+4]]:1: ERROR: `extern` not allowed on `fn` declaration that provides a definition. -// CHECK:STDERR: extern fn F() {} -// CHECK:STDERR: ^~~~~~ -// CHECK:STDERR: extern fn F() {} -// --- fail_def_for_extern_decl.carbon +// --- def_for_extern_decl.carbon library "def_for_extern_decl"; extern fn F(); -// CHECK:STDERR: fail_def_for_extern_decl.carbon:[[@LINE+7]]:1: ERROR: Redeclarations of `fn F` in the same library must match use of `extern`. +extern fn F() {} + +// --- split_library.carbon + +library "split_library"; + +extern fn F(); + +// --- split_library.impl.carbon + +impl library "split_library"; + +extern fn F() {} + +// --- fail_def_extern_mismatch.carbon + +library "def_extern_mismatch"; + +extern fn F(); +// CHECK:STDERR: fail_def_extern_mismatch.carbon:[[@LINE+7]]:1: ERROR: Redeclarations of `fn F` must match use of `extern`. // CHECK:STDERR: fn F() {} // CHECK:STDERR: ^~~~~~~~ -// CHECK:STDERR: fail_def_for_extern_decl.carbon:[[@LINE-4]]:1: Previously declared here. +// CHECK:STDERR: fail_def_extern_mismatch.carbon:[[@LINE-4]]:1: Previously declared here. // CHECK:STDERR: extern fn F(); // CHECK:STDERR: ^~~~~~~~~~~~~~ // CHECK:STDERR: fn F() {} +// --- fail_def_extern_mismatch_reverse.carbon + +library "def_extern_mismatch_reverse"; + +fn F(); +// CHECK:STDERR: fail_def_extern_mismatch_reverse.carbon:[[@LINE+7]]:1: ERROR: Redeclarations of `fn F` must match use of `extern`. +// CHECK:STDERR: extern fn F() {} +// CHECK:STDERR: ^~~~~~~~~~~~~~~ +// CHECK:STDERR: fail_def_extern_mismatch_reverse.carbon:[[@LINE-4]]:1: Previously declared here. +// CHECK:STDERR: fn F(); +// CHECK:STDERR: ^~~~~~~ +// CHECK:STDERR: +extern fn F() {} + // --- fail_extern_diag_suppressed.carbon library "extern_diag_suppressed"; @@ -60,7 +89,7 @@ fn F() {} // CHECK:STDERR: ^~~~~~~~ extern fn F(); -// CHECK:STDOUT: --- fail_extern_def.carbon +// CHECK:STDOUT: --- extern_def.carbon // CHECK:STDOUT: // CHECK:STDOUT: constants { // CHECK:STDOUT: %F.type: type = fn_type @F [template] @@ -75,12 +104,76 @@ extern fn F(); // CHECK:STDOUT: %F.decl: %F.type = fn_decl @F [template = constants.%F] {} // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: fn @F() { +// CHECK:STDOUT: extern fn @F() { // CHECK:STDOUT: !entry: // CHECK:STDOUT: return // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: --- fail_def_for_extern_decl.carbon +// CHECK:STDOUT: --- def_for_extern_decl.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %F.type: type = fn_type @F [template] +// CHECK:STDOUT: %.1: type = tuple_type () [template] +// CHECK:STDOUT: %F: %F.type = struct_value () [template] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .F = %F.decl.loc4 +// CHECK:STDOUT: } +// CHECK:STDOUT: %F.decl.loc4: %F.type = fn_decl @F [template = constants.%F] {} +// CHECK:STDOUT: %F.decl.loc5: %F.type = fn_decl @F [template = constants.%F] {} +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: extern fn @F() { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: return +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: --- split_library.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %F.type: type = fn_type @F [template] +// CHECK:STDOUT: %.1: type = tuple_type () [template] +// CHECK:STDOUT: %F: %F.type = 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.type = fn_decl @F [template = constants.%F] {} +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: extern fn @F(); +// CHECK:STDOUT: +// CHECK:STDOUT: --- split_library.impl.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %F.type: type = fn_type @F [template] +// CHECK:STDOUT: %.1: type = tuple_type () [template] +// CHECK:STDOUT: %F: %F.type = struct_value () [template] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: imports { +// CHECK:STDOUT: %import_ref: %F.type = import_ref Main//split_library, inst+1, loaded [template = constants.%F] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .F = %F.decl +// CHECK:STDOUT: } +// CHECK:STDOUT: %default.import.loc2_6.1 = import +// CHECK:STDOUT: %default.import.loc2_6.2 = import +// CHECK:STDOUT: %F.decl: %F.type = fn_decl @F [template = constants.%F] {} +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: extern fn @F() { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: return +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: --- fail_def_extern_mismatch.carbon // CHECK:STDOUT: // CHECK:STDOUT: constants { // CHECK:STDOUT: %F.type: type = fn_type @F [template] @@ -101,6 +194,27 @@ extern fn F(); // CHECK:STDOUT: return // CHECK:STDOUT: } // CHECK:STDOUT: +// CHECK:STDOUT: --- fail_def_extern_mismatch_reverse.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %F.type: type = fn_type @F [template] +// CHECK:STDOUT: %.1: type = tuple_type () [template] +// CHECK:STDOUT: %F: %F.type = struct_value () [template] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .F = %F.decl.loc4 +// CHECK:STDOUT: } +// CHECK:STDOUT: %F.decl.loc4: %F.type = fn_decl @F [template = constants.%F] {} +// CHECK:STDOUT: %F.decl.loc12: %F.type = fn_decl @F [template = constants.%F] {} +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @F() { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: return +// CHECK:STDOUT: } +// CHECK:STDOUT: // CHECK:STDOUT: --- fail_extern_diag_suppressed.carbon // CHECK:STDOUT: // CHECK:STDOUT: constants { diff --git a/toolchain/check/testdata/function/definition/no_prelude/extern_library.carbon b/toolchain/check/testdata/function/definition/no_prelude/extern_library.carbon new file mode 100644 index 000000000000..136275fff204 --- /dev/null +++ b/toolchain/check/testdata/function/definition/no_prelude/extern_library.carbon @@ -0,0 +1,382 @@ +// 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/no_prelude/extern_library.carbon +// TIP: To dump output, run: +// TIP: bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/function/definition/no_prelude/extern_library.carbon + +// --- one_file_extern.carbon + +library "one_file_extern"; + +extern library "one_file" fn F(); + +// --- one_file.carbon + +library "one_file"; + +extern fn F() {} + +// --- two_file_extern.carbon + +library "two_file_extern"; + +extern library "two_file" fn F(); + +// --- two_file.carbon + +library "two_file"; + +extern fn F(); + +// --- two_file.impl.carbon + +impl library "two_file"; + +extern fn F() {} + +// --- two_file_impl_mismatch_extern.carbon + +library "two_file_impl_mismatch_extern"; + +extern library "two_file_impl_mismatch" fn F(); + +// --- two_file_impl_mismatch.carbon + +library "two_file_impl_mismatch"; + +extern fn F(); + +// --- fail_two_file_impl_mismatch.impl.carbon + +impl library "two_file_impl_mismatch"; + +// CHECK:STDERR: fail_two_file_impl_mismatch.impl.carbon:[[@LINE+10]]:1: ERROR: Redeclarations of `fn F` must match use of `extern`. +// CHECK:STDERR: fn F() {} +// CHECK:STDERR: ^~~~~~~~ +// CHECK:STDERR: fail_two_file_impl_mismatch.impl.carbon:[[@LINE-5]]:6: In import. +// CHECK:STDERR: impl library "two_file_impl_mismatch"; +// CHECK:STDERR: ^~~~~~~ +// CHECK:STDERR: two_file_impl_mismatch.carbon:4:1: Previously declared here. +// CHECK:STDERR: extern fn F(); +// CHECK:STDERR: ^~~~~~~~~~~~~~ +// CHECK:STDERR: +fn F() {} + +// --- indirect_two_file_extern.carbon + +library "indirect_two_file_extern"; + +extern library "indirect_two_file" fn F(); + +// --- indirect_two_file.carbon + +library "indirect_two_file"; + +import library "indirect_two_file_extern"; + +// --- fail_todo_indirect_two_file.impl.carbon + +impl library "indirect_two_file"; + +// CHECK:STDERR: fail_todo_indirect_two_file.impl.carbon:[[@LINE+12]]:1: ERROR: Duplicate name being declared in the same scope. +// CHECK:STDERR: extern fn F() {} +// CHECK:STDERR: ^~~~~~~~~~~~~~~ +// CHECK:STDERR: fail_todo_indirect_two_file.impl.carbon:[[@LINE-5]]:6: In import. +// CHECK:STDERR: impl library "indirect_two_file"; +// CHECK:STDERR: ^~~~~~~ +// CHECK:STDERR: indirect_two_file.carbon:4:1: In import. +// CHECK:STDERR: import library "indirect_two_file_extern"; +// CHECK:STDERR: ^~~~~~ +// CHECK:STDERR: indirect_two_file_extern.carbon:4:1: Name is previously declared here. +// CHECK:STDERR: extern library "indirect_two_file" fn F(); +// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +extern fn F() {} + +// --- in_impl_extern.carbon + +library "in_impl_extern"; + +extern library "in_impl" fn F(); + +// --- in_impl.carbon + +library "in_impl"; + +// --- in_impl.impl.carbon + +impl library "in_impl"; + +import library "in_impl_extern"; + +extern fn F() {} + +// CHECK:STDOUT: --- one_file_extern.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %F.type: type = fn_type @F [template] +// CHECK:STDOUT: %.1: type = tuple_type () [template] +// CHECK:STDOUT: %F: %F.type = 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.type = fn_decl @F [template = constants.%F] {} +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: extern fn @F(); +// CHECK:STDOUT: +// CHECK:STDOUT: --- one_file.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %F.type: type = fn_type @F [template] +// CHECK:STDOUT: %.1: type = tuple_type () [template] +// CHECK:STDOUT: %F: %F.type = 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.type = fn_decl @F [template = constants.%F] {} +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: extern fn @F() { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: return +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: --- two_file_extern.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %F.type: type = fn_type @F [template] +// CHECK:STDOUT: %.1: type = tuple_type () [template] +// CHECK:STDOUT: %F: %F.type = 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.type = fn_decl @F [template = constants.%F] {} +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: extern fn @F(); +// CHECK:STDOUT: +// CHECK:STDOUT: --- two_file.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %F.type: type = fn_type @F [template] +// CHECK:STDOUT: %.1: type = tuple_type () [template] +// CHECK:STDOUT: %F: %F.type = 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.type = fn_decl @F [template = constants.%F] {} +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: extern fn @F(); +// CHECK:STDOUT: +// CHECK:STDOUT: --- two_file.impl.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %F.type: type = fn_type @F [template] +// CHECK:STDOUT: %.1: type = tuple_type () [template] +// CHECK:STDOUT: %F: %F.type = struct_value () [template] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: imports { +// CHECK:STDOUT: %import_ref: %F.type = import_ref Main//two_file, inst+1, loaded [template = constants.%F] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .F = %F.decl +// CHECK:STDOUT: } +// CHECK:STDOUT: %default.import.loc2_6.1 = import +// CHECK:STDOUT: %default.import.loc2_6.2 = import +// CHECK:STDOUT: %F.decl: %F.type = fn_decl @F [template = constants.%F] {} +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: extern fn @F() { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: return +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: --- two_file_impl_mismatch_extern.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %F.type: type = fn_type @F [template] +// CHECK:STDOUT: %.1: type = tuple_type () [template] +// CHECK:STDOUT: %F: %F.type = 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.type = fn_decl @F [template = constants.%F] {} +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: extern fn @F(); +// CHECK:STDOUT: +// CHECK:STDOUT: --- two_file_impl_mismatch.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %F.type: type = fn_type @F [template] +// CHECK:STDOUT: %.1: type = tuple_type () [template] +// CHECK:STDOUT: %F: %F.type = 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.type = fn_decl @F [template = constants.%F] {} +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: extern fn @F(); +// CHECK:STDOUT: +// CHECK:STDOUT: --- fail_two_file_impl_mismatch.impl.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %F.type: type = fn_type @F [template] +// CHECK:STDOUT: %.1: type = tuple_type () [template] +// CHECK:STDOUT: %F: %F.type = struct_value () [template] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: imports { +// CHECK:STDOUT: %import_ref: %F.type = import_ref Main//two_file_impl_mismatch, inst+1, loaded [template = constants.%F] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .F = %F.decl +// CHECK:STDOUT: } +// CHECK:STDOUT: %default.import.loc2_6.1 = import +// CHECK:STDOUT: %default.import.loc2_6.2 = import +// CHECK:STDOUT: %F.decl: %F.type = fn_decl @F [template = constants.%F] {} +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @F() { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: return +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: --- indirect_two_file_extern.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %F.type: type = fn_type @F [template] +// CHECK:STDOUT: %.1: type = tuple_type () [template] +// CHECK:STDOUT: %F: %F.type = 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.type = fn_decl @F [template = constants.%F] {} +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: extern fn @F(); +// CHECK:STDOUT: +// CHECK:STDOUT: --- indirect_two_file.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: imports { +// CHECK:STDOUT: %import_ref = import_ref Main//indirect_two_file_extern, inst+1, unloaded +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .F = imports.%import_ref +// CHECK:STDOUT: } +// CHECK:STDOUT: %default.import = import +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: --- fail_todo_indirect_two_file.impl.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %F.type: type = fn_type @F [template] +// CHECK:STDOUT: %.1: type = tuple_type () [template] +// CHECK:STDOUT: %F: %F.type = struct_value () [template] +// CHECK:STDOUT: %.type: type = fn_type @.1 [template] +// CHECK:STDOUT: %.2: %.type = struct_value () [template] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: imports { +// CHECK:STDOUT: %import_ref: %F.type = import_ref Main//indirect_two_file, inst+2, loaded [template = constants.%F] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .F = imports.%import_ref +// CHECK:STDOUT: } +// CHECK:STDOUT: %default.import.loc2_6.1 = import +// CHECK:STDOUT: %default.import.loc2_6.2 = import +// CHECK:STDOUT: %.decl: %.type = fn_decl @.1 [template = constants.%.2] {} +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: extern fn @F(); +// CHECK:STDOUT: +// CHECK:STDOUT: extern fn @.1() { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: return +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: --- in_impl_extern.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %F.type: type = fn_type @F [template] +// CHECK:STDOUT: %.1: type = tuple_type () [template] +// CHECK:STDOUT: %F: %F.type = 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.type = fn_decl @F [template = constants.%F] {} +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: extern fn @F(); +// CHECK:STDOUT: +// CHECK:STDOUT: --- in_impl.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] {} +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: --- in_impl.impl.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %F.type: type = fn_type @F [template] +// CHECK:STDOUT: %.1: type = tuple_type () [template] +// CHECK:STDOUT: %F: %F.type = struct_value () [template] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: imports { +// CHECK:STDOUT: %import_ref: %F.type = import_ref Main//in_impl_extern, inst+1, loaded [template = constants.%F] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .F = %F.decl +// CHECK:STDOUT: } +// CHECK:STDOUT: %default.import.loc2_6.1 = import +// CHECK:STDOUT: %default.import.loc2_6.2 = import +// CHECK:STDOUT: %F.decl: %F.type = fn_decl @F [template = constants.%F] {} +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: extern fn @F() { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: return +// CHECK:STDOUT: } +// CHECK:STDOUT: diff --git a/toolchain/check/testdata/function/definition/no_prelude/implicit_import.carbon b/toolchain/check/testdata/function/definition/no_prelude/implicit_import.carbon index ea24b9050815..ccfff4762135 100644 --- a/toolchain/check/testdata/function/definition/no_prelude/implicit_import.carbon +++ b/toolchain/check/testdata/function/definition/no_prelude/implicit_import.carbon @@ -30,7 +30,7 @@ extern fn A(); impl library "extern_api"; -// CHECK:STDERR: fail_extern_api.impl.carbon:[[@LINE+10]]:1: ERROR: Redeclarations of `fn A` in the same library must match use of `extern`. +// CHECK:STDERR: fail_extern_api.impl.carbon:[[@LINE+10]]:1: ERROR: Redeclarations of `fn A` must match use of `extern`. // CHECK:STDERR: fn A() {} // CHECK:STDERR: ^~~~~~~~ // CHECK:STDERR: fail_extern_api.impl.carbon:[[@LINE-5]]:6: In import. @@ -52,9 +52,15 @@ fn A(); impl library "extern_impl"; -// CHECK:STDERR: fail_extern_impl.impl.carbon:[[@LINE+4]]:1: ERROR: `extern` not allowed on `fn` declaration that provides a definition. +// CHECK:STDERR: fail_extern_impl.impl.carbon:[[@LINE+10]]:1: ERROR: Redeclarations of `fn A` must match use of `extern`. // CHECK:STDERR: extern fn A() {} -// CHECK:STDERR: ^~~~~~ +// CHECK:STDERR: ^~~~~~~~~~~~~~~ +// CHECK:STDERR: fail_extern_impl.impl.carbon:[[@LINE-5]]:6: In import. +// CHECK:STDERR: impl library "extern_impl"; +// CHECK:STDERR: ^~~~~~~ +// CHECK:STDERR: extern_impl.carbon:4:1: Previously declared here. +// CHECK:STDERR: fn A(); +// CHECK:STDERR: ^~~~~~~ // CHECK:STDERR: extern fn A() {} @@ -248,7 +254,7 @@ fn B() {} // CHECK:STDOUT: %A.decl: %A.type = fn_decl @A [template = constants.%A] {} // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: fn @A() { +// CHECK:STDOUT: extern fn @A() { // CHECK:STDOUT: !entry: // CHECK:STDOUT: return // CHECK:STDOUT: } diff --git a/toolchain/check/testdata/packages/no_prelude/cross_package_import.carbon b/toolchain/check/testdata/packages/no_prelude/cross_package_import.carbon index 0b51ca11c9d6..bc661e3ec554 100644 --- a/toolchain/check/testdata/packages/no_prelude/cross_package_import.carbon +++ b/toolchain/check/testdata/packages/no_prelude/cross_package_import.carbon @@ -144,7 +144,7 @@ import library "other_ns"; // CHECK:STDERR: import Other library "fn"; -// CHECK:STDERR: fail_main_namespace_conflict.carbon:[[@LINE+10]]:1: ERROR: Only one library can declare `fn F` without `extern`. +// CHECK:STDERR: fail_main_namespace_conflict.carbon:[[@LINE+10]]:1: ERROR: Redeclaration of `fn F` is redundant. // CHECK:STDERR: fn Other.F() {} // CHECK:STDERR: ^~~~~~~~~~~~~~ // CHECK:STDERR: fail_main_namespace_conflict.carbon:[[@LINE-5]]:1: In import. diff --git a/toolchain/diagnostics/diagnostic_kind.def b/toolchain/diagnostics/diagnostic_kind.def index 48c799426f64..cf2eb9e98c49 100644 --- a/toolchain/diagnostics/diagnostic_kind.def +++ b/toolchain/diagnostics/diagnostic_kind.def @@ -155,7 +155,6 @@ CARBON_DIAGNOSTIC_KIND(MissingDefinitionInImpl) // Merge-related redeclaration checking. CARBON_DIAGNOSTIC_KIND(RedeclPrevDecl) CARBON_DIAGNOSTIC_KIND(RedeclRedundant) -CARBON_DIAGNOSTIC_KIND(RedeclNonExtern) CARBON_DIAGNOSTIC_KIND(RedeclPrevDef) CARBON_DIAGNOSTIC_KIND(RedeclRedef) CARBON_DIAGNOSTIC_KIND(RedeclExternMismatch) @@ -167,6 +166,9 @@ CARBON_DIAGNOSTIC_KIND(RedeclParamDiffers) CARBON_DIAGNOSTIC_KIND(RedeclParamPrevious) CARBON_DIAGNOSTIC_KIND(RedeclParamSyntaxDiffers) CARBON_DIAGNOSTIC_KIND(RedeclParamSyntaxPrevious) +CARBON_DIAGNOSTIC_KIND(ExternLibraryInImporter) +CARBON_DIAGNOSTIC_KIND(ExternLibraryIncorrect) +CARBON_DIAGNOSTIC_KIND(ExternLibraryExpected) // Function call checking. CARBON_DIAGNOSTIC_KIND(AddrSelfIsNonRef) @@ -335,6 +337,8 @@ CARBON_DIAGNOSTIC_KIND(ModifierRepeated) CARBON_DIAGNOSTIC_KIND(ModifierNotAllowedWith) CARBON_DIAGNOSTIC_KIND(ModifierMustAppearBefore) CARBON_DIAGNOSTIC_KIND(ModifierPrevious) +CARBON_DIAGNOSTIC_KIND(ExternLibraryOnDefinition) +CARBON_DIAGNOSTIC_KIND(ExternLibraryIsCurrentLibrary) // Alias diagnostics. CARBON_DIAGNOSTIC_KIND(AliasRequiresNameRef) diff --git a/toolchain/sem_ir/entity_with_params_base.h b/toolchain/sem_ir/entity_with_params_base.h index 751efb7b3b6a..ba0ebf72a22a 100644 --- a/toolchain/sem_ir/entity_with_params_base.h +++ b/toolchain/sem_ir/entity_with_params_base.h @@ -49,6 +49,15 @@ struct EntityWithParamsBase { definition_id = definition.definition_id; } + // Returns the instruction for the first declaration. + auto first_decl_id() const -> SemIR::InstId { + if (non_owning_decl_id.is_valid()) { + return non_owning_decl_id; + } + CARBON_CHECK(first_owning_decl_id.is_valid()); + return first_owning_decl_id; + } + // Returns the instruction for the latest declaration. auto latest_decl_id() const -> SemIR::InstId { if (definition_id.is_valid()) { @@ -86,7 +95,7 @@ struct EntityWithParamsBase { // True if declarations are `extern`. bool is_extern; // For an `extern library` declaration, the library name. - StringLiteralValueId extern_library_id; + SemIR::LibraryNameId extern_library_id; // The non-owning declaration of the entity, if present. This will be a // Decl. InstId non_owning_decl_id;