diff mbox series

[v2] c++: Accept elaborated-enum-base in system headers

Message ID ZInBSpWMc7qz9m53@arm.com
State New
Headers show
Series [v2] c++: Accept elaborated-enum-base in system headers | expand

Commit Message

Alex Coplan June 14, 2023, 1:31 p.m. UTC
Hi,

This is a v2 patch addressing feedback for:
https://gcc.gnu.org/pipermail/gcc-patches/2023-June/621050.html

macOS SDK headers using the CF_ENUM macro can expand to invalid C++ code
of the form:

typedef enum T : BaseType T;

i.e. an elaborated-type-specifier with an additional enum-base.
Upstream LLVM can be made to accept the above construct with
-Wno-error=elaborated-enum-base.

This patch adds the -Welaborated-enum-base warning to GCC and adjusts
the C++ parser to emit this warning instead of rejecting this code
outright.

The macro expansion in the macOS headers occurs in the case that the
compiler declares support for enums with underlying type using
__has_feature, see
https://gcc.gnu.org/pipermail/gcc-patches/2023-May/618450.html

GCC rejecting this construct outright means that GCC fails to bootstrap
on Darwin in the case that it (correctly) implements __has_feature and
declares support for C++ enums with underlying type.

With this patch, GCC can bootstrap on Darwin in combination with the
(WIP) __has_feature patch posted at:
https://gcc.gnu.org/pipermail/gcc-patches/2023-May/617878.html

Bootstrapped/regtested on aarch64-linux-gnu and x86_64-apple-darwin.
OK for trunk?

Thanks,
Alex

gcc/c-family/ChangeLog:

        * c.opt (Welaborated-enum-base): New.

gcc/cp/ChangeLog:

        * parser.cc (cp_parser_enum_specifier): Don't reject
        elaborated-type-specifier with enum-base, instead emit new
        Welaborated-enum-base warning.

gcc/testsuite/ChangeLog:

        * g++.dg/cpp0x/enum40.C: Adjust expected diagnostics.
        * g++.dg/cpp0x/forw_enum6.C: Likewise.
        * g++.dg/cpp0x/elab-enum-base.C: New test.

Comments

Iain Sandoe June 15, 2023, 9:50 a.m. UTC | #1
Hi Alex

> On 14 Jun 2023, at 14:31, Alex Coplan <alex.coplan@arm.com> wrote:
> 
> Hi,
> 
> This is a v2 patch addressing feedback for:
> https://gcc.gnu.org/pipermail/gcc-patches/2023-June/621050.html
> 
> macOS SDK headers using the CF_ENUM macro can expand to invalid C++ code
> of the form:
> 
> typedef enum T : BaseType T;
> 
> i.e. an elaborated-type-specifier with an additional enum-base.
> Upstream LLVM can be made to accept the above construct with
> -Wno-error=elaborated-enum-base.
> 
> This patch adds the -Welaborated-enum-base warning to GCC and adjusts
> the C++ parser to emit this warning instead of rejecting this code
> outright.
> 
> The macro expansion in the macOS headers occurs in the case that the
> compiler declares support for enums with underlying type using
> __has_feature, see
> https://gcc.gnu.org/pipermail/gcc-patches/2023-May/618450.html
> 
> GCC rejecting this construct outright means that GCC fails to bootstrap
> on Darwin in the case that it (correctly) implements __has_feature and
> declares support for C++ enums with underlying type.
> 
> With this patch, GCC can bootstrap on Darwin in combination with the
> (WIP) __has_feature patch posted at:
> https://gcc.gnu.org/pipermail/gcc-patches/2023-May/617878.html
> 
> Bootstrapped/regtested on aarch64-linux-gnu and x86_64-apple-darwin.
> OK for trunk?

For the record, I have tried this on Darwin21 and Darwin17 together with
my patches for __attribute__((availability(….))) which is also instrumental
in exposing more of the SDK content than we have previously been able
to parse on GCC.  Bootstrap succeeded there, and I will try on some older
versions as time permits (likely after WG21 meeting is done).

