public inbox for gcc-rust@gcc.gnu.org
 help / color / mirror / Atom feed
* [PATCH 1/3] Parse optional visibility for enum item
@ 2021-09-05 22:48 Mark Wielaard
  2021-09-05 22:48 ` [PATCH 2/3] Resolve Enums and EnumItems Mark Wielaard
  2021-09-05 22:48 ` [PATCH 3/3] Add EnumItem HIR lowering Mark Wielaard
  0 siblings, 2 replies; 3+ messages in thread
From: Mark Wielaard @ 2021-09-05 22:48 UTC (permalink / raw)
  To: gcc-rust; +Cc: Mark Wielaard

Syntactically enum items can have a visibility. The visibility has to
be removed (through a cfg attribute or macro) before they get lowered.
The semantic checking will be done when we implement lowering enum items.

Make the AST EnumItem class a VisItem. This simplifies things a little
for cloning items, handling outer attributes and will help when adding
EnumItem (sub)classes to AST visitors (so they can be handled as
Items). Also add a get_identifier method to Enum and EnumItem.
---
 gcc/rust/ast/rust-ast-full-test.cc |  6 ++--
 gcc/rust/ast/rust-item.h           | 58 +++++++++++++++---------------
 gcc/rust/parse/rust-parse-impl.h   | 12 ++++---
 3 files changed, 38 insertions(+), 38 deletions(-)

diff --git a/gcc/rust/ast/rust-ast-full-test.cc b/gcc/rust/ast/rust-ast-full-test.cc
index 6241710226d..2477d7400a7 100644
--- a/gcc/rust/ast/rust-ast-full-test.cc
+++ b/gcc/rust/ast/rust-ast-full-test.cc
@@ -3311,10 +3311,8 @@ StructExprStructFields::as_string () const
 std::string
 EnumItem::as_string () const
 {
-  // outer attributes
-  std::string str = append_attributes (outer_attrs, OUTER);
-
-  str += "\n" + variant_name;
+  std::string str = VisItem::as_string ();
+  str += variant_name;
 
   return str;
 }
diff --git a/gcc/rust/ast/rust-item.h b/gcc/rust/ast/rust-item.h
index 0578329f54b..881a888f092 100644
--- a/gcc/rust/ast/rust-item.h
+++ b/gcc/rust/ast/rust-item.h
@@ -2119,12 +2119,10 @@ protected:
 };
 
 /* An item used in an "enum" tagged union - not abstract: base represents a
- * name-only enum */
-class EnumItem
+ * name-only enum. EnumItems (variants) syntactically allow a Visibility
+ * annotation. */
+class EnumItem : public VisItem
 {
-  // bool has_attrs;
-  std::vector<Attribute> outer_attrs;
-
   Identifier variant_name;
 
   Location locus;
@@ -2132,19 +2130,16 @@ class EnumItem
 public:
   virtual ~EnumItem () {}
 
-  // Returns whether enum item has outer attributes.
-  bool has_outer_attrs () const { return !outer_attrs.empty (); }
-
-  EnumItem (Identifier variant_name, std::vector<Attribute> outer_attrs,
-	    Location locus)
-    : outer_attrs (std::move (outer_attrs)),
+  EnumItem (Identifier variant_name, Visibility vis,
+	    std::vector<Attribute> outer_attrs, Location locus)
+    : VisItem (std::move (vis), std::move (outer_attrs)),
       variant_name (std::move (variant_name)), locus (locus)
   {}
 
   // Unique pointer custom clone function
   std::unique_ptr<EnumItem> clone_enum_item () const
   {
-    return std::unique_ptr<EnumItem> (clone_enum_item_impl ());
+    return std::unique_ptr<EnumItem> (clone_item_impl ());
   }
 
   virtual std::string as_string () const;
@@ -2152,20 +2147,16 @@ public:
   // not pure virtual as not abstract
   virtual void accept_vis (ASTVisitor &vis);
 
+  Location get_locus () const { return locus; }
+
+  Identifier get_identifier () const { return variant_name; }
+
   // Based on idea that name is never empty.
   void mark_for_strip () { variant_name = ""; }
   bool is_marked_for_strip () const { return variant_name.empty (); }
 
-  // TODO: this mutable getter seems really dodgy. Think up better way.
-  std::vector<Attribute> &get_outer_attrs () { return outer_attrs; }
-  const std::vector<Attribute> &get_outer_attrs () const { return outer_attrs; }
-
 protected:
-  // Clone function implementation as (not pure) virtual method
-  virtual EnumItem *clone_enum_item_impl () const
-  {
-    return new EnumItem (*this);
-  }
+  EnumItem *clone_item_impl () const override { return new EnumItem (*this); }
 };
 
 // A tuple item used in an "enum" tagged union
@@ -2178,9 +2169,11 @@ public:
   // Returns whether tuple enum item has tuple fields.
   bool has_tuple_fields () const { return !tuple_fields.empty (); }
 
