We have been accepting the following invalid code since revision 557831a91df
=== cut here === template <typename T> struct S { enum E { a }; enum E { b }; }; S<int> s; === cut here === The problem is that start_enum will set OPAQUE_ENUM_P to true even if it retrieves an existing definition for the enum, which causes the redefinition check in cp_parser_enum_specifier to be bypassed. This patch only sets OPAQUE_ENUM_P and ENUM_FIXED_UNDERLYING_TYPE_P when actually pushing a new tag for the enum. Successfully tested on x86_64-pc-linux-gnu. PR c++/115806 gcc/cp/ChangeLog: * decl.cc (start_enum): Only set OPAQUE_ENUM_P and ENUM_FIXED_UNDERLYING_TYPE_P when pushing a new tag. gcc/testsuite/ChangeLog: * g++.dg/parse/enum15.C: New test. --- gcc/cp/decl.cc | 22 ++++++++++++---------- gcc/testsuite/g++.dg/parse/enum15.C | 9 +++++++++ 2 files changed, 21 insertions(+), 10 deletions(-) create mode 100644 gcc/testsuite/g++.dg/parse/enum15.C diff --git a/gcc/cp/decl.cc b/gcc/cp/decl.cc index a468bfdb7b6..f23b635aec9 100644 --- a/gcc/cp/decl.cc +++ b/gcc/cp/decl.cc @@ -17059,22 +17059,24 @@ start_enum (tree name, tree enumtype, tree underlying_type, enumtype = cxx_make_type (ENUMERAL_TYPE); enumtype = pushtag (name, enumtype); - /* std::byte aliases anything. */ - if (enumtype != error_mark_node - && TYPE_CONTEXT (enumtype) == std_node - && !strcmp ("byte", TYPE_NAME_STRING (enumtype))) - TYPE_ALIAS_SET (enumtype) = 0; + if (enumtype != error_mark_node) + { + /* The enum is considered opaque until the opening '{' of the + enumerator list. */ + SET_OPAQUE_ENUM_P (enumtype, true); + ENUM_FIXED_UNDERLYING_TYPE_P (enumtype) = !! underlying_type; + + /* std::byte aliases anything. */ + if (TYPE_CONTEXT (enumtype) == std_node + && !strcmp ("byte", TYPE_NAME_STRING (enumtype))) + TYPE_ALIAS_SET (enumtype) = 0; + } } else enumtype = xref_tag (enum_type, name); if (enumtype == error_mark_node) return error_mark_node; - - /* The enum is considered opaque until the opening '{' of the - enumerator list. */ - SET_OPAQUE_ENUM_P (enumtype, true); - ENUM_FIXED_UNDERLYING_TYPE_P (enumtype) = !! underlying_type; } SET_SCOPED_ENUM_P (enumtype, scoped_enum_p); diff --git a/gcc/testsuite/g++.dg/parse/enum15.C b/gcc/testsuite/g++.dg/parse/enum15.C new file mode 100644 index 00000000000..d19262156b9 --- /dev/null +++ b/gcc/testsuite/g++.dg/parse/enum15.C @@ -0,0 +1,9 @@ +// PR c++/115806 +// { dg-do compile } + +template <typename T> +struct S { + enum E { a }; // { dg-note "previous definition" } + enum E { b }; // { dg-error "multiple definition" } +}; +S<int> s; -- 2.44.0