diff --git a/toolchain/check/context.cpp b/toolchain/check/context.cpp index 3ca425fcdf13..1c80bec14e17 100644 --- a/toolchain/check/context.cpp +++ b/toolchain/check/context.cpp @@ -326,7 +326,7 @@ static auto LookupInImportIRScopes(Context& context, SemIRLoc loc, auto import_inst_id = AddImportRef(context, {.ir_id = import_ir_id, .inst_id = it->second}); if (result_id.is_valid()) { - MergeImportRef(context, import_inst_id, result_id); + context.DiagnoseDuplicateName(import_inst_id, result_id); } else { LoadImportRef(context, import_inst_id, mark_imports_used ? loc : SemIR::LocId::Invalid); diff --git a/toolchain/check/import.cpp b/toolchain/check/import.cpp index 9bce88179eab..753b84ba9caf 100644 --- a/toolchain/check/import.cpp +++ b/toolchain/check/import.cpp @@ -253,7 +253,7 @@ auto ImportLibraryFromCurrentPackage(Context& context, .Get(enclosing_scope_id) .names.insert({name_id, target_id}); if (!success) { - MergeImportRef(context, target_id, it->second); + context.DiagnoseDuplicateName(target_id, it->second); } } } diff --git a/toolchain/check/import_ref.cpp b/toolchain/check/import_ref.cpp index 2f07743a6b19..d95467aa7baa 100644 --- a/toolchain/check/import_ref.cpp +++ b/toolchain/check/import_ref.cpp @@ -9,6 +9,7 @@ #include "toolchain/check/context.h" #include "toolchain/check/eval.h" #include "toolchain/parse/node_ids.h" +#include "toolchain/sem_ir/constant.h" #include "toolchain/sem_ir/file.h" #include "toolchain/sem_ir/ids.h" #include "toolchain/sem_ir/inst.h" @@ -40,11 +41,10 @@ auto SetApiImportIR(Context& context, SemIR::ImportIR import_ir) -> void { auto AddImportIR(Context& context, SemIR::ImportIR import_ir) -> SemIR::ImportIRId { auto& ir_id = context.check_ir_map()[import_ir.sem_ir->check_ir_id().index]; - if (ir_id.is_valid()) { - return ir_id; + if (!ir_id.is_valid()) { + // Note this updates check_ir_map. + ir_id = InternalAddImportIR(context, import_ir); } - // Note this updates check_ir_map. - ir_id = InternalAddImportIR(context, import_ir); return ir_id; } @@ -102,14 +102,19 @@ auto AddImportRef(Context& context, SemIR::ImportIRInst import_ir_inst) // chance of a second call, it's important to reserve all expensive logic until // it's been established that input constants are available; this in particular // includes GetTypeIdForTypeConstant calls which do a hash table lookup. +// +// TODO: Fix class `extern` handling and merging, rewrite tests. +// - check/testdata/class/cross_package_import.carbon +// - check/testdata/class/extern.carbon +// TODO: Fix function `extern` handling and merging, rewrite tests. +// - check/testdata/function/declaration/import.carbon +// - check/testdata/packages/cross_package_import.carbon class ImportRefResolver { public: explicit ImportRefResolver(Context& context, SemIR::ImportIRId import_ir_id) : context_(context), import_ir_id_(import_ir_id), - import_ir_(*context_.import_irs().Get(import_ir_id).sem_ir), - import_ir_constant_values_( - context_.import_ir_constant_values()[import_ir_id.index]) {} + import_ir_(*context_.import_irs().Get(import_ir_id).sem_ir) {} // Iteratively resolves an imported instruction's inner references until a // constant ID referencing the current IR is produced. See the class comment @@ -121,8 +126,8 @@ class ImportRefResolver { CARBON_CHECK(work.inst_id.is_valid()); // Step 1: check for a constant value. - auto existing_const_id = import_ir_constant_values_.Get(work.inst_id); - if (existing_const_id.is_valid() && !work.retry) { + auto existing = FindResolvedConstId(work.inst_id); + if (existing.const_id.is_valid() && !work.retry) { work_stack_.pop_back(); continue; } @@ -130,13 +135,15 @@ class ImportRefResolver { // Step 2: resolve the instruction. auto initial_work = work_stack_.size(); auto [new_const_id, finished] = - TryResolveInst(work.inst_id, existing_const_id); + TryResolveInst(work.inst_id, existing.const_id); CARBON_CHECK(finished == !HasNewWork(initial_work)); - CARBON_CHECK(!existing_const_id.is_valid() || - existing_const_id == new_const_id) + CARBON_CHECK(!existing.const_id.is_valid() || + existing.const_id == new_const_id) << "Constant value changed in second pass."; - import_ir_constant_values_.Set(work.inst_id, new_const_id); + if (!existing.const_id.is_valid()) { + SetResolvedConstId(work.inst_id, existing.indirect_insts, new_const_id); + } // Step 3: pop or retry. if (finished) { @@ -145,7 +152,7 @@ class ImportRefResolver { work_stack_[initial_work - 1].retry = true; } } - auto constant_id = import_ir_constant_values_.Get(inst_id); + auto constant_id = import_ir_constant_values().Get(inst_id); CARBON_CHECK(constant_id.is_valid()); return constant_id; } @@ -196,6 +203,83 @@ class ImportRefResolver { bool finished = true; }; + // The constant found by FindResolvedConstId. + struct ResolvedConstId { + // The constant for the instruction. Invalid if not yet resolved. + SemIR::ConstantId const_id = SemIR::ConstantId::Invalid; + + // Instructions which are indirect but equivalent to the current instruction + // being resolved, and should have their constant set to the same. Empty + // when const_id is valid. + llvm::SmallVector indirect_insts = {}; + }; + + // Looks to see if an instruction has been resolved. If a constant is only + // found indirectly, sets the constant for any indirect steps that don't + // already have the constant. If a constant isn't found, returns the indirect + // instructions so that they can have the resolved constant assigned later. + auto FindResolvedConstId(SemIR::InstId inst_id) -> ResolvedConstId { + ResolvedConstId result; + + if (auto existing_const_id = import_ir_constant_values().Get(inst_id); + existing_const_id.is_valid()) { + result.const_id = existing_const_id; + return result; + } + + const auto* cursor_ir = &import_ir_; + auto cursor_ir_id = SemIR::ImportIRId::Invalid; + auto cursor_inst_id = inst_id; + + while (true) { + auto loc_id = cursor_ir->insts().GetLocId(cursor_inst_id); + if (!loc_id.is_import_ir_inst_id()) { + return result; + } + auto ir_inst = + cursor_ir->import_ir_insts().Get(loc_id.import_ir_inst_id()); + + const auto* prev_ir = cursor_ir; + auto prev_inst_id = cursor_inst_id; + + cursor_ir = cursor_ir->import_irs().Get(ir_inst.ir_id).sem_ir; + cursor_ir_id = context_.check_ir_map()[cursor_ir->check_ir_id().index]; + if (!cursor_ir_id.is_valid()) { + // TODO: Should we figure out a location to assign here? + cursor_ir_id = AddImportIR( + context_, {.node_id = Parse::NodeId::Invalid, .sem_ir = cursor_ir}); + } + cursor_inst_id = ir_inst.inst_id; + + CARBON_CHECK(cursor_ir != prev_ir || cursor_inst_id != prev_inst_id) + << cursor_ir->insts().Get(cursor_inst_id); + + if (auto const_id = + context_.import_ir_constant_values()[cursor_ir_id.index].Get( + cursor_inst_id); + const_id.is_valid()) { + SetResolvedConstId(inst_id, result.indirect_insts, const_id); + result.const_id = const_id; + result.indirect_insts.clear(); + return result; + } else { + result.indirect_insts.push_back( + {.ir_id = cursor_ir_id, .inst_id = cursor_inst_id}); + } + } + } + + // Sets a resolved constant into the current and indirect instructions. + auto SetResolvedConstId(SemIR::InstId inst_id, + llvm::ArrayRef indirect_insts, + SemIR::ConstantId const_id) -> void { + import_ir_constant_values().Set(inst_id, const_id); + for (auto indirect_inst : indirect_insts) { + context_.import_ir_constant_values()[indirect_inst.ir_id.index].Set( + indirect_inst.inst_id, const_id); + } + } + // Returns true if new unresolved constants were found. // // At the start of a function, do: @@ -216,7 +300,7 @@ class ImportRefResolver { // Returns the ConstantId for an InstId. Adds unresolved constants to // work_stack_. auto GetLocalConstantId(SemIR::InstId inst_id) -> SemIR::ConstantId { - auto const_id = import_ir_constant_values_.Get(inst_id); + auto const_id = import_ir_constant_values().Get(inst_id); if (!const_id.is_valid()) { work_stack_.push_back({inst_id}); } @@ -1029,10 +1113,13 @@ class ImportRefResolver { context_.GetTypeIdForTypeConstant(elem_const_id)))}; } + auto import_ir_constant_values() -> SemIR::ConstantValueStore& { + return context_.import_ir_constant_values()[import_ir_id_.index]; + } + Context& context_; SemIR::ImportIRId import_ir_id_; const SemIR::File& import_ir_; - SemIR::ConstantValueStore& import_ir_constant_values_; llvm::SmallVector work_stack_; }; diff --git a/toolchain/check/merge.cpp b/toolchain/check/merge.cpp index b149a76396ed..4da5e1884291 100644 --- a/toolchain/check/merge.cpp +++ b/toolchain/check/merge.cpp @@ -157,44 +157,6 @@ auto ResolvePrevInstForMerge(Context& context, Parse::NodeId node_id, return result; } -// Returns the instruction to consider when merging the given inst_id. Returns -// nullopt if merging is infeasible and no diagnostic should be printed. -static auto ResolveMergeableInst(Context& context, SemIR::InstId inst_id) - -> std::optional { - auto inst = context.insts().Get(inst_id); - switch (inst.kind()) { - case SemIR::ImportRefUnloaded::Kind: - // Load before merging. - LoadImportRef(context, inst_id, SemIR::LocId::Invalid); - break; - - case SemIR::ImportRefLoaded::Kind: - case SemIR::ImportRefUsed::Kind: - // Already loaded. - break; - - case SemIR::Namespace::Kind: - // Return back the namespace directly. - return { - {.inst = inst, .import_ir_inst_id = SemIR::ImportIRInstId::Invalid}}; - - default: - CARBON_FATAL() << "Unexpected inst kind passed to ResolveMergeableInst: " - << inst; - } - - auto const_id = context.constant_values().Get(inst_id); - // TODO: Function and type declarations are constant, but `var` declarations - // are non-constant and should still merge. - if (!const_id.is_constant()) { - return std::nullopt; - } - - return { - {.inst = context.insts().Get(const_id.inst_id()), - .import_ir_inst_id = inst.As().import_ir_inst_id}}; -} - auto ReplacePrevInstForMerge(Context& context, SemIR::NameScopeId scope_id, SemIR::NameId name_id, SemIR::InstId new_inst_id) -> void { @@ -205,58 +167,4 @@ auto ReplacePrevInstForMerge(Context& context, SemIR::NameScopeId scope_id, } } -// TODO: On successful merges, this may need to "spoil" new_inst_id in order to -// prevent it from being emitted in lowering. -auto MergeImportRef(Context& context, SemIR::InstId new_inst_id, - SemIR::InstId prev_inst_id) -> void { - auto new_inst = ResolveMergeableInst(context, new_inst_id); - auto prev_inst = ResolveMergeableInst(context, prev_inst_id); - if (!new_inst || !prev_inst) { - // TODO: Once `var` declarations get an associated instruction for handling, - // it might be more appropriate to return without diagnosing here, to handle - // invalid declarations. - context.DiagnoseDuplicateName(new_inst_id, prev_inst_id); - return; - } - - if (new_inst->inst.kind() != prev_inst->inst.kind()) { - context.DiagnoseDuplicateName(new_inst_id, prev_inst_id); - return; - } - - CARBON_KIND_SWITCH(new_inst->inst) { - case CARBON_KIND(SemIR::FunctionDecl new_decl): { - auto prev_decl = prev_inst->inst.TryAs(); - if (!prev_decl) { - break; - } - - auto new_fn = context.functions().Get(new_decl.function_id); - MergeFunctionRedecl(context, new_inst_id, new_fn, - /*new_is_import=*/true, - /*new_is_definition=*/false, prev_decl->function_id, - prev_inst->import_ir_inst_id); - return; - } - case CARBON_KIND(SemIR::ClassType new_type): { - auto prev_type = prev_inst->inst.TryAs(); - if (!prev_type) { - break; - } - - auto new_class = context.classes().Get(new_type.class_id); - // TODO: Fix is_extern logic. - MergeClassRedecl(context, new_inst_id, new_class, - /*new_is_import=*/true, new_class.is_defined(), - /*new_is_extern=*/false, prev_type->class_id, - /*prev_is_extern=*/false, prev_inst->import_ir_inst_id); - return; - } - default: - context.TODO(new_inst_id, llvm::formatv("Merging {0} not yet supported.", - new_inst->inst.kind())); - return; - } -} - } // namespace Carbon::Check diff --git a/toolchain/check/merge.h b/toolchain/check/merge.h index de1bd769736c..b11aeecd2704 100644 --- a/toolchain/check/merge.h +++ b/toolchain/check/merge.h @@ -56,11 +56,6 @@ auto ReplacePrevInstForMerge(Context& context, SemIR::NameScopeId scope_id, SemIR::NameId name_id, SemIR::InstId new_inst_id) -> void; -// Merges an import ref at new_inst_id another at prev_inst_id. May print a -// diagnostic if merging is invalid. -auto MergeImportRef(Context& context, SemIR::InstId new_inst_id, - SemIR::InstId prev_inst_id) -> void; - } // namespace Carbon::Check #endif // CARBON_TOOLCHAIN_CHECK_MERGE_H_ diff --git a/toolchain/check/testdata/class/cross_package_import.carbon b/toolchain/check/testdata/class/cross_package_import.carbon index 06169a2b8a60..e82a2573453e 100644 --- a/toolchain/check/testdata/class/cross_package_import.carbon +++ b/toolchain/check/testdata/class/cross_package_import.carbon @@ -64,13 +64,13 @@ import Other library "define"; // CHECK:STDERR: fail_todo_merge_define_extern.carbon:[[@LINE+12]]:1: In import. // CHECK:STDERR: import Other library "extern"; // CHECK:STDERR: ^~~~~~ -// CHECK:STDERR: other_extern.carbon:4:1: ERROR: Only one library can declare `class C` without `extern`. +// CHECK:STDERR: other_extern.carbon:4:1: ERROR: Duplicate name being declared in the same scope. // CHECK:STDERR: extern class C; // CHECK:STDERR: ^~~~~~~~~~~~~~~ // CHECK:STDERR: fail_todo_merge_define_extern.carbon:[[@LINE-7]]:1: In import. // CHECK:STDERR: import Other library "define"; // CHECK:STDERR: ^~~~~~ -// CHECK:STDERR: other_define.carbon:4:1: Previously declared here. +// CHECK:STDERR: other_define.carbon:4:1: Name is previously declared here. // CHECK:STDERR: class C {} // CHECK:STDERR: ^~~~~~~~~ import Other library "extern"; @@ -235,9 +235,8 @@ var c: Other.C = {}; // CHECK:STDOUT: --- fail_todo_merge_define_extern.carbon // CHECK:STDOUT: // CHECK:STDOUT: constants { -// CHECK:STDOUT: %C.1: type = class_type @C.1 [template] +// CHECK:STDOUT: %C: type = class_type @C [template] // CHECK:STDOUT: %.1: type = struct_type {} [template] -// CHECK:STDOUT: %C.2: type = class_type @C.2 [template] // CHECK:STDOUT: %.2: type = tuple_type () [template] // CHECK:STDOUT: %.3: type = ptr_type {} [template] // CHECK:STDOUT: %struct: C = struct_value () [template] @@ -252,23 +251,20 @@ var c: Other.C = {}; // CHECK:STDOUT: %Core: = namespace [template] {} // CHECK:STDOUT: %Other: = namespace [template] {} // CHECK:STDOUT: %Other.ref: = name_ref Other, %Other [template = %Other] -// CHECK:STDOUT: %import_ref.1: type = import_ref ir2, inst+2, loc_19 [template = constants.%C.1] -// CHECK:STDOUT: %C.decl.1: type = class_decl @C.1 [template = constants.%C.1] {} +// CHECK:STDOUT: %import_ref.1: type = import_ref ir2, inst+2, loc_19 [template = constants.%C] +// CHECK:STDOUT: %C.decl: type = class_decl @C [template = constants.%C] {} // CHECK:STDOUT: %import_ref.2 = import_ref ir2, inst+3, unloaded -// CHECK:STDOUT: %import_ref.3: type = import_ref ir3, inst+2, loaded [template = constants.%C.2] -// CHECK:STDOUT: %C.decl.2: type = class_decl @C.2 [template = constants.%C.2] {} -// CHECK:STDOUT: %C.ref: type = name_ref C, %import_ref.1 [template = constants.%C.1] +// CHECK:STDOUT: %import_ref.3 = import_ref ir3, inst+2, unloaded +// CHECK:STDOUT: %C.ref: type = name_ref C, %import_ref.1 [template = constants.%C] // CHECK:STDOUT: %c.var: ref C = var c // CHECK:STDOUT: %c: ref C = bind_name c, %c.var // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: class @C.1 { +// CHECK:STDOUT: class @C { // CHECK:STDOUT: !members: // CHECK:STDOUT: .Self = file.%import_ref.2 // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: class @C.2; -// CHECK:STDOUT: // CHECK:STDOUT: fn @__global_init() { // CHECK:STDOUT: !entry: // CHECK:STDOUT: %.loc23_19.1: {} = struct_literal () @@ -281,7 +277,7 @@ var c: Other.C = {}; // CHECK:STDOUT: --- fail_conflict.carbon // CHECK:STDOUT: // CHECK:STDOUT: constants { -// CHECK:STDOUT: %C: type = class_type @C.2 [template] +// CHECK:STDOUT: %C: type = class_type @C [template] // CHECK:STDOUT: %.1: type = struct_type {} [template] // CHECK:STDOUT: %.2: type = tuple_type () [template] // CHECK:STDOUT: %.3: type = ptr_type {} [template] @@ -298,21 +294,19 @@ var c: Other.C = {}; // CHECK:STDOUT: %Core: = namespace [template] {} // CHECK:STDOUT: %Other.ref: = name_ref Other, %Other [template = %Other] // CHECK:STDOUT: %import_ref.1: type = import_ref ir1, inst+2, loc_19 [template = constants.%C] -// CHECK:STDOUT: %C.decl: type = class_decl @C.2 [template = constants.%C] {} +// CHECK:STDOUT: %C.decl: type = class_decl @C [template = constants.%C] {} // CHECK:STDOUT: %import_ref.2 = import_ref ir1, inst+3, unloaded -// CHECK:STDOUT: %import_ref.3: = import_ref ir2, inst+2, loaded [template = imports.%C] +// CHECK:STDOUT: %import_ref.3 = import_ref ir2, inst+2, unloaded // CHECK:STDOUT: %C.ref: type = name_ref C, %import_ref.1 [template = constants.%C] // CHECK:STDOUT: %c.var: ref C = var c // CHECK:STDOUT: %c: ref C = bind_name c, %c.var // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: class @C.2 { +// CHECK:STDOUT: class @C { // CHECK:STDOUT: !members: // CHECK:STDOUT: .Self = file.%import_ref.2 // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: fn @C.1(); -// CHECK:STDOUT: // CHECK:STDOUT: fn @__global_init() { // CHECK:STDOUT: !entry: // CHECK:STDOUT: %.loc22_19.1: {} = struct_literal () diff --git a/toolchain/check/testdata/class/extern.carbon b/toolchain/check/testdata/class/extern.carbon index 181d632add2e..8a65295573ef 100644 --- a/toolchain/check/testdata/class/extern.carbon +++ b/toolchain/check/testdata/class/extern.carbon @@ -129,13 +129,13 @@ import library "extern_decl"; // CHECK:STDERR: fail_todo_import_extern_decl_then_decl.carbon:[[@LINE+13]]:1: In import. // CHECK:STDERR: import library "decl"; // CHECK:STDERR: ^~~~~~ -// CHECK:STDERR: decl.carbon:4:1: ERROR: Only one library can declare `class C` without `extern`. +// 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: import library "extern_decl"; // CHECK:STDERR: ^~~~~~ -// CHECK:STDERR: extern_decl.carbon:4:1: Previously declared here. +// CHECK:STDERR: extern_decl.carbon:4:1: Name is previously declared here. // CHECK:STDERR: extern class C; // CHECK:STDERR: ^~~~~~~~~~~~~~~ // CHECK:STDERR: @@ -149,13 +149,13 @@ import library "decl"; // CHECK:STDERR: fail_todo_import_decl_then_extern_decl.carbon:[[@LINE+13]]:1: In import. // CHECK:STDERR: import library "extern_decl"; // CHECK:STDERR: ^~~~~~ -// CHECK:STDERR: extern_decl.carbon:4:1: ERROR: Only one library can declare `class C` without `extern`. +// 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: import library "decl"; // CHECK:STDERR: ^~~~~~ -// CHECK:STDERR: decl.carbon:4:1: Previously declared here. +// CHECK:STDERR: decl.carbon:4:1: Name is previously declared here. // CHECK:STDERR: class C; // CHECK:STDERR: ^~~~~~~~ // CHECK:STDERR: @@ -169,13 +169,13 @@ import library "extern_decl"; // CHECK:STDERR: fail_todo_import_extern_decl_then_def.carbon:[[@LINE+13]]:1: In import. // CHECK:STDERR: import library "def"; // CHECK:STDERR: ^~~~~~ -// CHECK:STDERR: def.carbon:4:1: ERROR: Only one library can declare `class C` without `extern`. +// 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: import library "extern_decl"; // CHECK:STDERR: ^~~~~~ -// CHECK:STDERR: extern_decl.carbon:4:1: Previously declared here. +// CHECK:STDERR: extern_decl.carbon:4:1: Name is previously declared here. // CHECK:STDERR: extern class C; // CHECK:STDERR: ^~~~~~~~~~~~~~~ // CHECK:STDERR: @@ -189,13 +189,13 @@ import library "extern_decl"; // CHECK:STDERR: fail_import_ownership_conflict.carbon:[[@LINE+13]]:1: In import. // CHECK:STDERR: import library "decl"; // CHECK:STDERR: ^~~~~~ -// CHECK:STDERR: decl.carbon:4:1: ERROR: Only one library can declare `class C` without `extern`. +// CHECK:STDERR: decl.carbon:4:1: ERROR: Duplicate name being declared in the same scope. // CHECK:STDERR: class C; // CHECK:STDERR: ^~~~~~~~ // CHECK:STDERR: fail_import_ownership_conflict.carbon:[[@LINE-7]]:1: In import. // CHECK:STDERR: import library "extern_decl"; // CHECK:STDERR: ^~~~~~ -// CHECK:STDERR: extern_decl.carbon:4:1: Previously declared here. +// CHECK:STDERR: extern_decl.carbon:4:1: Name is previously declared here. // CHECK:STDERR: extern class C; // CHECK:STDERR: ^~~~~~~~~~~~~~~ // CHECK:STDERR: @@ -203,13 +203,13 @@ import library "decl"; // CHECK:STDERR: fail_import_ownership_conflict.carbon:[[@LINE+13]]:1: In import. // CHECK:STDERR: import library "def"; // CHECK:STDERR: ^~~~~~ -// CHECK:STDERR: def.carbon:4:1: ERROR: Only one library can declare `class C` without `extern`. +// CHECK:STDERR: def.carbon:4:1: ERROR: Duplicate name being declared in the same scope. // CHECK:STDERR: class C {} // CHECK:STDERR: ^~~~~~~~~ // CHECK:STDERR: fail_import_ownership_conflict.carbon:[[@LINE-21]]:1: In import. // CHECK:STDERR: import library "extern_decl"; // CHECK:STDERR: ^~~~~~ -// CHECK:STDERR: extern_decl.carbon:4:1: Previously declared here. +// CHECK:STDERR: extern_decl.carbon:4:1: Name is previously declared here. // CHECK:STDERR: extern class C; // CHECK:STDERR: ^~~~~~~~~~~~~~~ // CHECK:STDERR: @@ -223,13 +223,13 @@ import library "extern_decl"; // CHECK:STDERR: fail_todo_import_extern_decl_copy.carbon:[[@LINE+12]]:1: In import. // CHECK:STDERR: import library "extern_decl_copy"; // CHECK:STDERR: ^~~~~~ -// CHECK:STDERR: extern_decl_copy.carbon:4:1: ERROR: Only one library can declare `class C` without `extern`. +// 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-7]]:1: In import. // CHECK:STDERR: import library "extern_decl"; // CHECK:STDERR: ^~~~~~ -// CHECK:STDERR: extern_decl.carbon:4:1: Previously declared here. +// CHECK:STDERR: extern_decl.carbon:4:1: Name is previously declared here. // CHECK:STDERR: extern class C; // CHECK:STDERR: ^~~~~~~~~~~~~~~ import library "extern_decl_copy"; @@ -484,140 +484,65 @@ extern class C; // CHECK:STDOUT: // CHECK:STDOUT: --- fail_todo_import_extern_decl_then_decl.carbon // CHECK:STDOUT: -// CHECK:STDOUT: constants { -// CHECK:STDOUT: %C.1: type = class_type @C.1 [template] -// CHECK:STDOUT: %C.2: type = class_type @C.2 [template] -// CHECK:STDOUT: } -// CHECK:STDOUT: // CHECK:STDOUT: file { // CHECK:STDOUT: package: = namespace [template] { // CHECK:STDOUT: .C = %import_ref.1 // CHECK:STDOUT: .Core = %Core // CHECK:STDOUT: } -// CHECK:STDOUT: %import_ref.1: type = import_ref ir1, inst+2, loaded [template = constants.%C.2] -// CHECK:STDOUT: %import_ref.2: type = import_ref ir2, inst+2, loaded [template = constants.%C.1] -// CHECK:STDOUT: %C.decl.1: type = class_decl @C.1 [template = constants.%C.1] {} -// CHECK:STDOUT: %C.decl.2: type = class_decl @C.2 [template = constants.%C.2] {} +// CHECK:STDOUT: %import_ref.1 = import_ref ir1, inst+2, unloaded +// CHECK:STDOUT: %import_ref.2 = import_ref ir2, inst+2, unloaded // CHECK:STDOUT: %Core: = namespace [template] {} // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: class @C.1; -// CHECK:STDOUT: -// CHECK:STDOUT: class @C.2; -// CHECK:STDOUT: // CHECK:STDOUT: --- fail_todo_import_decl_then_extern_decl.carbon // CHECK:STDOUT: -// CHECK:STDOUT: constants { -// CHECK:STDOUT: %C.1: type = class_type @C.1 [template] -// CHECK:STDOUT: %C.2: type = class_type @C.2 [template] -// CHECK:STDOUT: } -// CHECK:STDOUT: // CHECK:STDOUT: file { // CHECK:STDOUT: package: = namespace [template] { // CHECK:STDOUT: .C = %import_ref.1 // CHECK:STDOUT: .Core = %Core // CHECK:STDOUT: } -// CHECK:STDOUT: %import_ref.1: type = import_ref ir1, inst+2, loaded [template = constants.%C.2] -// CHECK:STDOUT: %import_ref.2: type = import_ref ir2, inst+2, loaded [template = constants.%C.1] -// CHECK:STDOUT: %C.decl.1: type = class_decl @C.1 [template = constants.%C.1] {} -// CHECK:STDOUT: %C.decl.2: type = class_decl @C.2 [template = constants.%C.2] {} +// CHECK:STDOUT: %import_ref.1 = import_ref ir1, inst+2, unloaded +// CHECK:STDOUT: %import_ref.2 = import_ref ir2, inst+2, unloaded // CHECK:STDOUT: %Core: = namespace [template] {} // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: class @C.1; -// CHECK:STDOUT: -// CHECK:STDOUT: class @C.2; -// CHECK:STDOUT: // CHECK:STDOUT: --- fail_todo_import_extern_decl_then_def.carbon // CHECK:STDOUT: -// CHECK:STDOUT: constants { -// CHECK:STDOUT: %C.1: type = class_type @C.1 [template] -// CHECK:STDOUT: %.1: type = struct_type {} [template] -// CHECK:STDOUT: %C.2: type = class_type @C.2 [template] -// CHECK:STDOUT: } -// CHECK:STDOUT: // CHECK:STDOUT: file { // CHECK:STDOUT: package: = namespace [template] { // CHECK:STDOUT: .C = %import_ref.1 // CHECK:STDOUT: .Core = %Core // CHECK:STDOUT: } -// CHECK:STDOUT: %import_ref.1: type = import_ref ir1, inst+2, loaded [template = constants.%C.2] -// CHECK:STDOUT: %import_ref.2: type = import_ref ir2, inst+2, loaded [template = constants.%C.1] -// CHECK:STDOUT: %C.decl.1: type = class_decl @C.1 [template = constants.%C.1] {} -// CHECK:STDOUT: %import_ref.3 = import_ref ir2, inst+3, unloaded -// CHECK:STDOUT: %C.decl.2: type = class_decl @C.2 [template = constants.%C.2] {} +// CHECK:STDOUT: %import_ref.1 = import_ref ir1, inst+2, unloaded +// CHECK:STDOUT: %import_ref.2 = import_ref ir2, inst+2, unloaded // CHECK:STDOUT: %Core: = namespace [template] {} // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: class @C.1 { -// CHECK:STDOUT: !members: -// CHECK:STDOUT: .Self = file.%import_ref.3 -// CHECK:STDOUT: } -// CHECK:STDOUT: -// CHECK:STDOUT: class @C.2 { -// CHECK:STDOUT: !members: -// CHECK:STDOUT: .Self = file.%import_ref.3 -// CHECK:STDOUT: } -// CHECK:STDOUT: // CHECK:STDOUT: --- fail_import_ownership_conflict.carbon // CHECK:STDOUT: -// CHECK:STDOUT: constants { -// CHECK:STDOUT: %C.1: type = class_type @C.1 [template] -// CHECK:STDOUT: %C.2: type = class_type @C.2 [template] -// CHECK:STDOUT: %C.3: type = class_type @C.3 [template] -// CHECK:STDOUT: %.1: type = struct_type {} [template] -// CHECK:STDOUT: } -// CHECK:STDOUT: // CHECK:STDOUT: file { // CHECK:STDOUT: package: = namespace [template] { // CHECK:STDOUT: .C = %import_ref.1 // CHECK:STDOUT: .Core = %Core // CHECK:STDOUT: } -// CHECK:STDOUT: %import_ref.1: type = import_ref ir1, inst+2, loaded [template = constants.%C.2] -// CHECK:STDOUT: %import_ref.2: type = import_ref ir2, inst+2, loaded [template = constants.%C.1] -// CHECK:STDOUT: %C.decl.1: type = class_decl @C.1 [template = constants.%C.1] {} -// CHECK:STDOUT: %C.decl.2: type = class_decl @C.2 [template = constants.%C.2] {} -// CHECK:STDOUT: %import_ref.3: type = import_ref ir3, inst+2, loaded [template = constants.%C.3] -// CHECK:STDOUT: %C.decl.3: type = class_decl @C.3 [template = constants.%C.3] {} -// CHECK:STDOUT: %import_ref.4 = import_ref ir3, inst+3, unloaded +// CHECK:STDOUT: %import_ref.1 = import_ref ir1, inst+2, unloaded +// CHECK:STDOUT: %import_ref.2 = import_ref ir2, inst+2, unloaded +// CHECK:STDOUT: %import_ref.3 = import_ref ir3, inst+2, unloaded // CHECK:STDOUT: %Core: = namespace [template] {} // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: class @C.1; -// CHECK:STDOUT: -// CHECK:STDOUT: class @C.2 { -// CHECK:STDOUT: !members: -// CHECK:STDOUT: .Self = file.%import_ref.4 -// CHECK:STDOUT: } -// CHECK:STDOUT: -// CHECK:STDOUT: class @C.3 { -// CHECK:STDOUT: !members: -// CHECK:STDOUT: .Self = file.%import_ref.4 -// CHECK:STDOUT: } -// CHECK:STDOUT: // CHECK:STDOUT: --- fail_todo_import_extern_decl_copy.carbon // CHECK:STDOUT: -// CHECK:STDOUT: constants { -// CHECK:STDOUT: %C.1: type = class_type @C.1 [template] -// CHECK:STDOUT: %C.2: type = class_type @C.2 [template] -// CHECK:STDOUT: } -// CHECK:STDOUT: // CHECK:STDOUT: file { // CHECK:STDOUT: package: = namespace [template] { // CHECK:STDOUT: .C = %import_ref.1 // CHECK:STDOUT: .Core = %Core // CHECK:STDOUT: } -// CHECK:STDOUT: %import_ref.1: type = import_ref ir1, inst+2, loaded [template = constants.%C.2] -// CHECK:STDOUT: %import_ref.2: type = import_ref ir2, inst+2, loaded [template = constants.%C.1] -// CHECK:STDOUT: %C.decl.1: type = class_decl @C.1 [template = constants.%C.1] {} -// CHECK:STDOUT: %C.decl.2: type = class_decl @C.2 [template = constants.%C.2] {} +// CHECK:STDOUT: %import_ref.1 = import_ref ir1, inst+2, unloaded +// CHECK:STDOUT: %import_ref.2 = import_ref ir2, inst+2, unloaded // CHECK:STDOUT: %Core: = namespace [template] {} // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: class @C.1; -// CHECK:STDOUT: -// CHECK:STDOUT: class @C.2; -// CHECK:STDOUT: // CHECK:STDOUT: --- extern_decl_after_import_extern_decl.carbon // CHECK:STDOUT: // CHECK:STDOUT: constants { diff --git a/toolchain/check/testdata/class/import_indirect.carbon b/toolchain/check/testdata/class/import_indirect.carbon new file mode 100644 index 000000000000..eab94f36748a --- /dev/null +++ b/toolchain/check/testdata/class/import_indirect.carbon @@ -0,0 +1,445 @@ +// 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 + +// Triangle: +// +// a <-- Define +// |\ +// | b <-- Re-export +// |/ +// X <-- Use both +// +// Diamond: +// +// a <-- Define +// / \ +// b c <-- Re-export +// \ / +// X <-- Use both + +// ============================================================================ +// Setup files +// ============================================================================ + +// --- a.carbon + +library "a" api; + +class C {} + +// --- b.carbon + +library "b" api; + +import library "a"; + +alias D = C; + +var b_val: C = {}; +var b_ptr: D* = &b_val; + +// --- c.carbon + +library "c" api; + +import library "a"; + +alias E = C; + +var c_val: C = {}; +var c_ptr: E* = &c_val; + +// ============================================================================ +// Test files +// ============================================================================ + +// --- triangle.carbon + +library "triangle" api; + +import library "a"; +import library "b"; + +var val: C = {}; +var ptr: D* = &val; + +// --- triangle_reverse.carbon + +library "triangle_reverse" api; + +import library "b"; +import library "a"; + +var val: C = {}; +var ptr: D* = &val; + +// --- diamond.carbon + +library "diamond" api; + +import library "b"; +import library "c"; + +var val: D = {}; +var ptr: E* = &val; + +// --- diamond_reverse.carbon + +library "diamond_reverse" api; + +import library "c"; +import library "b"; + +var val: D = {}; +var ptr: E* = &val; + +// CHECK:STDOUT: --- a.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %C: type = class_type @C [template] +// CHECK:STDOUT: %.1: type = struct_type {} [template] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .Core = %Core +// CHECK:STDOUT: .C = %C.decl +// CHECK:STDOUT: } +// CHECK:STDOUT: %Core: = namespace [template] {} +// CHECK:STDOUT: %C.decl: type = class_decl @C [template = constants.%C] {} +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: class @C { +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = constants.%C +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: --- b.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %C: type = class_type @C [template] +// CHECK:STDOUT: %.1: type = struct_type {} [template] +// CHECK:STDOUT: %.2: type = tuple_type () [template] +// CHECK:STDOUT: %.3: type = ptr_type {} [template] +// CHECK:STDOUT: %struct: C = struct_value () [template] +// CHECK:STDOUT: %.4: type = ptr_type C [template] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .C = %import_ref.1 +// CHECK:STDOUT: .Core = %Core +// CHECK:STDOUT: .D = %D +// CHECK:STDOUT: .b_val = %b_val +// CHECK:STDOUT: .b_ptr = %b_ptr +// CHECK:STDOUT: } +// CHECK:STDOUT: %import_ref.1: type = import_ref ir1, inst+2, loc_12 [template = constants.%C] +// CHECK:STDOUT: %Core: = namespace [template] {} +// CHECK:STDOUT: %C.decl: type = class_decl @C [template = constants.%C] {} +// CHECK:STDOUT: %import_ref.2 = import_ref ir1, inst+3, unloaded +// CHECK:STDOUT: %C.ref.loc6: type = name_ref C, %import_ref.1 [template = constants.%C] +// CHECK:STDOUT: %D: type = bind_alias D, %import_ref.1 [template = constants.%C] +// CHECK:STDOUT: %C.ref.loc8: type = name_ref C, %import_ref.1 [template = constants.%C] +// CHECK:STDOUT: %b_val.var: ref C = var b_val +// CHECK:STDOUT: %b_val: ref C = bind_name b_val, %b_val.var +// CHECK:STDOUT: %D.ref: type = name_ref D, %D [template = constants.%C] +// CHECK:STDOUT: %.loc9: type = ptr_type C [template = constants.%.4] +// CHECK:STDOUT: %b_ptr.var: ref C* = var b_ptr +// CHECK:STDOUT: %b_ptr: ref C* = bind_name b_ptr, %b_ptr.var +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: class @C { +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = file.%import_ref.2 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @__global_init() { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %.loc8_17.1: {} = struct_literal () +// CHECK:STDOUT: %.loc8_17.2: init C = class_init (), file.%b_val.var [template = constants.%struct] +// CHECK:STDOUT: %.loc8_18: init C = converted %.loc8_17.1, %.loc8_17.2 [template = constants.%struct] +// CHECK:STDOUT: assign file.%b_val.var, %.loc8_18 +// CHECK:STDOUT: %b_val.ref: ref C = name_ref b_val, file.%b_val +// CHECK:STDOUT: %.loc9: C* = addr_of %b_val.ref +// CHECK:STDOUT: assign file.%b_ptr.var, %.loc9 +// CHECK:STDOUT: return +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: --- c.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %C: type = class_type @C [template] +// CHECK:STDOUT: %.1: type = struct_type {} [template] +// CHECK:STDOUT: %.2: type = tuple_type () [template] +// CHECK:STDOUT: %.3: type = ptr_type {} [template] +// CHECK:STDOUT: %struct: C = struct_value () [template] +// CHECK:STDOUT: %.4: type = ptr_type C [template] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .C = %import_ref.1 +// CHECK:STDOUT: .Core = %Core +// CHECK:STDOUT: .E = %E +// CHECK:STDOUT: .c_val = %c_val +// CHECK:STDOUT: .c_ptr = %c_ptr +// CHECK:STDOUT: } +// CHECK:STDOUT: %import_ref.1: type = import_ref ir1, inst+2, loc_12 [template = constants.%C] +// CHECK:STDOUT: %Core: = namespace [template] {} +// CHECK:STDOUT: %C.decl: type = class_decl @C [template = constants.%C] {} +// CHECK:STDOUT: %import_ref.2 = import_ref ir1, inst+3, unloaded +// CHECK:STDOUT: %C.ref.loc6: type = name_ref C, %import_ref.1 [template = constants.%C] +// CHECK:STDOUT: %E: type = bind_alias E, %import_ref.1 [template = constants.%C] +// CHECK:STDOUT: %C.ref.loc8: type = name_ref C, %import_ref.1 [template = constants.%C] +// CHECK:STDOUT: %c_val.var: ref C = var c_val +// CHECK:STDOUT: %c_val: ref C = bind_name c_val, %c_val.var +// CHECK:STDOUT: %E.ref: type = name_ref E, %E [template = constants.%C] +// CHECK:STDOUT: %.loc9: type = ptr_type C [template = constants.%.4] +// CHECK:STDOUT: %c_ptr.var: ref C* = var c_ptr +// CHECK:STDOUT: %c_ptr: ref C* = bind_name c_ptr, %c_ptr.var +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: class @C { +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = file.%import_ref.2 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @__global_init() { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %.loc8_17.1: {} = struct_literal () +// CHECK:STDOUT: %.loc8_17.2: init C = class_init (), file.%c_val.var [template = constants.%struct] +// CHECK:STDOUT: %.loc8_18: init C = converted %.loc8_17.1, %.loc8_17.2 [template = constants.%struct] +// CHECK:STDOUT: assign file.%c_val.var, %.loc8_18 +// CHECK:STDOUT: %c_val.ref: ref C = name_ref c_val, file.%c_val +// CHECK:STDOUT: %.loc9: C* = addr_of %c_val.ref +// CHECK:STDOUT: assign file.%c_ptr.var, %.loc9 +// CHECK:STDOUT: return +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: --- triangle.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %C: type = class_type @C [template] +// CHECK:STDOUT: %.1: type = struct_type {} [template] +// CHECK:STDOUT: %.2: type = tuple_type () [template] +// CHECK:STDOUT: %.3: type = ptr_type {} [template] +// CHECK:STDOUT: %struct: C = struct_value () [template] +// CHECK:STDOUT: %.4: type = ptr_type C [template] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .C = %import_ref.1 +// CHECK:STDOUT: .D = %import_ref.2 +// CHECK:STDOUT: .b_val = %import_ref.3 +// CHECK:STDOUT: .b_ptr = %import_ref.4 +// CHECK:STDOUT: .Core = %Core +// CHECK:STDOUT: .val = %val +// CHECK:STDOUT: .ptr = %ptr +// CHECK:STDOUT: } +// CHECK:STDOUT: %import_ref.1: type = import_ref ir1, inst+2, loc_15 [template = constants.%C] +// CHECK:STDOUT: %import_ref.2: type = import_ref ir2, inst+8, loc_23 [template = constants.%C] +// CHECK:STDOUT: %import_ref.3 = import_ref ir2, inst+13, unloaded +// CHECK:STDOUT: %import_ref.4 = import_ref ir2, inst+23, unloaded +// CHECK:STDOUT: %Core: = namespace [template] {} +// CHECK:STDOUT: %C.decl: type = class_decl @C [template = constants.%C] {} +// CHECK:STDOUT: %import_ref.5 = import_ref ir1, inst+3, unloaded +// CHECK:STDOUT: %C.ref: type = name_ref C, %import_ref.1 [template = constants.%C] +// CHECK:STDOUT: %val.var: ref C = var val +// CHECK:STDOUT: %val: ref C = bind_name val, %val.var +// CHECK:STDOUT: %D.ref: type = name_ref D, %import_ref.2 [template = constants.%C] +// CHECK:STDOUT: %.loc8: type = ptr_type C [template = constants.%.4] +// CHECK:STDOUT: %ptr.var: ref C* = var ptr +// CHECK:STDOUT: %ptr: ref C* = bind_name ptr, %ptr.var +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: class @C { +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = file.%import_ref.5 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @__global_init() { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %.loc7_15.1: {} = struct_literal () +// CHECK:STDOUT: %.loc7_15.2: init C = class_init (), file.%val.var [template = constants.%struct] +// CHECK:STDOUT: %.loc7_16: init C = converted %.loc7_15.1, %.loc7_15.2 [template = constants.%struct] +// CHECK:STDOUT: assign file.%val.var, %.loc7_16 +// CHECK:STDOUT: %val.ref: ref C = name_ref val, file.%val +// CHECK:STDOUT: %.loc8: C* = addr_of %val.ref +// CHECK:STDOUT: assign file.%ptr.var, %.loc8 +// CHECK:STDOUT: return +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: --- triangle_reverse.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %C: type = class_type @C [template] +// CHECK:STDOUT: %.1: type = struct_type {} [template] +// CHECK:STDOUT: %.2: type = tuple_type () [template] +// CHECK:STDOUT: %.3: type = ptr_type {} [template] +// CHECK:STDOUT: %struct: C = struct_value () [template] +// CHECK:STDOUT: %.4: type = ptr_type C [template] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .D = %import_ref.1 +// CHECK:STDOUT: .b_val = %import_ref.2 +// CHECK:STDOUT: .b_ptr = %import_ref.3 +// CHECK:STDOUT: .C = %import_ref.4 +// CHECK:STDOUT: .Core = %Core +// CHECK:STDOUT: .val = %val +// CHECK:STDOUT: .ptr = %ptr +// CHECK:STDOUT: } +// CHECK:STDOUT: %import_ref.1: type = import_ref ir1, inst+8, loc_23 [template = constants.%C] +// CHECK:STDOUT: %import_ref.2 = import_ref ir1, inst+13, unloaded +// CHECK:STDOUT: %import_ref.3 = import_ref ir1, inst+23, unloaded +// CHECK:STDOUT: %import_ref.4: type = import_ref ir2, inst+2, loc_15 [template = constants.%C] +// CHECK:STDOUT: %Core: = namespace [template] {} +// CHECK:STDOUT: %C.decl: type = class_decl @C [template = constants.%C] {} +// CHECK:STDOUT: %import_ref.5 = import_ref ir2, inst+3, unloaded +// CHECK:STDOUT: %C.ref: type = name_ref C, %import_ref.4 [template = constants.%C] +// CHECK:STDOUT: %val.var: ref C = var val +// CHECK:STDOUT: %val: ref C = bind_name val, %val.var +// CHECK:STDOUT: %D.ref: type = name_ref D, %import_ref.1 [template = constants.%C] +// CHECK:STDOUT: %.loc8: type = ptr_type C [template = constants.%.4] +// CHECK:STDOUT: %ptr.var: ref C* = var ptr +// CHECK:STDOUT: %ptr: ref C* = bind_name ptr, %ptr.var +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: class @C { +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = file.%import_ref.5 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @__global_init() { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %.loc7_15.1: {} = struct_literal () +// CHECK:STDOUT: %.loc7_15.2: init C = class_init (), file.%val.var [template = constants.%struct] +// CHECK:STDOUT: %.loc7_16: init C = converted %.loc7_15.1, %.loc7_15.2 [template = constants.%struct] +// CHECK:STDOUT: assign file.%val.var, %.loc7_16 +// CHECK:STDOUT: %val.ref: ref C = name_ref val, file.%val +// CHECK:STDOUT: %.loc8: C* = addr_of %val.ref +// CHECK:STDOUT: assign file.%ptr.var, %.loc8 +// CHECK:STDOUT: return +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: --- diamond.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %C: type = class_type @C [template] +// CHECK:STDOUT: %.1: type = struct_type {} [template] +// CHECK:STDOUT: %.2: type = tuple_type () [template] +// CHECK:STDOUT: %.3: type = ptr_type {} [template] +// CHECK:STDOUT: %struct: C = struct_value () [template] +// CHECK:STDOUT: %.4: type = ptr_type C [template] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .D = %import_ref.1 +// CHECK:STDOUT: .b_val = %import_ref.2 +// CHECK:STDOUT: .b_ptr = %import_ref.3 +// CHECK:STDOUT: .E = %import_ref.4 +// CHECK:STDOUT: .c_val = %import_ref.5 +// CHECK:STDOUT: .c_ptr = %import_ref.6 +// CHECK:STDOUT: .Core = %Core +// CHECK:STDOUT: .val = %val +// CHECK:STDOUT: .ptr = %ptr +// CHECK:STDOUT: } +// CHECK:STDOUT: %import_ref.1: type = import_ref ir1, inst+8, loc_15 [template = constants.%C] +// CHECK:STDOUT: %import_ref.2 = import_ref ir1, inst+13, unloaded +// CHECK:STDOUT: %import_ref.3 = import_ref ir1, inst+23, unloaded +// CHECK:STDOUT: %import_ref.4: type = import_ref ir2, inst+8, loc_23 [template = constants.%C] +// CHECK:STDOUT: %import_ref.5 = import_ref ir2, inst+13, unloaded +// CHECK:STDOUT: %import_ref.6 = import_ref ir2, inst+23, unloaded +// CHECK:STDOUT: %Core: = namespace [template] {} +// CHECK:STDOUT: %C.decl: type = class_decl @C [template = constants.%C] {} +// CHECK:STDOUT: %import_ref.7 = import_ref ir1, inst+6, unloaded +// CHECK:STDOUT: %D.ref: type = name_ref D, %import_ref.1 [template = constants.%C] +// CHECK:STDOUT: %val.var: ref C = var val +// CHECK:STDOUT: %val: ref C = bind_name val, %val.var +// CHECK:STDOUT: %E.ref: type = name_ref E, %import_ref.4 [template = constants.%C] +// CHECK:STDOUT: %.loc8: type = ptr_type C [template = constants.%.4] +// CHECK:STDOUT: %ptr.var: ref C* = var ptr +// CHECK:STDOUT: %ptr: ref C* = bind_name ptr, %ptr.var +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: class @C { +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = file.%import_ref.7 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @__global_init() { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %.loc7_15.1: {} = struct_literal () +// CHECK:STDOUT: %.loc7_15.2: init C = class_init (), file.%val.var [template = constants.%struct] +// CHECK:STDOUT: %.loc7_16: init C = converted %.loc7_15.1, %.loc7_15.2 [template = constants.%struct] +// CHECK:STDOUT: assign file.%val.var, %.loc7_16 +// CHECK:STDOUT: %val.ref: ref C = name_ref val, file.%val +// CHECK:STDOUT: %.loc8: C* = addr_of %val.ref +// CHECK:STDOUT: assign file.%ptr.var, %.loc8 +// CHECK:STDOUT: return +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: --- diamond_reverse.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %C: type = class_type @C [template] +// CHECK:STDOUT: %.1: type = struct_type {} [template] +// CHECK:STDOUT: %.2: type = tuple_type () [template] +// CHECK:STDOUT: %.3: type = ptr_type {} [template] +// CHECK:STDOUT: %struct: C = struct_value () [template] +// CHECK:STDOUT: %.4: type = ptr_type C [template] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .E = %import_ref.1 +// CHECK:STDOUT: .c_val = %import_ref.2 +// CHECK:STDOUT: .c_ptr = %import_ref.3 +// CHECK:STDOUT: .D = %import_ref.4 +// CHECK:STDOUT: .b_val = %import_ref.5 +// CHECK:STDOUT: .b_ptr = %import_ref.6 +// CHECK:STDOUT: .Core = %Core +// CHECK:STDOUT: .val = %val +// CHECK:STDOUT: .ptr = %ptr +// CHECK:STDOUT: } +// CHECK:STDOUT: %import_ref.1: type = import_ref ir1, inst+8, loc_23 [template = constants.%C] +// CHECK:STDOUT: %import_ref.2 = import_ref ir1, inst+13, unloaded +// CHECK:STDOUT: %import_ref.3 = import_ref ir1, inst+23, unloaded +// CHECK:STDOUT: %import_ref.4: type = import_ref ir2, inst+8, loc_15 [template = constants.%C] +// CHECK:STDOUT: %import_ref.5 = import_ref ir2, inst+13, unloaded +// CHECK:STDOUT: %import_ref.6 = import_ref ir2, inst+23, unloaded +// CHECK:STDOUT: %Core: = namespace [template] {} +// CHECK:STDOUT: %C.decl: type = class_decl @C [template = constants.%C] {} +// CHECK:STDOUT: %import_ref.7 = import_ref ir2, inst+6, unloaded +// CHECK:STDOUT: %D.ref: type = name_ref D, %import_ref.4 [template = constants.%C] +// CHECK:STDOUT: %val.var: ref C = var val +// CHECK:STDOUT: %val: ref C = bind_name val, %val.var +// CHECK:STDOUT: %E.ref: type = name_ref E, %import_ref.1 [template = constants.%C] +// CHECK:STDOUT: %.loc8: type = ptr_type C [template = constants.%.4] +// CHECK:STDOUT: %ptr.var: ref C* = var ptr +// CHECK:STDOUT: %ptr: ref C* = bind_name ptr, %ptr.var +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: class @C { +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = file.%import_ref.7 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @__global_init() { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %.loc7_15.1: {} = struct_literal () +// CHECK:STDOUT: %.loc7_15.2: init C = class_init (), file.%val.var [template = constants.%struct] +// CHECK:STDOUT: %.loc7_16: init C = converted %.loc7_15.1, %.loc7_15.2 [template = constants.%struct] +// CHECK:STDOUT: assign file.%val.var, %.loc7_16 +// CHECK:STDOUT: %val.ref: ref C = name_ref val, file.%val +// CHECK:STDOUT: %.loc8: C* = addr_of %val.ref +// CHECK:STDOUT: assign file.%ptr.var, %.loc8 +// CHECK:STDOUT: return +// CHECK:STDOUT: } +// CHECK:STDOUT: diff --git a/toolchain/check/testdata/class/import_triangle.carbon b/toolchain/check/testdata/class/import_triangle.carbon deleted file mode 100644 index b4ac331d31c5..000000000000 --- a/toolchain/check/testdata/class/import_triangle.carbon +++ /dev/null @@ -1,171 +0,0 @@ -// Part of the Carbon Language project, under the Apache License v2.0 with LLVM -// Exceptions. See /LICENSE for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -// AUTOUPDATE - -// --- a.carbon - -library "a" api; - -class C {} - -// --- b.carbon - -library "b" api; - -import library "a"; - -alias D = C; - -var c1: C = {}; -var d1: D* = &c1; - -// --- fail_c.carbon - -library "c" api; - -import library "a"; -import library "b"; - -var c2: C = {}; -// CHECK:STDERR: fail_c.carbon:[[@LINE+3]]:1: ERROR: Cannot implicitly convert from `C*` to `C*`. -// CHECK:STDERR: var d2: D* = &c2; -// CHECK:STDERR: ^~~~~~~~~~~~~~~~~ -var d2: D* = &c2; - -// CHECK:STDOUT: --- a.carbon -// CHECK:STDOUT: -// CHECK:STDOUT: constants { -// CHECK:STDOUT: %C: type = class_type @C [template] -// CHECK:STDOUT: %.1: type = struct_type {} [template] -// CHECK:STDOUT: } -// CHECK:STDOUT: -// CHECK:STDOUT: file { -// CHECK:STDOUT: package: = namespace [template] { -// CHECK:STDOUT: .Core = %Core -// CHECK:STDOUT: .C = %C.decl -// CHECK:STDOUT: } -// CHECK:STDOUT: %Core: = namespace [template] {} -// CHECK:STDOUT: %C.decl: type = class_decl @C [template = constants.%C] {} -// CHECK:STDOUT: } -// CHECK:STDOUT: -// CHECK:STDOUT: class @C { -// CHECK:STDOUT: !members: -// CHECK:STDOUT: .Self = constants.%C -// CHECK:STDOUT: } -// CHECK:STDOUT: -// CHECK:STDOUT: --- b.carbon -// CHECK:STDOUT: -// CHECK:STDOUT: constants { -// CHECK:STDOUT: %C: type = class_type @C [template] -// CHECK:STDOUT: %.1: type = struct_type {} [template] -// CHECK:STDOUT: %.2: type = tuple_type () [template] -// CHECK:STDOUT: %.3: type = ptr_type {} [template] -// CHECK:STDOUT: %struct: C = struct_value () [template] -// CHECK:STDOUT: %.4: type = ptr_type C [template] -// CHECK:STDOUT: } -// CHECK:STDOUT: -// CHECK:STDOUT: file { -// CHECK:STDOUT: package: = namespace [template] { -// CHECK:STDOUT: .C = %import_ref.1 -// CHECK:STDOUT: .Core = %Core -// CHECK:STDOUT: .D = %D -// CHECK:STDOUT: .c1 = %c1 -// CHECK:STDOUT: .d1 = %d1 -// CHECK:STDOUT: } -// CHECK:STDOUT: %import_ref.1: type = import_ref ir1, inst+2, loc_12 [template = constants.%C] -// CHECK:STDOUT: %Core: = namespace [template] {} -// CHECK:STDOUT: %C.decl: type = class_decl @C [template = constants.%C] {} -// CHECK:STDOUT: %import_ref.2 = import_ref ir1, inst+3, unloaded -// CHECK:STDOUT: %C.ref.loc6: type = name_ref C, %import_ref.1 [template = constants.%C] -// CHECK:STDOUT: %D: type = bind_alias D, %import_ref.1 [template = constants.%C] -// CHECK:STDOUT: %C.ref.loc8: type = name_ref C, %import_ref.1 [template = constants.%C] -// CHECK:STDOUT: %c1.var: ref C = var c1 -// CHECK:STDOUT: %c1: ref C = bind_name c1, %c1.var -// CHECK:STDOUT: %D.ref: type = name_ref D, %D [template = constants.%C] -// CHECK:STDOUT: %.loc9: type = ptr_type C [template = constants.%.4] -// CHECK:STDOUT: %d1.var: ref C* = var d1 -// CHECK:STDOUT: %d1: ref C* = bind_name d1, %d1.var -// CHECK:STDOUT: } -// CHECK:STDOUT: -// CHECK:STDOUT: class @C { -// CHECK:STDOUT: !members: -// CHECK:STDOUT: .Self = file.%import_ref.2 -// CHECK:STDOUT: } -// CHECK:STDOUT: -// CHECK:STDOUT: fn @__global_init() { -// CHECK:STDOUT: !entry: -// CHECK:STDOUT: %.loc8_14.1: {} = struct_literal () -// CHECK:STDOUT: %.loc8_14.2: init C = class_init (), file.%c1.var [template = constants.%struct] -// CHECK:STDOUT: %.loc8_15: init C = converted %.loc8_14.1, %.loc8_14.2 [template = constants.%struct] -// CHECK:STDOUT: assign file.%c1.var, %.loc8_15 -// CHECK:STDOUT: %c1.ref: ref C = name_ref c1, file.%c1 -// CHECK:STDOUT: %.loc9: C* = addr_of %c1.ref -// CHECK:STDOUT: assign file.%d1.var, %.loc9 -// CHECK:STDOUT: return -// CHECK:STDOUT: } -// CHECK:STDOUT: -// CHECK:STDOUT: --- fail_c.carbon -// CHECK:STDOUT: -// CHECK:STDOUT: constants { -// CHECK:STDOUT: %C.1: type = class_type @C.1 [template] -// CHECK:STDOUT: %.1: type = struct_type {} [template] -// CHECK:STDOUT: %.2: type = tuple_type () [template] -// CHECK:STDOUT: %.3: type = ptr_type {} [template] -// CHECK:STDOUT: %struct: C = struct_value () [template] -// CHECK:STDOUT: %C.2: type = class_type @C.2 [template] -// CHECK:STDOUT: %.4: type = ptr_type C [template] -// CHECK:STDOUT: %.5: type = ptr_type C [template] -// CHECK:STDOUT: } -// CHECK:STDOUT: -// CHECK:STDOUT: file { -// CHECK:STDOUT: package: = namespace [template] { -// CHECK:STDOUT: .C = %import_ref.1 -// CHECK:STDOUT: .D = %import_ref.2 -// CHECK:STDOUT: .c1 = %import_ref.3 -// CHECK:STDOUT: .d1 = %import_ref.4 -// CHECK:STDOUT: .Core = %Core -// CHECK:STDOUT: .c2 = %c2 -// CHECK:STDOUT: .d2 = %d2 -// CHECK:STDOUT: } -// CHECK:STDOUT: %import_ref.1: type = import_ref ir1, inst+2, loc_15 [template = constants.%C.1] -// CHECK:STDOUT: %import_ref.2: type = import_ref ir2, inst+8, loc_23 [template = constants.%C.2] -// CHECK:STDOUT: %import_ref.3 = import_ref ir2, inst+13, unloaded -// CHECK:STDOUT: %import_ref.4 = import_ref ir2, inst+23, unloaded -// CHECK:STDOUT: %Core: = namespace [template] {} -// CHECK:STDOUT: %C.decl.1: type = class_decl @C.1 [template = constants.%C.1] {} -// CHECK:STDOUT: %import_ref.5 = import_ref ir1, inst+3, unloaded -// CHECK:STDOUT: %C.ref: type = name_ref C, %import_ref.1 [template = constants.%C.1] -// CHECK:STDOUT: %c2.var: ref C = var c2 -// CHECK:STDOUT: %c2: ref C = bind_name c2, %c2.var -// CHECK:STDOUT: %C.decl.2: type = class_decl @C.2 [template = constants.%C.2] {} -// CHECK:STDOUT: %import_ref.6 = import_ref ir2, inst+6, unloaded -// CHECK:STDOUT: %D.ref: type = name_ref D, %import_ref.2 [template = constants.%C.2] -// CHECK:STDOUT: %.loc11: type = ptr_type C [template = constants.%.4] -// CHECK:STDOUT: %d2.var: ref C* = var d2 -// CHECK:STDOUT: %d2: ref C* = bind_name d2, %d2.var -// CHECK:STDOUT: } -// CHECK:STDOUT: -// CHECK:STDOUT: class @C.1 { -// CHECK:STDOUT: !members: -// CHECK:STDOUT: .Self = file.%import_ref.5 -// CHECK:STDOUT: } -// CHECK:STDOUT: -// CHECK:STDOUT: class @C.2 { -// CHECK:STDOUT: !members: -// CHECK:STDOUT: .Self = file.%import_ref.6 -// CHECK:STDOUT: } -// CHECK:STDOUT: -// CHECK:STDOUT: fn @__global_init() { -// CHECK:STDOUT: !entry: -// CHECK:STDOUT: %.loc7_14.1: {} = struct_literal () -// CHECK:STDOUT: %.loc7_14.2: init C = class_init (), file.%c2.var [template = constants.%struct] -// CHECK:STDOUT: %.loc7_15: init C = converted %.loc7_14.1, %.loc7_14.2 [template = constants.%struct] -// CHECK:STDOUT: assign file.%c2.var, %.loc7_15 -// CHECK:STDOUT: %c2.ref: ref C = name_ref c2, file.%c2 -// CHECK:STDOUT: %.loc11: C* = addr_of %c2.ref -// CHECK:STDOUT: assign file.%d2.var, -// CHECK:STDOUT: return -// CHECK:STDOUT: } -// CHECK:STDOUT: diff --git a/toolchain/check/testdata/function/declaration/import.carbon b/toolchain/check/testdata/function/declaration/import.carbon index dc020d326754..10fe4b9caf4f 100644 --- a/toolchain/check/testdata/function/declaration/import.carbon +++ b/toolchain/check/testdata/function/declaration/import.carbon @@ -84,11 +84,76 @@ var c: {.c: i32} = C((1,)); var d: () = D(); var e: () = NS.E(); -// --- merge.carbon +// --- fail_todo_merge.carbon library "merge" api; import library "api"; +// CHECK:STDERR: fail_todo_merge.carbon:[[@LINE+65]]:1: In import. +// CHECK:STDERR: import library "extern_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-7]]: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: import library "extern_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-20]]: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: import library "extern_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: 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: import library "extern_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-46]]: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: import library "extern_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-59]]: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: ^~~~~~~~~~ +// CHECK:STDERR: import library "extern_api"; var a: () = A(); @@ -97,11 +162,76 @@ var c: {.c: i32} = C((1,)); var d: () = D(); var e: () = NS.E(); -// --- merge_reverse.carbon +// --- fail_todo_merge_reverse.carbon library "merge_reverse" api; import library "extern_api"; +// CHECK:STDERR: fail_todo_merge_reverse.carbon:[[@LINE+65]]:1: In import. +// CHECK:STDERR: import library "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-7]]: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: +// CHECK:STDERR: fail_todo_merge_reverse.carbon:[[@LINE+52]]:1: In import. +// CHECK:STDERR: import library "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-20]]: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: +// CHECK:STDERR: fail_todo_merge_reverse.carbon:[[@LINE+39]]:1: In import. +// CHECK:STDERR: import library "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: 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: +// CHECK:STDERR: fail_todo_merge_reverse.carbon:[[@LINE+26]]:1: In import. +// CHECK:STDERR: import library "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-46]]: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: +// CHECK:STDERR: fail_todo_merge_reverse.carbon:[[@LINE+13]]:1: In import. +// CHECK:STDERR: import library "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-59]]: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: import library "api"; var a: () = A(); @@ -162,12 +292,13 @@ import library "api"; var a: () = A(); -// CHECK:STDERR: fail_extern_after_use.carbon:[[@LINE+6]]:1: ERROR: Redeclaration of imported entity that was previously used. +// CHECK:STDERR: fail_extern_after_use.carbon:[[@LINE+7]]:1: ERROR: Redeclaration of imported entity that was previously used. // CHECK:STDERR: extern fn A(); // CHECK:STDERR: ^~~~~~~~~~~~~~ // CHECK:STDERR: fail_extern_after_use.carbon:[[@LINE-5]]:13: Import used here. // CHECK:STDERR: var a: () = A(); // CHECK:STDERR: ^ +// CHECK:STDERR: extern fn A(); // --- unloaded.carbon @@ -182,11 +313,75 @@ library "unloaded_extern" api; import library "extern_api"; -// --- loaded_merge.carbon +// --- fail_todo_loaded_merge.carbon library "loaded_merge" api; import library "api"; +// CHECK:STDERR: fail_todo_loaded_merge.carbon:[[@LINE+64]]:1: In import. +// CHECK:STDERR: import library "extern_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-7]]: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 "extern_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-20]]: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 "extern_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-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_loaded_merge.carbon:[[@LINE+25]]:1: In import. +// CHECK:STDERR: import library "extern_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-46]]: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 "extern_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-59]]: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 "extern_api"; // CHECK:STDOUT: --- api.carbon @@ -588,14 +783,14 @@ import library "extern_api"; // CHECK:STDOUT: return // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: --- merge.carbon +// CHECK:STDOUT: --- fail_todo_merge.carbon // CHECK:STDOUT: // CHECK:STDOUT: constants { -// CHECK:STDOUT: %.1: type = tuple_type (i32) [template] -// CHECK:STDOUT: %.2: type = struct_type {.c: i32} [template] -// CHECK:STDOUT: %.3: type = tuple_type () [template] -// CHECK:STDOUT: %.4: i32 = int_literal 1 [template] -// CHECK:STDOUT: %tuple: (i32,) = tuple_value (%.4) [template] +// CHECK:STDOUT: %.1: type = tuple_type () [template] +// CHECK:STDOUT: %.2: i32 = int_literal 1 [template] +// CHECK:STDOUT: %.3: type = struct_type {.c: i32} [template] +// CHECK:STDOUT: %.4: type = tuple_type (i32) [template] +// CHECK:STDOUT: %tuple: (i32,) = tuple_value (%.2) [template] // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: file { @@ -612,103 +807,93 @@ import library "extern_api"; // CHECK:STDOUT: .d = %d // CHECK:STDOUT: .e = %e // CHECK:STDOUT: } -// CHECK:STDOUT: %import_ref.1: = import_ref ir1, inst+2, loc_19 [template = imports.%A.1] -// CHECK:STDOUT: %import_ref.2: = import_ref ir1, inst+6, loc_28 [template = imports.%B.1] -// CHECK:STDOUT: %import_ref.3: = import_ref ir1, inst+18, loc_43 [template = imports.%C.1] -// CHECK:STDOUT: %import_ref.4: = import_ref ir1, inst+19, loc_57 [template = imports.%D.1] +// CHECK:STDOUT: %import_ref.1: = import_ref ir1, inst+2, loc_19 [template = imports.%A] +// CHECK:STDOUT: %import_ref.2: = import_ref ir1, inst+6, loc_28 [template = imports.%B] +// CHECK:STDOUT: %import_ref.3: = import_ref ir1, inst+18, loc_43 [template = imports.%C] +// CHECK:STDOUT: %import_ref.4: = import_ref ir1, inst+19, loc_57 [template = imports.%D] // CHECK:STDOUT: %import_ref.5: = import_ref ir1, inst+20, loaded // CHECK:STDOUT: %NS: = namespace %import_ref.5, [template] { // CHECK:STDOUT: .E = %import_ref.6 // CHECK:STDOUT: } -// CHECK:STDOUT: %import_ref.6: = import_ref ir1, inst+21, loc_69 [template = imports.%E.1] -// CHECK:STDOUT: %import_ref.7: = import_ref ir2, inst+2, loaded [template = imports.%A.2] -// CHECK:STDOUT: %import_ref.8: = import_ref ir2, inst+6, loaded [template = imports.%B.2] -// CHECK:STDOUT: %import_ref.9: = import_ref ir2, inst+18, loaded [template = imports.%C.2] -// CHECK:STDOUT: %import_ref.10: = import_ref ir2, inst+19, loaded [template = imports.%D.2] -// CHECK:STDOUT: %import_ref.11: = import_ref ir2, inst+21, loaded [template = imports.%E.2] +// CHECK:STDOUT: %import_ref.6: = import_ref ir1, inst+21, loc_69 [template = imports.%E] +// CHECK:STDOUT: %import_ref.7 = import_ref ir2, inst+2, unloaded +// CHECK:STDOUT: %import_ref.8 = import_ref ir2, inst+6, unloaded +// CHECK:STDOUT: %import_ref.9 = import_ref ir2, inst+18, unloaded +// CHECK:STDOUT: %import_ref.10 = import_ref ir2, inst+19, unloaded +// CHECK:STDOUT: %import_ref.11 = import_ref ir2, inst+21, unloaded // CHECK:STDOUT: %Core: = namespace [template] {} -// CHECK:STDOUT: %.loc7_9.1: () = tuple_literal () -// CHECK:STDOUT: %.loc7_9.2: type = converted %.loc7_9.1, constants.%.3 [template = constants.%.3] +// CHECK:STDOUT: %.loc72_9.1: () = tuple_literal () +// CHECK:STDOUT: %.loc72_9.2: type = converted %.loc72_9.1, constants.%.1 [template = constants.%.1] // CHECK:STDOUT: %a.var: ref () = var a // CHECK:STDOUT: %a: ref () = bind_name a, %a.var // CHECK:STDOUT: %b.var: ref i32 = var b // CHECK:STDOUT: %b: ref i32 = bind_name b, %b.var -// CHECK:STDOUT: %.loc9: type = struct_type {.c: i32} [template = constants.%.2] +// CHECK:STDOUT: %.loc74: type = struct_type {.c: i32} [template = constants.%.3] // CHECK:STDOUT: %c.var: ref {.c: i32} = var c // CHECK:STDOUT: %c: ref {.c: i32} = bind_name c, %c.var -// CHECK:STDOUT: %.loc10_9.1: () = tuple_literal () -// CHECK:STDOUT: %.loc10_9.2: type = converted %.loc10_9.1, constants.%.3 [template = constants.%.3] +// CHECK:STDOUT: %.loc75_9.1: () = tuple_literal () +// CHECK:STDOUT: %.loc75_9.2: type = converted %.loc75_9.1, constants.%.1 [template = constants.%.1] // CHECK:STDOUT: %d.var: ref () = var d // CHECK:STDOUT: %d: ref () = bind_name d, %d.var -// CHECK:STDOUT: %.loc11_9.1: () = tuple_literal () -// CHECK:STDOUT: %.loc11_9.2: type = converted %.loc11_9.1, constants.%.3 [template = constants.%.3] +// CHECK:STDOUT: %.loc76_9.1: () = tuple_literal () +// CHECK:STDOUT: %.loc76_9.2: type = converted %.loc76_9.1, constants.%.1 [template = constants.%.1] // CHECK:STDOUT: %e.var: ref () = var e // CHECK:STDOUT: %e: ref () = bind_name e, %e.var // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: extern fn @A.1(); +// CHECK:STDOUT: fn @A(); // CHECK:STDOUT: -// CHECK:STDOUT: fn @A.2(); +// CHECK:STDOUT: fn @B(%b: i32) -> i32; // CHECK:STDOUT: -// CHECK:STDOUT: extern fn @B.1(%b: i32) -> i32; +// CHECK:STDOUT: fn @C(%c: (i32,)) -> {.c: i32}; // CHECK:STDOUT: -// CHECK:STDOUT: fn @B.2(%b: i32) -> i32; +// CHECK:STDOUT: extern fn @D(); // CHECK:STDOUT: -// CHECK:STDOUT: extern fn @C.1(%c: (i32,)) -> {.c: i32}; -// CHECK:STDOUT: -// CHECK:STDOUT: fn @C.2(%c: (i32,)) -> {.c: i32}; -// CHECK:STDOUT: -// CHECK:STDOUT: extern fn @D.1(); -// CHECK:STDOUT: -// CHECK:STDOUT: extern fn @D.2(); -// CHECK:STDOUT: -// CHECK:STDOUT: extern fn @E.1(); -// CHECK:STDOUT: -// CHECK:STDOUT: fn @E.2(); +// CHECK:STDOUT: fn @E(); // CHECK:STDOUT: // CHECK:STDOUT: fn @__global_init() { // CHECK:STDOUT: !entry: -// CHECK:STDOUT: %A.ref: = name_ref A, file.%import_ref.1 [template = imports.%A.1] +// CHECK:STDOUT: %A.ref: = name_ref A, file.%import_ref.1 [template = imports.%A] // CHECK:STDOUT: %A.call: init () = call %A.ref() // CHECK:STDOUT: assign file.%a.var, %A.call -// CHECK:STDOUT: %B.ref: = name_ref B, file.%import_ref.2 [template = imports.%B.1] -// CHECK:STDOUT: %.loc8: i32 = int_literal 1 [template = constants.%.4] -// CHECK:STDOUT: %B.call: init i32 = call %B.ref(%.loc8) +// CHECK:STDOUT: %B.ref: = name_ref B, file.%import_ref.2 [template = imports.%B] +// CHECK:STDOUT: %.loc73: i32 = int_literal 1 [template = constants.%.2] +// CHECK:STDOUT: %B.call: init i32 = call %B.ref(%.loc73) // CHECK:STDOUT: assign file.%b.var, %B.call -// CHECK:STDOUT: %C.ref: = name_ref C, file.%import_ref.3 [template = imports.%C.1] -// CHECK:STDOUT: %.loc9_23: i32 = int_literal 1 [template = constants.%.4] -// CHECK:STDOUT: %.loc9_25: (i32,) = tuple_literal (%.loc9_23) -// CHECK:STDOUT: %tuple: (i32,) = tuple_value (%.loc9_23) [template = constants.%tuple] -// CHECK:STDOUT: %.loc9_21: (i32,) = converted %.loc9_25, %tuple [template = constants.%tuple] -// CHECK:STDOUT: %C.call: init {.c: i32} = call %C.ref(%.loc9_21) +// CHECK:STDOUT: %C.ref: = name_ref C, file.%import_ref.3 [template = imports.%C] +// CHECK:STDOUT: %.loc74_23: i32 = int_literal 1 [template = constants.%.2] +// CHECK:STDOUT: %.loc74_25: (i32,) = tuple_literal (%.loc74_23) +// CHECK:STDOUT: %tuple: (i32,) = tuple_value (%.loc74_23) [template = constants.%tuple] +// CHECK:STDOUT: %.loc74_21: (i32,) = converted %.loc74_25, %tuple [template = constants.%tuple] +// CHECK:STDOUT: %C.call: init {.c: i32} = call %C.ref(%.loc74_21) // CHECK:STDOUT: assign file.%c.var, %C.call -// CHECK:STDOUT: %D.ref: = name_ref D, file.%import_ref.4 [template = imports.%D.1] +// CHECK:STDOUT: %D.ref: = name_ref D, file.%import_ref.4 [template = imports.%D] // CHECK:STDOUT: %D.call: init () = call %D.ref() // CHECK:STDOUT: assign file.%d.var, %D.call // CHECK:STDOUT: %NS.ref: = name_ref NS, file.%NS [template = file.%NS] -// CHECK:STDOUT: %E.ref: = name_ref E, file.%import_ref.6 [template = imports.%E.1] +// CHECK:STDOUT: %E.ref: = name_ref E, file.%import_ref.6 [template = imports.%E] // CHECK:STDOUT: %E.call: init () = call %E.ref() // CHECK:STDOUT: assign file.%e.var, %E.call // CHECK:STDOUT: return // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: --- merge_reverse.carbon +// CHECK:STDOUT: --- fail_todo_merge_reverse.carbon // CHECK:STDOUT: // CHECK:STDOUT: constants { -// CHECK:STDOUT: %.1: type = tuple_type (i32) [template] -// CHECK:STDOUT: %.2: type = struct_type {.c: i32} [template] -// CHECK:STDOUT: %.3: type = tuple_type () [template] -// CHECK:STDOUT: %.4: i32 = int_literal 1 [template] -// CHECK:STDOUT: %tuple: (i32,) = tuple_value (%.4) [template] +// CHECK:STDOUT: %.1: type = tuple_type () [template] +// CHECK:STDOUT: %.2: i32 = int_literal 1 [template] +// CHECK:STDOUT: %.3: type = struct_type {.c: i32} [template] +// CHECK:STDOUT: %.4: type = tuple_type (i32) [template] +// CHECK:STDOUT: %tuple: (i32,) = tuple_value (%.2) [template] // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: file { // CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .A = %import_ref.1 +// CHECK:STDOUT: .B = %import_ref.2 +// CHECK:STDOUT: .C = %import_ref.3 // CHECK:STDOUT: .D = %import_ref.4 // CHECK:STDOUT: .NS = %NS -// CHECK:STDOUT: .A = imports.%A.2 -// CHECK:STDOUT: .B = imports.%B.2 -// CHECK:STDOUT: .C = imports.%C.2 // CHECK:STDOUT: .Core = %Core // CHECK:STDOUT: .a = %a // CHECK:STDOUT: .b = %b @@ -716,81 +901,71 @@ import library "extern_api"; // CHECK:STDOUT: .d = %d // CHECK:STDOUT: .e = %e // CHECK:STDOUT: } -// CHECK:STDOUT: %import_ref.1: = import_ref ir1, inst+2, loaded [template = imports.%A.1] -// CHECK:STDOUT: %import_ref.2: = import_ref ir1, inst+6, loaded [template = imports.%B.1] -// CHECK:STDOUT: %import_ref.3: = import_ref ir1, inst+18, loaded [template = imports.%C.1] -// CHECK:STDOUT: %import_ref.4: = import_ref ir1, inst+19, loc_57 [template = imports.%D.1] +// CHECK:STDOUT: %import_ref.1: = import_ref ir1, inst+2, loc_19 [template = imports.%A] +// CHECK:STDOUT: %import_ref.2: = import_ref ir1, inst+6, loc_28 [template = imports.%B] +// CHECK:STDOUT: %import_ref.3: = import_ref ir1, inst+18, loc_43 [template = imports.%C] +// CHECK:STDOUT: %import_ref.4: = import_ref ir1, inst+19, loc_57 [template = imports.%D] // CHECK:STDOUT: %import_ref.5: = import_ref ir1, inst+20, loaded // CHECK:STDOUT: %NS: = namespace %import_ref.5, [template] { -// CHECK:STDOUT: .E = imports.%E.2 +// CHECK:STDOUT: .E = %import_ref.6 // CHECK:STDOUT: } -// CHECK:STDOUT: %import_ref.6: = import_ref ir1, inst+21, loaded [template = imports.%E.1] -// CHECK:STDOUT: %import_ref.7: = import_ref ir2, inst+2, loaded [template = imports.%A.2] -// CHECK:STDOUT: %import_ref.8: = import_ref ir2, inst+6, loaded [template = imports.%B.2] -// CHECK:STDOUT: %import_ref.9: = import_ref ir2, inst+18, loaded [template = imports.%C.2] -// CHECK:STDOUT: %import_ref.10: = import_ref ir2, inst+19, loaded [template = imports.%D.2] -// CHECK:STDOUT: %import_ref.11: = import_ref ir2, inst+21, loaded [template = imports.%E.2] +// CHECK:STDOUT: %import_ref.6: = import_ref ir1, inst+21, loc_69 [template = imports.%E] +// CHECK:STDOUT: %import_ref.7 = import_ref ir2, inst+2, unloaded +// CHECK:STDOUT: %import_ref.8 = import_ref ir2, inst+6, unloaded +// CHECK:STDOUT: %import_ref.9 = import_ref ir2, inst+18, unloaded +// CHECK:STDOUT: %import_ref.10 = import_ref ir2, inst+19, unloaded +// CHECK:STDOUT: %import_ref.11 = import_ref ir2, inst+21, unloaded // CHECK:STDOUT: %Core: = namespace [template] {} -// CHECK:STDOUT: %.loc7_9.1: () = tuple_literal () -// CHECK:STDOUT: %.loc7_9.2: type = converted %.loc7_9.1, constants.%.3 [template = constants.%.3] +// CHECK:STDOUT: %.loc72_9.1: () = tuple_literal () +// CHECK:STDOUT: %.loc72_9.2: type = converted %.loc72_9.1, constants.%.1 [template = constants.%.1] // CHECK:STDOUT: %a.var: ref () = var a // CHECK:STDOUT: %a: ref () = bind_name a, %a.var // CHECK:STDOUT: %b.var: ref i32 = var b // CHECK:STDOUT: %b: ref i32 = bind_name b, %b.var -// CHECK:STDOUT: %.loc9: type = struct_type {.c: i32} [template = constants.%.2] +// CHECK:STDOUT: %.loc74: type = struct_type {.c: i32} [template = constants.%.3] // CHECK:STDOUT: %c.var: ref {.c: i32} = var c // CHECK:STDOUT: %c: ref {.c: i32} = bind_name c, %c.var -// CHECK:STDOUT: %.loc10_9.1: () = tuple_literal () -// CHECK:STDOUT: %.loc10_9.2: type = converted %.loc10_9.1, constants.%.3 [template = constants.%.3] +// CHECK:STDOUT: %.loc75_9.1: () = tuple_literal () +// CHECK:STDOUT: %.loc75_9.2: type = converted %.loc75_9.1, constants.%.1 [template = constants.%.1] // CHECK:STDOUT: %d.var: ref () = var d // CHECK:STDOUT: %d: ref () = bind_name d, %d.var -// CHECK:STDOUT: %.loc11_9.1: () = tuple_literal () -// CHECK:STDOUT: %.loc11_9.2: type = converted %.loc11_9.1, constants.%.3 [template = constants.%.3] +// CHECK:STDOUT: %.loc76_9.1: () = tuple_literal () +// CHECK:STDOUT: %.loc76_9.2: type = converted %.loc76_9.1, constants.%.1 [template = constants.%.1] // CHECK:STDOUT: %e.var: ref () = var e // CHECK:STDOUT: %e: ref () = bind_name e, %e.var // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: fn @A.1(); +// CHECK:STDOUT: extern fn @A(); // CHECK:STDOUT: -// CHECK:STDOUT: fn @A.2(); +// CHECK:STDOUT: extern fn @B(%b: i32) -> i32; // CHECK:STDOUT: -// CHECK:STDOUT: fn @B.1(%b: i32) -> i32; +// CHECK:STDOUT: extern fn @C(%c: (i32,)) -> {.c: i32}; // CHECK:STDOUT: -// CHECK:STDOUT: fn @B.2(%b: i32) -> i32; +// CHECK:STDOUT: extern fn @D(); // CHECK:STDOUT: -// CHECK:STDOUT: fn @C.1(%c: (i32,)) -> {.c: i32}; -// CHECK:STDOUT: -// CHECK:STDOUT: fn @C.2(%c: (i32,)) -> {.c: i32}; -// CHECK:STDOUT: -// CHECK:STDOUT: extern fn @D.1(); -// CHECK:STDOUT: -// CHECK:STDOUT: extern fn @D.2(); -// CHECK:STDOUT: -// CHECK:STDOUT: fn @E.1(); -// CHECK:STDOUT: -// CHECK:STDOUT: fn @E.2(); +// CHECK:STDOUT: extern fn @E(); // CHECK:STDOUT: // CHECK:STDOUT: fn @__global_init() { // CHECK:STDOUT: !entry: -// CHECK:STDOUT: %A.ref: = name_ref A, imports.%A.2 [template = imports.%A.2] +// CHECK:STDOUT: %A.ref: = name_ref A, file.%import_ref.1 [template = imports.%A] // CHECK:STDOUT: %A.call: init () = call %A.ref() // CHECK:STDOUT: assign file.%a.var, %A.call -// CHECK:STDOUT: %B.ref: = name_ref B, imports.%B.2 [template = imports.%B.2] -// CHECK:STDOUT: %.loc8: i32 = int_literal 1 [template = constants.%.4] -// CHECK:STDOUT: %B.call: init i32 = call %B.ref(%.loc8) +// CHECK:STDOUT: %B.ref: = name_ref B, file.%import_ref.2 [template = imports.%B] +// CHECK:STDOUT: %.loc73: i32 = int_literal 1 [template = constants.%.2] +// CHECK:STDOUT: %B.call: init i32 = call %B.ref(%.loc73) // CHECK:STDOUT: assign file.%b.var, %B.call -// CHECK:STDOUT: %C.ref: = name_ref C, imports.%C.2 [template = imports.%C.2] -// CHECK:STDOUT: %.loc9_23: i32 = int_literal 1 [template = constants.%.4] -// CHECK:STDOUT: %.loc9_25: (i32,) = tuple_literal (%.loc9_23) -// CHECK:STDOUT: %tuple: (i32,) = tuple_value (%.loc9_23) [template = constants.%tuple] -// CHECK:STDOUT: %.loc9_21: (i32,) = converted %.loc9_25, %tuple [template = constants.%tuple] -// CHECK:STDOUT: %C.call: init {.c: i32} = call %C.ref(%.loc9_21) +// CHECK:STDOUT: %C.ref: = name_ref C, file.%import_ref.3 [template = imports.%C] +// CHECK:STDOUT: %.loc74_23: i32 = int_literal 1 [template = constants.%.2] +// CHECK:STDOUT: %.loc74_25: (i32,) = tuple_literal (%.loc74_23) +// CHECK:STDOUT: %tuple: (i32,) = tuple_value (%.loc74_23) [template = constants.%tuple] +// CHECK:STDOUT: %.loc74_21: (i32,) = converted %.loc74_25, %tuple [template = constants.%tuple] +// CHECK:STDOUT: %C.call: init {.c: i32} = call %C.ref(%.loc74_21) // CHECK:STDOUT: assign file.%c.var, %C.call -// CHECK:STDOUT: %D.ref: = name_ref D, file.%import_ref.4 [template = imports.%D.1] +// CHECK:STDOUT: %D.ref: = name_ref D, file.%import_ref.4 [template = imports.%D] // CHECK:STDOUT: %D.call: init () = call %D.ref() // CHECK:STDOUT: assign file.%d.var, %D.call // CHECK:STDOUT: %NS.ref: = name_ref NS, file.%NS [template = file.%NS] -// CHECK:STDOUT: %E.ref: = name_ref E, imports.%E.2 [template = imports.%E.2] +// CHECK:STDOUT: %E.ref: = name_ref E, file.%import_ref.6 [template = imports.%E] // CHECK:STDOUT: %E.call: init () = call %E.ref() // CHECK:STDOUT: assign file.%e.var, %E.call // CHECK:STDOUT: return @@ -975,12 +1150,7 @@ import library "extern_api"; // CHECK:STDOUT: %Core: = namespace [template] {} // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: --- loaded_merge.carbon -// CHECK:STDOUT: -// CHECK:STDOUT: constants { -// CHECK:STDOUT: %.1: type = tuple_type (i32) [template] -// CHECK:STDOUT: %.2: type = struct_type {.c: i32} [template] -// CHECK:STDOUT: } +// CHECK:STDOUT: --- fail_todo_loaded_merge.carbon // CHECK:STDOUT: // CHECK:STDOUT: file { // CHECK:STDOUT: package: = namespace [template] { @@ -991,40 +1161,20 @@ import library "extern_api"; // CHECK:STDOUT: .NS = %NS // CHECK:STDOUT: .Core = %Core // CHECK:STDOUT: } -// CHECK:STDOUT: %import_ref.1: = import_ref ir1, inst+2, loaded [template = imports.%A.1] -// CHECK:STDOUT: %import_ref.2: = import_ref ir1, inst+6, loaded [template = imports.%B.1] -// CHECK:STDOUT: %import_ref.3: = import_ref ir1, inst+18, loaded [template = imports.%C.1] -// CHECK:STDOUT: %import_ref.4: = import_ref ir1, inst+19, loaded [template = imports.%D.1] +// CHECK:STDOUT: %import_ref.1 = import_ref ir1, inst+2, unloaded +// CHECK:STDOUT: %import_ref.2 = import_ref ir1, inst+6, unloaded +// CHECK:STDOUT: %import_ref.3 = import_ref ir1, inst+18, unloaded +// CHECK:STDOUT: %import_ref.4 = import_ref ir1, inst+19, unloaded // CHECK:STDOUT: %import_ref.5: = import_ref ir1, inst+20, loaded // CHECK:STDOUT: %NS: = namespace %import_ref.5, [template] { // CHECK:STDOUT: .E = %import_ref.6 // CHECK:STDOUT: } -// CHECK:STDOUT: %import_ref.6: = import_ref ir1, inst+21, loaded [template = imports.%E.1] -// CHECK:STDOUT: %import_ref.7: = import_ref ir2, inst+2, loaded [template = imports.%A.2] -// CHECK:STDOUT: %import_ref.8: = import_ref ir2, inst+6, loaded [template = imports.%B.2] -// CHECK:STDOUT: %import_ref.9: = import_ref ir2, inst+18, loaded [template = imports.%C.2] -// CHECK:STDOUT: %import_ref.10: = import_ref ir2, inst+19, loaded [template = imports.%D.2] -// CHECK:STDOUT: %import_ref.11: = import_ref ir2, inst+21, loaded [template = imports.%E.2] +// CHECK:STDOUT: %import_ref.6 = import_ref ir1, inst+21, unloaded +// CHECK:STDOUT: %import_ref.7 = import_ref ir2, inst+2, unloaded +// CHECK:STDOUT: %import_ref.8 = import_ref ir2, inst+6, unloaded +// CHECK:STDOUT: %import_ref.9 = import_ref ir2, inst+18, unloaded +// CHECK:STDOUT: %import_ref.10 = import_ref ir2, inst+19, unloaded +// CHECK:STDOUT: %import_ref.11 = import_ref ir2, inst+21, unloaded // CHECK:STDOUT: %Core: = namespace [template] {} // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: extern fn @A.1(); -// CHECK:STDOUT: -// CHECK:STDOUT: fn @A.2(); -// CHECK:STDOUT: -// CHECK:STDOUT: extern fn @B.1(%b: i32) -> i32; -// CHECK:STDOUT: -// CHECK:STDOUT: fn @B.2(%b: i32) -> i32; -// CHECK:STDOUT: -// CHECK:STDOUT: extern fn @C.1(%c: (i32,)) -> {.c: i32}; -// CHECK:STDOUT: -// CHECK:STDOUT: fn @C.2(%c: (i32,)) -> {.c: i32}; -// CHECK:STDOUT: -// CHECK:STDOUT: extern fn @D.1(); -// CHECK:STDOUT: -// CHECK:STDOUT: extern fn @D.2(); -// CHECK:STDOUT: -// CHECK:STDOUT: extern fn @E.1(); -// CHECK:STDOUT: -// CHECK:STDOUT: fn @E.2(); -// CHECK:STDOUT: diff --git a/toolchain/check/testdata/namespace/fail_conflict_in_imports_namespace_first.carbon b/toolchain/check/testdata/namespace/fail_conflict_in_imports_namespace_first.carbon index 77bbd7b4f130..054fadaecd6c 100644 --- a/toolchain/check/testdata/namespace/fail_conflict_in_imports_namespace_first.carbon +++ b/toolchain/check/testdata/namespace/fail_conflict_in_imports_namespace_first.carbon @@ -86,13 +86,11 @@ fn NS.Bar() {} // CHECK:STDOUT: .Bar = %Bar // CHECK:STDOUT: } // CHECK:STDOUT: %import_ref.2 = import_ref ir1, inst+3, unloaded -// CHECK:STDOUT: %import_ref.3: = import_ref ir2, inst+2, loaded [template = imports.%NS] +// CHECK:STDOUT: %import_ref.3 = import_ref ir2, inst+2, unloaded // CHECK:STDOUT: %Core: = namespace [template] {} // CHECK:STDOUT: %Bar: = fn_decl @Bar [template] {} // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: fn @NS(); -// CHECK:STDOUT: // CHECK:STDOUT: fn @Bar() { // CHECK:STDOUT: !entry: // CHECK:STDOUT: return diff --git a/toolchain/check/testdata/packages/cross_package_import.carbon b/toolchain/check/testdata/packages/cross_package_import.carbon index 4bb352073c20..448fad4c6d05 100644 --- a/toolchain/check/testdata/packages/cross_package_import.carbon +++ b/toolchain/check/testdata/packages/cross_package_import.carbon @@ -54,14 +54,30 @@ fn Run() { Other.F2(); } -// --- main_use_other_extern.carbon +// --- fail_todo_main_use_other_extern.carbon library "use_other_extern" api; import Other library "fn"; +// CHECK:STDERR: fail_todo_main_use_other_extern.carbon:[[@LINE+12]]:1: In import. +// CHECK:STDERR: import Other library "fn_extern"; +// CHECK:STDERR: ^~~~~~ +// CHECK:STDERR: other_fn_extern.carbon:4:1: ERROR: Duplicate name being declared in the same scope. +// CHECK:STDERR: extern fn F(); +// CHECK:STDERR: ^~~~~~~~~~~~~~ +// CHECK:STDERR: fail_todo_main_use_other_extern.carbon:[[@LINE-7]]:1: In import. +// CHECK:STDERR: import Other library "fn"; +// CHECK:STDERR: ^~~~~~ +// CHECK:STDERR: other_fn.carbon:4:1: Name is previously declared here. +// CHECK:STDERR: fn F() {} +// CHECK:STDERR: ^~~~~~~~ import Other library "fn_extern"; fn Run() { + // CHECK:STDERR: fail_todo_main_use_other_extern.carbon:[[@LINE+4]]:3: In name lookup for `F`. + // CHECK:STDERR: Other.F(); + // CHECK:STDERR: ^~~~~~~ + // CHECK:STDERR: Other.F(); } @@ -80,13 +96,13 @@ import Other library "fn"; // CHECK:STDERR: fail_main_use_other_ambiguous.carbon:[[@LINE+12]]:1: In import. // CHECK:STDERR: import Other library "fn_conflict"; // CHECK:STDERR: ^~~~~~ -// CHECK:STDERR: other_fn_conflict.carbon:4:1: ERROR: Function redeclaration differs because of parameter count of 1. +// CHECK:STDERR: other_fn_conflict.carbon:4:1: ERROR: Duplicate name being declared in the same scope. // CHECK:STDERR: fn F(x: i32) {} // CHECK:STDERR: ^~~~~~~~~~~~~~ // CHECK:STDERR: fail_main_use_other_ambiguous.carbon:[[@LINE-7]]:1: In import. // CHECK:STDERR: import Other library "fn"; // CHECK:STDERR: ^~~~~~ -// CHECK:STDERR: other_fn.carbon:4:1: Previously declared with parameter count of 0. +// CHECK:STDERR: other_fn.carbon:4:1: Name is previously declared here. // CHECK:STDERR: fn F() {} // CHECK:STDERR: ^~~~~~~~ import Other library "fn_conflict"; @@ -269,7 +285,7 @@ fn Other.G() {} // CHECK:STDOUT: // CHECK:STDOUT: fn @F2(); // CHECK:STDOUT: -// CHECK:STDOUT: --- main_use_other_extern.carbon +// CHECK:STDOUT: --- fail_todo_main_use_other_extern.carbon // CHECK:STDOUT: // CHECK:STDOUT: constants { // CHECK:STDOUT: %.1: type = tuple_type () [template] @@ -284,21 +300,19 @@ fn Other.G() {} // CHECK:STDOUT: %Core: = namespace [template] {} // CHECK:STDOUT: %Other: = namespace [template] {} // CHECK:STDOUT: %Run: = fn_decl @Run [template] {} -// CHECK:STDOUT: %import_ref.1: = import_ref ir2, inst+2, loc_22 [template = imports.%F.1] -// CHECK:STDOUT: %import_ref.2: = import_ref ir3, inst+2, loaded [template = imports.%F.2] +// CHECK:STDOUT: %import_ref.1: = import_ref ir2, inst+2, loc_22 [template = imports.%F] +// CHECK:STDOUT: %import_ref.2 = import_ref ir3, inst+2, unloaded // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: fn @Run() { // CHECK:STDOUT: !entry: // CHECK:STDOUT: %Other.ref: = name_ref Other, file.%Other [template = file.%Other] -// CHECK:STDOUT: %F.ref: = name_ref F, file.%import_ref.1 [template = imports.%F.1] +// CHECK:STDOUT: %F.ref: = name_ref F, file.%import_ref.1 [template = imports.%F] // CHECK:STDOUT: %F.call: init () = call %F.ref() // CHECK:STDOUT: return // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: fn @F.1(); -// CHECK:STDOUT: -// CHECK:STDOUT: extern fn @F.2(); +// CHECK:STDOUT: fn @F(); // CHECK:STDOUT: // CHECK:STDOUT: --- main_unused_other_ambiguous.carbon // CHECK:STDOUT: @@ -326,21 +340,19 @@ fn Other.G() {} // CHECK:STDOUT: %Core: = namespace [template] {} // CHECK:STDOUT: %Other: = namespace [template] {} // CHECK:STDOUT: %Run: = fn_decl @Run [template] {} -// CHECK:STDOUT: %import_ref.1: = import_ref ir2, inst+2, loc_22 [template = imports.%F.1] -// CHECK:STDOUT: %import_ref.2: = import_ref ir3, inst+4, loaded [template = imports.%F.2] +// CHECK:STDOUT: %import_ref.1: = import_ref ir2, inst+2, loc_22 [template = imports.%F] +// CHECK:STDOUT: %import_ref.2 = import_ref ir3, inst+4, unloaded // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: fn @Run() { // CHECK:STDOUT: !entry: // CHECK:STDOUT: %Other.ref: = name_ref Other, file.%Other [template = file.%Other] -// CHECK:STDOUT: %F.ref: = name_ref F, file.%import_ref.1 [template = imports.%F.1] +// CHECK:STDOUT: %F.ref: = name_ref F, file.%import_ref.1 [template = imports.%F] // CHECK:STDOUT: %F.call: init () = call %F.ref() // CHECK:STDOUT: return // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: fn @F.1(); -// CHECK:STDOUT: -// CHECK:STDOUT: fn @F.2(%x: i32); +// CHECK:STDOUT: fn @F(); // CHECK:STDOUT: // CHECK:STDOUT: --- fail_main_namespace_conflict.carbon // CHECK:STDOUT: diff --git a/toolchain/check/testdata/packages/fail_conflict_no_namespaces.carbon b/toolchain/check/testdata/packages/fail_conflict_no_namespaces.carbon index 7e2c103cdcb1..cc83c8c07042 100644 --- a/toolchain/check/testdata/packages/fail_conflict_no_namespaces.carbon +++ b/toolchain/check/testdata/packages/fail_conflict_no_namespaces.carbon @@ -67,10 +67,8 @@ import library "var"; // CHECK:STDOUT: .Foo = %import_ref.1 // CHECK:STDOUT: .Core = %Core // CHECK:STDOUT: } -// CHECK:STDOUT: %import_ref.1: = import_ref ir1, inst+2, loaded [template = imports.%Foo] -// CHECK:STDOUT: %import_ref.2: ref i32 = import_ref ir2, inst+3, loaded +// CHECK:STDOUT: %import_ref.1 = import_ref ir1, inst+2, unloaded +// CHECK:STDOUT: %import_ref.2 = import_ref ir2, inst+3, unloaded // CHECK:STDOUT: %Core: = namespace [template] {} // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: fn @Foo(); -// CHECK:STDOUT: