On 5/9/24 14:12, Jakub Jelinek wrote:

The C++26 P2662R3 Pack indexing paper mentions that both GCC
and MSVC don't handle T...[10] parameter declaration when T
is a pack.  While that will change meaning in C++26, in C++11 .. C++23
this ought to be valid.

Sure, but I don't think it does anyone any favors to start accepting a pattern that we know is going to break before long. Us not accepting it was part of the rationale for the paper.

Also, T...(args) as well.

This part of the patch is OK.

The following patch handles those in cp_parser_direct_declarator.

Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?

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

        PR c++/115012
        * parser.cc (cp_parser_direct_declarator): Handle
        abstract declarator starting with ... followed by [
        or (.

        * g++.dg/cpp0x/variadic185.C: New test.
        * g++.dg/cpp0x/variadic186.C: New test.

--- gcc/cp/parser.cc.jj 2024-05-09 10:30:58.000000000 +0200
+++ gcc/cp/parser.cc    2024-05-09 16:44:01.250777325 +0200
@@ -23916,7 +23916,12 @@ cp_parser_direct_declarator (cp_parser*
      {
        /* Peek at the next token.  */
        token = cp_lexer_peek_token (parser->lexer);
-      if (token->type == CPP_OPEN_PAREN)
+      if (token->type == CPP_OPEN_PAREN
+         || (first
+             && dcl_kind != CP_PARSER_DECLARATOR_NAMED
+             && token->type == CPP_ELLIPSIS
+             && cxx_dialect > cxx98
+             && cp_lexer_nth_token_is (parser->lexer, 2, CPP_OPEN_PAREN)))
        {
          /* This is either a parameter-declaration-clause, or a
             parenthesized declarator. When we know we are parsing a
@@ -23955,6 +23960,11 @@ cp_parser_direct_declarator (cp_parser*
Thus again, we try a parameter-declaration-clause, and if
             that fails, we back out and return.  */
+         bool pack_expansion_p = token->type == CPP_ELLIPSIS;
+
+         if (pack_expansion_p)
+           /* Consume the `...' */
+           cp_lexer_consume_token (parser->lexer);
if (!first || dcl_kind != CP_PARSER_DECLARATOR_NAMED)
            {
@@ -24098,6 +24108,7 @@ cp_parser_direct_declarator (cp_parser*
                                                     attrs,
                                                     parens_loc);
                  declarator->attributes = gnu_attrs;
+                 declarator->parameter_pack_p |= pack_expansion_p;
                  /* Any subsequent parameter lists are to do with
                     return type, so are not those of the declared
                     function.  */
@@ -24121,7 +24132,7 @@ cp_parser_direct_declarator (cp_parser*
/* If this is the first, we can try a parenthesized
             declarator.  */
-         if (first)
+         if (first && !pack_expansion_p)
            {
              bool saved_in_type_id_in_expr_p;
@@ -24156,16 +24167,27 @@ cp_parser_direct_declarator (cp_parser*
          else
            break;
        }
-      else if ((!first || dcl_kind != CP_PARSER_DECLARATOR_NAMED)
-              && token->type == CPP_OPEN_SQUARE
-              && !cp_next_tokens_can_be_attribute_p (parser))
+      else if (((!first || dcl_kind != CP_PARSER_DECLARATOR_NAMED)
+               && token->type == CPP_OPEN_SQUARE
+               && !cp_next_tokens_can_be_attribute_p (parser))
+              || (first
+                  && dcl_kind != CP_PARSER_DECLARATOR_NAMED
+                  && token->type == CPP_ELLIPSIS
+                  && cp_lexer_nth_token_is (parser->lexer, 2, CPP_OPEN_SQUARE)
+                  && cxx_dialect > cxx98
+                  && !cp_nth_tokens_can_be_std_attribute_p (parser, 2)))
        {
          /* Parse an array-declarator.  */
          tree bounds, attrs;
+         bool pack_expansion_p = token->type == CPP_ELLIPSIS;
if (ctor_dtor_or_conv_p)
            *ctor_dtor_or_conv_p = 0;
+ if (pack_expansion_p)
+           /* Consume the `...' */
+           cp_lexer_consume_token (parser->lexer);
+
          open_paren = NULL;
          first = false;
          parser->default_arg_ok_p = false;
@@ -24220,6 +24242,7 @@ cp_parser_direct_declarator (cp_parser*
          attrs = cp_parser_std_attribute_spec_seq (parser);
          declarator = make_array_declarator (declarator, bounds);
          declarator->std_attributes = attrs;
+         declarator->parameter_pack_p |= pack_expansion_p;
        }
        else if (first && dcl_kind != CP_PARSER_DECLARATOR_ABSTRACT)
        {
--- gcc/testsuite/g++.dg/cpp0x/variadic185.C.jj 2024-05-09 15:08:49.070651189 
+0200
+++ gcc/testsuite/g++.dg/cpp0x/variadic185.C    2024-05-09 15:07:40.045583153 
+0200
@@ -0,0 +1,39 @@
+// PR c++/115012
+// { dg-do compile { target { c++11 && c++23_down } } }
+// { dg-final { scan-assembler "_Z3fooILi10EJidEEvDpAT__T0_" } }
+// { dg-final { scan-assembler "_Z3barILi10EiEvPT0_" } }
+// { dg-final { scan-assembler "_Z3bazILi10EJidEEvDpAT__T0_" } }
+// { dg-final { scan-assembler "_Z3quxILi5EJifEEvDpAT__AT__T0_" } }
+
+template <int N, typename ...T>
+void
+foo (T... x[N])
+{
+}
+
+template <int N, typename T>
+void
+bar (T [N])
+{
+}
+
+template <int N, typename ...T>
+void
+baz (T... [N])
+{
+}
+
+template <int N, typename ...T>
+void
+qux (T... [N][N])
+{
+}
+
+void
+corge (int a[10], double b[10], int c[5][5], float d[5][5])
+{
+  foo <10, int, double> (a, b);
+  bar <10, int> (a);
+  baz <10, int, double> (a, b);
+  qux <5, int, float> (c, d);
+}
--- gcc/testsuite/g++.dg/cpp0x/variadic186.C.jj 2024-05-09 16:39:50.409153099 
+0200
+++ gcc/testsuite/g++.dg/cpp0x/variadic186.C    2024-05-09 15:37:22.469569809 
+0200
@@ -0,0 +1,43 @@
+// PR c++/115012
+// { dg-do compile { target { c++11 } } }
+// { dg-final { scan-assembler "_Z3fooIJidEEvDpFT_iE" } }
+// { dg-final { scan-assembler "_Z3barIiEvPFT_iE" } }
+// { dg-final { scan-assembler "_Z3bazIJidEEvDpFT_iE" } }
+
+template <typename ...T>
+void
+foo (T... x (int))
+{
+}
+
+template <typename T>
+void
+bar (T (int))
+{
+}
+
+template <typename ...T>
+void
+baz (T... (int))
+{
+}
+
+int
+f1 (int)
+{
+  return 0;
+}
+
+double
+f2 (int)
+{
+  return 0;
+}
+
+void
+corge ()
+{
+  foo <int, double> (f1, f2);
+  bar <int> (f1);
+  baz <int, double> (f1, f2);
+}

        Jakub


Reply via email to