On Thu, Mar 13, 2025 at 01:45:43PM -0400, Jason Merrill wrote: > On 3/13/25 11:27 AM, Jakub Jelinek wrote: > Parsing a jump-statement under cp_parser_expression_statement just because > it happens to start with __attribute is pretty strange.
It is true that it is pretty strange, but that is where we handle the empty declarations with GNU attributes (or shall those be called attribute declarations) as well. Or are empty statements with GNU attribute expression-statement with no expression? > How about changing cp_parser_std_attribute_spec_seq in cp_parser_statement > to cp_parser_attributes_opt? I'd be afraid that would be quite significant change of behavior everywhere, something that C doesn't allow (like mixing std and GNU attributes in any orders or [[]] __attribute__(()) [[]][[]] __attribute__(()) expression-statement). Or it would allow __attribute__(()) on while, do, for, if, switch, ..., again something that wasn't accepted before. In any case, calling cp_parser_jump_expression from cp_parser_statement directly rather than from cp_parser_expression_statement is easily possible just by doing else if (cp_next_tokens_can_be_gnu_attribute_p (parser)) { unsigned int n = cp_parser_skip_gnu_attributes_opt (parser, 1); if (cp_lexer_nth_token_is_keyword (parser->lexer, n, RID_RETURN)) { tree attr = cp_parser_gnu_attributes_opt (parser); for (tree a = lookup_attribute ("musttail", attr); a; a = lookup_attribute ("musttail", TREE_CHAIN (a))) if (TREE_VALUE (a)) error ("%qs attribute does not take any arguments", "musttail"); statement = cp_parser_jump_statement (parser, attr); if (attr != NULL_TREE && any_nonignored_attribute_p (attr)) warning_at (loc, OPT_Wattributes, "attributes at the beginning of statement are " "ignored"); return statement; } } after else if (token->type == CPP_EOF) { cp_parser_error (parser, "expected statement"); return; } Or the GNU attributes on empty statement stuff could move there as well. Jakub