-  EnumItemTuple (Identifier variant_name, std::vector<TupleField> tuple_fields,
+  EnumItemTuple (Identifier variant_name, Visibility vis,
+		 std::vector<TupleField> tuple_fields,
 		 std::vector<Attribute> outer_attrs, Location locus)
-    : EnumItem (std::move (variant_name), std::move (outer_attrs), locus),
+    : EnumItem (std::move (variant_name), std::move (vis),
+		std::move (outer_attrs), locus),
       tuple_fields (std::move (tuple_fields))
   {}
 
@@ -2197,7 +2190,7 @@ public:
 
 protected:
   // Clone function implementation as (not pure) virtual method
-  EnumItemTuple *clone_enum_item_impl () const override
+  EnumItemTuple *clone_item_impl () const override
   {
     return new EnumItemTuple (*this);
   }
@@ -2213,10 +2206,11 @@ public:
   // Returns whether struct enum item has struct fields.
   bool has_struct_fields () const { return !struct_fields.empty (); }
 
-  EnumItemStruct (Identifier variant_name,
+  EnumItemStruct (Identifier variant_name, Visibility vis,
 		  std::vector<StructField> struct_fields,
 		  std::vector<Attribute> outer_attrs, Location locus)
-    : EnumItem (std::move (variant_name), std::move (outer_attrs), locus),
+    : EnumItem (std::move (variant_name), std::move (vis),
+		std::move (outer_attrs), locus),
       struct_fields (std::move (struct_fields))
   {}
 
@@ -2233,7 +2227,7 @@ public:
 
 protected:
   // Clone function implementation as (not pure) virtual method
-  EnumItemStruct *clone_enum_item_impl () const override
+  EnumItemStruct *clone_item_impl () const override
   {
     return new EnumItemStruct (*this);
   }
@@ -2245,9 +2239,11 @@ class EnumItemDiscriminant : public EnumItem
   std::unique_ptr<Expr> expression;
 
 public:
-  EnumItemDiscriminant (Identifier variant_name, std::unique_ptr<Expr> expr,
+  EnumItemDiscriminant (Identifier variant_name, Visibility vis,
+			std::unique_ptr<Expr> expr,
 			std::vector<Attribute> outer_attrs, Location locus)
-    : EnumItem (std::move (variant_name), std::move (outer_attrs), locus),
+    : EnumItem (std::move (variant_name), std::move (vis),
+		std::move (outer_attrs), locus),
       expression (std::move (expr))
   {}
 
@@ -2284,7 +2280,7 @@ public:
 
 protected:
   // Clone function implementation as (not pure) virtual method
-  EnumItemDiscriminant *clone_enum_item_impl () const override
+  EnumItemDiscriminant *clone_item_impl () const override
   {
     return new EnumItemDiscriminant (*this);
   }
@@ -2374,6 +2370,8 @@ public:
 
   void accept_vis (ASTVisitor &vis) override;
 
+  Identifier get_identifier () const { return enum_name; }
+
   // Invalid if name is empty, so base stripping on that.
   void mark_for_strip () override { enum_name = ""; }
   bool is_marked_for_strip () const override { return enum_name.empty (); }
diff --git a/gcc/rust/parse/rust-parse-impl.h b/gcc/rust/parse/rust-parse-impl.h
index 1c0644d42ae..8cce9332350 100644
--- a/gcc/rust/parse/rust-parse-impl.h
+++ b/gcc/rust/parse/rust-parse-impl.h
@@ -4431,6 +4431,9 @@ Parser<ManagedTokenSource>::parse_enum_item ()
   // parse outer attributes if they exist
   AST::AttrVec outer_attrs = parse_outer_attributes ();
 
+  // parse visibility, which may or may not exist
+  AST::Visibility vis = parse_visibility ();
+
   // parse name for enum item, which is required
   const_TokenPtr item_name_tok = lexer.peek_token ();
   if (item_name_tok->get_id () != IDENTIFIER)
@@ -4463,7 +4466,7 @@ Parser<ManagedTokenSource>::parse_enum_item ()
 	  }
 
 	return std::unique_ptr<AST::EnumItemTuple> (new AST::EnumItemTuple (
-	  std::move (item_name), std::move (tuple_fields),
+	  std::move (item_name), std::move (vis), std::move (tuple_fields),
 	  std::move (outer_attrs), item_name_tok->get_locus ()));
       }
       case LEFT_CURLY: {
@@ -4480,7 +4483,7 @@ Parser<ManagedTokenSource>::parse_enum_item ()
 	  }
 
 	return std::unique_ptr<AST::EnumItemStruct> (new AST::EnumItemStruct (
-	  std::move (item_name), std::move (struct_fields),
+	  std::move (item_name), std::move (vis), std::move (struct_fields),
 	  std::move (outer_attrs), item_name_tok->get_locus ()));
       }
       case EQUAL: {
@@ -4490,7 +4493,7 @@ Parser<ManagedTokenSource>::parse_enum_item ()
 	std::unique_ptr<AST::Expr> discriminant_expr = parse_expr ();
 
 	return std::unique_ptr<AST::EnumItemDiscriminant> (
-	  new AST::EnumItemDiscriminant (std::move (item_name),
+	  new AST::EnumItemDiscriminant (std::move (item_name), std::move (vis),
 					 std::move (discriminant_expr),
 					 std::move (outer_attrs),
 					 item_name_tok->get_locus ()));
@@ -4498,7 +4501,8 @@ Parser<ManagedTokenSource>::parse_enum_item ()
     default:
       // regular enum with just an identifier
       return std::unique_ptr<AST::EnumItem> (
-	new AST::EnumItem (std::move (item_name), std::move (outer_attrs),
+	new AST::EnumItem (std::move (item_name), std::move (vis),
+			   std::move (outer_attrs),
 			   item_name_tok->get_locus ()));
     }
 }
-- 
2.32.0


^ permalink raw reply	[flat|nested] 3+ messages in thread

* [PATCH 2/3] Resolve Enums and EnumItems
  2021-09-05 22:48 [PATCH 1/3] Parse optional visibility for enum item Mark Wielaard
@ 2021-09-05 22:48 ` Mark Wielaard
  2021-09-05 22:48 ` [PATCH 3/3] Add EnumItem HIR lowering Mark Wielaard
  1 sibling, 0 replies; 3+ messages in thread
From: Mark Wielaard @ 2021-09-05 22:48 UTC (permalink / raw)
  To: gcc-rust; +Cc: Mark Wielaard

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.
---
 gcc/rust/resolve/rust-ast-resolve-item.h      |  36 ++++++
 gcc/rust/resolve/rust-ast-resolve-stmt.h      | 105 +++++++++++++++++-
 gcc/rust/resolve/rust-ast-resolve-toplevel.h  |  69 ++++++++++++
 gcc/testsuite/rust/compile/bad_stmt_enums.rs  |  22 ++++
 .../rust/compile/bad_toplevel_enums.rs        |  19 ++++
 .../compile/torture/tuple_enum_variants.rs    |   7 +-
 6 files changed, 254 insertions(+), 4 deletions(-)
 create mode 100644 gcc/testsuite/rust/compile/bad_stmt_enums.rs
 create mode 100644 gcc/testsuite/rust/compile/bad_toplevel_enums.rs

diff --git a/gcc/rust/resolve/rust-ast-resolve-item.h b/gcc/rust/resolve/rust-ast-resolve-item.h
index d3c053b609f..2a2f956a385 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 b6044327b27..43bf0a421d6 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 12392067be7..6f802a5b6e8 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 00000000000..7b09a94fd27
--- /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 00000000000..b655e30a93d
--- /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 26e3e5d0a71..f65bd3b5c69 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,())
-- 
2.32.0


