On Fri, Feb 16, 2024 at 10:20:26PM +0100, Jakub Jelinek wrote:
> I've tried that (see below), but am getting
> Excess errors:
> /usr/src/gcc/gcc/testsuite/g++.dg/cpp23/explicit-obj-diagnostics3.C:33:29: 
> error: parameter packs not expanded with '...':

And the reason for those is that e.g. on the reduced
struct S0 {
  void j(this auto... selves) {}  // { dg-error "an explicit object parameter 
cannot be a function parameter pack" }
};
with the first posted patch we first do:
if (xobj_param_p && (declarator && declarator->parameter_pack_p))
and clear declarator->parameter_pack_p there.
Then comes
  if (parser->implicit_template_parms
      && ((token->type == CPP_ELLIPSIS
           && declarator_can_be_parameter_pack (declarator))
          || (declarator && declarator->parameter_pack_p)))
which is true only with the second patch and not the first.

Adding
   if (parser->implicit_template_parms
       && ((token->type == CPP_ELLIPSIS
           && declarator_can_be_parameter_pack (declarator))
-         || (declarator && declarator->parameter_pack_p)))
+         || (declarator && declarator->parameter_pack_p && !xobj_param_p)))
     {
       int latest_template_parm_idx = TREE_VEC_LENGTH
        (INNERMOST_TEMPLATE_PARMS (current_template_parms));
fixes some of the excess errors, but not all of them, e.g. on
struct S1 {
  void h(this auto&...) {}  // { dg-error "an explicit object parameter cannot 
be a function parameter pack" }
};
it still remains.  The problem in there is that apparently we
need declarator->parameter_pack_p cleared on the xobj diagnostics
iff it was previously set before the CPP_ELLIPSIS handling above it,
but not if it was set in that handling.  I'm afraid I have no idea
why though.

The following patch works.

2024-02-16  Jakub Jelinek  <ja...@redhat.com>

        PR c++/113802
        * parser.cc (cp_parser_parameter_declaration): Move the xobj_param_p
        pack diagnostics after ellipsis handling, but only clear
        declarator->parameter_pack_p for it if it was set before CPP_ELLIPSIS
        handling.  Ignore declarator->parameter_pack_p if xobj_param_p.
        Formatting fix.

        * g++.dg/cpp23/explicit-obj-diagnostics3.C (S0, S1, S2, S3, S4): Don't
        expect any diagnostics on f and fd member function templates, add
        similar templates with ...Selves instead of Selves as k and kd and
        expect diagnostics for those.

--- gcc/cp/parser.cc.jj 2024-02-16 17:38:27.802845433 +0100
+++ gcc/cp/parser.cc    2024-02-16 22:42:38.393896067 +0100
@@ -25734,39 +25734,25 @@ cp_parser_parameter_declaration (cp_pars
       decl_specifiers.locations[ds_this] = 0;
     }
 
-  if (xobj_param_p
-      && ((declarator && declarator->parameter_pack_p)
-         || cp_lexer_next_token_is (parser->lexer, CPP_ELLIPSIS)))
-    {
-      location_t xobj_param
-       = make_location (decl_specifiers.locations[ds_this],
-                        decl_spec_token_start->location,
-                        input_location);
-      error_at (xobj_param,
-               "an explicit object parameter cannot "
-               "be a function parameter pack");
-      /* Suppress errors that occur down the line.  */
-      if (declarator)
-       declarator->parameter_pack_p = false;
-    }
-
   /* If a function parameter pack was specified and an implicit template
      parameter was introduced during cp_parser_parameter_declaration,
      change any implicit parameters introduced into packs.  */
   if (parser->implicit_template_parms
       && ((token->type == CPP_ELLIPSIS
           && declarator_can_be_parameter_pack (declarator))
-         || (declarator && declarator->parameter_pack_p)))
+         || (declarator && declarator->parameter_pack_p && !xobj_param_p)))
     {
       int latest_template_parm_idx = TREE_VEC_LENGTH
        (INNERMOST_TEMPLATE_PARMS (current_template_parms));
 
       if (latest_template_parm_idx != template_parm_idx)
-       decl_specifiers.type = convert_generic_types_to_packs
-         (decl_specifiers.type,
-          template_parm_idx, latest_template_parm_idx);
+       decl_specifiers.type
+         = convert_generic_types_to_packs (decl_specifiers.type,
+                                           template_parm_idx,
+                                           latest_template_parm_idx);
     }
 
