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

Reply via email to