c++: Fix parsing [[]][[]];
Checks
Commit Message
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 <jakub@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.
Jakub
Comments
On Tue, Dec 05, 2023 at 08:51:51AM +0100, Jakub Jelinek wrote:
> Hi!
>
> When working on the previous patch I put [[]] [[]] asm (""); into a
> testcase, but was surprised it wasn't parsed.
By wasn't parsed you mean we gave an error, right? I only see an error
with block-scope [[]] [[]];.
> 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?
It seems marginally better to me to use void_list_node so that we don't
need a new parm, like what we do when parsing parameters: ()/(void)/(...),
but I should let others decide.
If we stay with any_p, please add a comment saying that it means "found any",
not "accepts any" or something else. Thanks,
> 2023-12-05 Jakub Jelinek <jakub@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
>
Marek
@@ -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;
@@ -0,0 +1,9 @@
+// { dg-do compile { target c++11 } }
+
+[[]] [[]];
+
+[[]] [[]] void
+foo ()
+{
+ [[]] [[]];
+}