https://gcc.gnu.org/g:8a5a1b4d61179b5af345e6765bd933a6af1243b3

commit 8a5a1b4d61179b5af345e6765bd933a6af1243b3
Author: Pierre-Emmanuel Patry <pierre-emmanuel.pa...@embecosm.com>
Date:   Fri Sep 15 13:14:56 2023 +0200

    Emit error on identical use declarations
    
    The compiler did not emit any warning when a same target was declared
    from different sources.
    
    gcc/rust/ChangeLog:
    
            * resolve/rust-toplevel-name-resolver-2.0.cc 
(TopLevel::handle_use_dec):
            Use the new dict to track down already resolved use declarations.
            * resolve/rust-toplevel-name-resolver-2.0.h: Add new dict to store
            previous use declarations.
    
    Signed-off-by: Pierre-Emmanuel Patry <pierre-emmanuel.pa...@embecosm.com>

Diff:
---
 .../resolve/rust-toplevel-name-resolver-2.0.cc     | 76 ++++++++++++----------
 gcc/rust/resolve/rust-toplevel-name-resolver-2.0.h |  4 ++
 2 files changed, 46 insertions(+), 34 deletions(-)

diff --git a/gcc/rust/resolve/rust-toplevel-name-resolver-2.0.cc 
b/gcc/rust/resolve/rust-toplevel-name-resolver-2.0.cc
index 407892bb7bbd..94cc3cb62d94 100644
--- a/gcc/rust/resolve/rust-toplevel-name-resolver-2.0.cc
+++ b/gcc/rust/resolve/rust-toplevel-name-resolver-2.0.cc
@@ -319,40 +319,48 @@ TopLevel::handle_use_dec (AST::SimplePath path)
 
   auto found = false;
 
-  auto resolve_and_insert = [this, &found, &declared_name,
-                            locus] (Namespace ns,
-                                    const AST::SimplePath &path) {
-    tl::optional<NodeId> resolved = tl::nullopt;
-
-    // FIXME: resolve_path needs to return an `expected<NodeId, Error>` so
-    // that we can improve it with hints or location or w/ever. and maybe
-    // only emit it the first time.
-    switch (ns)
-      {
-      case Namespace::Values:
-       resolved = ctx.values.resolve_path (path.get_segments ());
-       break;
-      case Namespace::Types:
-       resolved = ctx.types.resolve_path (path.get_segments ());
-       break;
-      case Namespace::Macros:
-       resolved = ctx.macros.resolve_path (path.get_segments ());
-       break;
-      case Namespace::Labels:
-       // TODO: Is that okay?
-       rust_unreachable ();
-      }
-
-    // FIXME: Ugly
-    (void) resolved.map ([this, &found, &declared_name, locus, ns] (NodeId id) 
{
-      found = true;
-
-      // what do we do with the id?
-      insert_or_error_out (declared_name, locus, id, ns);
-
-      return id;
-    });
-  };
+  auto resolve_and_insert
+    = [this, &found, &declared_name, locus] (Namespace ns,
+                                            const AST::SimplePath &path) {
+       tl::optional<NodeId> resolved = tl::nullopt;
+
+       // FIXME: resolve_path needs to return an `expected<NodeId, Error>` so
+       // that we can improve it with hints or location or w/ever. and maybe
+       // only emit it the first time.
+       switch (ns)
+         {
+         case Namespace::Values:
+           resolved = ctx.values.resolve_path (path.get_segments ());
+           break;
+         case Namespace::Types:
+           resolved = ctx.types.resolve_path (path.get_segments ());
+           break;
+         case Namespace::Macros:
+           resolved = ctx.macros.resolve_path (path.get_segments ());
+           break;
+         case Namespace::Labels:
+           // TODO: Is that okay?
+           rust_unreachable ();
+         }
+
+       // FIXME: Ugly
+       (void) resolved.map (
+         [this, &found, &declared_name, locus, ns, path] (NodeId id) {
+           found = true;
+
+           // what do we do with the id?
+           insert_or_error_out (declared_name, locus, id, ns);
+           auto result = node_forwarding.find (id);
+           if (result != node_forwarding.cend ()
+               && result->second != path.get_node_id ())
+             rust_error_at (path.get_locus (), "%<%s%> defined multiple times",
+                            declared_name.c_str ());
+           else // No previous thing has inserted this into our scope
+             node_forwarding.insert ({id, path.get_node_id ()});
+
+           return id;
+         });
+      };
 
   // do this for all namespaces (even Labels?)
 
diff --git a/gcc/rust/resolve/rust-toplevel-name-resolver-2.0.h 
b/gcc/rust/resolve/rust-toplevel-name-resolver-2.0.h
index ac11f3103708..0a766bab2598 100644
--- a/gcc/rust/resolve/rust-toplevel-name-resolver-2.0.h
+++ b/gcc/rust/resolve/rust-toplevel-name-resolver-2.0.h
@@ -60,6 +60,10 @@ private:
   // FIXME: Do we move these to our mappings?
   std::unordered_map<NodeId, location_t> node_locations;
 
+  // Store node forwarding for use declaration, the link between a
+  // "new" local name and its definition.
+  std::unordered_map<NodeId, NodeId> node_forwarding;
+
   void visit (AST::Module &module) override;
   void visit (AST::MacroRulesDefinition &macro) override;
   void visit (AST::Function &function) override;

Reply via email to