thanks
Iain

> 
> Thanks,
> Alex
> 
> gcc/c-family/ChangeLog:
> 
>        * c.opt (Welaborated-enum-base): New.
> 
> gcc/cp/ChangeLog:
> 
>        * parser.cc (cp_parser_enum_specifier): Don't reject
>        elaborated-type-specifier with enum-base, instead emit new
>        Welaborated-enum-base warning.
> 
> gcc/testsuite/ChangeLog:
> 
>        * g++.dg/cpp0x/enum40.C: Adjust expected diagnostics.
>        * g++.dg/cpp0x/forw_enum6.C: Likewise.
>        * g++.dg/cpp0x/elab-enum-base.C: New test.
> <patch.txt>
Jason Merrill June 15, 2023, 11:47 a.m. UTC | #2
On 6/14/23 09:31, Alex Coplan wrote:
> Hi,
> 
> This is a v2 patch addressing feedback for:
> https://gcc.gnu.org/pipermail/gcc-patches/2023-June/621050.html
> 
> macOS SDK headers using the CF_ENUM macro can expand to invalid C++ code
> of the form:
> 
> typedef enum T : BaseType T;
> 
> i.e. an elaborated-type-specifier with an additional enum-base.
> Upstream LLVM can be made to accept the above construct with
> -Wno-error=elaborated-enum-base.
> 
> This patch adds the -Welaborated-enum-base warning to GCC and adjusts
> the C++ parser to emit this warning instead of rejecting this code
> outright.
> 
> The macro expansion in the macOS headers occurs in the case that the
> compiler declares support for enums with underlying type using
> __has_feature, see
> https://gcc.gnu.org/pipermail/gcc-patches/2023-May/618450.html
> 
> GCC rejecting this construct outright means that GCC fails to bootstrap
> on Darwin in the case that it (correctly) implements __has_feature and
> declares support for C++ enums with underlying type.
> 
> With this patch, GCC can bootstrap on Darwin in combination with the
> (WIP) __has_feature patch posted at:
> https://gcc.gnu.org/pipermail/gcc-patches/2023-May/617878.html
> 
> Bootstrapped/regtested on aarch64-linux-gnu and x86_64-apple-darwin.
> OK for trunk?
> 
> Thanks,
> Alex
> 
> gcc/c-family/ChangeLog:
> 
>          * c.opt (Welaborated-enum-base): New.

> +Welaborated-enum-base
> +C++ ObjC++ Var(warn_elaborated_enum_base) Warning Init(1)
> +Warn if an additional enum-base is used in an elaborated-type-specifier.
> +That is, if an enum with given underlying type and no enumerator list
> +is used in a declaration other than just a standalone declaration of the
> +enum.

Just the first line of description here; the rest should go in 
doc/invoke.texi.

Jason
diff mbox series

Patch

diff --git a/gcc/c-family/c.opt b/gcc/c-family/c.opt
index cead1995561..f935665d629 100644
--- a/gcc/c-family/c.opt
+++ b/gcc/c-family/c.opt
@@ -1488,6 +1488,13 @@  Wsubobject-linkage
 C++ ObjC++ Var(warn_subobject_linkage) Warning Init(1)
 Warn if a class type has a base or a field whose type uses the anonymous namespace or depends on a type with no linkage.
 
+Welaborated-enum-base
+C++ ObjC++ Var(warn_elaborated_enum_base) Warning Init(1)
+Warn if an additional enum-base is used in an elaborated-type-specifier.
+That is, if an enum with given underlying type and no enumerator list
+is used in a declaration other than just a standalone declaration of the
+enum.
+
 Wduplicate-decl-specifier
 C ObjC Var(warn_duplicate_decl_specifier) Warning LangEnabledBy(C ObjC,Wall)
 Warn when a declaration has duplicate const, volatile, restrict or _Atomic specifier.
diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc
index d77fbd20e56..4dd290717de 100644
--- a/gcc/cp/parser.cc
+++ b/gcc/cp/parser.cc
@@ -21024,11 +21024,13 @@  cp_parser_enum_specifier (cp_parser* parser)
 
   /* Check for the `:' that denotes a specified underlying type in C++0x.
      Note that a ':' could also indicate a bitfield width, however.  */
+  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
@@ -21077,10 +21079,13 @@  cp_parser_enum_specifier (cp_parser* parser)
 	  && cp_lexer_next_token_is_not (parser->lexer, CPP_SEMICOLON))
 	{
 	  if (has_underlying_type)
-	    cp_parser_commit_to_tentative_parse (parser);
-	  cp_parser_error (parser, "expected %<;%> or %<{%>");
-	  if (has_underlying_type)
-	    return error_mark_node;
+	    pedwarn (colon_loc,
+		     OPT_Welaborated_enum_base,
+		     "declaration of enumeration with "
+		     "fixed underlying type and no enumerator list is "
+		     "only permitted as a standalone declaration");
+	  else
+	    cp_parser_error (parser, "expected %<;%> or %<{%>");
 	}
     }
 
diff --git a/gcc/testsuite/g++.dg/cpp0x/elab-enum-base.C b/gcc/testsuite/g++.dg/cpp0x/elab-enum-base.C
new file mode 100644
index 00000000000..57141f013bd
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/elab-enum-base.C
@@ -0,0 +1,7 @@ 
+// { dg-do compile { target c++11 } }
+// { dg-options "" }
+// Empty dg-options to override -pedantic-errors.
+
+typedef long CFIndex;
+typedef enum CFComparisonResult : CFIndex CFComparisonResult;
+// { dg-warning "declaration of enumeration with fixed underlying type" "" { target *-*-* } .-1 }
diff --git a/gcc/testsuite/g++.dg/cpp0x/enum40.C b/gcc/testsuite/g++.dg/cpp0x/enum40.C
index cfdf2a4a18a..d3ffeb62d70 100644
--- a/gcc/testsuite/g++.dg/cpp0x/enum40.C
+++ b/gcc/testsuite/g++.dg/cpp0x/enum40.C
@@ -4,23 +4,25 @@ 
 void
 foo ()
 {
-  enum : int a alignas;		// { dg-error "expected" }
+  enum : int a alignas;		// { dg-error "declaration of enum" }
+  // { dg-error {expected '\(' before ';'} "" { target *-*-* } .-1 }
 }
 
 void
 bar ()
 {
-  enum : int a;			// { dg-error "expected" }
+  enum : int a;			// { dg-error "declaration of enum" }
 }
 
 void
 baz ()
 {
-  enum class a : int b alignas;	// { dg-error "expected" }
+  enum class a : int b alignas;	// { dg-error "declaration of enum" }
+  // { dg-error {expected '\(' before ';'} "" { target *-*-* } .-1 }
 }
 
 void
 qux ()
 {
-  enum class a : int b;		// { dg-error "expected" }
+  enum class a : int b;		// { dg-error "declaration of enum" }
 }
diff --git a/gcc/testsuite/g++.dg/cpp0x/forw_enum6.C b/gcc/testsuite/g++.dg/cpp0x/forw_enum6.C
index 01bf563bcdd..8ad3f733292 100644
--- a/gcc/testsuite/g++.dg/cpp0x/forw_enum6.C
+++ b/gcc/testsuite/g++.dg/cpp0x/forw_enum6.C
@@ -23,7 +23,7 @@  enum class E7 : int; //ok
 
 enum class E3 e3; // { dg-error "scoped enum must not use" }
 enum struct E3 e4; // { dg-error "scoped enum must not use" }
-enum E5 : int e5; // { dg-error "expected|invalid type" }
+enum E5 : int e5; // { dg-error "declaration of enumeration with fixed underlying type|invalid type" }
 
 enum E6 : int { a, b, c }; // { dg-message "previous definition" }
 enum E6 : int { a, b, c }; // { dg-error "multiple definition" }