public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [PATCH][RFC] c++: Accept elaborated-enum-base in system headers
@ 2023-06-08 11:06 Alex Coplan
  2023-06-08 18:06 ` Jason Merrill
  0 siblings, 1 reply; 3+ messages in thread
From: Alex Coplan @ 2023-06-08 11:06 UTC (permalink / raw)
  To: gcc-patches; +Cc: Jason Merrill, Nathan Sidwell, Iain Sandoe

[-- Attachment #1: Type: text/plain, Size: 2143 bytes --]

Hi,

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 macro expansion 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.

This patch attempts to accept this construct in the C++ parser but only
if it appears in system headers. 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

We also attempt to improve the diagnostic for this case, using a
similar diagnostic to that given by LLVM.

If it is more palatable I can look into restricting the change to accept
this code to only take effect on Darwin, but it's not clear that that's
any better or worse.

Other possible approaches here include trying to fixincludes the SDK
framework headers, but as Iain pointed out in the review of the
has_feature RFC, the necessary infrastructure doesn't exist at the
moment. Even if this support did exist, I believe the headers would
require quite extensive non-trivial "fixing".

Adjusting the parser to accept this construct in system headers seemed
more pragmatic and cleaner on balance.

Bootstrapped/regtested on aarch64-linux-gnu and x86_64-apple-darwin.

Any thoughts?

Thanks,
Alex

gcc/cp/ChangeLog:

	* parser.cc (cp_parser_enum_specifier): Accept
	elaborated-type-specifier with enum-base if in system headers.
	Improve diagnostic when rejecting such a construct.

gcc/testsuite/ChangeLog:

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

[-- Attachment #2: patch.txt --]
[-- Type: text/plain, Size: 4048 bytes --]

diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc
index d77fbd20e56..e13133a6cfb 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
@@ -21073,12 +21075,20 @@ cp_parser_enum_specifier (cp_parser* parser)
 	    return error_mark_node;
 	}
       /* An opaque-enum-specifier must have a ';' here.  */
-      if ((scoped_enum_p || underlying_type)
+      if ((scoped_enum_p
+	   || (underlying_type && !in_system_header_at (colon_loc)))
 	  && 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 %<{%>");
+	    {
+	      cp_parser_commit_to_tentative_parse (parser);
+	      error_at (colon_loc,
+			"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 %<{%>");
 	  if (has_underlying_type)
 	    return error_mark_node;
 	}
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" }
diff --git a/gcc/testsuite/g++.dg/ext/elab-enum-header.C b/gcc/testsuite/g++.dg/ext/elab-enum-header.C
new file mode 100644
index 00000000000..d8c03faf443
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/elab-enum-header.C
@@ -0,0 +1,5 @@
+// { dg-do compile { target c++11 } }
+// { dg-additional-options "-fpreprocessed" }
+# 1 "" 3
+typedef long CFIndex;
+typedef enum CFComparisonResult : CFIndex CFComparisonResult;
diff --git a/gcc/testsuite/g++.dg/ext/elab-enum-invalid.C b/gcc/testsuite/g++.dg/ext/elab-enum-invalid.C
new file mode 100644
index 00000000000..db3957d7367
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/elab-enum-invalid.C
@@ -0,0 +1,4 @@
+// { dg-do compile { target c++11 } }
+typedef long CFIndex;
+typedef enum CFComparisonResult : CFIndex CFComparisonResult;
+// { dg-error "declaration of enumeration with fixed underlying type" "" {target *-*-*} .-1 }

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [PATCH][RFC] c++: Accept elaborated-enum-base in system headers
  2023-06-08 11:06 [PATCH][RFC] c++: Accept elaborated-enum-base in system headers Alex Coplan
@ 2023-06-08 18:06 ` Jason Merrill
  2023-06-08 18:47   ` Fwd: " Iain Sandoe
  0 siblings, 1 reply; 3+ messages in thread
From: Jason Merrill @ 2023-06-08 18:06 UTC (permalink / raw)
  To: Alex Coplan, gcc-patches; +Cc: Nathan Sidwell, Iain Sandoe

On 6/8/23 07:06, Alex Coplan wrote:
> Hi,
> 
> 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.

I guess we might as well follow that example, and so instead of this check:

> +	   || (underlying_type && !in_system_header_at (colon_loc)))

Make the below an on-by-default pedwarn using OPT_Welaborated_enum_base, 
and don't return error_mark_node.

> +	      cp_parser_commit_to_tentative_parse (parser);
> +	      error_at (colon_loc,
> +			"declaration of enumeration with "
> +			"fixed underlying type and no enumerator list is "
> +			"only permitted as a standalone declaration");



^ permalink raw reply	[flat|nested] 3+ messages in thread

* Fwd: [PATCH][RFC] c++: Accept elaborated-enum-base in system headers
  2023-06-08 18:06 ` Jason Merrill
@ 2023-06-08 18:47   ` Iain Sandoe
  0 siblings, 0 replies; 3+ messages in thread
From: Iain Sandoe @ 2023-06-08 18:47 UTC (permalink / raw)
  To: Jason Merrill; +Cc: Alex Coplan, Nathan Sidwell, GCC Patches

[-- Attachment #1: Type: text/plain, Size: 1479 bytes --]



> Begin forwarded message:
> 
> From: Jason Merrill <jason@redhat.com>
> Subject: Re: [PATCH][RFC] c++: Accept elaborated-enum-base in system headers
> Date: 8 June 2023 at 19:06:36 BST
> To: Alex Coplan <alex.coplan@arm.com>, gcc-patches@gcc.gnu.org
> Cc: Nathan Sidwell <nathan@acm.org>, Iain Sandoe <iain@sandoe.co.uk>
> 
> On 6/8/23 07:06, Alex Coplan wrote:
>> Hi,
>> 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.
> 
> I guess we might as well follow that example, and so instead of this check:
> 
>> +	   || (underlying_type && !in_system_header_at (colon_loc)))
> 
> Make the below an on-by-default pedwarn using OPT_Welaborated_enum_base, and don't return error_mark_node.

I was also wondering about (for this and other reasons) a -fclang-compat to put some of these things behind (since std=clang++NN is not really going to work to describe other non-standard extensions etc. since most are not synchronised to std revisions.)

Iain

> 
>> +	      cp_parser_commit_to_tentative_parse (parser);
>> +	      error_at (colon_loc,
>> +			"declaration of enumeration with "
>> +			"fixed underlying type and no enumerator list is "
>> +			"only permitted as a standalone declaration");
> 
> 


^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2023-06-08 18:47 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-06-08 11:06 [PATCH][RFC] c++: Accept elaborated-enum-base in system headers Alex Coplan
2023-06-08 18:06 ` Jason Merrill
2023-06-08 18:47   ` Fwd: " Iain Sandoe

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).