[PATCH] c++: Diagnose when "requires" is used instead of "requires requires" [PR94306]

Jason Merrill jason@redhat.com
Fri Mar 27 02:04:25 GMT 2020


On 3/26/20 6:36 PM, Patrick Palka wrote:
> On Thu, 26 Mar 2020, Jason Merrill wrote:
> 
>> On 3/26/20 5:28 PM, Patrick Palka wrote:
>>> This adds support to detect and recover from the case where an opening brace
>>> immediately follows the start of a requires-clause.  So rather than emitting
>>> the
>>> error
>>>
>>>     error: expected primary-expression before '{' token
>>>
>>> followed by a slew of irrevelant errors, we now assume the user had intended
>>> to
>>> write "requires requires {" and diagnose and recover accordingly.
>>>
>>> Tested on x86_64-pc-linux-gnu, does this look OK?
>>>
>>> gcc/cp/ChangeLog:
>>>
>>> 	PR c++/94306
>>> 	* parser.c (cp_parser_requires_clause_opt): Diagnose and recover from
>>> 	"requires {" when "requires requires {" was probably intended.
>>>
>>> gcc/testsuite/ChangeLog:
>>>
>>> 	PR c++/94306
>>> 	* g++.dg/concepts/diagnostic8.C: New test.
>>> ---
>>>    gcc/cp/parser.c                             | 17 ++++++++++++++++-
>>>    gcc/testsuite/g++.dg/concepts/diagnostic8.C |  6 ++++++
>>>    2 files changed, 22 insertions(+), 1 deletion(-)
>>>    create mode 100644 gcc/testsuite/g++.dg/concepts/diagnostic8.C
>>>
>>> diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
>>> index 05363653691..73c2c2cb010 100644
>>> --- a/gcc/cp/parser.c
>>> +++ b/gcc/cp/parser.c
>>> @@ -27639,7 +27639,22 @@ cp_parser_requires_clause_opt (cp_parser *parser,
>>> bool lambda_p)
>>>    	}
>>>          return NULL_TREE;
>>>        }
>>> -  cp_lexer_consume_token (parser->lexer);
>>> +
>>> +  cp_token *tok2 = cp_lexer_peek_nth_token (parser->lexer, 2);
>>> +  if (tok2->type == CPP_OPEN_BRACE)
>>
>> Do we want to handle an open paren the same way?
> 
> Hmm, wouldn't the error recovery be significantly different for an open
> paren here?  Just pretending that there's another "requires" token would
> mean we proceed as if we got "requires requires (" but that is still
> ill-formed I think.

Not ill-formed; a requires-expression can have a parameter-list.

>>
>>> +    {
>>> +      /* An opening brace following the start of a requires-clause is
>>> +	 ill-formed; the user likely forgot the second `requires' that
>>> +	 would start a requires-expression.  */
>>> +      gcc_rich_location richloc (tok2->location);
>>> +      richloc.add_fixit_insert_before (" requires");
>>> +      error_at (&richloc, "missing additional %<requires%> to start "
>>> +		"a requires-expression");
>>> +      /* Don't consume the `requires', so that it's reused as the start of
>>> a
>>> +	 requires-expression.  */
>>> +    }
>>> +  else
>>> +    cp_lexer_consume_token (parser->lexer);
>>>        if (!flag_concepts_ts)
>>>        return cp_parser_requires_clause_expression (parser, lambda_p);
>>> diff --git a/gcc/testsuite/g++.dg/concepts/diagnostic8.C
>>> b/gcc/testsuite/g++.dg/concepts/diagnostic8.C
>>> new file mode 100644
>>> index 00000000000..70d7e4a9cc1
>>> --- /dev/null
>>> +++ b/gcc/testsuite/g++.dg/concepts/diagnostic8.C
>>> @@ -0,0 +1,6 @@
>>> +// PR c++/94306
>>> +// { dg-do compile { target c++2a } }
>>> +
>>> +template<typename T> struct S { };
>>> +template<typename T> requires { typename T::type; } struct S<T> { };
>>> +// { dg-error "missing additional .requires." "" { target *-*-* } .-1 }
>>>
>>
>>
> 



More information about the Gcc-patches mailing list