On 8/5/24 4:00 PM, Marek Polacek wrote:
On Mon, Aug 05, 2024 at 02:52:32PM -0400, Jason Merrill wrote:
On 8/5/24 2:44 PM, Marek Polacek wrote:
On Mon, Aug 05, 2024 at 12:00:04PM -0400, Jason Merrill wrote:
I think we also want to adjust the 'concept bool' handling in
cp_parser_decl_specifier_seq:
/* Warn for concept as a decl-specifier. We'll rewrite these
as
concept declarations later. */
{
cp_token *next = cp_lexer_peek_token (parser->lexer);
if (next->keyword == RID_BOOL)
=> permerror (next->location, "the %<bool%> keyword is not "
"allowed in a C++20 concept definition");
else
error_at (token->location, "C++20 concept definition syntax "
"is %<concept <name> = <expr>%>");
}
After the permerror let's skip the 'bool' token and continue trying to parse
a concept declaration. I think that should allow us to remove more of the
code in grokfndecl/grokvardecl?
If by skip you mean cp_lexer_consume_token, then that results in worse
diagnostics for e.g.
concept bool f3();
where it adds the extra "with no type" error:
Ah, yeah, cp_parser_decl_specifier_seq is too late for what I was thinking.
How about in cp_parser_template_declaration_after_parameters:
else if (flag_concepts
&& cp_lexer_next_token_is_keyword (parser->lexer, RID_CONCEPT)
&& cp_lexer_nth_token_is (parser->lexer, 2, CPP_NAME))
/* -fconcept-ts 'concept bool' syntax is handled below, in
cp_parser_single_declaration. */
decl = cp_parser_concept_definition (parser);
What happens if we remove the CPP_NAME check, so we commit to concept
parsing as soon as we see the keyword?
Hmm, for
template<typename T>
concept int f2() { return 0; }
concept bool f3();
it produces this output:
t.C:2:9: error: expected identifier before 'int'
2 | concept int f2() { return 0; }
| ^~~
t.C:2:31: error: expected ';' before 'concept'
2 | concept int f2() { return 0; }
| ^
| ;
3 | concept bool f3();
| ~~~~~~~
In cp_parser_concept_definition we have
cp_expr id = cp_parser_identifier (parser);
if (id == error_mark_node)
{
cp_parser_skip_to_end_of_statement (parser);
cp_parser_consume_semicolon_at_end_of_statement (parser);
return NULL_TREE;
}
cp_parser_identifier emits an error on the "int",
cp_parser_skip_to_end_of_statement consumes all tokens up to the '}'
(including) and then the next token is "concept", not a ';'. After
cp_parser_consume_semicolon_at_end_of_statement we end up at EOF. So
the whole f3 decl is skipped.
But the same thing will happen with a valid concept if you forget the ';':
template<typename T>
concept C = true
concept bool f3();
so I can "fix" it by adding a "stray" ';' in the test. That sound good?
Eh, I guess the current diagnostics are better, never mind. OK with the
small tweaks.
Jason