https://gcc.gnu.org/g:3ecc5071797c4ceb6da67a6c2b2527a046091de2

commit r14-9384-g3ecc5071797c4ceb6da67a6c2b2527a046091de2
Author: Jakub Jelinek <ja...@redhat.com>
Date:   Fri Mar 8 09:11:57 2024 +0100

    c++: Fix up parameter pack diagnostics on xobj vs. varargs functions 
[PR113802]
    
    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.
    
    This patch just moves the diagnostics later (after the CPP_ELLIPSIS 
handling)
    and changes the error recovery behavior by pretending the this specifier
    didn't appear if an error is reported.
    
    2024-03-08  Jakub Jelinek  <ja...@redhat.com>
    
            PR c++/113802
            * parser.cc (cp_parser_parameter_declaration): Move the xobj_param_p
            pack diagnostics after ellipsis handling and if an error is 
reported,
            pretend this specifier didn't appear.  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.  Expect extra diagnostics in error
            recovery for g and gd member function templates.

Diff:
---
 gcc/cp/parser.cc                                   | 38 +++++++-------
 .../g++.dg/cpp23/explicit-obj-diagnostics3.C       | 61 ++++++++++++++++++----
 2 files changed, 69 insertions(+), 30 deletions(-)

diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc
index e32acfc30a2..bc3aa9dd6ad 100644
--- a/gcc/cp/parser.cc
+++ b/gcc/cp/parser.cc
@@ -25734,22 +25734,6 @@ cp_parser_parameter_declaration (cp_parser *parser,
       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_parser *parser,
        (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_parser *parser,
        }
     }
 
+  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;
diff --git a/gcc/testsuite/g++.dg/cpp23/explicit-obj-diagnostics3.C 
b/gcc/testsuite/g++.dg/cpp23/explicit-obj-diagnostics3.C
index 304cf029f8f..f6a892eb069 100644
--- a/gcc/testsuite/g++.dg/cpp23/explicit-obj-diagnostics3.C
+++ b/gcc/testsuite/g++.dg/cpp23/explicit-obj-diagnostics3.C
@@ -24,101 +24,140 @@ void S::f12(this S s = {}) {} // { dg-error "an explicit 
object parameter may no
 
 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" }
+                                   // { dg-error "contains no parameter packs" 
"" { target *-*-* } .-1 }
 
   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" }
+                                  // { dg-error "contains no parameter packs" 
"" { target *-*-* } .-1 }
 
   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" }
+                                    // { dg-error "contains no parameter 
packs" "" { target *-*-* } .-1 }
 
   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" }
+                                   // { dg-error "contains no parameter packs" 
"" { target *-*-* } .-1 }
 
   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" }
+                                     // { dg-error "contains no parameter 
packs" "" { target *-*-* } .-1 }
 
   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" }
+                                    // { dg-error "contains no parameter 
packs" "" { target *-*-* } .-1 }
 
   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" }
+                                          // { dg-error "contains no parameter 
packs" "" { target *-*-* } .-1 }
 
   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" }
+                                         // { dg-error "contains no parameter 
packs" "" { target *-*-* } .-1 }
 
   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" }
+                                           // { dg-error "contains no 
parameter packs" "" { target *-*-* } .-1 }
 
   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" }
+                                          // { dg-error "contains no parameter 
packs" "" { target *-*-* } .-1 }
 
   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" }
+};

Reply via email to