^ permalink raw reply	[flat|nested] 3+ messages in thread

* [PATCH 3/3] Add EnumItem HIR lowering
  2021-09-05 22:48 [PATCH 1/3] Parse optional visibility for enum item Mark Wielaard
  2021-09-05 22:48 ` [PATCH 2/3] Resolve Enums and EnumItems Mark Wielaard
@ 2021-09-05 22:48 ` Mark Wielaard
  1 sibling, 0 replies; 3+ messages in thread
From: Mark Wielaard @ 2021-09-05 22:48 UTC (permalink / raw)
  To: gcc-rust; +Cc: Mark Wielaard

Make HIT EnumItem class an Item, not VisItem like in the AST. At the
HIR level EnumItems shouldn't have visibility anymore.

Move struct_field_name_exists to rust-ast-lower.cc with the
declaration in rust-ast-lower.h to make it reusable in the different
visitors.

Add a new ASTLoweringEnumItem that can be used from ASTLoweringItem
and ASTLoweringStmt. It checks the EnumItems don't have visibility and
that EnumItemStruct fields are not duplicated.

Add a new testcase 'bad_pub_enumitems.rs' to check the no-visibility and
no-duplicates properties hold.
---
 gcc/rust/hir/rust-ast-lower-enumitem.h        | 192 ++++++++++++++++++
 gcc/rust/hir/rust-ast-lower-item.h            |  59 ++++--
 gcc/rust/hir/rust-ast-lower-stmt.h            |  58 ++++--
 gcc/rust/hir/rust-ast-lower.cc                |  20 ++
 gcc/rust/hir/rust-ast-lower.h                 |   5 +
 gcc/rust/hir/tree/rust-hir-full-test.cc       |  19 +-
 gcc/rust/hir/tree/rust-hir-item.h             |  58 +++---
 .../rust/compile/bad_pub_enumitems.rs         |  47 +++++
 8 files changed, 376 insertions(+), 82 deletions(-)
 create mode 100644 gcc/rust/hir/rust-ast-lower-enumitem.h
 create mode 100644 gcc/testsuite/rust/compile/bad_pub_enumitems.rs

