diff options
author | Mark Wielaard <mark@klomp.org> | 2021-09-06 00:48:10 +0200 |
---|---|---|
committer | Philip Herron <philip.herron@embecosm.com> | 2021-09-06 10:31:43 +0100 |
commit | a3ac8573495919f1c8f6d6cca6578edd5e3ab01e (patch) | |
tree | 9be0522fb83ecfc8bec9c559b58cd7b9e57e848c /gcc | |
parent | 2bbe1af01db19b67cf668384b096e0e6a01765e6 (diff) | |
download | gcc-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.h | 36 | ||||
-rw-r--r-- | gcc/rust/resolve/rust-ast-resolve-stmt.h | 105 | ||||
-rw-r--r-- | gcc/rust/resolve/rust-ast-resolve-toplevel.h | 69 | ||||
-rw-r--r-- | gcc/testsuite/rust/compile/bad_stmt_enums.rs | 22 | ||||
-rw-r--r-- | gcc/testsuite/rust/compile/bad_toplevel_enums.rs | 19 | ||||
-rw-r--r-- | gcc/testsuite/rust/compile/torture/tuple_enum_variants.rs | 7 |
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,()) |