On 8/9/24 4:19 AM, Simon Martin wrote:
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.
OK.
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;