diff --git a/gcc/rust/hir/rust-ast-lower-enumitem.h b/gcc/rust/hir/rust-ast-lower-enumitem.h
new file mode 100644
index 00000000000..333cb7ba3fb
--- /dev/null
+++ b/gcc/rust/hir/rust-ast-lower-enumitem.h
@@ -0,0 +1,192 @@
+// Copyright (C) 2020 Free Software Foundation, Inc.
+
+// This file is part of GCC.
+
+// GCC is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 3, or (at your option) any later
+// version.
+
+// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+// for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with GCC; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+#ifndef RUST_AST_LOWER_ENUMITEM
+#define RUST_AST_LOWER_ENUMITEM
+
+#include "rust-diagnostics.h"
+
+#include "rust-ast-lower-base.h"
+#include "rust-ast-lower-type.h"
+#include "rust-ast-lower-expr.h"
+#include "rust-hir-full-decls.h"
+
+namespace Rust {
+namespace HIR {
+
+class ASTLoweringEnumItem : public ASTLoweringBase
+{
+  using Rust::HIR::ASTLoweringBase::visit;
+
+public:
+  static HIR::EnumItem *translate (AST::EnumItem *item)
+  {
+    ASTLoweringEnumItem resolver;
+    item->accept_vis (resolver);
+    return resolver.translated;
+  }
+
+  void visit (AST::EnumItem &item) override
+  {
+    auto crate_num = mappings->get_current_crate ();
+    Analysis::NodeMapping mapping (crate_num, item.get_node_id (),
+				   mappings->get_next_hir_id (crate_num),
+				   mappings->get_next_localdef_id (crate_num));
+
+    if (item.has_visibility ())
+      rust_error_at (item.get_locus (),
+		     "visibility qualifier %qs not allowed on enum item",
+		     item.get_vis ().as_string ().c_str ());
+
+    translated = new HIR::EnumItem (mapping, item.get_identifier (),
+				    item.get_outer_attrs (), item.get_locus ());
+
+    mappings->insert_defid_mapping (mapping.get_defid (), translated);
+    mappings->insert_hir_item (mapping.get_crate_num (), mapping.get_hirid (),
+			       translated);
+    mappings->insert_location (crate_num, mapping.get_hirid (),
+			       item.get_locus ());
+  }
+
+  void visit (AST::EnumItemTuple &item) override
+  {
+    auto crate_num = mappings->get_current_crate ();
+    Analysis::NodeMapping mapping (crate_num, item.get_node_id (),
+				   mappings->get_next_hir_id (crate_num),
+				   mappings->get_next_localdef_id (crate_num));
+
+    if (item.has_visibility ())
+      rust_error_at (item.get_locus (),
+		     "visibility qualifier %qs not allowed on enum item",
+		     item.get_vis ().as_string ().c_str ());
+
+    std::vector<HIR::TupleField> fields;
+    for (auto &field : item.get_tuple_fields ())
+      {
+	HIR::Visibility vis = HIR::Visibility::create_public ();
+	HIR::Type *type
+	  = ASTLoweringType::translate (field.get_field_type ().get ());
+
+	auto crate_num = mappings->get_current_crate ();
+	Analysis::NodeMapping field_mapping (
+	  crate_num, field.get_node_id (),
+	  mappings->get_next_hir_id (crate_num),
+	  mappings->get_next_localdef_id (crate_num));
+
+	HIR::TupleField translated_field (field_mapping,
+					  std::unique_ptr<HIR::Type> (type),
+					  vis, field.get_locus (),
+					  field.get_outer_attrs ());
+	fields.push_back (std::move (translated_field));
+      }
+
+    translated
+      = new HIR::EnumItemTuple (mapping, item.get_identifier (),
+				std::move (fields), item.get_outer_attrs (),
+				item.get_locus ());
+
+    mappings->insert_defid_mapping (mapping.get_defid (), translated);
+    mappings->insert_hir_item (mapping.get_crate_num (), mapping.get_hirid (),
+			       translated);
+    mappings->insert_location (crate_num, mapping.get_hirid (),
+			       item.get_locus ());
+  }
+
+  void visit (AST::EnumItemStruct &item) override
+  {
+    auto crate_num = mappings->get_current_crate ();
+    Analysis::NodeMapping mapping (crate_num, item.get_node_id (),
+				   mappings->get_next_hir_id (crate_num),
+				   mappings->get_next_localdef_id (crate_num));
+
+    if (item.has_visibility ())
+      rust_error_at (item.get_locus (),
+		     "visibility qualifier %qs not allowed on enum item",
+		     item.get_vis ().as_string ().c_str ());
+
+    std::vector<HIR::StructField> fields;
+    for (auto &field : item.get_struct_fields ())
+      {
+	HIR::Visibility vis = HIR::Visibility::create_public ();
+	HIR::Type *type
+	  = ASTLoweringType::translate (field.get_field_type ().get ());
+
+	auto crate_num = mappings->get_current_crate ();
+	Analysis::NodeMapping field_mapping (
+	  crate_num, field.get_node_id (),
+	  mappings->get_next_hir_id (crate_num),
+	  mappings->get_next_localdef_id (crate_num));
+
+	HIR::StructField translated_field (field_mapping,
+					   field.get_field_name (),
+					   std::unique_ptr<HIR::Type> (type),
+					   vis, field.get_locus (),
+					   field.get_outer_attrs ());
+
+	if (struct_field_name_exists (fields, translated_field))
+	  break;
+
+	fields.push_back (std::move (translated_field));
+      }
+
+    translated
+      = new HIR::EnumItemStruct (mapping, item.get_identifier (),
+				 std::move (fields), item.get_outer_attrs (),
+				 item.get_locus ());
+
+    mappings->insert_defid_mapping (mapping.get_defid (), translated);
+    mappings->insert_hir_item (mapping.get_crate_num (), mapping.get_hirid (),
+			       translated);
+    mappings->insert_location (crate_num, mapping.get_hirid (),
+			       item.get_locus ());
+  }
+  void visit (AST::EnumItemDiscriminant &item) override
+  {
+    auto crate_num = mappings->get_current_crate ();
+    Analysis::NodeMapping mapping (crate_num, item.get_node_id (),
+				   mappings->get_next_hir_id (crate_num),
+				   mappings->get_next_localdef_id (crate_num));
+
+    if (item.has_visibility ())
+      rust_error_at (item.get_locus (),
+		     "visibility qualifier %qs not allowed on enum item",
+		     item.get_vis ().as_string ().c_str ());
+
+    HIR::Expr *expr = ASTLoweringExpr::translate (item.get_expr ().get ());
+    translated
+      = new HIR::EnumItemDiscriminant (mapping, item.get_identifier (),
+				       std::unique_ptr<HIR::Expr> (expr),
+				       item.get_outer_attrs (),
+				       item.get_locus ());
+
+    mappings->insert_defid_mapping (mapping.get_defid (), translated);
+    mappings->insert_hir_item (mapping.get_crate_num (), mapping.get_hirid (),
+			       translated);
+    mappings->insert_location (crate_num, mapping.get_hirid (),
+			       item.get_locus ());
+  }
+
+private:
+  ASTLoweringEnumItem () : translated (nullptr) {}
+  HIR::EnumItem *translated;
+};
+
+} // namespace HIR
+} // namespace Rust
+
+#endif // RUST_AST_LOWER_ENUMITEM
diff --git a/gcc/rust/hir/rust-ast-lower-item.h b/gcc/rust/hir/rust-ast-lower-item.h
index 7efcffaf05b..2b56cbbf203 100644
--- a/gcc/rust/hir/rust-ast-lower-item.h
+++ b/gcc/rust/hir/rust-ast-lower-item.h
@@ -22,6 +22,7 @@
 #include "rust-diagnostics.h"
 
 #include "rust-ast-lower-base.h"
