diff mbox series

c++: Fix up C++23 [] <...> requires primary -> type {} parsing [PR99850]

Message ID 20210414191837.GW1179226@tucnak
State New
Headers show
Series c++: Fix up C++23 [] <...> requires primary -> type {} parsing [PR99850] | expand

Commit Message

Jakub Jelinek April 14, 2021, 7:18 p.m. UTC
Hi!

The requires clause parsing has code to suggest users wrapping
non-primary expressions in (), so if it e.g. parses a primary expression
and sees it is followed by ++, --, ., ( or -> among other things it
will try to reparse it as assignment expression or what and if that works
suggests wrapping it inside of parens.
When it is requires-clause that is after <typename T> etc. it already
has an exception from that as ( can occur in valid C++20 expression there
- starting the parameters of the lambda.
In C++23 another case can occur, as the parameters with the ()s can be
omitted, requires C can be followed immediately by -> which starts a
trailing return type.  Even in that case, we don't want to parse that
as C->...

Fixed thusly, bootstrapped/regtested on x86_64-linux and i686-linux (with
GXX_TESTSUITE_STDS=98,11,14,17,20,2b ), ok for trunk?

2021-04-14  Jakub Jelinek  <jakub@redhat.com>

	PR c++/99850
	* parser.c (cp_parser_constraint_requires_parens) <case CPP_DEREF>:
	If lambda_p, return pce_ok for C++23 or later instead of
	pce_maybe_postfix.

	* g++.dg/cpp23/lambda-specifiers2.C: New test.


	Jakub

Comments

Jason Merrill April 15, 2021, 7:43 p.m. UTC | #1
On 4/14/21 3:18 PM, Jakub Jelinek wrote:
> The requires clause parsing has code to suggest users wrapping
> non-primary expressions in (), so if it e.g. parses a primary expression
> and sees it is followed by ++, --, ., ( or -> among other things it
> will try to reparse it as assignment expression or what and if that works
> suggests wrapping it inside of parens.
> When it is requires-clause that is after <typename T> etc. it already
> has an exception from that as ( can occur in valid C++20 expression there
> - starting the parameters of the lambda.
> In C++23 another case can occur, as the parameters with the ()s can be
> omitted, requires C can be followed immediately by -> which starts a
> trailing return type.  Even in that case, we don't want to parse that
> as C->...

> Fixed thusly, bootstrapped/regtested on x86_64-linux and i686-linux (with
> GXX_TESTSUITE_STDS=98,11,14,17,20,2b ), ok for trunk?
> 
> 2021-04-14  Jakub Jelinek  <jakub@redhat.com>
> 
> 	PR c++/99850
> 	* parser.c (cp_parser_constraint_requires_parens) <case CPP_DEREF>:
> 	If lambda_p, return pce_ok for C++23 or later instead of
> 	pce_maybe_postfix.
> 
> 	* g++.dg/cpp23/lambda-specifiers2.C: New test.
> 
> --- gcc/cp/parser.c.jj	2021-04-14 10:48:41.318103715 +0200
> +++ gcc/cp/parser.c	2021-04-14 14:52:03.220235527 +0200
> @@ -28526,7 +28526,19 @@ cp_parser_constraint_requires_parens (cp
>         case CPP_PLUS_PLUS:
>         case CPP_MINUS_MINUS:
>         case CPP_DOT:
> +	/* Unenclosed postfix operator.  */
> +	return pce_maybe_postfix;
> +
>         case CPP_DEREF:
> +	/* A primary constraint that precedes the lambda-declarator of a
> +	   lambda expression is followed by trailing return type.
> +
> +	      []<typename T> requires C -> void {}
> +
> +	   Don't try to re-parse this as a postfix expression in
> +	   C++23 and later.  In C++20 ( needs to come in between.  */
> +	if (lambda_p && cxx_dialect >= cxx23)
> +	  return pce_ok;

I think let's not make this depend on cxx_dialect, since we allow this 
in C++20 mode as well with a pedwarn.  OK with that change.

>   	/* Unenclosed postfix operator.  */
>   	return pce_maybe_postfix;
>      }
> --- gcc/testsuite/g++.dg/cpp23/lambda-specifiers2.C.jj	2021-04-14 15:01:41.728714721 +0200
> +++ gcc/testsuite/g++.dg/cpp23/lambda-specifiers2.C	2021-04-14 15:01:32.959813534 +0200
> @@ -0,0 +1,7 @@
> +// PR c++/99850
> +// P1102R2 - Down with ()!
> +// { dg-do compile { target c++23 } }
> +
> +auto l = []<auto> requires true -> void {};
> +template <typename...> concept C = true;
> +auto m = []<typename... Ts> requires (C<Ts> && ...) -> void {};
> 
> 	Jakub
>
diff mbox series

Patch

--- gcc/cp/parser.c.jj	2021-04-14 10:48:41.318103715 +0200
+++ gcc/cp/parser.c	2021-04-14 14:52:03.220235527 +0200
@@ -28526,7 +28526,19 @@  cp_parser_constraint_requires_parens (cp
       case CPP_PLUS_PLUS:
       case CPP_MINUS_MINUS:
       case CPP_DOT:
+	/* Unenclosed postfix operator.  */
+	return pce_maybe_postfix;
+
       case CPP_DEREF:
+	/* A primary constraint that precedes the lambda-declarator of a
+	   lambda expression is followed by trailing return type.
+
+	      []<typename T> requires C -> void {}
+
+	   Don't try to re-parse this as a postfix expression in
+	   C++23 and later.  In C++20 ( needs to come in between.  */
+	if (lambda_p && cxx_dialect >= cxx23)
+	  return pce_ok;
 	/* Unenclosed postfix operator.  */
 	return pce_maybe_postfix;
    }
--- gcc/testsuite/g++.dg/cpp23/lambda-specifiers2.C.jj	2021-04-14 15:01:41.728714721 +0200
+++ gcc/testsuite/g++.dg/cpp23/lambda-specifiers2.C	2021-04-14 15:01:32.959813534 +0200
@@ -0,0 +1,7 @@ 
+// PR c++/99850
+// P1102R2 - Down with ()!
+// { dg-do compile { target c++23 } }
+
+auto l = []<auto> requires true -> void {};
+template <typename...> concept C = true;
+auto m = []<typename... Ts> requires (C<Ts> && ...) -> void {};