aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorPierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>2025-03-04 16:41:48 +0100
committerP-E-P <32375388+P-E-P@users.noreply.github.com>2025-03-11 14:06:30 +0000
commitc67466b2b28dac51da6d3a4694b31a2e53df80cd (patch)
tree0f3375d44a16a8a187f1b387bb1d1a11a633e654 /gcc
parent126680c6116cd7413b3163e41f1db968ce26666a (diff)
downloadgcc-c67466b2b28dac51da6d3a4694b31a2e53df80cd.zip
gcc-c67466b2b28dac51da6d3a4694b31a2e53df80cd.tar.gz
gcc-c67466b2b28dac51da6d3a4694b31a2e53df80cd.tar.bz2
Keep definition provenance to skip enum variants
Enum variants shouldn't be accessed directly even from within an enum. This commit keeps the provenance for enum variants definition so we can skip them when resolving a value within an enum definition. gcc/rust/ChangeLog: * resolve/rust-forever-stack.h: Add new function to insert enum variants and add argument to resolver's get function to explicitely skip enum variants. * resolve/rust-forever-stack.hxx: Update function definitions. * resolve/rust-name-resolution-context.cc (NameResolutionContext::insert_variant): Add function to insert enum variants. * resolve/rust-name-resolution-context.h: Add function's prototype. * resolve/rust-rib.cc (Rib::Definition::Definition): Add new boolean to hint at enum variant provenance. (Rib::Definition::is_variant): New getter for variant status. (Rib::Definition::Shadowable): Update constructor to opt out of enum variants. (Rib::Definition::Globbed): Likewise. (Rib::Definition::NonShadowable): Change constructor to forward enum variant provenance status. * resolve/rust-rib.h: Update function prototypes. * resolve/rust-toplevel-name-resolver-2.0.cc (TopLevel::insert_enum_variant_or_error_out): Add function to insert enum variants in the name resolver. (TopLevel::visit): Update several enum variant's visitor function with the new enum variant name resolving code. * resolve/rust-toplevel-name-resolver-2.0.h: Update function prototypes. Signed-off-by: Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>
Diffstat (limited to 'gcc')
-rw-r--r--gcc/rust/resolve/rust-forever-stack.h3
-rw-r--r--gcc/rust/resolve/rust-forever-stack.hxx18
-rw-r--r--gcc/rust/resolve/rust-name-resolution-context.cc6
-rw-r--r--gcc/rust/resolve/rust-name-resolution-context.h3
-rw-r--r--gcc/rust/resolve/rust-rib.cc17
-rw-r--r--gcc/rust/resolve/rust-rib.h14
-rw-r--r--gcc/rust/resolve/rust-toplevel-name-resolver-2.0.cc54
-rw-r--r--gcc/rust/resolve/rust-toplevel-name-resolver-2.0.h17
8 files changed, 106 insertions, 26 deletions
diff --git a/gcc/rust/resolve/rust-forever-stack.h b/gcc/rust/resolve/rust-forever-stack.h
index 74944fb..4c61582 100644
--- a/gcc/rust/resolve/rust-forever-stack.h
+++ b/gcc/rust/resolve/rust-forever-stack.h
@@ -591,6 +591,9 @@ public:
*/
tl::expected<NodeId, DuplicateNameError> insert (Identifier name, NodeId id);
+ tl::expected<NodeId, DuplicateNameError> insert_variant (Identifier name,
+ NodeId id);
+
/**
* Insert a new shadowable definition in the innermost `Rib` in this stack
*
diff --git a/gcc/rust/resolve/rust-forever-stack.hxx b/gcc/rust/resolve/rust-forever-stack.hxx
index 43061ff..fcd50af 100644
--- a/gcc/rust/resolve/rust-forever-stack.hxx
+++ b/gcc/rust/resolve/rust-forever-stack.hxx
@@ -173,6 +173,14 @@ ForeverStack<Namespace::Labels>::insert (Identifier name, NodeId node)
Rib::Definition::Shadowable (node));
}
+template <>
+inline tl::expected<NodeId, DuplicateNameError>
+ForeverStack<Namespace::Types>::insert_variant (Identifier name, NodeId node)
+{
+ return insert_inner (peek (), name.as_string (),
+ Rib::Definition::NonShadowable (node, true));
+}
+
template <Namespace N>
Rib &
ForeverStack<N>::peek ()
@@ -275,10 +283,12 @@ ForeverStack<N>::get (const Identifier &name)
return candidate.map_or (
[&resolved_definition] (Rib::Definition found) {
- // for most namespaces, we do not need to care about various ribs - they
- // are available from all contexts if defined in the current scope, or
- // an outermore one. so if we do have a candidate, we can return it
- // directly and stop iterating
+ if (found.is_variant ())
+ return KeepGoing::Yes;
+ // for most namespaces, we do not need to care about various ribs -
+ // they are available from all contexts if defined in the current
+ // scope, or an outermore one. so if we do have a candidate, we can
+ // return it directly and stop iterating
resolved_definition = found;
return KeepGoing::No;
diff --git a/gcc/rust/resolve/rust-name-resolution-context.cc b/gcc/rust/resolve/rust-name-resolution-context.cc
index 1a70cd0..38994fe 100644
--- a/gcc/rust/resolve/rust-name-resolution-context.cc
+++ b/gcc/rust/resolve/rust-name-resolution-context.cc
@@ -46,6 +46,12 @@ NameResolutionContext::insert (Identifier name, NodeId id, Namespace ns)
}
tl::expected<NodeId, DuplicateNameError>
+NameResolutionContext::insert_variant (Identifier name, NodeId id)
+{
+ return types.insert_variant (name, id);
+}
+
+tl::expected<NodeId, DuplicateNameError>
NameResolutionContext::insert_shadowable (Identifier name, NodeId id,
Namespace ns)
{
diff --git a/gcc/rust/resolve/rust-name-resolution-context.h b/gcc/rust/resolve/rust-name-resolution-context.h
index 19b9436..d21b868 100644
--- a/gcc/rust/resolve/rust-name-resolution-context.h
+++ b/gcc/rust/resolve/rust-name-resolution-context.h
@@ -172,6 +172,9 @@ public:
tl::expected<NodeId, DuplicateNameError> insert (Identifier name, NodeId id,
Namespace ns);
+ tl::expected<NodeId, DuplicateNameError> insert_variant (Identifier name,
+ NodeId id);
+
tl::expected<NodeId, DuplicateNameError>
insert_shadowable (Identifier name, NodeId id, Namespace ns);
diff --git a/gcc/rust/resolve/rust-rib.cc b/gcc/rust/resolve/rust-rib.cc
index 34abbff..e3d1d31 100644
--- a/gcc/rust/resolve/rust-rib.cc
+++ b/gcc/rust/resolve/rust-rib.cc
@@ -22,7 +22,8 @@
namespace Rust {
namespace Resolver2_0 {
-Rib::Definition::Definition (NodeId id, Mode mode)
+Rib::Definition::Definition (NodeId id, Mode mode, bool enum_variant)
+ : enum_variant (enum_variant)
{
switch (mode)
{
@@ -51,6 +52,12 @@ Rib::Definition::is_ambiguous () const
return ids_globbed.size () > 1;
}
+bool
+Rib::Definition::is_variant () const
+{
+ return enum_variant;
+}
+
std::string
Rib::Definition::to_string () const
{
@@ -75,19 +82,19 @@ Rib::Definition::to_string () const
Rib::Definition
Rib::Definition::Shadowable (NodeId id)
{
- return Definition (id, Mode::SHADOWABLE);
+ return Definition (id, Mode::SHADOWABLE, false);
}
Rib::Definition
-Rib::Definition::NonShadowable (NodeId id)
+Rib::Definition::NonShadowable (NodeId id, bool enum_variant)
{
- return Definition (id, Mode::NON_SHADOWABLE);
+ return Definition (id, Mode::NON_SHADOWABLE, enum_variant);
}
Rib::Definition
Rib::Definition::Globbed (NodeId id)
{
- return Definition (id, Mode::GLOBBED);
+ return Definition (id, Mode::GLOBBED, false);
}
DuplicateNameError::DuplicateNameError (std::string name, NodeId existing)
diff --git a/gcc/rust/resolve/rust-rib.h b/gcc/rust/resolve/rust-rib.h
index da1838a..8748969 100644
--- a/gcc/rust/resolve/rust-rib.h
+++ b/gcc/rust/resolve/rust-rib.h
@@ -111,7 +111,7 @@ public:
class Definition
{
public:
- static Definition NonShadowable (NodeId id);
+ static Definition NonShadowable (NodeId id, bool enum_variant = false);
static Definition Shadowable (NodeId id);
static Definition Globbed (NodeId id);
@@ -124,11 +124,21 @@ public:
std::vector<NodeId> ids_non_shadowable;
std::vector<NodeId> ids_globbed;
+ // Enum variant should be skipped when dealing with inner definition.
+ // struct E2;
+ //
+ // enum MyEnum<T> /* <-- Should be kept */{
+ // E2 /* <-- Should be skipped */ (E2);
+ // }
+ bool enum_variant;
+
Definition () = default;
Definition &operator= (const Definition &) = default;
Definition (Definition const &) = default;
+ bool is_variant () const;
+
bool is_ambiguous () const;
NodeId get_node_id () const
@@ -155,7 +165,7 @@ public:
GLOBBED
};
- Definition (NodeId id, Mode mode);
+ Definition (NodeId id, Mode mode, bool enum_variant);
};
enum class Kind
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 310b3c5..2c0cc66 100644
--- a/gcc/rust/resolve/rust-toplevel-name-resolver-2.0.cc
+++ b/gcc/rust/resolve/rust-toplevel-name-resolver-2.0.cc
@@ -32,21 +32,18 @@ TopLevel::TopLevel (NameResolutionContext &resolver)
template <typename T>
void
-TopLevel::insert_or_error_out (const Identifier &identifier, const T &node,
- Namespace ns)
+TopLevel::insert_enum_variant_or_error_out (const Identifier &identifier,
+ const T &node)
{
- insert_or_error_out (identifier, node.get_locus (), node.get_node_id (), ns);
+ insert_enum_variant_or_error_out (identifier, node.get_locus (),
+ node.get_node_id ());
}
void
-TopLevel::insert_or_error_out (const Identifier &identifier,
- const location_t &locus, const NodeId &node_id,
- Namespace ns)
+TopLevel::check_multiple_insertion_error (
+ tl::expected<NodeId, DuplicateNameError> result, const Identifier &identifier,
+ const location_t &locus, const NodeId node_id)
{
- // keep track of each node's location to provide useful errors
- node_locations.emplace (node_id, locus);
-
- auto result = ctx.insert (identifier, node_id, ns);
if (result)
dirty = true;
else if (result.error ().existing != node_id)
@@ -58,6 +55,37 @@ TopLevel::insert_or_error_out (const Identifier &identifier,
identifier.as_string ().c_str ());
}
}
+void
+TopLevel::insert_enum_variant_or_error_out (const Identifier &identifier,
+ const location_t &locus,
+ const NodeId node_id)
+{
+ // keep track of each node's location to provide useful errors
+ node_locations.emplace (node_id, locus);
+
+ auto result = ctx.insert_variant (identifier, node_id);
+ check_multiple_insertion_error (result, identifier, locus, node_id);
+}
+
+template <typename T>
+void
+TopLevel::insert_or_error_out (const Identifier &identifier, const T &node,
+ Namespace ns)
+{
+ insert_or_error_out (identifier, node.get_locus (), node.get_node_id (), ns);
+}
+
+void
+TopLevel::insert_or_error_out (const Identifier &identifier,
+ const location_t &locus, const NodeId &node_id,
+ Namespace ns)
+{
+ // keep track of each node's location to provide useful errors
+ node_locations.emplace (node_id, locus);
+
+ auto result = ctx.insert (identifier, node_id, ns);
+ check_multiple_insertion_error (result, identifier, locus, node_id);
+}
void
TopLevel::go (AST::Crate &crate)
@@ -336,19 +364,19 @@ TopLevel::visit (AST::TupleStruct &tuple_struct)
void
TopLevel::visit (AST::EnumItem &variant)
{
- insert_or_error_out (variant.get_identifier (), variant, Namespace::Types);
+ insert_enum_variant_or_error_out (variant.get_identifier (), variant);
}
void
TopLevel::visit (AST::EnumItemTuple &variant)
{
- insert_or_error_out (variant.get_identifier (), variant, Namespace::Types);
+ insert_enum_variant_or_error_out (variant.get_identifier (), variant);
}
void
TopLevel::visit (AST::EnumItemStruct &variant)
{
- insert_or_error_out (variant.get_identifier (), variant, Namespace::Types);
+ insert_enum_variant_or_error_out (variant.get_identifier (), variant);
}
void
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 ff86cf4..f385bc1 100644
--- a/gcc/rust/resolve/rust-toplevel-name-resolver-2.0.h
+++ b/gcc/rust/resolve/rust-toplevel-name-resolver-2.0.h
@@ -114,9 +114,14 @@ public:
return std::move (imports_to_resolve);
}
+ void check_multiple_insertion_error (
+ tl::expected<NodeId, DuplicateNameError> result,
+ const Identifier &identifier, const location_t &locus,
+ const NodeId node_id);
+
/**
- * Insert a new definition or error out if a definition with the same name was
- * already present in the same namespace in the same scope.
+ * Insert a new definition or error out if a definition with the same name
+ * was already present in the same namespace in the same scope.
*
* @param identifier The identifier of the definition to add.
* @param node A reference to the node, so we can get its `NodeId` and
@@ -130,6 +135,14 @@ public:
const location_t &locus, const NodeId &id,
Namespace ns);
+ template <typename T>
+ void insert_enum_variant_or_error_out (const Identifier &identifier,
+ const T &node);
+
+ void insert_enum_variant_or_error_out (const Identifier &identifier,
+ const location_t &locus,
+ const NodeId node_id);
+
private:
// If a new export has been defined whilst visiting the visitor is considered
// dirty