+#include "rust-ast-lower-enumitem.h"
 #include "rust-ast-lower-type.h"
 #include "rust-ast-lower-implitem.h"
 #include "rust-ast-lower-stmt.h"
@@ -175,25 +176,6 @@ public:
 			       struct_decl.get_locus ());
   }
 
-  /* Checks whether the name of a field already exists.  Returns true
-     and produces an error if so.  */
-  static bool struct_field_name_exists (std::vector<HIR::StructField> &fields,
-					HIR::StructField &new_field)
-  {
-    for (auto &field : fields)
-      {
-	if (field.get_field_name ().compare (new_field.get_field_name ()) == 0)
-	  {
-	    RichLocation r (new_field.get_locus ());
-	    r.add_range (field.get_locus ());
-	    rust_error_at (r, "duplicate field name %qs",
-			   field.get_field_name ().c_str ());
-	    return true;
-	  }
-      }
-    return false;
-  }
-
   void visit (AST::StructStruct &struct_decl) override
   {
     std::vector<std::unique_ptr<HIR::GenericParam> > generic_params;
@@ -251,6 +233,45 @@ public:
 			       struct_decl.get_locus ());
   }
 
+  void visit (AST::Enum &enum_decl) override
+  {
+    std::vector<std::unique_ptr<HIR::GenericParam>> generic_params;
+    if (enum_decl.has_generics ())
+      {
+	generic_params = lower_generic_params (enum_decl.get_generic_params ());
+      }
+
+    std::vector<std::unique_ptr<HIR::WhereClauseItem>> where_clause_items;
+    HIR::WhereClause where_clause (std::move (where_clause_items));
+    HIR::Visibility vis = HIR::Visibility::create_public ();
+
+    // bool is_unit = enum_decl.is_zero_variant ();
+    std::vector<std::unique_ptr<HIR::EnumItem>> items;
+    for (auto &variant : enum_decl.get_variants ())
+      {
+	HIR::EnumItem *hir_item
+	  = ASTLoweringEnumItem::translate (variant.get ());
+	items.push_back (std::unique_ptr<HIR::EnumItem> (hir_item));
+      }
+
+    auto crate_num = mappings->get_current_crate ();
+    Analysis::NodeMapping mapping (crate_num, enum_decl.get_node_id (),
+				   mappings->get_next_hir_id (crate_num),
+				   mappings->get_next_localdef_id (crate_num));
+
+    translated = new HIR::Enum (mapping, enum_decl.get_identifier (), vis,
+				std::move (generic_params),
+				std::move (where_clause), /* is_unit, */
+				std::move (items), enum_decl.get_outer_attrs (),
+				enum_decl.get_locus ());
+
+    mappings->insert_defid_mapping (mapping.get_defid (), translated);
+    mappings->insert_hir_item (mapping.get_crate_num (), mapping.get_hirid (),
+			       translated);
+    mappings->insert_location (crate_num, mapping.get_hirid (),
+			       enum_decl.get_locus ());
+  }
+
   void visit (AST::Union &union_decl) override
   {
     std::vector<std::unique_ptr<HIR::GenericParam> > generic_params;
diff --git a/gcc/rust/hir/rust-ast-lower-stmt.h b/gcc/rust/hir/rust-ast-lower-stmt.h
index fdd5041d602..05c70e9c03b 100644
--- a/gcc/rust/hir/rust-ast-lower-stmt.h
+++ b/gcc/rust/hir/rust-ast-lower-stmt.h
@@ -22,6 +22,7 @@
 #include "rust-diagnostics.h"
 
 #include "rust-ast-lower-base.h"
+#include "rust-ast-lower-enumitem.h"
 #include "rust-ast-lower-type.h"
 #include "rust-ast-lower-block.h"
 #include "rust-ast-lower-expr.h"
@@ -159,25 +160,6 @@ public:
 			       struct_decl.get_locus ());
   }
 
