aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorPierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>2024-08-21 17:14:46 +0200
committerP-E-P <32375388+P-E-P@users.noreply.github.com>2024-09-26 22:48:32 +0000
commitab8a0b5cc06c23cea99124ef60d717ac198fc063 (patch)
treec061ed0002ad5305b3a6b8e52acf30bec6e5159d /gcc
parent76131dd1d561bdc2064e9f91ed19c275d09e7166 (diff)
downloadgcc-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.cc4
-rw-r--r--gcc/rust/resolve/rust-early-name-resolver-2.0.h4
-rw-r--r--gcc/rust/resolve/rust-toplevel-name-resolver-2.0.cc7
-rw-r--r--gcc/rust/resolve/rust-toplevel-name-resolver-2.0.h6
-rw-r--r--gcc/rust/rust-session-manager.cc5
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++;