aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorMark Wielaard <mark@klomp.org>2021-09-06 00:48:10 +0200
committerPhilip Herron <philip.herron@embecosm.com>2021-09-06 10:31:43 +0100
commita3ac8573495919f1c8f6d6cca6578edd5e3ab01e (patch)
tree9be0522fb83ecfc8bec9c559b58cd7b9e57e848c /gcc
parent2bbe1af01db19b67cf668384b096e0e6a01765e6 (diff)
downloadgcc-a3ac8573495919f1c8f6d6cca6578edd5e3ab01e.zip
gcc-a3ac8573495919f1c8f6d6cca6578edd5e3ab01e.tar.gz
gcc-a3ac8573495919f1c8f6d6cca6578edd5e3ab01e.tar.bz2
Resolve Enums and EnumItems
Generate paths for Enum and EnumItem AST NodeIds and resolve the types of tuple and struct enum items. EnumItems always have the Enum as prefix. To make this work for ResolveStms (declaration statements are not given a canonical path) we add an enum_prefix to be used when resolving EnumItems. For ResolveType the tuple and struct fields get resolved using the Enum type scope. Add tests for toplevel or stmt enums with duplicate variant names. And adjust the tuple_enum_variants.rs testcase to expect unused name warnings.
Diffstat (limited to 'gcc')
-rw-r--r--gcc/rust/resolve/rust-ast-resolve-item.h36
-rw-r--r--gcc/rust/resolve/rust-ast-resolve-stmt.h105
-rw-r--r--gcc/rust/resolve/rust-ast-resolve-toplevel.h69
-rw-r--r--gcc/testsuite/rust/compile/bad_stmt_enums.rs22
-rw-r--r--gcc/testsuite/rust/compile/bad_toplevel_enums.rs19
-rw-r--r--gcc/testsuite/rust/compile/torture/tuple_enum_variants.rs7
6 files changed, 254 insertions, 4 deletions
diff --git a/gcc/rust/resolve/rust-ast-resolve-item.h b/gcc/rust/resolve/rust-ast-resolve-item.h
index d3c053b..2a2f956 100644
--- a/gcc/rust/resolve/rust-ast-resolve-item.h
+++ b/gcc/rust/resolve/rust-ast-resolve-item.h
@@ -260,6 +260,42 @@ public:
resolver->get_type_scope ().pop ();
}
+ void visit (AST::Enum &enum_decl) override
+ {
+ NodeId scope_node_id = enum_decl.get_node_id ();
+ resolver->get_type_scope ().push (scope_node_id);
+
+ if (enum_decl.has_generics ())
+ {
+ for (auto &generic : enum_decl.get_generic_params ())
+ {
+ ResolveGenericParam::go (generic.get (), enum_decl.get_node_id ());
+ }
+ }
+
+ /* The actual fields are inside the variants. */
+ for (auto &variant : enum_decl.get_variants ())
+ ResolveItem::go (variant.get ());
+
+ resolver->get_type_scope ().pop ();
+ }
+
+ /* EnumItem doesn't need to be handled, no fields. */
+
+ void visit (AST::EnumItemTuple &item) override
+ {
+ for (auto &field : item.get_tuple_fields ())
+ ResolveType::go (field.get_field_type ().get (), item.get_node_id ());
+ }
+
+ void visit (AST::EnumItemStruct &item) override
+ {
+ for (auto &field : item.get_struct_fields ())
+ ResolveType::go (field.get_field_type ().get (), item.get_node_id ());
+ }
+
+ /* EnumItemDiscriminant doesn't need to be handled, no fields. */
+
void visit (AST::StructStruct &struct_decl) override
{
NodeId scope_node_id = struct_decl.get_node_id ();
diff --git a/gcc/rust/resolve/rust-ast-resolve-stmt.h b/gcc/rust/resolve/rust-ast-resolve-stmt.h
index b604432..43bf0a4 100644
--- a/gcc/rust/resolve/rust-ast-resolve-stmt.h
+++ b/gcc/rust/resolve/rust-ast-resolve-stmt.h
@@ -33,9 +33,11 @@ class ResolveStmt : public ResolverBase
using Rust::Resolver::ResolverBase::visit;
public:
- static void go (AST::Stmt *stmt, NodeId parent)
+ static void go (AST::Stmt *stmt, NodeId parent,
+ const CanonicalPath &enum_prefix
+ = CanonicalPath::create_empty ())
{
- ResolveStmt resolver (parent);
+ ResolveStmt resolver (parent, enum_prefix);
stmt->accept_vis (resolver);
};
@@ -98,6 +100,97 @@ public:
resolver->get_type_scope ().pop ();
}
+ void visit (AST::Enum &enum_decl) override
+ {
+ auto enum_path = CanonicalPath::new_seg (enum_decl.get_node_id (),
+ enum_decl.get_identifier ());
+ resolver->get_type_scope ().insert (
+ enum_path, enum_decl.get_node_id (), enum_decl.get_locus (), false,
+ [&] (const CanonicalPath &, NodeId, Location locus) -> void {
+ RichLocation r (enum_decl.get_locus ());
+ r.add_range (locus);
+ rust_error_at (r, "redefined multiple times");
+ });
+
+ NodeId scope_node_id = enum_decl.get_node_id ();
+ resolver->get_type_scope ().push (scope_node_id);
+
+ if (enum_decl.has_generics ())
+ {
+ for (auto &generic : enum_decl.get_generic_params ())
+ {
+ ResolveGenericParam::go (generic.get (), enum_decl.get_node_id ());
+ }
+ }
+
+ for (auto &variant : enum_decl.get_variants ())
+ ResolveStmt::go (variant.get (), parent, enum_path);
+
+ resolver->get_type_scope ().pop ();
+ }
+
+ void visit (AST::EnumItem &item) override
+ {
+ auto path = enum_prefix.append (
+ CanonicalPath::new_seg (item.get_node_id (), item.get_identifier ()));
+ resolver->get_type_scope ().insert (
+ path, item.get_node_id (), item.get_locus (), false,
+ [&] (const CanonicalPath &, NodeId, Location locus) -> void {
+ RichLocation r (item.get_locus ());
+ r.add_range (locus);
+ rust_error_at (r, "redefined multiple times");
+ });
+
+ // Done, no fields.
+ }
+
+ void visit (AST::EnumItemTuple &item) override
+ {
+ auto path = enum_prefix.append (
+ CanonicalPath::new_seg (item.get_node_id (), item.get_identifier ()));
+ resolver->get_type_scope ().insert (
+ path, item.get_node_id (), item.get_locus (), false,
+ [&] (const CanonicalPath &, NodeId, Location locus) -> void {
+ RichLocation r (item.get_locus ());
+ r.add_range (locus);
+ rust_error_at (r, "redefined multiple times");
+ });
+
+ for (auto &field : item.get_tuple_fields ())
+ ResolveType::go (field.get_field_type ().get (), item.get_node_id ());
+ }
+
+ void visit (AST::EnumItemStruct &item) override
+ {
+ auto path = enum_prefix.append (
+ CanonicalPath::new_seg (item.get_node_id (), item.get_identifier ()));
+ resolver->get_type_scope ().insert (
+ path, item.get_node_id (), item.get_locus (), false,
+ [&] (const CanonicalPath &, NodeId, Location locus) -> void {
+ RichLocation r (item.get_locus ());
+ r.add_range (locus);
+ rust_error_at (r, "redefined multiple times");
+ });
+
+ for (auto &field : item.get_struct_fields ())
+ ResolveType::go (field.get_field_type ().get (), item.get_node_id ());
+ }
+
+ void visit (AST::EnumItemDiscriminant &item) override
+ {
+ auto path = enum_prefix.append (
+ CanonicalPath::new_seg (item.get_node_id (), item.get_identifier ()));
+ resolver->get_type_scope ().insert (
+ path, item.get_node_id (), item.get_locus (), false,
+ [&] (const CanonicalPath &, NodeId, Location locus) -> void {
+ RichLocation r (item.get_locus ());
+ r.add_range (locus);
+ rust_error_at (r, "redefined multiple times");
+ });
+
+ // Done, no fields.
+ }
+
void visit (AST::StructStruct &struct_decl) override
{
auto path = CanonicalPath::new_seg (struct_decl.get_node_id (),
@@ -219,7 +312,13 @@ public:
}
private:
- ResolveStmt (NodeId parent) : ResolverBase (parent) {}
+ ResolveStmt (NodeId parent, const CanonicalPath &enum_prefix)
+ : ResolverBase (parent), enum_prefix (enum_prefix)
+ {}
+
+ /* item declaration statements are not given a canonical path, but enum items
+ * (variants) do inherit the enum path/identifier name. */
+ const CanonicalPath &enum_prefix;
};
} // namespace Resolver
diff --git a/gcc/rust/resolve/rust-ast-resolve-toplevel.h b/gcc/rust/resolve/rust-ast-resolve-toplevel.h
index 1239206..6f802a5 100644
--- a/gcc/rust/resolve/rust-ast-resolve-toplevel.h
+++ b/gcc/rust/resolve/rust-ast-resolve-toplevel.h
@@ -88,6 +88,75 @@ public:
});
}
+ void visit (AST::Enum &enum_decl) override
+ {
+ auto path
+ = prefix.append (CanonicalPath::new_seg (enum_decl.get_node_id (),
+ enum_decl.get_identifier ()));
+ resolver->get_type_scope ().insert (
+ path, enum_decl.get_node_id (), enum_decl.get_locus (), false,
+ [&] (const CanonicalPath &, NodeId, Location locus) -> void {
+ RichLocation r (enum_decl.get_locus ());
+ r.add_range (locus);
+ rust_error_at (r, "redefined multiple times");
+ });
+
+ for (auto &variant : enum_decl.get_variants ())
+ ResolveTopLevel::go (variant.get (), path);
+ }
+
+ void visit (AST::EnumItem &item) override
+ {
+ auto path = prefix.append (
+ CanonicalPath::new_seg (item.get_node_id (), item.get_identifier ()));
+ resolver->get_type_scope ().insert (
+ path, item.get_node_id (), item.get_locus (), false,
+ [&] (const CanonicalPath &, NodeId, Location locus) -> void {
+ RichLocation r (item.get_locus ());
+ r.add_range (locus);
+ rust_error_at (r, "redefined multiple times");
+ });
+ }
+
+ void visit (AST::EnumItemTuple &item) override
+ {
+ auto path = prefix.append (
+ CanonicalPath::new_seg (item.get_node_id (), item.get_identifier ()));
+ resolver->get_type_scope ().insert (
+ path, item.get_node_id (), item.get_locus (), false,
+ [&] (const CanonicalPath &, NodeId, Location locus) -> void {
+ RichLocation r (item.get_locus ());
+ r.add_range (locus);
+ rust_error_at (r, "redefined multiple times");
+ });
+ }
+
+ void visit (AST::EnumItemStruct &item) override
+ {
+ auto path = prefix.append (
+ CanonicalPath::new_seg (item.get_node_id (), item.get_identifier ()));
+ resolver->get_type_scope ().insert (
+ path, item.get_node_id (), item.get_locus (), false,
+ [&] (const CanonicalPath &, NodeId, Location locus) -> void {
+ RichLocation r (item.get_locus ());
+ r.add_range (locus);
+ rust_error_at (r, "redefined multiple times");
+ });
+ }
+
+ void visit (AST::EnumItemDiscriminant &item) override
+ {
+ auto path = prefix.append (
+ CanonicalPath::new_seg (item.get_node_id (), item.get_identifier ()));
+ resolver->get_type_scope ().insert (
+ path, item.get_node_id (), item.get_locus (), false,
+ [&] (const CanonicalPath &, NodeId, Location locus) -> void {
+ RichLocation r (item.get_locus ());
+ r.add_range (locus);
+ rust_error_at (r, "redefined multiple times");
+ });
+ }
+
void visit (AST::StructStruct &struct_decl) override
{
auto path
diff --git a/gcc/testsuite/rust/compile/bad_stmt_enums.rs b/gcc/testsuite/rust/compile/bad_stmt_enums.rs
new file mode 100644
index 0000000..7b09a94
--- /dev/null
+++ b/gcc/testsuite/rust/compile/bad_stmt_enums.rs
@@ -0,0 +1,22 @@
+fn main ()
+{
+ enum EE
+ {
+ Alpha { alpha: i32 },
+ pub Beta (u8),
+ pub Gamma,
+ Gamma { gamma: u32 } // { dg-error "redefined" }
+ }
+
+ struct EE2 { }
+ enum EE2 { } // { dg-error "redefined" }
+
+ enum EE1
+ {
+ pub Alpha,
+ Beta = 41,
+ Beta = 42, // { dg-error "redefined" }
+ pub Gamma = 3,
+ D,
+ }
+}
diff --git a/gcc/testsuite/rust/compile/bad_toplevel_enums.rs b/gcc/testsuite/rust/compile/bad_toplevel_enums.rs
new file mode 100644
index 0000000..b655e30
--- /dev/null
+++ b/gcc/testsuite/rust/compile/bad_toplevel_enums.rs
@@ -0,0 +1,19 @@
+pub enum E
+{
+ pub A { a: i32 },
+ B (u8),
+ pub C,
+ B // { dg-error "redefined" }
+}
+
+enum E2 { }
+struct E2 { } // { dg-error "redefined" }
+
+enum E1
+{
+ A,
+ pub B = 42,
+ C = 3,
+ A { a: u8 }, // { dg-error "redefined" }
+ pub D
+}
diff --git a/gcc/testsuite/rust/compile/torture/tuple_enum_variants.rs b/gcc/testsuite/rust/compile/torture/tuple_enum_variants.rs
index 26e3e5d..f65bd3b 100644
--- a/gcc/testsuite/rust/compile/torture/tuple_enum_variants.rs
+++ b/gcc/testsuite/rust/compile/torture/tuple_enum_variants.rs
@@ -1,4 +1,9 @@
-enum E { T0(), T1(i32), T2(i32,u32) }
+enum E // { dg-warning "unused name" }
+{
+ T0(), // { dg-warning "unused name" }
+ T1(i32), // { dg-warning "unused name" }
+ T2(i32,u32) // { dg-warning "unused name" }
+}
/* The following doesn't parse yet...
fn f(e0: E, e1: E, e2: E) -> (E,E,E,())