diff mbox series

C++ PATCH for c++/64095, unnamed generic lambda parameter pack

Message ID CADzB+2=KwBitT=p=c3_V=E5Hvbz5JzFfNcq6vM2O6J4nhAQjEA@mail.gmail.com
State New
Headers show
Series C++ PATCH for c++/64095, unnamed generic lambda parameter pack | expand

Commit Message

Jason Merrill April 2, 2018, 6:18 p.m. UTC
In this testcase, we have (auto...), a function parameter pack without
a declarator.  Because there is no declarator, we were never hitting
the code for turning the auto type into a template parameter pack, so
the ... ended up being parsed as a C-style trailing ellipsis.

Tested x86_64-pc-linux-gnu, applying to trunk.
diff mbox series

Patch

commit 476a47b844613603961cb1e7aedcbcc8601297b5
Author: Jason Merrill <jason@redhat.com>
Date:   Mon Apr 2 07:45:02 2018 -0400

            PR c++/64095 - auto... parameter pack.
    
            * parser.c (cp_parser_parameter_declaration): Handle turning autos
            into packs here.
            (cp_parser_parameter_declaration_list): Not here.

diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index e946d0b7229..d526a4eb365 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -21320,9 +21320,6 @@  cp_parser_parameter_declaration_list (cp_parser* parser, bool *is_error)
       cp_parameter_declarator *parameter;
       tree decl = error_mark_node;
       bool parenthesized_p = false;
-      int template_parm_idx = (function_being_declared_is_template_p (parser)?
-			       TREE_VEC_LENGTH (INNERMOST_TEMPLATE_PARMS
-						(current_template_parms)) : 0);
 
       /* Parse the parameter.  */
       parameter
@@ -21336,22 +21333,6 @@  cp_parser_parameter_declaration_list (cp_parser* parser, bool *is_error)
 
       if (parameter)
 	{
-	  /* 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
-	      && parameter->declarator
-	      && parameter->declarator->parameter_pack_p)
-	    {
-	      int latest_template_parm_idx = TREE_VEC_LENGTH
-		(INNERMOST_TEMPLATE_PARMS (current_template_parms));
-
-	      if (latest_template_parm_idx != template_parm_idx)
-		parameter->decl_specifiers.type = convert_generic_types_to_packs
-		  (parameter->decl_specifiers.type,
-		   template_parm_idx, latest_template_parm_idx);
-	    }
-
 	  decl = grokdeclarator (parameter->declarator,
 				 &parameter->decl_specifiers,
 				 PARM,
@@ -21511,6 +21492,10 @@  cp_parser_parameter_declaration (cp_parser *parser,
   parser->type_definition_forbidden_message
     = G_("types may not be defined in parameter types");
 
+  int template_parm_idx = (function_being_declared_is_template_p (parser) ?
+			   TREE_VEC_LENGTH (INNERMOST_TEMPLATE_PARMS
+					    (current_template_parms)) : 0);
+
   /* Parse the declaration-specifiers.  */
   cp_token *decl_spec_token_start = cp_lexer_peek_token (parser->lexer);
   cp_parser_decl_specifier_seq (parser,
@@ -21600,6 +21585,23 @@  cp_parser_parameter_declaration (cp_parser *parser,
      parameter pack expansion expression. Otherwise, leave the ellipsis
      for a C-style variadic function. */
   token = cp_lexer_peek_token (parser->lexer);
+
+  /* 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 && declarator->parameter_pack_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);
+    }
+
   if (cp_lexer_next_token_is (parser->lexer, CPP_ELLIPSIS))
     {
       tree type = decl_specifiers.type;
diff --git a/gcc/testsuite/g++.dg/cpp1y/lambda-generic-variadic16.C b/gcc/testsuite/g++.dg/cpp1y/lambda-generic-variadic16.C
new file mode 100644
index 00000000000..a9292253453
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1y/lambda-generic-variadic16.C
@@ -0,0 +1,8 @@ 
+// PR c++/64095
+// { dg-do compile { target c++14 } }
+
+void f()
+{
+  [](auto...){}();
+  [](auto&&...){}();
+}
diff --git a/gcc/testsuite/g++.dg/cpp1y/lambda-mangle-1.C b/gcc/testsuite/g++.dg/cpp1y/lambda-mangle-1.C
index ca0910be503..8f135358465 100644
--- a/gcc/testsuite/g++.dg/cpp1y/lambda-mangle-1.C
+++ b/gcc/testsuite/g++.dg/cpp1y/lambda-mangle-1.C
@@ -85,4 +85,4 @@  void Baz ()
 // { dg-final { scan-assembler "_Z3eatIZ3FoovEUlPT_PT0_E4_Z3FoovEUlS1_S3_E5_EvRS0_RS2_:" } }
 // { dg-final { scan-assembler "_Z3eatIPiZ3BarIsEvvEUlPsPfS3_E_EvRT_RT0_:" } }
 // { dg-final { scan-assembler "_Z3eatIPiZ3BarIsEvvEUlPsPT_PT0_E0_EvRS3_RS5_:" } }
-// { dg-final { scan-assembler "_Z3eatIPiZ3BarIsEvvEUlPsPT_zE1_EvRS3_RT0_:" } }
+// { dg-final { scan-assembler "_Z3eatIPiZ3BarIsEvvEUlPsDpPT_E1_EvRT_RT0_:" } }