Преглед изворни кода

Add the used name to the `NameUseBeforeDecl` diagnostic (#4901)

Part of #4622.
Boaz Brickner пре 1 година
родитељ
комит
4a93b6667e

+ 2 - 2
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 {

+ 1 - 1
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:

+ 2 - 2
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;
   }
 

+ 2 - 2
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,

+ 2 - 2
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 =

+ 2 - 2
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 =

+ 4 - 3
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();
 }

+ 2 - 1
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.

+ 1 - 1
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;

+ 16 - 16
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;

+ 1 - 1
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*) {}