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