Bootstrapped and tested on x86_64-pc-linux-gnu. I don't understand why
we give the scoped enum pedantic error in parse/enum5.C, so maybe we can
remove that pedwarn? I don't see why it would be helpful when parsing an
enum-base...

See https://gcc.gnu.org/pipermail/gcc-patches/2026-February/708061.html
for v1.

-- 8< --

Previously, we did not parse definitely in cp_parser_enum_specifier
after seeing CPP_COLON, since we allowed for bitfield widths to follow
"enum identifier :" in member-declarations. However, ISO says that in
such a situation, the colon should be parsed as an enum-base
([dcl.enum]/a), which means bitfield widths are not allowed. This
patch reverts the changes which allowed for bitfield widths, since
parsing definitely improves diagnostics for errant underlying types.

        PR c++/118374

gcc/cp/ChangeLog:

        * parser.cc (cp_parser_enum_specifier): Parse definitely
        before cp_parser_type_specifier_seq.

gcc/testsuite/ChangeLog:

        * g++.dg/cpp0x/enum1.C: Update test.
        * g++.dg/parse/enum5.C: Expect error with bitfield width
        and enum-key in member.
        * g++.dg/cpp0x/enum45.C: New test.
---
 gcc/cp/parser.cc                    | 24 +++++++++++++-----------
 gcc/testsuite/g++.dg/cpp0x/enum1.C  |  2 +-
 gcc/testsuite/g++.dg/cpp0x/enum45.C |  4 ++++
 gcc/testsuite/g++.dg/parse/enum5.C  |  2 +-
 4 files changed, 19 insertions(+), 13 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/cpp0x/enum45.C

diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc
index 0f53ff90215..f550ead1fb4 100644
--- a/gcc/cp/parser.cc
+++ b/gcc/cp/parser.cc
@@ -23838,26 +23838,18 @@ cp_parser_enum_specifier (cp_parser* parser)
   pop_deferring_access_checks ();
 
   /* Check for the `:' that denotes a specified underlying type in C++0x.
-     Note that a ':' could also indicate a bitfield width, however.  */
+     [dcl.enum]/1 says that a `:' following an enum-key is parsed as part
+     of an enum-base, so we can expect a type-specifier-seq rather than a
+     bitfield width.  */
   location_t colon_loc = UNKNOWN_LOCATION;
   if (cp_lexer_next_token_is (parser->lexer, CPP_COLON))
     {
       cp_decl_specifier_seq type_specifiers;
 
-      /* Consume the `:'.  */
-      colon_loc = cp_lexer_peek_token (parser->lexer)->location;
-      cp_lexer_consume_token (parser->lexer);
-
       auto tdf
        = make_temp_override (parser->type_definition_forbidden_message,
                              G_("types may not be defined in enum-base"));
 
-      /* Parse the type-specifier-seq.  */
-      cp_parser_type_specifier_seq (parser, CP_PARSER_FLAGS_NONE,
-                                   /*is_declaration=*/false,
-                                   /*is_trailing_return=*/false,
-                                    &type_specifiers);
-
       /* At this point this is surely not elaborated type specifier.  */
       if (!cp_parser_parse_definitely (parser))
        return NULL_TREE;
@@ -23865,8 +23857,18 @@ cp_parser_enum_specifier (cp_parser* parser)
       if (cxx_dialect < cxx11)
         maybe_warn_cpp0x (CPP0X_SCOPED_ENUMS);
 
+      /* Consume the `:'.  */
+      colon_loc = cp_lexer_peek_token (parser->lexer)->location;
+      cp_lexer_consume_token (parser->lexer);
+
       has_underlying_type = true;
 
+      /* Parse the type-specifier-seq.  */
+      cp_parser_type_specifier_seq (parser, CP_PARSER_FLAGS_NONE,
+                                   /*is_declaration=*/false,
+                                   /*is_trailing_return=*/false,
+                                   &type_specifiers);
+
       /* If that didn't work, stop.  */
       if (type_specifiers.type != error_mark_node)
         {
diff --git a/gcc/testsuite/g++.dg/cpp0x/enum1.C 
b/gcc/testsuite/g++.dg/cpp0x/enum1.C
index bf174295248..49d0fe1519d 100644
--- a/gcc/testsuite/g++.dg/cpp0x/enum1.C
+++ b/gcc/testsuite/g++.dg/cpp0x/enum1.C
@@ -1,5 +1,5 @@
 // PR c++/38021
 // { dg-do compile { target c++11 } }
 
-enum : { };    // { dg-error "expected" }
+enum : { };    // { dg-error "expected|ISO" }
 enum : 3 { };  // { dg-error "expected" }
diff --git a/gcc/testsuite/g++.dg/cpp0x/enum45.C 
b/gcc/testsuite/g++.dg/cpp0x/enum45.C
new file mode 100644
index 00000000000..c9f66d7be56
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/enum45.C
@@ -0,0 +1,4 @@
+// PR c++/118374
+// { dg-do compile { target c++11 } }
+
+enum class X : int8_t; // { dg-error "does not name a type" }
diff --git a/gcc/testsuite/g++.dg/parse/enum5.C 
b/gcc/testsuite/g++.dg/parse/enum5.C
index 18480520a6f..3d2b0820934 100644
--- a/gcc/testsuite/g++.dg/parse/enum5.C
+++ b/gcc/testsuite/g++.dg/parse/enum5.C
@@ -7,7 +7,7 @@ typedef unsigned int T;
 struct D {
         T : sizeof(unsigned int) * CHAR_BIT; // OK
         EE : sizeof(EE) * CHAR_BIT; // OK
-        enum EE : sizeof(EE) * CHAR_BIT; // not OK
+        enum EE : sizeof(EE) * CHAR_BIT; // { dg-error "expected|scoped" }
         enum EE xxxx : sizeof(EE) * CHAR_BIT; // OK
         T x : sizeof(unsigned int) * CHAR_BIT; // OK
         enum FF {ff} : sizeof(FF) * CHAR_BIT; // OK
-- 
2.52.0

Reply via email to