Hi! When working on the previous patch I put [[]] [[]] asm (""); into a testcase, but was surprised it wasn't parsed. The problem is that when cp_parser_std_attribute_spec returns NULL, it can mean 2 different things, one is that the next token(s) are neither [[ nor alignas (in that case the caller should break from the loop), or when we parsed something like [[]] - it was valid attribute specifier, but didn't specify any attributes in it.
The following patch fixes that by adding another parameter to differentiate between the cases, guess another option would be to use some magic tree value for the break case instead of NULL_TREE (but error_mark_node is already taken and means something else). Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk? Or shall I go with some magic return which will never happen otherwise? void_node? 2023-12-05 Jakub Jelinek <ja...@redhat.com> * parser.cc (cp_parser_std_attribute_spec): Add ANY_P argument, set what it points to initially to true and only if token is neither CPP_OPEN_SQUARE nor RID_ALIGNAS CPP_KEYWORD set it to false. (cp_parser_std_attribute_spec_seq): Adjust cp_parser_std_attribute_spec caller. If it returns NULL_TREE and any_p is true, continue rather than break. * g++.dg/cpp0x/gen-attrs-79.C: New test. --- gcc/cp/parser.cc.jj 2023-12-04 20:23:53.225009856 +0100 +++ gcc/cp/parser.cc 2023-12-04 20:49:21.160426104 +0100 @@ -2703,7 +2703,7 @@ static tree cp_parser_gnu_attribute_list static tree cp_parser_std_attribute (cp_parser *, tree); static tree cp_parser_std_attribute_spec - (cp_parser *); + (cp_parser *, bool *); static tree cp_parser_std_attribute_spec_seq (cp_parser *); static size_t cp_parser_skip_std_attribute_spec_seq @@ -30265,11 +30265,12 @@ void cp_parser_late_contract_condition ( conditional-expression ] ] */ static tree -cp_parser_std_attribute_spec (cp_parser *parser) +cp_parser_std_attribute_spec (cp_parser *parser, bool *any_p) { tree attributes = NULL_TREE; cp_token *token = cp_lexer_peek_token (parser->lexer); + *any_p = true; if (token->type == CPP_OPEN_SQUARE && cp_lexer_peek_nth_token (parser->lexer, 2)->type == CPP_OPEN_SQUARE) { @@ -30342,7 +30343,10 @@ cp_parser_std_attribute_spec (cp_parser if (token->type != CPP_KEYWORD || token->keyword != RID_ALIGNAS) - return NULL_TREE; + { + *any_p = false; + return NULL_TREE; + } cp_lexer_consume_token (parser->lexer); maybe_warn_cpp0x (CPP0X_ATTRIBUTES); @@ -30414,9 +30418,16 @@ cp_parser_std_attribute_spec_seq (cp_par while (true) { - tree attr_spec = cp_parser_std_attribute_spec (parser); + bool any_p; + tree attr_spec = cp_parser_std_attribute_spec (parser, &any_p); if (attr_spec == NULL_TREE) - break; + { + /* Accept [[]][[]]; for which cp_parser_std_attribute_spec + also returns NULL_TREE as there are no attributes. */ + if (any_p) + continue; + break; + } if (attr_spec == error_mark_node) return error_mark_node; --- gcc/testsuite/g++.dg/cpp0x/gen-attrs-79.C.jj 2023-12-04 20:38:35.122574430 +0100 +++ gcc/testsuite/g++.dg/cpp0x/gen-attrs-79.C 2023-12-04 20:38:29.468654143 +0100 @@ -0,0 +1,9 @@ +// { dg-do compile { target c++11 } } + +[[]] [[]]; + +[[]] [[]] void +foo () +{ + [[]] [[]]; +} Jakub