From 57c0a6c076e7cea39edeea8ffb53301f1a8e693c Mon Sep 17 00:00:00 2001 From: Jon Ross-Perkins Date: Tue, 21 May 2024 14:02:09 -0700 Subject: [PATCH] Handling for cross-package imports of "export name". (#3967) Starts warning on duplicate "export name" because I'm updating name lookup to make it work. Need to think harder about how to handle cross-package "export import". But adding some failing tests to sketch out what *should* work. --- toolchain/check/handle_export.cpp | 22 + .../alias/no_prelude/export_name.carbon | 4 +- .../class/no_prelude/export_name.carbon | 2 +- .../declaration/no_prelude/export_name.carbon | 2 +- .../interface/no_prelude/export_name.carbon | 2 +- .../no_prelude/cross_package_export.carbon | 429 ++++++++++++++++++ .../packages/no_prelude/export_mixed.carbon | 4 +- .../packages/no_prelude/export_name.carbon | 22 +- .../var/no_prelude/export_name.carbon | 2 +- toolchain/diagnostics/diagnostic_kind.def | 2 + 10 files changed, 475 insertions(+), 16 deletions(-) create mode 100644 toolchain/check/testdata/packages/no_prelude/cross_package_export.carbon diff --git a/toolchain/check/handle_export.cpp b/toolchain/check/handle_export.cpp index 13042fad0a60..6d3697e9e1fa 100644 --- a/toolchain/check/handle_export.cpp +++ b/toolchain/check/handle_export.cpp @@ -38,6 +38,20 @@ auto HandleExportDecl(Context& context, Parse::ExportDeclId node_id) -> bool { return true; } + auto inst = context.insts().Get(inst_id); + + if (inst.Is()) { + CARBON_DIAGNOSTIC(ExportRedundant, Warning, + "`export` matches previous `export`."); + CARBON_DIAGNOSTIC(ExportPrevious, Note, "Previous `export` here."); + context.emitter() + .Build(node_id, ExportRedundant) + // Use the location of the export itself, not the exported instruction. + .Note(context.insts().GetLocId(inst_id), ExportPrevious) + .Emit(); + return true; + } + auto import_ref = context.insts().TryGetAs(inst_id); if (!import_ref) { CARBON_DIAGNOSTIC(ExportNotImportedEntity, Error, @@ -57,6 +71,14 @@ auto HandleExportDecl(Context& context, Parse::ExportDeclId node_id) -> bool { .value_id = inst_id}}); context.AddExport(export_id); + // Replace the ImportRef in name lookup, both for the above duplicate + // diagnostic and so that cross-package imports can find it easily. + auto bind_name = context.bind_names().Get(import_ref->bind_name_id); + auto& names = context.name_scopes().Get(bind_name.enclosing_scope_id).names; + auto it = names.find(bind_name.name_id); + CARBON_CHECK(it->second == inst_id); + it->second = export_id; + return true; } diff --git a/toolchain/check/testdata/alias/no_prelude/export_name.carbon b/toolchain/check/testdata/alias/no_prelude/export_name.carbon index 97773582467e..f71539908ede 100644 --- a/toolchain/check/testdata/alias/no_prelude/export_name.carbon +++ b/toolchain/check/testdata/alias/no_prelude/export_name.carbon @@ -96,7 +96,7 @@ var d: D* = &c; // CHECK:STDOUT: file { // CHECK:STDOUT: package: = namespace [template] { // CHECK:STDOUT: .C = %import_ref.1 -// CHECK:STDOUT: .D = %import_ref.2 +// CHECK:STDOUT: .D = %D // CHECK:STDOUT: } // CHECK:STDOUT: %import_ref.1 = import_ref ir1, inst+1, unloaded // CHECK:STDOUT: %import_ref.2: type = import_ref ir1, inst+5, loaded [template = constants.%C] @@ -118,8 +118,8 @@ var d: D* = &c; // CHECK:STDOUT: // CHECK:STDOUT: file { // CHECK:STDOUT: package: = namespace [template] { -// CHECK:STDOUT: .C = %import_ref.1 // CHECK:STDOUT: .D = %import_ref.2 +// CHECK:STDOUT: .C = %C // CHECK:STDOUT: } // CHECK:STDOUT: %import_ref.1: type = import_ref ir1, inst+1, loaded [template = constants.%C] // CHECK:STDOUT: %import_ref.2 = import_ref ir1, inst+5, unloaded diff --git a/toolchain/check/testdata/class/no_prelude/export_name.carbon b/toolchain/check/testdata/class/no_prelude/export_name.carbon index 648e555e38d0..a244da2a970f 100644 --- a/toolchain/check/testdata/class/no_prelude/export_name.carbon +++ b/toolchain/check/testdata/class/no_prelude/export_name.carbon @@ -62,7 +62,7 @@ var c: C = {}; // CHECK:STDOUT: // CHECK:STDOUT: file { // CHECK:STDOUT: package: = namespace [template] { -// CHECK:STDOUT: .C = %import_ref.1 +// CHECK:STDOUT: .C = %C // CHECK:STDOUT: } // CHECK:STDOUT: %import_ref.1: type = import_ref ir1, inst+1, loaded [template = constants.%C] // CHECK:STDOUT: %import_ref.2 = import_ref ir1, inst+2, unloaded diff --git a/toolchain/check/testdata/function/declaration/no_prelude/export_name.carbon b/toolchain/check/testdata/function/declaration/no_prelude/export_name.carbon index cd1467ff2ef0..596498264f71 100644 --- a/toolchain/check/testdata/function/declaration/no_prelude/export_name.carbon +++ b/toolchain/check/testdata/function/declaration/no_prelude/export_name.carbon @@ -61,7 +61,7 @@ var f: () = F(); // CHECK:STDOUT: // CHECK:STDOUT: file { // CHECK:STDOUT: package: = namespace [template] { -// CHECK:STDOUT: .F = %import_ref +// CHECK:STDOUT: .F = %F // CHECK:STDOUT: } // CHECK:STDOUT: %import_ref: F = import_ref ir1, inst+1, loaded [template = constants.%struct] // CHECK:STDOUT: %F: F = export F, %import_ref [template = constants.%struct] diff --git a/toolchain/check/testdata/interface/no_prelude/export_name.carbon b/toolchain/check/testdata/interface/no_prelude/export_name.carbon index 192754d1ee19..76c1ca2db046 100644 --- a/toolchain/check/testdata/interface/no_prelude/export_name.carbon +++ b/toolchain/check/testdata/interface/no_prelude/export_name.carbon @@ -65,7 +65,7 @@ fn UseEmpty(i: I) {} // CHECK:STDOUT: // CHECK:STDOUT: file { // CHECK:STDOUT: package: = namespace [template] { -// CHECK:STDOUT: .I = %import_ref.1 +// CHECK:STDOUT: .I = %I // CHECK:STDOUT: } // CHECK:STDOUT: %import_ref.1: type = import_ref ir1, inst+1, loaded [template = constants.%.1] // CHECK:STDOUT: %import_ref.2 = import_ref ir1, inst+3, unloaded diff --git a/toolchain/check/testdata/packages/no_prelude/cross_package_export.carbon b/toolchain/check/testdata/packages/no_prelude/cross_package_export.carbon new file mode 100644 index 000000000000..87fb10b8210f --- /dev/null +++ b/toolchain/check/testdata/packages/no_prelude/cross_package_export.carbon @@ -0,0 +1,429 @@ +// 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 + +// ============================================================================ +// Setup files +// ============================================================================ + +// --- base.carbon + +package Other library "base"; + +class C { + var x: (); +}; + +// --- export_import.carbon + +package Other library "export_import"; + +export import library "base"; + +// --- export_import_copy.carbon + +package Other library "export_import_copy"; + +export import library "base"; + +// --- export_name.carbon + +package Other library "export_name"; + +import library "base"; + +export C; + +// --- export_name_copy.carbon + +package Other library "export_name_copy"; + +import library "base"; + +export C; + +// ============================================================================ +// Test files +// ============================================================================ + +// --- fail_todo_use_export_import.carbon + +library "use_export_import"; + +import Other library "export_import"; + +// CHECK:STDERR: fail_todo_use_export_import.carbon:[[@LINE+4]]:8: ERROR: Name `C` not found. +// CHECK:STDERR: var c: Other.C = {.x = ()}; +// CHECK:STDERR: ^~~~~~~ +// CHECK:STDERR: +var c: Other.C = {.x = ()}; + +// --- fail_todo_use_export_import_both.carbon + +library "use_export_import_both"; + +import Other library "export_import"; +import Other library "export_import_copy"; + +// CHECK:STDERR: fail_todo_use_export_import_both.carbon:[[@LINE+4]]:8: ERROR: Name `C` not found. +// CHECK:STDERR: var c: Other.C = {.x = ()}; +// CHECK:STDERR: ^~~~~~~ +// CHECK:STDERR: +var c: Other.C = {.x = ()}; + +// --- use_export_name.carbon + +library "use_export_name"; + +import Other library "export_name"; + +var c: Other.C = {.x = ()}; + +// --- fail_todo_use_export_name_both.carbon + +library "use_export_name_both"; + +import Other library "export_name"; +// CHECK:STDERR: fail_todo_use_export_name_both.carbon:[[@LINE+18]]:1: In import. +// CHECK:STDERR: import Other library "export_name_copy"; +// CHECK:STDERR: ^~~~~~ +// CHECK:STDERR: export_name_copy.carbon:4:1: In import. +// CHECK:STDERR: import library "base"; +// CHECK:STDERR: ^~~~~~ +// CHECK:STDERR: base.carbon:4:1: ERROR: Duplicate name being declared in the same scope. +// CHECK:STDERR: class C { +// CHECK:STDERR: ^~~~~~~~~ +// CHECK:STDERR: fail_todo_use_export_name_both.carbon:[[@LINE-10]]:1: In import. +// CHECK:STDERR: import Other library "export_name"; +// CHECK:STDERR: ^~~~~~ +// CHECK:STDERR: export_name.carbon:4:1: In import. +// CHECK:STDERR: import library "base"; +// CHECK:STDERR: ^~~~~~ +// CHECK:STDERR: base.carbon:4:1: Name is previously declared here. +// CHECK:STDERR: class C { +// CHECK:STDERR: ^~~~~~~~~ +import Other library "export_name_copy"; + +// CHECK:STDERR: fail_todo_use_export_name_both.carbon:[[@LINE+4]]:8: In name lookup for `C`. +// CHECK:STDERR: var c: Other.C = {.x = ()}; +// CHECK:STDERR: ^~~~~~~ +// CHECK:STDERR: +var c: Other.C = {.x = ()}; + +// --- fail_todo_use_export_all.carbon + +library "use_export_all"; + +import Other library "export_import"; +import Other library "export_name"; +import Other library "export_import_copy"; +// CHECK:STDERR: fail_todo_use_export_all.carbon:[[@LINE+18]]:1: In import. +// CHECK:STDERR: import Other library "export_name_copy"; +// CHECK:STDERR: ^~~~~~ +// CHECK:STDERR: export_name_copy.carbon:4:1: In import. +// CHECK:STDERR: import library "base"; +// CHECK:STDERR: ^~~~~~ +// CHECK:STDERR: base.carbon:4:1: ERROR: Duplicate name being declared in the same scope. +// CHECK:STDERR: class C { +// CHECK:STDERR: ^~~~~~~~~ +// CHECK:STDERR: fail_todo_use_export_all.carbon:[[@LINE-11]]:1: In import. +// CHECK:STDERR: import Other library "export_name"; +// CHECK:STDERR: ^~~~~~ +// CHECK:STDERR: export_name.carbon:4:1: In import. +// CHECK:STDERR: import library "base"; +// CHECK:STDERR: ^~~~~~ +// CHECK:STDERR: base.carbon:4:1: Name is previously declared here. +// CHECK:STDERR: class C { +// CHECK:STDERR: ^~~~~~~~~ +import Other library "export_name_copy"; + +// CHECK:STDERR: fail_todo_use_export_all.carbon:[[@LINE+3]]:8: In name lookup for `C`. +// CHECK:STDERR: var c: Other.C = {.x = ()}; +// CHECK:STDERR: ^~~~~~~ +var c: Other.C = {.x = ()}; + +// CHECK:STDOUT: --- base.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %C: type = class_type @C [template] +// CHECK:STDOUT: %.1: type = tuple_type () [template] +// CHECK:STDOUT: %.2: type = unbound_element_type C, () [template] +// CHECK:STDOUT: %.3: type = struct_type {.x: ()} [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: %.loc5_11.1: () = tuple_literal () +// CHECK:STDOUT: %.loc5_11.2: type = converted %.loc5_11.1, constants.%.1 [template = constants.%.1] +// CHECK:STDOUT: %.loc5_8: = field_decl x, element0 [template] +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = constants.%C +// CHECK:STDOUT: .x = %.loc5_8 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: --- export_import.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .C = %import_ref +// CHECK:STDOUT: } +// CHECK:STDOUT: %import_ref = import_ref ir1, inst+1, unloaded +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: --- export_import_copy.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .C = %import_ref +// CHECK:STDOUT: } +// CHECK:STDOUT: %import_ref = import_ref ir1, inst+1, unloaded +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: --- export_name.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %C: type = class_type @C [template] +// CHECK:STDOUT: %.1: type = tuple_type () [template] +// CHECK:STDOUT: %.2: type = struct_type {.x: ()} [template] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .C = %C +// CHECK:STDOUT: } +// CHECK:STDOUT: %import_ref.1: type = import_ref ir1, inst+1, loaded [template = constants.%C] +// CHECK:STDOUT: %import_ref.2 = import_ref ir1, inst+2, unloaded +// CHECK:STDOUT: %import_ref.3 = import_ref ir1, inst+7, unloaded +// CHECK:STDOUT: %C: type = export C, %import_ref.1 [template = constants.%C] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: class @C { +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = file.%import_ref.2 +// CHECK:STDOUT: .x = file.%import_ref.3 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: --- export_name_copy.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %C: type = class_type @C [template] +// CHECK:STDOUT: %.1: type = tuple_type () [template] +// CHECK:STDOUT: %.2: type = struct_type {.x: ()} [template] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .C = %C +// CHECK:STDOUT: } +// CHECK:STDOUT: %import_ref.1: type = import_ref ir1, inst+1, loaded [template = constants.%C] +// CHECK:STDOUT: %import_ref.2 = import_ref ir1, inst+2, unloaded +// CHECK:STDOUT: %import_ref.3 = import_ref ir1, inst+7, unloaded +// CHECK:STDOUT: %C: type = export C, %import_ref.1 [template = constants.%C] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: class @C { +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = file.%import_ref.2 +// CHECK:STDOUT: .x = file.%import_ref.3 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: --- fail_todo_use_export_import.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %.1: type = tuple_type () [template] +// CHECK:STDOUT: %.2: type = struct_type {.x: ()} [template] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .Other = %Other +// CHECK:STDOUT: .c = %c +// CHECK:STDOUT: } +// CHECK:STDOUT: %Other: = namespace [template] {} +// CHECK:STDOUT: %Other.ref: = name_ref Other, %Other [template = %Other] +// CHECK:STDOUT: %C.ref: = name_ref C, [template = ] +// CHECK:STDOUT: %c.var: ref = var c +// CHECK:STDOUT: %c: ref = bind_name c, %c.var +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @__global_init() { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %.loc10_25: () = tuple_literal () +// CHECK:STDOUT: %.loc10_26: {.x: ()} = struct_literal (%.loc10_25) +// CHECK:STDOUT: assign file.%c.var, +// CHECK:STDOUT: return +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: --- fail_todo_use_export_import_both.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %.1: type = tuple_type () [template] +// CHECK:STDOUT: %.2: type = struct_type {.x: ()} [template] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .Other = %Other +// CHECK:STDOUT: .c = %c +// CHECK:STDOUT: } +// CHECK:STDOUT: %Other: = namespace [template] {} +// CHECK:STDOUT: %Other.ref: = name_ref Other, %Other [template = %Other] +// CHECK:STDOUT: %C.ref: = name_ref C, [template = ] +// CHECK:STDOUT: %c.var: ref = var c +// CHECK:STDOUT: %c: ref = bind_name c, %c.var +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @__global_init() { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %.loc11_25: () = tuple_literal () +// CHECK:STDOUT: %.loc11_26: {.x: ()} = struct_literal (%.loc11_25) +// CHECK:STDOUT: assign file.%c.var, +// CHECK:STDOUT: return +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: --- use_export_name.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %C: type = class_type @C [template] +// CHECK:STDOUT: %.1: type = tuple_type () [template] +// CHECK:STDOUT: %.2: type = struct_type {.x: ()} [template] +// CHECK:STDOUT: %.3: type = ptr_type {.x: ()} [template] +// CHECK:STDOUT: %tuple: () = tuple_value () [template] +// CHECK:STDOUT: %struct: C = struct_value (%tuple) [template] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .Other = %Other +// CHECK:STDOUT: .c = %c +// CHECK:STDOUT: } +// CHECK:STDOUT: %Other: = namespace [template] {} +// CHECK:STDOUT: %Other.ref: = name_ref Other, %Other [template = %Other] +// CHECK:STDOUT: %import_ref.1: type = import_ref ir1, inst+10, loaded [template = constants.%C] +// CHECK:STDOUT: %import_ref.2 = import_ref ir1, inst+8, unloaded +// CHECK:STDOUT: %import_ref.3 = import_ref ir1, inst+9, 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 { +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = file.%import_ref.2 +// CHECK:STDOUT: .x = file.%import_ref.3 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @__global_init() { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %.loc6_25.1: () = tuple_literal () +// CHECK:STDOUT: %.loc6_26.1: {.x: ()} = struct_literal (%.loc6_25.1) +// CHECK:STDOUT: %.loc6_26.2: ref () = class_element_access file.%c.var, element0 +// CHECK:STDOUT: %.loc6_25.2: init () = tuple_init () to %.loc6_26.2 [template = constants.%tuple] +// CHECK:STDOUT: %.loc6_26.3: init () = converted %.loc6_25.1, %.loc6_25.2 [template = constants.%tuple] +// CHECK:STDOUT: %.loc6_26.4: init C = class_init (%.loc6_26.3), file.%c.var [template = constants.%struct] +// CHECK:STDOUT: %.loc6_27: init C = converted %.loc6_26.1, %.loc6_26.4 [template = constants.%struct] +// CHECK:STDOUT: assign file.%c.var, %.loc6_27 +// CHECK:STDOUT: return +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: --- fail_todo_use_export_name_both.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %C: type = class_type @C [template] +// CHECK:STDOUT: %.1: type = tuple_type () [template] +// CHECK:STDOUT: %.2: type = struct_type {.x: ()} [template] +// CHECK:STDOUT: %.3: type = ptr_type {.x: ()} [template] +// CHECK:STDOUT: %tuple: () = tuple_value () [template] +// CHECK:STDOUT: %struct: C = struct_value (%tuple) [template] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .Other = %Other +// CHECK:STDOUT: .c = %c +// CHECK:STDOUT: } +// CHECK:STDOUT: %Other: = namespace [template] {} +// CHECK:STDOUT: %Other.ref: = name_ref Other, %Other [template = %Other] +// CHECK:STDOUT: %import_ref.1: type = import_ref ir1, inst+10, loaded [template = constants.%C] +// CHECK:STDOUT: %import_ref.2 = import_ref ir1, inst+8, unloaded +// CHECK:STDOUT: %import_ref.3 = import_ref ir1, inst+9, unloaded +// CHECK:STDOUT: %import_ref.4 = import_ref ir2, inst+10, 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 { +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = file.%import_ref.2 +// CHECK:STDOUT: .x = file.%import_ref.3 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @__global_init() { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %.loc29_25.1: () = tuple_literal () +// CHECK:STDOUT: %.loc29_26.1: {.x: ()} = struct_literal (%.loc29_25.1) +// CHECK:STDOUT: %.loc29_26.2: ref () = class_element_access file.%c.var, element0 +// CHECK:STDOUT: %.loc29_25.2: init () = tuple_init () to %.loc29_26.2 [template = constants.%tuple] +// CHECK:STDOUT: %.loc29_26.3: init () = converted %.loc29_25.1, %.loc29_25.2 [template = constants.%tuple] +// CHECK:STDOUT: %.loc29_26.4: init C = class_init (%.loc29_26.3), file.%c.var [template = constants.%struct] +// CHECK:STDOUT: %.loc29_27: init C = converted %.loc29_26.1, %.loc29_26.4 [template = constants.%struct] +// CHECK:STDOUT: assign file.%c.var, %.loc29_27 +// CHECK:STDOUT: return +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: --- fail_todo_use_export_all.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %C: type = class_type @C [template] +// CHECK:STDOUT: %.1: type = tuple_type () [template] +// CHECK:STDOUT: %.2: type = struct_type {.x: ()} [template] +// CHECK:STDOUT: %.3: type = ptr_type {.x: ()} [template] +// CHECK:STDOUT: %tuple: () = tuple_value () [template] +// CHECK:STDOUT: %struct: C = struct_value (%tuple) [template] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .Other = %Other +// CHECK:STDOUT: .c = %c +// CHECK:STDOUT: } +// 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+10, loaded [template = constants.%C] +// CHECK:STDOUT: %import_ref.2 = import_ref ir2, inst+8, unloaded +// CHECK:STDOUT: %import_ref.3 = import_ref ir2, inst+9, unloaded +// CHECK:STDOUT: %import_ref.4 = import_ref ir4, inst+10, 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 { +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = file.%import_ref.2 +// CHECK:STDOUT: .x = file.%import_ref.3 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @__global_init() { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %.loc30_25.1: () = tuple_literal () +// CHECK:STDOUT: %.loc30_26.1: {.x: ()} = struct_literal (%.loc30_25.1) +// CHECK:STDOUT: %.loc30_26.2: ref () = class_element_access file.%c.var, element0 +// CHECK:STDOUT: %.loc30_25.2: init () = tuple_init () to %.loc30_26.2 [template = constants.%tuple] +// CHECK:STDOUT: %.loc30_26.3: init () = converted %.loc30_25.1, %.loc30_25.2 [template = constants.%tuple] +// CHECK:STDOUT: %.loc30_26.4: init C = class_init (%.loc30_26.3), file.%c.var [template = constants.%struct] +// CHECK:STDOUT: %.loc30_27: init C = converted %.loc30_26.1, %.loc30_26.4 [template = constants.%struct] +// CHECK:STDOUT: assign file.%c.var, %.loc30_27 +// CHECK:STDOUT: return +// CHECK:STDOUT: } +// CHECK:STDOUT: diff --git a/toolchain/check/testdata/packages/no_prelude/export_mixed.carbon b/toolchain/check/testdata/packages/no_prelude/export_mixed.carbon index 72e4bfc74290..83efcf38a999 100644 --- a/toolchain/check/testdata/packages/no_prelude/export_mixed.carbon +++ b/toolchain/check/testdata/packages/no_prelude/export_mixed.carbon @@ -171,8 +171,8 @@ var d: D = {.y = ()}; // CHECK:STDOUT: // CHECK:STDOUT: file { // CHECK:STDOUT: package: = namespace [template] { -// CHECK:STDOUT: .C = %import_ref.1 // CHECK:STDOUT: .D = %import_ref.2 +// CHECK:STDOUT: .C = %C // CHECK:STDOUT: } // CHECK:STDOUT: %import_ref.1: type = import_ref ir2, inst+1, loaded [template = constants.%C] // CHECK:STDOUT: %import_ref.2 = import_ref ir2, inst+11, unloaded @@ -197,8 +197,8 @@ var d: D = {.y = ()}; // CHECK:STDOUT: // CHECK:STDOUT: file { // CHECK:STDOUT: package: = namespace [template] { -// CHECK:STDOUT: .C = %import_ref.1 // CHECK:STDOUT: .D = %import_ref.2 +// CHECK:STDOUT: .C = %C // CHECK:STDOUT: } // CHECK:STDOUT: %import_ref.1: type = import_ref ir1, inst+1, loaded [template = constants.%C] // CHECK:STDOUT: %import_ref.2 = import_ref ir1, inst+11, unloaded diff --git a/toolchain/check/testdata/packages/no_prelude/export_name.carbon b/toolchain/check/testdata/packages/no_prelude/export_name.carbon index 8a58a1a678cb..7f32a4d69427 100644 --- a/toolchain/check/testdata/packages/no_prelude/export_name.carbon +++ b/toolchain/check/testdata/packages/no_prelude/export_name.carbon @@ -169,6 +169,13 @@ library "repeat_export"; import library "base"; export C; +// CHECK:STDERR: repeat_export.carbon:[[@LINE+7]]:1: WARNING: `export` matches previous `export`. +// CHECK:STDERR: export C; +// CHECK:STDERR: ^~~~~~~~~ +// CHECK:STDERR: repeat_export.carbon:[[@LINE-4]]:1: Previous `export` here. +// CHECK:STDERR: export C; +// CHECK:STDERR: ^~~~~~~~~ +// CHECK:STDERR: export C; // --- use_repeat_export.carbon @@ -246,13 +253,13 @@ private export C; // CHECK:STDOUT: // CHECK:STDOUT: file { // CHECK:STDOUT: package: = namespace [template] { -// CHECK:STDOUT: .C = %import_ref.1 // CHECK:STDOUT: .NS = %NS +// CHECK:STDOUT: .C = %C // CHECK:STDOUT: } // CHECK:STDOUT: %import_ref.1: type = import_ref ir1, inst+1, loaded [template = constants.%C] // CHECK:STDOUT: %import_ref.2: = import_ref ir1, inst+11, loaded // CHECK:STDOUT: %NS: = namespace %import_ref.2, [template] { -// CHECK:STDOUT: .NSC = %import_ref.3 +// CHECK:STDOUT: .NSC = %NSC // CHECK:STDOUT: } // CHECK:STDOUT: %import_ref.3: type = import_ref ir1, inst+12, loaded [template = constants.%NSC] // CHECK:STDOUT: %import_ref.4 = import_ref ir1, inst+7, unloaded @@ -302,13 +309,13 @@ private export C; // CHECK:STDOUT: // CHECK:STDOUT: file { // CHECK:STDOUT: package: = namespace [template] { -// CHECK:STDOUT: .C = %import_ref.1 // CHECK:STDOUT: .NS = %NS +// CHECK:STDOUT: .C = %C // CHECK:STDOUT: } // CHECK:STDOUT: %import_ref.1: type = import_ref ir1, inst+13, loaded [template = constants.%C] // CHECK:STDOUT: %import_ref.2: = import_ref ir1, inst+3, loaded // CHECK:STDOUT: %NS: = namespace %import_ref.2, [template] { -// CHECK:STDOUT: .NSC = %import_ref.3 +// CHECK:STDOUT: .NSC = %NSC // CHECK:STDOUT: } // CHECK:STDOUT: %import_ref.3: type = import_ref ir1, inst+21, loaded [template = constants.%NSC] // CHECK:STDOUT: %import_ref.4 = import_ref ir1, inst+12, unloaded @@ -793,8 +800,8 @@ private export C; // CHECK:STDOUT: // CHECK:STDOUT: file { // CHECK:STDOUT: package: = namespace [template] { -// CHECK:STDOUT: .C = %import_ref.1 // CHECK:STDOUT: .NS = %NS +// CHECK:STDOUT: .C = %C // CHECK:STDOUT: } // CHECK:STDOUT: %import_ref.1: type = import_ref ir1, inst+1, loaded [template = constants.%C] // CHECK:STDOUT: %import_ref.2: = import_ref ir1, inst+11, loaded @@ -804,8 +811,7 @@ private export C; // CHECK:STDOUT: %import_ref.3 = import_ref ir1, inst+12, unloaded // CHECK:STDOUT: %import_ref.4 = import_ref ir1, inst+7, unloaded // CHECK:STDOUT: %import_ref.5 = import_ref ir1, inst+2, unloaded -// CHECK:STDOUT: %C.loc6: type = export C, %import_ref.1 [template = constants.%C] -// CHECK:STDOUT: %C.loc7: type = export C, %import_ref.1 [template = constants.%C] +// CHECK:STDOUT: %C: type = export C, %import_ref.1 [template = constants.%C] // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: class @C { @@ -867,8 +873,8 @@ private export C; // CHECK:STDOUT: // CHECK:STDOUT: file { // CHECK:STDOUT: package: = namespace [template] { -// CHECK:STDOUT: .C = %import_ref.1 // CHECK:STDOUT: .NS = %NS +// CHECK:STDOUT: .C = %C // CHECK:STDOUT: } // CHECK:STDOUT: %import_ref.1: type = import_ref ir1, inst+1, loaded [template = constants.%C] // CHECK:STDOUT: %import_ref.2: = import_ref ir1, inst+11, loaded diff --git a/toolchain/check/testdata/var/no_prelude/export_name.carbon b/toolchain/check/testdata/var/no_prelude/export_name.carbon index c7768fb92f38..736ebeb7321d 100644 --- a/toolchain/check/testdata/var/no_prelude/export_name.carbon +++ b/toolchain/check/testdata/var/no_prelude/export_name.carbon @@ -67,7 +67,7 @@ var w: () = v; // CHECK:STDOUT: // CHECK:STDOUT: file { // CHECK:STDOUT: package: = namespace [template] { -// CHECK:STDOUT: .v = %import_ref +// CHECK:STDOUT: .v = %v // CHECK:STDOUT: } // CHECK:STDOUT: %import_ref: ref () = import_ref ir1, inst+5, loaded // CHECK:STDOUT: %v: ref () = export v, %import_ref diff --git a/toolchain/diagnostics/diagnostic_kind.def b/toolchain/diagnostics/diagnostic_kind.def index ee89f8217cd8..fc923fbabd52 100644 --- a/toolchain/diagnostics/diagnostic_kind.def +++ b/toolchain/diagnostics/diagnostic_kind.def @@ -203,6 +203,8 @@ CARBON_DIAGNOSTIC_KIND(ConstructionOfAbstractClass) // Export checking. CARBON_DIAGNOSTIC_KIND(ExportNotImportedEntity) CARBON_DIAGNOSTIC_KIND(ExportNotImportedEntitySource) +CARBON_DIAGNOSTIC_KIND(ExportRedundant) +CARBON_DIAGNOSTIC_KIND(ExportPrevious) // Interface checking. CARBON_DIAGNOSTIC_KIND(InterfacePreviousDefinition)