c++: Fix up parameter pack diagnostics on xobj vs. varargs functions [PR113802]

Message ID Zc8k0y5zsJQhZ+2k@tucnak
State New
Headers
Series c++: Fix up parameter pack diagnostics on xobj vs. varargs functions [PR113802] |

Checks

Context Check Description
linaro-tcwg-bot/tcwg_gcc_build--master-aarch64 fail Patch failed to apply
linaro-tcwg-bot/tcwg_gcc_build--master-arm fail Patch failed to apply

Commit Message

Jakub Jelinek Feb. 16, 2024, 9:03 a.m. UTC
  Hi!

The simple presence of ellipsis as next token after the parameter
declaration doesn't imply it is a parameter pack, it sometimes is, e.g.
if its type is a pack, but sometimes is not and in that case it acts
the same as if the next tokens were , ... instead of just ...
The xobj param cannot be a function parameter pack though treats both
the declarator->parameter_pack_p and token->type == CPP_ELLIPSIS as
sufficient conditions for the error.  The conditions for CPP_ELLIPSIS
are done a little bit later in the same function and complex enough that
IMHO shouldn't be repeated, on the other side for the
declarator->parameter_pack_p case we clear that flag for xobj params
for error recovery reasons.
In order to avoid diagnosing this in two spots, one at the current spot
for declarator->parameter_pack_p and one for the ellipsis case after
we decide if it is parameter pack or varargs, the following patch instead
just sets a boolean flag whether we should emit this diagnostics, does it
early for declarator->parameter_pack_p case and clears the parameter_pack_p
flag in that case like the older patch did, and for the ellipsis case
sets the flag later, then emits the diagnostics.

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

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

	PR c++/113802
	* parser.cc (cp_parser_parameter_declaration): Don't emit
	PR113307 diagnostics too early, instead for the
	declarator->parameter_pack_p case just set a flag it should be emitted
	later.  Set that flag also when consuming following ellipsis as part
	of a parameter pack and diagnose either afterwards.  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.


	Jakub
  

Comments

