From 2d3842fc06a2c1b407188b64e35bd1b5de79dab1 Mon Sep 17 00:00:00 2001 From: Jon Ross-Perkins Date: Mon, 19 Aug 2024 15:12:21 -0700 Subject: [PATCH] Implement 'extern library' support for functions. (#4220) Support for types (particularly classes) is left as a TODO. There's also an issue I'm observing with a "define in impl" test, but this is probably an issue with resolving the prior declaration which is imported indirectly. The PR was already feeling big, so I'm choosing to cut here. Note, this does not implement the rule "The owning library's API file must import the `extern` declaration, and must also contain a declaration." --- toolchain/check/decl_introducer_state.h | 3 + toolchain/check/decl_name_stack.h | 11 +- toolchain/check/global_init.cpp | 2 +- toolchain/check/handle_class.cpp | 36 +- toolchain/check/handle_function.cpp | 16 +- toolchain/check/handle_import_and_package.cpp | 20 +- toolchain/check/handle_interface.cpp | 18 +- toolchain/check/handle_modifier.cpp | 31 +- toolchain/check/handle_struct.cpp | 2 +- toolchain/check/import_ref.cpp | 27 +- toolchain/check/merge.cpp | 57 +- toolchain/check/merge.h | 9 + toolchain/check/modifiers.cpp | 28 +- toolchain/check/modifiers.h | 4 +- toolchain/check/node_stack.h | 21 +- .../check/sem_ir_diagnostic_converter.cpp | 15 + .../testdata/class/fail_import_misuses.carbon | 2 +- .../testdata/class/fail_modifiers.carbon | 18 +- .../class/{ => no_prelude}/extern.carbon | 400 +++-------- .../class/no_prelude/extern_library.carbon | 32 + .../function/declaration/import.carbon | 662 +++++------------- .../declaration/no_prelude/extern.carbon | 62 +- .../no_prelude/extern_library.carbon | 381 ++++++++++ .../extern_library_for_default.carbon | 102 +++ .../extern_library_from_default.carbon | 100 +++ .../no_prelude/fail_modifiers.carbon | 6 +- .../no_prelude/implicit_import.carbon | 4 +- .../function/definition/import.carbon | 46 +- .../definition/no_prelude/extern.carbon | 136 +++- .../no_prelude/extern_library.carbon | 382 ++++++++++ .../no_prelude/implicit_import.carbon | 14 +- .../no_prelude/cross_package_import.carbon | 2 +- toolchain/diagnostics/diagnostic_kind.def | 6 +- toolchain/sem_ir/entity_with_params_base.h | 11 +- 34 files changed, 1729 insertions(+), 937 deletions(-) rename toolchain/check/testdata/class/{ => no_prelude}/extern.carbon (56%) create mode 100644 toolchain/check/testdata/class/no_prelude/extern_library.carbon create mode 100644 toolchain/check/testdata/function/declaration/no_prelude/extern_library.carbon create mode 100644 toolchain/check/testdata/function/declaration/no_prelude/extern_library_for_default.carbon create mode 100644 toolchain/check/testdata/function/declaration/no_prelude/extern_library_from_default.carbon create mode 100644 toolchain/check/testdata/function/definition/no_prelude/extern_library.carbon 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;