diff options
author | Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com> | 2024-08-21 17:14:46 +0200 |
---|---|---|
committer | P-E-P <32375388+P-E-P@users.noreply.github.com> | 2024-09-26 22:48:32 +0000 |
commit | ab8a0b5cc06c23cea99124ef60d717ac198fc063 (patch) | |
tree | c061ed0002ad5305b3a6b8e52acf30bec6e5159d /gcc | |
parent | 76131dd1d561bdc2064e9f91ed19c275d09e7166 (diff) | |
download | gcc-ab8a0b5cc06c23cea99124ef60d717ac198fc063.zip gcc-ab8a0b5cc06c23cea99124ef60d717ac198fc063.tar.gz gcc-ab8a0b5cc06c23cea99124ef60d717ac198fc063.tar.bz2 |
Loop on expansion if a new export has been defined
When a use statement requires a reexported item it cannot find it in
the same pass, an additional pass shall be performed. This means we need
to detect whether a new item has been reexported and resolve until the
end.
gcc/rust/ChangeLog:
* resolve/rust-early-name-resolver-2.0.cc (Early::Early): Add dirty
flag initialization.
(Early::go): Set dirty flag using top level resolver.
* resolve/rust-early-name-resolver-2.0.h: Add dirty flag.
* resolve/rust-toplevel-name-resolver-2.0.cc (TopLevel::TopLevel):
Initialize dirty flag.
(TopLevel::insert_or_error_out): Set dirty flag on successful
namespace modification.
* resolve/rust-toplevel-name-resolver-2.0.h: Add dirty flag.
* rust-session-manager.cc (Session::expansion): Modify fixed point
condition to include name resolution modifications.
Signed-off-by: Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/rust/resolve/rust-early-name-resolver-2.0.cc | 4 | ||||
-rw-r--r-- | gcc/rust/resolve/rust-early-name-resolver-2.0.h | 4 | ||||
-rw-r--r-- | gcc/rust/resolve/rust-toplevel-name-resolver-2.0.cc | 7 | ||||
-rw-r--r-- | gcc/rust/resolve/rust-toplevel-name-resolver-2.0.h | 6 | ||||
-rw-r--r-- | gcc/rust/rust-session-manager.cc | 5 |
5 files changed, 21 insertions, 5 deletions
diff --git a/gcc/rust/resolve/rust-early-name-resolver-2.0.cc b/gcc/rust/resolve/rust-early-name-resolver-2.0.cc index fe6f576..402af27 100644 --- a/gcc/rust/resolve/rust-early-name-resolver-2.0.cc +++ b/gcc/rust/resolve/rust-early-name-resolver-2.0.cc @@ -26,7 +26,8 @@ namespace Rust { namespace Resolver2_0 { -Early::Early (NameResolutionContext &ctx) : DefaultResolver (ctx) {} +Early::Early (NameResolutionContext &ctx) : DefaultResolver (ctx), dirty (false) +{} void Early::insert_once (AST::MacroInvocation &invocation, NodeId resolved) @@ -61,6 +62,7 @@ Early::go (AST::Crate &crate) // Once this is done, we finalize their resolution FinalizeImports (std::move (import_mappings), toplevel, ctx).go (crate); + dirty = toplevel.is_dirty (); // We now proceed with resolving macros, which can be nested in almost any // items textual_scope.push (); diff --git a/gcc/rust/resolve/rust-early-name-resolver-2.0.h b/gcc/rust/resolve/rust-early-name-resolver-2.0.h index c97caaa..dd199cc 100644 --- a/gcc/rust/resolve/rust-early-name-resolver-2.0.h +++ b/gcc/rust/resolve/rust-early-name-resolver-2.0.h @@ -34,9 +34,13 @@ class Early : public DefaultResolver { using DefaultResolver::visit; + bool dirty; + public: Early (NameResolutionContext &ctx); + bool is_dirty () { return dirty; } + void go (AST::Crate &crate); const std::vector<Error> &get_macro_resolve_errors () const 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 b4b1a85..ea64e25 100644 --- a/gcc/rust/resolve/rust-toplevel-name-resolver-2.0.cc +++ b/gcc/rust/resolve/rust-toplevel-name-resolver-2.0.cc @@ -27,7 +27,7 @@ namespace Rust { namespace Resolver2_0 { TopLevel::TopLevel (NameResolutionContext &resolver) - : DefaultResolver (resolver) + : DefaultResolver (resolver), dirty (false) {} template <typename T> @@ -47,8 +47,9 @@ TopLevel::insert_or_error_out (const Identifier &identifier, node_locations.emplace (node_id, locus); auto result = ctx.insert (identifier, node_id, ns); - - if (!result && result.error ().existing != node_id) + if (result) + dirty = true; + else if (result.error ().existing != node_id) { rich_location rich_loc (line_table, locus); rich_loc.add_range (node_locations[result.error ().existing]); 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 fd26891..7309e70 100644 --- a/gcc/rust/resolve/rust-toplevel-name-resolver-2.0.h +++ b/gcc/rust/resolve/rust-toplevel-name-resolver-2.0.h @@ -43,6 +43,8 @@ public: void go (AST::Crate &crate); + bool is_dirty () { return dirty; } + // Each import will be transformed into an instance of `ImportKind`, a class // representing some of the data we need to resolve in the // `EarlyNameResolver`. Basically, for each `UseTree` that we see in @@ -129,6 +131,10 @@ public: Namespace ns); private: + // If a new export has been defined whilst visiting the visitor is considered + // dirty + bool dirty; + // FIXME: Do we move these to our mappings? std::unordered_map<NodeId, location_t> node_locations; diff --git a/gcc/rust/rust-session-manager.cc b/gcc/rust/rust-session-manager.cc index 56c8bda..2cc20ec 100644 --- a/gcc/rust/rust-session-manager.cc +++ b/gcc/rust/rust-session-manager.cc @@ -928,18 +928,21 @@ Session::expansion (AST::Crate &crate, Resolver2_0::NameResolutionContext &ctx) if (saw_errors ()) break; + bool visitor_dirty = false; + if (flag_name_resolution_2_0) { Resolver2_0::Early early (ctx); early.go (crate); macro_errors = early.get_macro_resolve_errors (); + visitor_dirty = early.is_dirty (); } else Resolver::EarlyNameResolver ().go (crate); ExpandVisitor (expander).go (crate); - fixed_point_reached = !expander.has_changed (); + fixed_point_reached = !expander.has_changed () && !visitor_dirty; expander.reset_changed_state (); iterations++; |