On 2/14/26 10:15 AM, Ben Wu wrote:
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.
Thanks, I've queued this patch for next stage 1.
-- 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