From: Simon Martin Date: Thu, 8 Aug 2024 12:59:49 +0000 (+0200) Subject: c++: Don't accept multiple enum definitions within template class [PR115806] X-Git-Tag: basepoints/gcc-16~6698 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=786ebbd6058540b2110da16a693f0c582c11413c;p=thirdparty%2Fgcc.git c++: Don't accept multiple enum definitions within template class [PR115806] We have been accepting the following invalid code since revision 557831a91df === cut here === template struct S { enum E { a }; enum E { b }; }; S 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. 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. --- 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 +struct S { + enum E { a }; // { dg-note "previous definition" } + enum E { b }; // { dg-error "multiple definition" } +}; +S s;