diff --git a/toolchain/check/decl_name_stack.cpp b/toolchain/check/decl_name_stack.cpp index cf5b4bedb2a0..35ce1c1053c1 100644 --- a/toolchain/check/decl_name_stack.cpp +++ b/toolchain/check/decl_name_stack.cpp @@ -177,8 +177,8 @@ auto DeclNameStack::AddNameOrDiagnose(NameContext name_context, SemIR::InstId target_id, SemIR::AccessKind access_kind) -> void { if (name_context.state == DeclNameStack::NameContext::State::Poisoned) { - DiagnosePoisonedName(*context_, name_context.poisoning_loc_id, - name_context.loc_id); + DiagnosePoisonedName(*context_, name_context.name_id_for_new_inst(), + name_context.poisoning_loc_id, name_context.loc_id); } else if (auto id = name_context.prev_inst_id(); id.has_value()) { DiagnoseDuplicateName(*context_, name_context.loc_id, id); } else { diff --git a/toolchain/check/decl_name_stack.h b/toolchain/check/decl_name_stack.h index 7a3f93d1d210..4d4cbea93e46 100644 --- a/toolchain/check/decl_name_stack.h +++ b/toolchain/check/decl_name_stack.h @@ -121,7 +121,7 @@ class DeclNameStack { // Returns the name_id for a new instruction. This is `None` when the name // resolved. - auto name_id_for_new_inst() -> SemIR::NameId { + auto name_id_for_new_inst() const -> SemIR::NameId { switch (state) { case State::Unresolved: case State::Poisoned: diff --git a/toolchain/check/handle_class.cpp b/toolchain/check/handle_class.cpp index e3c459a0ff42..e543d06cc8d9 100644 --- a/toolchain/check/handle_class.cpp +++ b/toolchain/check/handle_class.cpp @@ -114,8 +114,8 @@ static auto MergeOrAddName(Context& context, Parse::AnyClassDeclId node_id, access_kind); if (lookup_result.is_poisoned()) { // This is a declaration of a poisoned name. - DiagnosePoisonedName(context, lookup_result.poisoning_loc_id(), - name_context.loc_id); + DiagnosePoisonedName(context, name_context.name_id_for_new_inst(), + lookup_result.poisoning_loc_id(), name_context.loc_id); return; } diff --git a/toolchain/check/handle_function.cpp b/toolchain/check/handle_function.cpp index 4f95754d637d..b6a38246c6e1 100644 --- a/toolchain/check/handle_function.cpp +++ b/toolchain/check/handle_function.cpp @@ -293,8 +293,8 @@ static auto BuildFunctionDecl(Context& context, } if (name_context.state == DeclNameStack::NameContext::State::Poisoned) { - DiagnosePoisonedName(context, name_context.poisoning_loc_id, - name_context.loc_id); + DiagnosePoisonedName(context, name_context.name_id_for_new_inst(), + name_context.poisoning_loc_id, name_context.loc_id); } else { TryMergeRedecl(context, node_id, name_context.prev_inst_id(), name_context.loc_id, function_decl, function_info, diff --git a/toolchain/check/handle_interface.cpp b/toolchain/check/handle_interface.cpp index f1e6db9aaab8..79a92f27c8c1 100644 --- a/toolchain/check/handle_interface.cpp +++ b/toolchain/check/handle_interface.cpp @@ -68,8 +68,8 @@ static auto BuildInterfaceDecl(Context& context, introducer.modifier_set.GetAccessKind()); if (lookup_result.is_poisoned()) { // This is a declaration of a poisoned name. - DiagnosePoisonedName(context, lookup_result.poisoning_loc_id(), - name_context.loc_id); + DiagnosePoisonedName(context, name_context.name_id_for_new_inst(), + lookup_result.poisoning_loc_id(), name_context.loc_id); } else if (lookup_result.is_found()) { SemIR::InstId existing_id = lookup_result.target_inst_id(); if (auto existing_interface_decl = diff --git a/toolchain/check/handle_namespace.cpp b/toolchain/check/handle_namespace.cpp index d8784efc6e01..43e87a1c08e3 100644 --- a/toolchain/check/handle_namespace.cpp +++ b/toolchain/check/handle_namespace.cpp @@ -49,8 +49,8 @@ auto HandleParseNode(Context& context, Parse::NamespaceId node_id) -> bool { context.decl_name_stack().LookupOrAddName(name_context, namespace_id, SemIR::AccessKind::Public); if (lookup_result.is_poisoned()) { - DiagnosePoisonedName(context, lookup_result.poisoning_loc_id(), - name_context.loc_id); + DiagnosePoisonedName(context, name_context.name_id_for_new_inst(), + lookup_result.poisoning_loc_id(), name_context.loc_id); } else if (lookup_result.is_found()) { SemIR::InstId existing_inst_id = lookup_result.target_inst_id(); if (auto existing = diff --git a/toolchain/check/name_lookup.cpp b/toolchain/check/name_lookup.cpp index 6d42f2c74799..dfb4460927b2 100644 --- a/toolchain/check/name_lookup.cpp +++ b/toolchain/check/name_lookup.cpp @@ -495,15 +495,16 @@ auto DiagnoseDuplicateName(Context& context, SemIRLoc dup_def, .Emit(); } -auto DiagnosePoisonedName(Context& context, SemIR::LocId poisoning_loc_id, +auto DiagnosePoisonedName(Context& context, SemIR::NameId name_id, + SemIR::LocId poisoning_loc_id, SemIR::LocId decl_name_loc_id) -> void { CARBON_CHECK(poisoning_loc_id.has_value(), "Trying to diagnose poisoned name with no poisoning location"); CARBON_DIAGNOSTIC(NameUseBeforeDecl, Error, - "name used before it was declared"); + "name `{0}` used before it was declared", SemIR::NameId); CARBON_DIAGNOSTIC(NameUseBeforeDeclNote, Note, "declared here"); context.emitter() - .Build(poisoning_loc_id, NameUseBeforeDecl) + .Build(poisoning_loc_id, NameUseBeforeDecl, name_id) .Note(decl_name_loc_id, NameUseBeforeDeclNote) .Emit(); } diff --git a/toolchain/check/name_lookup.h b/toolchain/check/name_lookup.h index 5427c9e578d3..e6751e2191ee 100644 --- a/toolchain/check/name_lookup.h +++ b/toolchain/check/name_lookup.h @@ -104,7 +104,8 @@ auto DiagnoseDuplicateName(Context& context, SemIRLoc dup_def, SemIRLoc prev_def) -> void; // Prints a diagnostic for a poisoned name when it's later declared. -auto DiagnosePoisonedName(Context& context, SemIR::LocId poisoning_loc_id, +auto DiagnosePoisonedName(Context& context, SemIR::NameId name_id, + SemIR::LocId poisoning_loc_id, SemIR::LocId decl_name_loc_id) -> void; // Prints a diagnostic for a missing name. diff --git a/toolchain/check/testdata/class/no_prelude/name_poisoning.carbon b/toolchain/check/testdata/class/no_prelude/name_poisoning.carbon index 88f5bb984cd8..ab2fc9765906 100644 --- a/toolchain/check/testdata/class/no_prelude/name_poisoning.carbon +++ b/toolchain/check/testdata/class/no_prelude/name_poisoning.carbon @@ -17,7 +17,7 @@ library "[[@TEST_NAME]]"; base class B {} class C { - // CHECK:STDERR: fail_extend_poison_class_members.carbon:[[@LINE+3]]:16: error: name used before it was declared [NameUseBeforeDecl] + // CHECK:STDERR: fail_extend_poison_class_members.carbon:[[@LINE+3]]:16: error: name `B` used before it was declared [NameUseBeforeDecl] // CHECK:STDERR: extend base: B; // CHECK:STDERR: ^ extend base: B; diff --git a/toolchain/check/testdata/function/declaration/no_prelude/name_poisoning.carbon b/toolchain/check/testdata/function/declaration/no_prelude/name_poisoning.carbon index d014bb5d8cbb..741b80f776d6 100644 --- a/toolchain/check/testdata/function/declaration/no_prelude/name_poisoning.carbon +++ b/toolchain/check/testdata/function/declaration/no_prelude/name_poisoning.carbon @@ -38,7 +38,7 @@ class C {}; namespace N; // Here we use C and poison N.C. -// CHECK:STDERR: fail_poison_class_without_usage.carbon:[[@LINE+3]]:12: error: name used before it was declared [NameUseBeforeDecl] +// CHECK:STDERR: fail_poison_class_without_usage.carbon:[[@LINE+3]]:12: error: name `C` used before it was declared [NameUseBeforeDecl] // CHECK:STDERR: fn N.F1(x: C); // CHECK:STDERR: ^ fn N.F1(x: C); @@ -59,7 +59,7 @@ interface I {}; namespace N; // Here we use I and poison N.I. -// CHECK:STDERR: fail_poison_interface_without_usage.carbon:[[@LINE+3]]:12: error: name used before it was declared [NameUseBeforeDecl] +// CHECK:STDERR: fail_poison_interface_without_usage.carbon:[[@LINE+3]]:12: error: name `I` used before it was declared [NameUseBeforeDecl] // CHECK:STDERR: fn N.F1(x: I); // CHECK:STDERR: ^ fn N.F1(x: I); @@ -80,7 +80,7 @@ class C {}; namespace N; // Here we use C and poison N.C. -// CHECK:STDERR: fail_poison_namespace_without_usage.carbon:[[@LINE+3]]:12: error: name used before it was declared [NameUseBeforeDecl] +// CHECK:STDERR: fail_poison_namespace_without_usage.carbon:[[@LINE+3]]:12: error: name `C` used before it was declared [NameUseBeforeDecl] // CHECK:STDERR: fn N.F1(x: C); // CHECK:STDERR: ^ fn N.F1(x: C); @@ -101,7 +101,7 @@ class C1 {}; class D { // Here we use C1 and poison D.C1. - // CHECK:STDERR: fail_poison_member_without_usage.carbon:[[@LINE+3]]:12: error: name used before it was declared [NameUseBeforeDecl] + // CHECK:STDERR: fail_poison_member_without_usage.carbon:[[@LINE+3]]:12: error: name `C1` used before it was declared [NameUseBeforeDecl] // CHECK:STDERR: fn F1(x: C1); // CHECK:STDERR: ^~ fn F1(x: C1); @@ -124,7 +124,7 @@ class C {}; namespace N; // Here we use C and poison N.C. -// CHECK:STDERR: fail_poison_function_without_usage.carbon:[[@LINE+3]]:12: error: name used before it was declared [NameUseBeforeDecl] +// CHECK:STDERR: fail_poison_function_without_usage.carbon:[[@LINE+3]]:12: error: name `C` used before it was declared [NameUseBeforeDecl] // CHECK:STDERR: fn N.F1(x: C); // CHECK:STDERR: ^ fn N.F1(x: C); @@ -162,7 +162,7 @@ class C {}; namespace N; // Here we use C and poison N.C. -// CHECK:STDERR: fail_poison_with_usage.carbon:[[@LINE+3]]:12: error: name used before it was declared [NameUseBeforeDecl] +// CHECK:STDERR: fail_poison_with_usage.carbon:[[@LINE+3]]:12: error: name `C` used before it was declared [NameUseBeforeDecl] // CHECK:STDERR: fn N.F1(x: C); // CHECK:STDERR: ^ fn N.F1(x: C); @@ -198,7 +198,7 @@ class N1.N2.N3.D1 { // * N1.N2.N3.D1.C // * N1.N2.N3.D1.D2.C // * N1.N2.N3.D1.D2.D3.C - // CHECK:STDERR: fail_poison_multiple_scopes.carbon:[[@LINE+3]]:15: error: name used before it was declared [NameUseBeforeDecl] + // CHECK:STDERR: fail_poison_multiple_scopes.carbon:[[@LINE+3]]:15: error: name `C` used before it was declared [NameUseBeforeDecl] // CHECK:STDERR: fn F(x: C); // CHECK:STDERR: ^ fn F(x: C); @@ -207,7 +207,7 @@ class N1.N2.N3.D1 { // CHECK:STDERR: class C {} // CHECK:STDERR: ^ // CHECK:STDERR: - // CHECK:STDERR: fail_poison_multiple_scopes.carbon:[[@LINE-6]]:15: error: name used before it was declared [NameUseBeforeDecl] + // CHECK:STDERR: fail_poison_multiple_scopes.carbon:[[@LINE-6]]:15: error: name `C` used before it was declared [NameUseBeforeDecl] // CHECK:STDERR: fn F(x: C); // CHECK:STDERR: ^ class C {} @@ -216,7 +216,7 @@ class N1.N2.N3.D1 { // CHECK:STDERR: class C {} // CHECK:STDERR: ^ // CHECK:STDERR: - // CHECK:STDERR: fail_poison_multiple_scopes.carbon:[[@LINE-15]]:15: error: name used before it was declared [NameUseBeforeDecl] + // CHECK:STDERR: fail_poison_multiple_scopes.carbon:[[@LINE-15]]:15: error: name `C` used before it was declared [NameUseBeforeDecl] // CHECK:STDERR: fn F(x: C); // CHECK:STDERR: ^ class C {} @@ -225,7 +225,7 @@ class N1.N2.N3.D1 { // CHECK:STDERR: class C {} // CHECK:STDERR: ^ // CHECK:STDERR: - // CHECK:STDERR: fail_poison_multiple_scopes.carbon:[[@LINE-24]]:15: error: name used before it was declared [NameUseBeforeDecl] + // CHECK:STDERR: fail_poison_multiple_scopes.carbon:[[@LINE-24]]:15: error: name `C` used before it was declared [NameUseBeforeDecl] // CHECK:STDERR: fn F(x: C); // CHECK:STDERR: ^ class C {} @@ -235,7 +235,7 @@ class N1.N2.N3.D1 { // CHECK:STDERR: class N1.C {} // CHECK:STDERR: ^ // CHECK:STDERR: -// CHECK:STDERR: fail_poison_multiple_scopes.carbon:[[@LINE-34]]:15: error: name used before it was declared [NameUseBeforeDecl] +// CHECK:STDERR: fail_poison_multiple_scopes.carbon:[[@LINE-34]]:15: error: name `C` used before it was declared [NameUseBeforeDecl] // CHECK:STDERR: fn F(x: C); // CHECK:STDERR: ^ class N1.C {} @@ -244,7 +244,7 @@ class N1.C {} // CHECK:STDERR: interface N1.N2.C {} // CHECK:STDERR: ^ // CHECK:STDERR: -// CHECK:STDERR: fail_poison_multiple_scopes.carbon:[[@LINE-43]]:15: error: name used before it was declared [NameUseBeforeDecl] +// CHECK:STDERR: fail_poison_multiple_scopes.carbon:[[@LINE-43]]:15: error: name `C` used before it was declared [NameUseBeforeDecl] // CHECK:STDERR: fn F(x: C); // CHECK:STDERR: ^ interface N1.N2.C {} @@ -262,7 +262,7 @@ library "[[@TEST_NAME]]"; class C {} namespace N; -// CHECK:STDERR: fail_alias.carbon:[[@LINE+7]]:13: error: name used before it was declared [NameUseBeforeDecl] +// CHECK:STDERR: fail_alias.carbon:[[@LINE+7]]:13: error: name `C` used before it was declared [NameUseBeforeDecl] // CHECK:STDERR: alias N.C = C; // CHECK:STDERR: ^ // CHECK:STDERR: fail_alias.carbon:[[@LINE+4]]:9: note: declared here [NameUseBeforeDeclNote] @@ -310,7 +310,7 @@ namespace N; // CHECK:STDERR: fn N.F(x: C); // CHECK:STDERR: ^ // CHECK:STDERR: -// CHECK:STDERR: fail_poison_when_lookup_fails.carbon:[[@LINE+3]]:11: error: name used before it was declared [NameUseBeforeDecl] +// CHECK:STDERR: fail_poison_when_lookup_fails.carbon:[[@LINE+3]]:11: error: name `C` used before it was declared [NameUseBeforeDecl] // CHECK:STDERR: fn N.F(x: C); // CHECK:STDERR: ^ fn N.F(x: C); @@ -320,7 +320,7 @@ fn N.F(x: C); // CHECK:STDERR: class C {} // CHECK:STDERR: ^ // CHECK:STDERR: -// CHECK:STDERR: fail_poison_when_lookup_fails.carbon:[[@LINE-7]]:11: error: name used before it was declared [NameUseBeforeDecl] +// CHECK:STDERR: fail_poison_when_lookup_fails.carbon:[[@LINE-7]]:11: error: name `C` used before it was declared [NameUseBeforeDecl] // CHECK:STDERR: fn N.F(x: C); // CHECK:STDERR: ^ class C {} @@ -338,7 +338,7 @@ fn F() { class A {} class B { - // CHECK:STDERR: fail_poison_with_lexical_result.carbon:[[@LINE+3]]:12: error: name used before it was declared [NameUseBeforeDecl] + // CHECK:STDERR: fail_poison_with_lexical_result.carbon:[[@LINE+3]]:12: error: name `A` used before it was declared [NameUseBeforeDecl] // CHECK:STDERR: var v: A; // CHECK:STDERR: ^ var v: A; diff --git a/toolchain/check/testdata/interface/no_prelude/import_access.carbon b/toolchain/check/testdata/interface/no_prelude/import_access.carbon index 946dacc99fd1..844acd6d6ecc 100644 --- a/toolchain/check/testdata/interface/no_prelude/import_access.carbon +++ b/toolchain/check/testdata/interface/no_prelude/import_access.carbon @@ -105,7 +105,7 @@ impl package Test library "[[@TEST_NAME]]"; // CHECK:STDERR: fn F(i: Forward*) {} // CHECK:STDERR: ^~~~~~~ // CHECK:STDERR: -// CHECK:STDERR: fail_todo_forward.impl.carbon:[[@LINE+3]]:9: error: name used before it was declared [NameUseBeforeDecl] +// CHECK:STDERR: fail_todo_forward.impl.carbon:[[@LINE+3]]:9: error: name `Forward` used before it was declared [NameUseBeforeDecl] // CHECK:STDERR: fn F(i: Forward*) {} // CHECK:STDERR: ^~~~~~~ fn F(i: Forward*) {}