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


Reply via email to