+  bool prev_parameter_pack_p = declarator && declarator->parameter_pack_p;
   if (cp_lexer_next_token_is (parser->lexer, CPP_ELLIPSIS))
     {
       tree type = decl_specifiers.type;
@@ -25794,6 +25780,22 @@ cp_parser_parameter_declaration (cp_pars
        }
     }
 
+  if (xobj_param_p
+      && (declarator ? declarator->parameter_pack_p
+                    : PACK_EXPANSION_P (decl_specifiers.type)))
+    {
+      location_t xobj_param
+       = make_location (decl_specifiers.locations[ds_this],
+                        decl_spec_token_start->location,
+                        input_location);
+      error_at (xobj_param,
+               "an explicit object parameter cannot "
+               "be a function parameter pack");
+      /* Suppress errors that occur down the line.  */
+      if (declarator)
+       declarator->parameter_pack_p = !prev_parameter_pack_p;
+    }
+
   /* The restriction on defining new types applies only to the type
      of the parameter, not to the default argument.  */
   parser->type_definition_forbidden_message = saved_message;
--- gcc/testsuite/g++.dg/cpp23/explicit-obj-diagnostics3.C.jj   2024-02-15 
20:01:40.349239387 +0100
+++ gcc/testsuite/g++.dg/cpp23/explicit-obj-diagnostics3.C      2024-02-16 
21:57:48.269851483 +0100
@@ -24,7 +24,7 @@ void S::f12(this S s = {}) {} // { dg-er
 
 struct S0 {
   template<typename Selves>
-  void f(this Selves...) {} // { dg-error "an explicit object parameter cannot 
be a function parameter pack" }
+  void f(this Selves...) {}
 
   template<typename Selves>
   void g(this Selves... selves) {}  // { dg-error "an explicit object 
parameter cannot be a function parameter pack" }
@@ -32,19 +32,25 @@ struct S0 {
   void h(this auto...) {}  // { dg-error "an explicit object parameter cannot 
be a function parameter pack" }
   void j(this auto... selves) {}  // { dg-error "an explicit object parameter 
cannot be a function parameter pack" }
 
+  template<typename ...Selves>
+  void k(this Selves...) {}  // { dg-error "an explicit object parameter 
cannot be a function parameter pack" }
+
   template<typename Selves>
-  void fd(this Selves...);  // { dg-error "an explicit object parameter cannot 
be a function parameter pack" }
+  void fd(this Selves...);
 
   template<typename Selves>
   void gd(this Selves... selves);  // { dg-error "an explicit object parameter 
cannot be a function parameter pack" }
 
   void hd(this auto...);  // { dg-error "an explicit object parameter cannot 
be a function parameter pack" }
   void jd(this auto... selves);  // { dg-error "an explicit object parameter 
cannot be a function parameter pack" }
+
+  template<typename ...Selves>
+  void kd(this Selves...);  // { dg-error "an explicit object parameter cannot 
be a function parameter pack" }
 };
 
 struct S1 {
   template<typename Selves>
-  void f(this Selves&...) {}  // { dg-error "an explicit object parameter 
cannot be a function parameter pack" }
+  void f(this Selves&...) {}
 
   template<typename Selves>
   void g(this Selves&... selves) {}  // { dg-error "an explicit object 
parameter cannot be a function parameter pack" }
@@ -52,19 +58,25 @@ struct S1 {
   void h(this auto&...) {}  // { dg-error "an explicit object parameter cannot 
be a function parameter pack" }
   void j(this auto&... selves) {}  // { dg-error "an explicit object parameter 
cannot be a function parameter pack" }
 
+  template<typename ...Selves>
+  void k(this Selves&...) {}  // { dg-error "an explicit object parameter 
cannot be a function parameter pack" }
+
   template<typename Selves>
-  void fd(this Selves&...);  // { dg-error "an explicit object parameter 
cannot be a function parameter pack" }
+  void fd(this Selves&...);
 
   template<typename Selves>
   void gd(this Selves&... selves);  // { dg-error "an explicit object 
parameter cannot be a function parameter pack" }
 
   void hd(this auto&...);  // { dg-error "an explicit object parameter cannot 
be a function parameter pack" }
   void jd(this auto&... selves);  // { dg-error "an explicit object parameter 
cannot be a function parameter pack" }
+
+  template<typename ...Selves>
+  void kd(this Selves&...);  // { dg-error "an explicit object parameter 
cannot be a function parameter pack" }
 };
 
 struct S2 {
   template<typename Selves>
-  void f(this Selves&&...) {}  // { dg-error "an explicit object parameter 
cannot be a function parameter pack" }
+  void f(this Selves&&...) {}
 
   template<typename Selves>
   void g(this Selves&&... selves) {}  // { dg-error "an explicit object 
parameter cannot be a function parameter pack" }
@@ -72,19 +84,25 @@ struct S2 {
   void h(this auto&&...) {}  // { dg-error "an explicit object parameter 
cannot be a function parameter pack" }
   void j(this auto&&... selves) {}  // { dg-error "an explicit object 
parameter cannot be a function parameter pack" }
 
+  template<typename ...Selves>
+  void k(this Selves&&...) {}  // { dg-error "an explicit object parameter 
cannot be a function parameter pack" }
+
   template<typename Selves>
-  void fd(this Selves&&...);  // { dg-error "an explicit object parameter 
cannot be a function parameter pack" }
+  void fd(this Selves&&...);
 
   template<typename Selves>
   void gd(this Selves&&... selves);  // { dg-error "an explicit object 
parameter cannot be a function parameter pack" }
 
   void hd(this auto&&...);  // { dg-error "an explicit object parameter cannot 
be a function parameter pack" }
   void jd(this auto&&... selves);  // { dg-error "an explicit object parameter 
cannot be a function parameter pack" }
+
+  template<typename ...Selves>
+  void kd(this Selves&&...);  // { dg-error "an explicit object parameter 
cannot be a function parameter pack" }
 };
 
 struct S3 {
   template<typename Selves>
-  void f(this Selves const&...) {}  // { dg-error "an explicit object 
parameter cannot be a function parameter pack" }
+  void f(this Selves const&...) {}
 
   template<typename Selves>
   void g(this Selves const&... selves) {}  // { dg-error "an explicit object 
parameter cannot be a function parameter pack" }
@@ -92,19 +110,25 @@ struct S3 {
   void h(this auto const&...) {}  // { dg-error "an explicit object parameter 
cannot be a function parameter pack" }
   void j(this auto const&... selves) {}  // { dg-error "an explicit object 
parameter cannot be a function parameter pack" }
 
+  template<typename ...Selves>
+  void k(this Selves const&...) {}  // { dg-error "an explicit object 
parameter cannot be a function parameter pack" }
+
   template<typename Selves>
-  void fd(this Selves const&...);  // { dg-error "an explicit object parameter 
cannot be a function parameter pack" }
+  void fd(this Selves const&...);
 
   template<typename Selves>
   void gd(this Selves const&... selves);  // { dg-error "an explicit object 
parameter cannot be a function parameter pack" }
 
   void hd(this auto const&...);  // { dg-error "an explicit object parameter 
cannot be a function parameter pack" }
   void jd(this auto const&... selves);  // { dg-error "an explicit object 
parameter cannot be a function parameter pack" }
+
+  template<typename ...Selves>
+  void kd(this Selves const&...);  // { dg-error "an explicit object parameter 
cannot be a function parameter pack" }
 };
 
 struct S4 {
   template<typename Selves>
-  void f(this Selves const&&...) {}  // { dg-error "an explicit object 
parameter cannot be a function parameter pack" }
+  void f(this Selves const&&...) {}
 
   template<typename Selves>
   void g(this Selves const&&... selves) {}  // { dg-error "an explicit object 
parameter cannot be a function parameter pack" }
@@ -112,13 +136,18 @@ struct S4 {
   void h(this auto const&&...) {}  // { dg-error "an explicit object parameter 
cannot be a function parameter pack" }
   void j(this auto const&&... selves) {}  // { dg-error "an explicit object 
parameter cannot be a function parameter pack" }
 
+  template<typename ...Selves>
+  void k(this Selves const&&...) {}  // { dg-error "an explicit object 
parameter cannot be a function parameter pack" }
+
   template<typename Selves>
-  void fd(this Selves const&&...);  // { dg-error "an explicit object 
parameter cannot be a function parameter pack" }
+  void fd(this Selves const&&...);
 
   template<typename Selves>
   void gd(this Selves const&&... selves);  // { dg-error "an explicit object 
parameter cannot be a function parameter pack" }
 
   void hd(this auto const&&...);  // { dg-error "an explicit object parameter 
cannot be a function parameter pack" }
   void jd(this auto const&&... selves);  // { dg-error "an explicit object 
parameter cannot be a function parameter pack" }
-};
 
+  template<typename ...Selves>
+  void kd(this Selves const&&...);  // { dg-error "an explicit object 
parameter cannot be a function parameter pack" }
+};


        Jakub

Reply via email to