-  /* Checks whether the name of a field already exists.  Returns true
-     and produces an error if so.  */
-  static bool struct_field_name_exists (std::vector<HIR::StructField> &fields,
-					HIR::StructField &new_field)
-  {
-    for (auto &field : fields)
-      {
-	if (field.get_field_name ().compare (new_field.get_field_name ()) == 0)
-	  {
-	    RichLocation r (new_field.get_locus ());
-	    r.add_range (field.get_locus ());
-	    rust_error_at (r, "duplicate field name %qs",
-			   field.get_field_name ().c_str ());
-	    return true;
-	  }
-      }
-    return false;
-  }
-
   void visit (AST::StructStruct &struct_decl) override
   {
     std::vector<std::unique_ptr<HIR::GenericParam> > generic_params;
@@ -288,6 +270,44 @@ public:
 			       union_decl.get_locus ());
   }
 
+  void visit (AST::Enum &enum_decl) override
+  {
+    std::vector<std::unique_ptr<HIR::GenericParam>> generic_params;
+    if (enum_decl.has_generics ())
+      {
+	generic_params = lower_generic_params (enum_decl.get_generic_params ());
+      }
+
+    std::vector<std::unique_ptr<HIR::WhereClauseItem>> where_clause_items;
+    HIR::WhereClause where_clause (std::move (where_clause_items));
+    HIR::Visibility vis = HIR::Visibility::create_public ();
+
+    // bool is_unit = enum_decl.is_zero_variant ();
+    std::vector<std::unique_ptr<HIR::EnumItem>> items;
+    for (auto &variant : enum_decl.get_variants ())
+      {
+	HIR::EnumItem *hir_item
+	  = ASTLoweringEnumItem::translate (variant.get ());
+	items.push_back (std::unique_ptr<HIR::EnumItem> (hir_item));
+      }
+
+    auto crate_num = mappings->get_current_crate ();
+    Analysis::NodeMapping mapping (crate_num, enum_decl.get_node_id (),
+				   mappings->get_next_hir_id (crate_num),
+				   mappings->get_next_localdef_id (crate_num));
+
+    translated = new HIR::Enum (mapping, enum_decl.get_identifier (), vis,
+				std::move (generic_params),
+				std::move (where_clause), /* is_unit, */
+				std::move (items), enum_decl.get_outer_attrs (),
+				enum_decl.get_locus ());
+
+    mappings->insert_hir_stmt (mapping.get_crate_num (), mapping.get_hirid (),
+			       translated);
+    mappings->insert_location (crate_num, mapping.get_hirid (),
+			       enum_decl.get_locus ());
+  }
+
   void visit (AST::EmptyStmt &empty) override
   {
     auto crate_num = mappings->get_current_crate ();
diff --git a/gcc/rust/hir/rust-ast-lower.cc b/gcc/rust/hir/rust-ast-lower.cc
index e8784b61da5..b64e1a05438 100644
--- a/gcc/rust/hir/rust-ast-lower.cc
+++ b/gcc/rust/hir/rust-ast-lower.cc
@@ -520,5 +520,25 @@ ASTLoweringBase::lower_bound (AST::TypeParamBound *bound)
   return ASTLoweringTypeBounds::translate (bound);
 }
 
