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? Marek