On Tue, May 09, 2023 at 01:17:09PM -0400, Jason Merrill wrote:
> How about changing cp_parser_std_attribute to set TREE_VALUE to
> error_mark_node if it skips arguments?

In limited testing that seems to work (tried
GXX_TESTSUITE_STDS=98,11,14,17,20,2b make -j32 -k check-g++ 
RUNTESTFLAGS='dg.exp=*attr*'
so far with it).

Will bootstrap/regtest it tonight.

Ok if it passes?

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

        PR c++/109756
        * parser.cc (cp_parser_std_attribute): For unknown attributes with
        arguments set TREE_VALUE (attribute) to error_mark_node after skipping
        the balanced tokens.
        (cp_parser_std_attribute_list): If ... is used after attribute without
        arguments, diagnose it and return error_mark_node.  If
        TREE_VALUE (attribute) is error_mark_node, don't call
        make_pack_expansion nor return early error_mark_node.

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

--- gcc/cp/parser.cc.jj 2023-04-25 16:40:42.010723809 +0200
+++ gcc/cp/parser.cc    2023-05-09 20:22:42.025601924 +0200
@@ -29468,9 +29468,12 @@ cp_parser_std_attribute (cp_parser *pars
          }
 
        /* For unknown attributes, just skip balanced tokens instead of
-          trying to parse the arguments.  */
+          trying to parse the arguments.  Set TREE_VALUE (attribute) to
+          error_mark_node to distinguish skipped arguments from attributes
+          with no arguments.  */
        for (size_t n = cp_parser_skip_balanced_tokens (parser, 1) - 1; n; --n)
          cp_lexer_consume_token (parser->lexer);
+       TREE_VALUE (attribute) = error_mark_node;
        return attribute;
       }
 
@@ -29562,7 +29565,13 @@ cp_parser_std_attribute_list (cp_parser
          if (attribute == NULL_TREE)
            error_at (token->location,
                      "expected attribute before %<...%>");
-         else
+         else if (TREE_VALUE (attribute) == NULL_TREE)
+           {
+             error_at (token->location, "attribute with no arguments "
+                                        "contains no parameter packs");
+             return error_mark_node;
+           }
+         else if (TREE_VALUE (attribute) != error_mark_node)
            {
              tree pack = make_pack_expansion (TREE_VALUE (attribute));
              if (pack == error_mark_node)
--- gcc/testsuite/g++.dg/cpp0x/gen-attrs-78.C.jj        2023-05-08 
12:33:13.387581760 +0200
+++ gcc/testsuite/g++.dg/cpp0x/gen-attrs-78.C   2023-05-08 12:32:23.146301128 
+0200
@@ -0,0 +1,29 @@
+// PR c++/109756
+// { dg-do compile { target c++11 } }
+// { dg-options "-Wno-attributes" }
+
+template <int ...args>
+[[noreturn...]]                                        // { dg-error 
"attribute with no arguments contains no parameter packs" }
+[[deprecated...]]                              // { dg-error "attribute with 
no arguments contains no parameter packs" }
+[[nodiscard...]]                               // { dg-error "attribute with 
no arguments contains no parameter packs" }
+int foo (int x)
+{
+  switch (x)
+    {
+    case 1:
+      [[likely...]];                           // { dg-error "attribute with 
no arguments contains no parameter packs" }
+      [[fallthrough...]];                      // { dg-error "attribute with 
no arguments contains no parameter packs" }
+    case 2:
+      [[unlikely...]];                         // { dg-error "attribute with 
no arguments contains no parameter packs" }
+
+      break;
+    default:
+      break;
+    }
+  struct T {};
+  struct S { [[no_unique_address...]] T t; };  // { dg-error "attribute with 
no arguments contains no parameter packs" }
+  for (;;)
+    ;
+}
+
+int a = foo <1, 2, 3> (4);


        Jakub

Reply via email to