On Tue, Dec 05, 2023 at 09:45:32AM -0500, Marek Polacek wrote:
> > 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 [[]] [[]];.

Yeah.
The reason why [[]][[]]; works at namespace scope is that if
  else if (cp_lexer_nth_token_is (parser->lexer,
                                  cp_parser_skip_std_attribute_spec_seq (parser,
                                                                         1),
                                  CPP_SEMICOLON))
which is the case here then even if after parsing the attributes next token
isn't CPP_SEMICOLON (the case here without the patch), it will just return
and another cp_parser_declaration will parse another [[]], that time also
with CPP_SEMICOLON.

> 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.

Here is a modified version of the patch which does it like that.

2023-12-05  Jakub Jelinek  <ja...@redhat.com>

        * parser.cc (cp_parser_std_attribute_spec): Return void_list_node
        rather than NULL_TREE if token is neither CPP_OPEN_SQUARE nor
        RID_ALIGNAS CPP_KEYWORD.
        (cp_parser_std_attribute_spec_seq): For attr_spec == void_list_node
        break, for attr_spec == NULL_TREE continue.

        * g++.dg/cpp0x/gen-attrs-79.C: New test.

--- gcc/cp/parser.cc.jj 2023-12-05 16:18:32.224909370 +0100
+++ gcc/cp/parser.cc    2023-12-05 17:07:34.690170639 +0100
@@ -30244,7 +30244,11 @@ void cp_parser_late_contract_condition (
      [ [ assert :  contract-mode [opt] : conditional-expression ] ]
      [ [ pre :  contract-mode [opt] : conditional-expression ] ]
      [ [ post :  contract-mode [opt] identifier [opt] :
-        conditional-expression ] ]  */
+        conditional-expression ] ]
+
+   Return void_list_node if the current token doesn't start an
+   attribute-specifier to differentiate from NULL_TREE returned e.g.
+   for [ [ ] ].  */
 
 static tree
 cp_parser_std_attribute_spec (cp_parser *parser)
@@ -30324,7 +30328,7 @@ cp_parser_std_attribute_spec (cp_parser
 
       if (token->type != CPP_KEYWORD
          || token->keyword != RID_ALIGNAS)
-       return NULL_TREE;
+       return void_list_node;
 
       cp_lexer_consume_token (parser->lexer);
       maybe_warn_cpp0x (CPP0X_ATTRIBUTES);
@@ -30397,8 +30401,12 @@ cp_parser_std_attribute_spec_seq (cp_par
   while (true)
     {
       tree attr_spec = cp_parser_std_attribute_spec (parser);
-      if (attr_spec == NULL_TREE)
+      if (attr_spec == void_list_node)
        break;
+      /* Accept [[]][[]]; for which cp_parser_std_attribute_spec
+        returns NULL_TREE as there are no attributes.  */
+      if (attr_spec == NULL_TREE)
+       continue;
       if (attr_spec == error_mark_node)
        return error_mark_node;
 
--- gcc/testsuite/g++.dg/cpp0x/gen-attrs-79.C.jj        2023-12-05 
17:04:14.235988879 +0100
+++ gcc/testsuite/g++.dg/cpp0x/gen-attrs-79.C   2023-12-05 17:04:14.235988879 
+0100
@@ -0,0 +1,9 @@
+// { dg-do compile { target c++11 } }
+
+[[]] [[]];
+
+[[]] [[]] void
+foo ()
+{
+  [[]] [[]];
+}


        Jakub

Reply via email to