Jason Merrill Feb. 16, 2024, 8:47 p.m. UTC | #1
On 2/16/24 04:03, Jakub Jelinek wrote:
> Hi!
> 
> The simple presence of ellipsis as next token after the parameter
> declaration doesn't imply it is a parameter pack, it sometimes is, e.g.
> if its type is a pack, but sometimes is not and in that case it acts
> the same as if the next tokens were , ... instead of just ...
> The xobj param cannot be a function parameter pack though treats both
> the declarator->parameter_pack_p and token->type == CPP_ELLIPSIS as
> sufficient conditions for the error.  The conditions for CPP_ELLIPSIS
> are done a little bit later in the same function and complex enough that
> IMHO shouldn't be repeated, on the other side for the
> declarator->parameter_pack_p case we clear that flag for xobj params
> for error recovery reasons.
> In order to avoid diagnosing this in two spots, one at the current spot
> for declarator->parameter_pack_p and one for the ellipsis case after
> we decide if it is parameter pack or varargs, the following patch instead
> just sets a boolean flag whether we should emit this diagnostics, does it
> early for declarator->parameter_pack_p case and clears the parameter_pack_p
> flag in that case like the older patch did, and for the ellipsis case
> sets the flag later, then emits the diagnostics.
> 
> Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?
> 
> 2024-02-16  Jakub Jelinek  <jakub@redhat.com>
> 
> 	PR c++/113802
> 	* parser.cc (cp_parser_parameter_declaration): Don't emit
> 	PR113307 diagnostics too early, instead for the
> 	declarator->parameter_pack_p case just set a flag it should be emitted
> 	later.  Set that flag also when consuming following ellipsis as part
> 	of a parameter pack and diagnose either afterwards.  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-14 14:26:19.000000000 +0100
> +++ gcc/cp/parser.cc	2024-02-15 11:58:27.033618967 +0100
> @@ -25727,17 +25727,10 @@ cp_parser_parameter_declaration (cp_pars
>     bool const xobj_param_p
>       = decl_spec_seq_has_spec_p (&decl_specifiers, ds_this);
>   
> -  if (xobj_param_p
> -      && ((declarator && declarator->parameter_pack_p)
> -	  || cp_lexer_next_token_is (parser->lexer, CPP_ELLIPSIS)))
> +  bool diag_xobj_parameter_pack = false;
> +  if (xobj_param_p && (declarator && declarator->parameter_pack_p))
>       {
> -      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");
> +      diag_xobj_parameter_pack = true;
>         /* Suppress errors that occur down the line.  */
>         if (declarator)
>   	declarator->parameter_pack_p = false;
> @@ -25755,9 +25748,10 @@ cp_parser_parameter_declaration (cp_pars
>   	(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);
>       }
>   
>     if (cp_lexer_next_token_is (parser->lexer, CPP_ELLIPSIS))
> @@ -25773,6 +25767,8 @@ cp_parser_parameter_declaration (cp_pars
>   	   || (!type && template_parm_p))
>   	  && declarator_can_be_parameter_pack (declarator))
>   	{
> +	  if (xobj_param_p)
> +	    diag_xobj_parameter_pack = true;
>   	  /* Consume the `...'. */
>   	  cp_lexer_consume_token (parser->lexer);
>   	  maybe_warn_variadic_templates ();
> @@ -25787,6 +25783,17 @@ cp_parser_parameter_declaration (cp_pars
>   	}
>       }
>   
> +  if (diag_xobj_parameter_pack)

Can we move all the xobj handling down here (where we can trust 
declarator->parameter_pack_p) instead of adding a new variable?

> +    {
> +      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");
> +    }
> +
>     /* 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-01-17 10:34:49.812597960 +0100
> +++ gcc/testsuite/g++.dg/cpp23/explicit-obj-diagnostics3.C	2024-02-15 12:14:29.994356800 +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
>
  
Jakub Jelinek Feb. 16, 2024, 9:20 p.m. UTC | #2
On Fri, Feb 16, 2024 at 03:47:41PM -0500, Jason Merrill wrote:
> Can we move all the xobj handling down here (where we can trust
> declarator->parameter_pack_p) instead of adding a new variable?

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 '...':
/usr/src/gcc/gcc/testsuite/g++.dg/cpp23/explicit-obj-diagnostics3.C:45:30: error: parameter packs not expanded with '...':
/usr/src/gcc/gcc/testsuite/g++.dg/cpp23/explicit-obj-diagnostics3.C:58:23: error: parameter packs not expanded with '...':
/usr/src/gcc/gcc/testsuite/g++.dg/cpp23/explicit-obj-diagnostics3.C:59:30: error: parameter packs not expanded with '...':
/usr/src/gcc/gcc/testsuite/g++.dg/cpp23/explicit-obj-diagnostics3.C:62:25: error: parameter packs not expanded with '...':
/usr/src/gcc/gcc/testsuite/g++.dg/cpp23/explicit-obj-diagnostics3.C:70:24: error: parameter packs not expanded with '...':
/usr/src/gcc/gcc/testsuite/g++.dg/cpp23/explicit-obj-diagnostics3.C:71:31: error: parameter packs not expanded with '...':
/usr/src/gcc/gcc/testsuite/g++.dg/cpp23/explicit-obj-diagnostics3.C:74:26: error: parameter packs not expanded with '...':
/usr/src/gcc/gcc/testsuite/g++.dg/cpp23/explicit-obj-diagnostics3.C:84:24: error: parameter packs not expanded with '...':
/usr/src/gcc/gcc/testsuite/g++.dg/cpp23/explicit-obj-diagnostics3.C:85:31: error: parameter packs not expanded with '...':
/usr/src/gcc/gcc/testsuite/g++.dg/cpp23/explicit-obj-diagnostics3.C:88:26: error: parameter packs not expanded with '...':
/usr/src/gcc/gcc/testsuite/g++.dg/cpp23/explicit-obj-diagnostics3.C:96:25: error: parameter packs not expanded with '...':
/usr/src/gcc/gcc/testsuite/g++.dg/cpp23/explicit-obj-diagnostics3.C:97:32: error: parameter packs not expanded with '...':
/usr/src/gcc/gcc/testsuite/g++.dg/cpp23/explicit-obj-diagnostics3.C:100:27: error: parameter packs not expanded with '...':
/usr/src/gcc/gcc/testsuite/g++.dg/cpp23/explicit-obj-diagnostics3.C:110:29: error: parameter packs not expanded with '...':
/usr/src/gcc/gcc/testsuite/g++.dg/cpp23/explicit-obj-diagnostics3.C:111:36: error: parameter packs not expanded with '...':
/usr/src/gcc/gcc/testsuite/g++.dg/cpp23/explicit-obj-diagnostics3.C:114:31: error: parameter packs not expanded with '...':
/usr/src/gcc/gcc/testsuite/g++.dg/cpp23/explicit-obj-diagnostics3.C:122:30: error: parameter packs not expanded with '...':
/usr/src/gcc/gcc/testsuite/g++.dg/cpp23/explicit-obj-diagnostics3.C:123:37: error: parameter packs not expanded with '...':
/usr/src/gcc/gcc/testsuite/g++.dg/cpp23/explicit-obj-diagnostics3.C:126:32: error: parameter packs not expanded with '...':
/usr/src/gcc/gcc/testsuite/g++.dg/cpp23/explicit-obj-diagnostics3.C:136:30: error: parameter packs not expanded with '...':
/usr/src/gcc/gcc/testsuite/g++.dg/cpp23/explicit-obj-diagnostics3.C:137:37: error: parameter packs not expanded with '...':
/usr/src/gcc/gcc/testsuite/g++.dg/cpp23/explicit-obj-diagnostics3.C:140:32: error: parameter packs not expanded with '...':
/usr/src/gcc/gcc/testsuite/g++.dg/cpp23/explicit-obj-diagnostics3.C:148:31: error: parameter packs not expanded with '...':
/usr/src/gcc/gcc/testsuite/g++.dg/cpp23/explicit-obj-diagnostics3.C:149:38: error: parameter packs not expanded with '...':
/usr/src/gcc/gcc/testsuite/g++.dg/cpp23/explicit-obj-diagnostics3.C:152:33: error: parameter packs not expanded with '...':
with it (the other errors are emitted as expected).

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

	PR c++/113802
	* parser.cc (cp_parser_parameter_declaration): Move the xobj_param_p
	pack diagnostics after ellipsis handling.  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:10:32.904353402 +0100
@@ -25734,22 +25734,6 @@ 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.  */
@@ -25762,9 +25746,10 @@ cp_parser_parameter_declaration (cp_pars
 	(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);
     }
 
   if (cp_lexer_next_token_is (parser->lexer, CPP_ELLIPSIS))
@@ -25794,6 +25779,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 = false;
+    }
+
   /* 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
  
Jakub Jelinek Feb. 16, 2024, 9:47 p.m. UTC | #3
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  <jakub@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
  
Jakub Jelinek Feb. 16, 2024, 10:15 p.m. UTC | #4
On Fri, Feb 16, 2024 at 10:47:47PM +0100, Jakub Jelinek wrote:
> The following patch works.

Or yet another option would be instead of (sometimes) clearing
declarator->parameter_pack_p when we diagnose this bug for error
recovery ignore the this specifier.
With the following patch (testsuite patch remains the same),
I get excess errors though:
/usr/src/gcc/gcc/testsuite/g++.dg/cpp23/explicit-obj-diagnostics3.C:30:25: error: expansion pattern 'Selves' contains no parameter packs
/usr/src/gcc/gcc/testsuite/g++.dg/cpp23/explicit-obj-diagnostics3.C:42:26: error: expansion pattern 'Selves' contains no parameter packs
/usr/src/gcc/gcc/testsuite/g++.dg/cpp23/explicit-obj-diagnostics3.C:56:26: error: expansion pattern 'Selves&' contains no parameter packs
/usr/src/gcc/gcc/testsuite/g++.dg/cpp23/explicit-obj-diagnostics3.C:68:27: error: expansion pattern 'Selves&' contains no parameter packs
/usr/src/gcc/gcc/testsuite/g++.dg/cpp23/explicit-obj-diagnostics3.C:82:27: error: expansion pattern 'Selves&&' contains no parameter packs
/usr/src/gcc/gcc/testsuite/g++.dg/cpp23/explicit-obj-diagnostics3.C:94:28: error: expansion pattern 'Selves&&' contains no parameter packs
/usr/src/gcc/gcc/testsuite/g++.dg/cpp23/explicit-obj-diagnostics3.C:108:32: error: expansion pattern 'const Selves&' contains no parameter packs
/usr/src/gcc/gcc/testsuite/g++.dg/cpp23/explicit-obj-diagnostics3.C:120:33: error: expansion pattern 'const Selves&' contains no parameter packs
/usr/src/gcc/gcc/testsuite/g++.dg/cpp23/explicit-obj-diagnostics3.C:134:33: error: expansion pattern 'const Selves&&' contains no parameter packs
/usr/src/gcc/gcc/testsuite/g++.dg/cpp23/explicit-obj-diagnostics3.C:146:34: error: expansion pattern 'const Selves&&' contains no parameter packs
though, that is e.g. on
struct S0 {
  template<typename Selves>
  void g(this Selves... selves) {}  // { dg-error "an explicit object parameter cannot be a function parameter pack" }
}
where such an extra error would have been emitted if the this keyword was
omitted.

--- gcc/cp/parser.cc.jj	2024-02-16 17:38:27.802845433 +0100
+++ gcc/cp/parser.cc	2024-02-16 23:08:40.835437740 +0100
@@ -25734,22 +25734,6 @@ 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.  */
@@ -25762,9 +25746,10 @@ cp_parser_parameter_declaration (cp_pars
 	(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);
     }
 
   if (cp_lexer_next_token_is (parser->lexer, CPP_ELLIPSIS))