+/* Checks whether the name of a field already exists.  Returns true
+   and produces an error if so.  */
+bool
+struct_field_name_exists (std::vector<HIR::StructField> &fields,
+			  HIR::StructField &new_field)
+{
+  for (auto &field : fields)
+    {
+      if (field.get_field_name ().compare (new_field.get_field_name ()) == 0)
+	{
+	  RichLocation r (new_field.get_locus ());
+	  r.add_range (field.get_locus ());
+	  rust_error_at (r, "duplicate field name %qs",
+			 field.get_field_name ().c_str ());
+	  return true;
+	}
+    }
+  return false;
+}
+
 } // namespace HIR
 } // namespace Rust
diff --git a/gcc/rust/hir/rust-ast-lower.h b/gcc/rust/hir/rust-ast-lower.h
index bdc21ba486b..254f68649db 100644
--- a/gcc/rust/hir/rust-ast-lower.h
+++ b/gcc/rust/hir/rust-ast-lower.h
@@ -27,6 +27,11 @@
 namespace Rust {
 namespace HIR {
 
+/* Checks whether the name of a field already exists.  Returns true
+   and produces an error if so.  */
+bool
+struct_field_name_exists (std::vector<HIR::StructField> &fields,
+			  HIR::StructField &new_field);
 class ASTLowering
 {
 public:
diff --git a/gcc/rust/hir/tree/rust-hir-full-test.cc b/gcc/rust/hir/tree/rust-hir-full-test.cc
index f328ae67abe..b0e418c166b 100644
--- a/gcc/rust/hir/tree/rust-hir-full-test.cc
+++ b/gcc/rust/hir/tree/rust-hir-full-test.cc
@@ -3086,23 +3086,8 @@ StructExprStructFields::as_string () const
 std::string
 EnumItem::as_string () const
 {
-  // outer attributes
-  std::string str = "outer attributes: ";
-  if (outer_attrs.empty ())
-    {
-      str += "none";
-    }
-  else
-    {
-      /* note that this does not print them with "outer attribute" syntax -
-       * just the body */
-      for (const auto &attr : outer_attrs)
-	{
-	  str += "\n  " + attr.as_string ();
-	}
-    }
-
-  str += "\n" + variant_name;
+  std::string str = Item::as_string ();
+  str += variant_name;
 
   return str;
 }
diff --git a/gcc/rust/hir/tree/rust-hir-item.h b/gcc/rust/hir/tree/rust-hir-item.h
index 7a2c2676825..35b1c64e6d2 100644
--- a/gcc/rust/hir/tree/rust-hir-item.h
+++ b/gcc/rust/hir/tree/rust-hir-item.h
@@ -1636,12 +1636,11 @@ protected:
 };
 
 /* An item used in an "enum" tagged union - not abstract: base represents a
- * name-only enum */
-class EnumItem
+   name-only enum. Syntactically EnumItem's can have a Visibility. But not
+   Semantically. So check there is no Visibility when lowering and make this
+   an Item, not an VisItem.  */
+class EnumItem : public Item
 {
-  // bool has_attrs;
-  AST::AttrVec outer_attrs;
-
   Identifier variant_name;
 
   Location locus;
@@ -1649,18 +1648,16 @@ class EnumItem
 public:
   virtual ~EnumItem () {}
 
-  // Returns whether enum item has outer attributes.
-  bool has_outer_attrs () const { return !outer_attrs.empty (); }
-
-  EnumItem (Identifier variant_name, AST::AttrVec outer_attrs, Location locus)
-    : outer_attrs (std::move (outer_attrs)),
+  EnumItem (Analysis::NodeMapping mappings, Identifier variant_name,
+	    AST::AttrVec outer_attrs, Location locus)
+    : Item (std::move (mappings), std::move (outer_attrs)),
       variant_name (std::move (variant_name)), locus (locus)
   {}
 
   // Unique pointer custom clone function
   std::unique_ptr<EnumItem> clone_enum_item () const
   {
-    return std::unique_ptr<EnumItem> (clone_enum_item_impl ());
+    return std::unique_ptr<EnumItem> (clone_item_impl ());
   }
 
   virtual std::string as_string () const;
@@ -1668,12 +1665,12 @@ public:
   // not pure virtual as not abstract
   virtual void accept_vis (HIRVisitor &vis);
 
+  Location get_locus () const { return locus; }
+
+  Identifier get_identifier () const { return variant_name; }
+
 protected:
-  // Clone function implementation as (not pure) virtual method
-  virtual EnumItem *clone_enum_item_impl () const
-  {
-    return new EnumItem (*this);
-  }
+  EnumItem *clone_item_impl () const override { return new EnumItem (*this); }
 };
 
 // A tuple item used in an "enum" tagged union
@@ -1686,9 +1683,11 @@ public:
   // Returns whether tuple enum item has tuple fields.
   bool has_tuple_fields () const { return !tuple_fields.empty (); }
 
-  EnumItemTuple (Identifier variant_name, std::vector<TupleField> tuple_fields,
-		 AST::AttrVec outer_attrs, Location locus)
-    : EnumItem (std::move (variant_name), std::move (outer_attrs), locus),
+  EnumItemTuple (Analysis::NodeMapping mappings, Identifier variant_name,
+		 std::vector<TupleField> tuple_fields, AST::AttrVec outer_attrs,
+		 Location locus)
+    : EnumItem (std::move (mappings), std::move (variant_name),
+		std::move (outer_attrs), locus),
       tuple_fields (std::move (tuple_fields))
   {}
 
@@ -1698,7 +1697,7 @@ public:
 
 protected:
   // Clone function implementation as (not pure) virtual method
-  EnumItemTuple *clone_enum_item_impl () const override
+  EnumItemTuple *clone_item_impl () const override
   {
     return new EnumItemTuple (*this);
   }
@@ -1714,10 +1713,11 @@ public:
   // Returns whether struct enum item has struct fields.
   bool has_struct_fields () const { return !struct_fields.empty (); }
 
-  EnumItemStruct (Identifier variant_name,
+  EnumItemStruct (Analysis::NodeMapping mappings, Identifier variant_name,
 		  std::vector<StructField> struct_fields,
 		  AST::AttrVec outer_attrs, Location locus)
-    : EnumItem (std::move (variant_name), std::move (outer_attrs), locus),
+    : EnumItem (std::move (mappings), std::move (variant_name),
+		std::move (outer_attrs), locus),
       struct_fields (std::move (struct_fields))
   {}
 
@@ -1727,7 +1727,7 @@ public:
 
 protected:
   // Clone function implementation as (not pure) virtual method
-  EnumItemStruct *clone_enum_item_impl () const override
+  EnumItemStruct *clone_item_impl () const override
   {
     return new EnumItemStruct (*this);
   }
@@ -1739,9 +1739,11 @@ class EnumItemDiscriminant : public EnumItem
   std::unique_ptr<Expr> expression;
 
 public:
-  EnumItemDiscriminant (Identifier variant_name, std::unique_ptr<Expr> expr,
-			AST::AttrVec outer_attrs, Location locus)
-    : EnumItem (std::move (variant_name), std::move (outer_attrs), locus),
+  EnumItemDiscriminant (Analysis::NodeMapping mappings, Identifier variant_name,
+			std::unique_ptr<Expr> expr, AST::AttrVec outer_attrs,
+			Location locus)
+    : EnumItem (std::move (mappings), std::move (variant_name),
+		std::move (outer_attrs), locus),
       expression (std::move (expr))
   {}
 
@@ -1771,7 +1773,7 @@ public:
 
 protected:
   // Clone function implementation as (not pure) virtual method
-  EnumItemDiscriminant *clone_enum_item_impl () const override
+  EnumItemDiscriminant *clone_item_impl () const override
   {
     return new EnumItemDiscriminant (*this);
   }
@@ -1861,6 +1863,8 @@ public:
 
   void accept_vis (HIRVisitor &vis) override;
 
+  Identifier get_identifier () const { return enum_name; }
+
 protected:
   /* Use covariance to implement clone function as returning this object
    * rather than base */
diff --git a/gcc/testsuite/rust/compile/bad_pub_enumitems.rs b/gcc/testsuite/rust/compile/bad_pub_enumitems.rs
new file mode 100644
index 00000000000..e7fd5edb981
--- /dev/null
+++ b/gcc/testsuite/rust/compile/bad_pub_enumitems.rs
@@ -0,0 +1,47 @@
+pub enum E
+{
+  pub A { a: i32 }, // { dg-error "visibility qualifier" }
+  B (u8),
+  pub C, // { dg-error "visibility qualifier" }
+  D
+}
+
+enum E1
+{
+  A,
+  pub B = 42, // { dg-error "visibility qualifier" }
+  C = 3,
+  D,
+  pub E // { dg-error "visibility qualifier" }
+}
+
+enum E2
+{
+  pub A (u8, i32, u64), // { dg-error "visibility qualifier" }
+  B { a: u8, a: u8 }  // { dg-error "duplicate field" }}
+}
+
+fn main ()
+{
+  enum EE
+    {
+      Alpha { alpha: i32 },
+      pub Beta (u8), // { dg-error "visibility qualifier" }
+      pub Gamma, // { dg-error "visibility qualifier" }
+      Delta { delta: u32 }
+    }
+
+  enum EE1
+    {
+      pub Alpha, // { dg-error "visibility qualifier" }
+      Beta = 41,
+      pub Gamma = 3, // { dg-error "visibility qualifier" }
+      Delta,
+    }
+
+  enum E2
+    {
+      Alpha { a: u8, a: u8 },  // { dg-error "duplicate field" }}
+      pub Beta (u8, i32, u64) // { dg-error "visibility qualifier" }
+    }
+}
-- 
2.32.0


^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2021-09-05 22:48 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-09-05 22:48 [PATCH 1/3] Parse optional visibility for enum item Mark Wielaard
2021-09-05 22:48 ` [PATCH 2/3] Resolve Enums and EnumItems Mark Wielaard
2021-09-05 22:48 ` [PATCH 3/3] Add EnumItem HIR lowering Mark Wielaard

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).