From: Pierre-Emmanuel Patry <pierre-emmanuel.pa...@embecosm.com> 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> --- .../rust-toplevel-name-resolver-2.0.cc | 76 ++++++++++--------- .../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 407892bb7bb..94cc3cb62d9 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 ac11f310370..0a766bab259 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 ¯o) override; void visit (AST::Function &function) override; -- 2.45.2