@@ -25794,6 +25779,21 @@ 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");
+      xobj_param_p = false;
+      decl_specifiers.locations[ds_this] = 0;
+    }
+
   /* 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;

	Jakub
  
Jason Merrill March 6, 2024, 11:43 p.m. UTC | #5
On 2/16/24 17:15, Jakub Jelinek wrote:
> On Fri, Feb 16, 2024 at 10:47:47PM +0100, Jakub Jelinek wrote:
>> The following patch works.
> 
> Or yet another option would be instead of (sometimes) clearing
> declarator->parameter_pack_p when we diagnose this bug for error
> recovery ignore the this specifier.

Let's go with this one.  OK.

> With the following patch (testsuite patch remains the same),
> I get excess errors though:
> /usr/src/gcc/gcc/testsuite/g++.dg/cpp23/explicit-obj-diagnostics3.C:30:25: error: expansion pattern 'Selves' contains no parameter packs
> /usr/src/gcc/gcc/testsuite/g++.dg/cpp23/explicit-obj-diagnostics3.C:42:26: error: expansion pattern 'Selves' contains no parameter packs
> /usr/src/gcc/gcc/testsuite/g++.dg/cpp23/explicit-obj-diagnostics3.C:56:26: error: expansion pattern 'Selves&' contains no parameter packs
> /usr/src/gcc/gcc/testsuite/g++.dg/cpp23/explicit-obj-diagnostics3.C:68:27: error: expansion pattern 'Selves&' contains no parameter packs
> /usr/src/gcc/gcc/testsuite/g++.dg/cpp23/explicit-obj-diagnostics3.C:82:27: error: expansion pattern 'Selves&&' contains no parameter packs
> /usr/src/gcc/gcc/testsuite/g++.dg/cpp23/explicit-obj-diagnostics3.C:94:28: error: expansion pattern 'Selves&&' contains no parameter packs
> /usr/src/gcc/gcc/testsuite/g++.dg/cpp23/explicit-obj-diagnostics3.C:108:32: error: expansion pattern 'const Selves&' contains no parameter packs
> /usr/src/gcc/gcc/testsuite/g++.dg/cpp23/explicit-obj-diagnostics3.C:120:33: error: expansion pattern 'const Selves&' contains no parameter packs
> /usr/src/gcc/gcc/testsuite/g++.dg/cpp23/explicit-obj-diagnostics3.C:134:33: error: expansion pattern 'const Selves&&' contains no parameter packs
> /usr/src/gcc/gcc/testsuite/g++.dg/cpp23/explicit-obj-diagnostics3.C:146:34: error: expansion pattern 'const Selves&&' contains no parameter packs
> though, that is e.g. on
> struct S0 {
>    template<typename Selves>
>    void g(this Selves... selves) {}  // { dg-error "an explicit object parameter cannot be a function parameter pack" }
> }
> where such an extra error would have been emitted if the this keyword was
> omitted.
> 
> --- gcc/cp/parser.cc.jj	2024-02-16 17:38:27.802845433 +0100
> +++ gcc/cp/parser.cc	2024-02-16 23:08:40.835437740 +0100
> @@ -25734,22 +25734,6 @@ 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.  */
> @@ -25762,9 +25746,10 @@ cp_parser_parameter_declaration (cp_pars
>   	(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);
>       }
>   
>     if (cp_lexer_next_token_is (parser->lexer, CPP_ELLIPSIS))
> @@ -25794,6 +25779,21 @@ 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");
> +      xobj_param_p = false;
> +      decl_specifiers.locations[ds_this] = 0;
> +    }
> +
>     /* 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;
> 
> 	Jakub
>
  

Patch

--- gcc/cp/parser.cc.jj	2024-02-14 14:26:19.000000000 +0100
+++ gcc/cp/parser.cc	2024-02-15 11:58:27.033618967 +0100
@@ -25727,17 +25727,10 @@  cp_parser_parameter_declaration (cp_pars
   bool const xobj_param_p
     = decl_spec_seq_has_spec_p (&decl_specifiers, ds_this);
 
-  if (xobj_param_p
-      && ((declarator && declarator->parameter_pack_p)
-	  || cp_lexer_next_token_is (parser->lexer, CPP_ELLIPSIS)))
+  bool diag_xobj_parameter_pack = false;
+  if (xobj_param_p && (declarator && declarator->parameter_pack_p))
     {
-      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");
+      diag_xobj_parameter_pack = true;
       /* Suppress errors that occur down the line.  */
       if (declarator)
 	declarator->parameter_pack_p = false;
@@ -25755,9 +25748,10 @@  cp_parser_parameter_declaration (cp_pars
 	(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);
     }
 
   if (cp_lexer_next_token_is (parser->lexer, CPP_ELLIPSIS))
@@ -25773,6 +25767,8 @@  cp_parser_parameter_declaration (cp_pars
 	   || (!type && template_parm_p))
 	  && declarator_can_be_parameter_pack (declarator))
 	{
+	  if (xobj_param_p)
+	    diag_xobj_parameter_pack = true;
 	  /* Consume the `...'. */
 	  cp_lexer_consume_token (parser->lexer);
 	  maybe_warn_variadic_templates ();
@@ -25787,6 +25783,17 @@  cp_parser_parameter_declaration (cp_pars
 	}
     }
 
+  if (diag_xobj_parameter_pack)
+    {
+      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");
+    }
+
   /* 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-01-17 10:34:49.812597960 +0100
+++ gcc/testsuite/g++.dg/cpp23/explicit-obj-diagnostics3.C	2024-02-15 12:14:29.994356800 +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" }
+};