Hi Jason,

I did intend to break this up but as I've completed the first pass at refactoring implicit function templates and along the way fixed the 5 bugs submitted by Volker I thought I'd post the rolled up patch for you to peruse.

It (should) support arbitrarily complex use of 'auto' in a parameter list to introduce template parameters. Implicit pack expansion parameters containing a single 'auto' are handled by tentatively assuming a single 'auto' might be a pack then reverting the flag if found not to be. This now fully supports the current C++14 generic lambda examples.

No new regressions on trunk as of this morning.

Any feedback appreciated.  Diff attached with -w -b.

Cheers,
Adam

      TODO: Changelog post review.
      PR c++/58534
      PR c++/58536
      PR c++/58548
      PR c++/58549
      PR c++/58637

 gcc/cp/decl.c                        |  30 +---
gcc/cp/parser.c | 312 ++++++++++++++++++++++++++---------
 gcc/cp/parser.h                      |  15 ++
 gcc/testsuite/g++.dg/cpp1y/pr58534.C |   9 +
 gcc/testsuite/g++.dg/cpp1y/pr58536.C |  12 ++
 gcc/testsuite/g++.dg/cpp1y/pr58548.C |  10 ++
 gcc/testsuite/g++.dg/cpp1y/pr58549.C |  10 ++
 gcc/testsuite/g++.dg/cpp1y/pr58637.C |   7 +
 8 files changed, 299 insertions(+), 106 deletions(-)

commit 90c77cdd87eb63617719a9ad129803a2048761ff
Author: Adam Butcher <a...@jessamine.co.uk>
Date:   Wed Sep 18 17:39:40 2013 +0100

    Refactor implicit function template implementation and fix 58534, 58536, 58548, 58549 and 58637.
    
    	TODO: Changelog post review.
    	PR c++/58534
    	PR c++/58536
    	PR c++/58548
    	PR c++/58549
    	PR c++/58637

diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index 81ed409..8095eca 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -10323,34 +10323,12 @@ grokdeclarator (const cp_declarator *declarator,
 
       if (type_uses_auto (type))
 	{
-	  if (template_parm_flag)
-	    {
-	      error ("template parameter declared %<auto%>");
-	      type = error_mark_node;
-	    }
-	  else if (decl_context == CATCHPARM)
-	    {
-	      error ("catch parameter declared %<auto%>");
+	  if (cxx_dialect >= cxx1y)
+	    error ("%<auto%> parameter not permitted in this context");
+	  else
+	    error ("parameter declared %<auto%>");
 	  type = error_mark_node;
 	}
-	  else if (current_class_type && LAMBDA_TYPE_P (current_class_type))
-	    {
-	      if (cxx_dialect < cxx1y)
-		pedwarn (location_of (type), 0,
-			 "use of %<auto%> in lambda parameter declaration "
-			 "only available with "
-			 "-std=c++1y or -std=gnu++1y");
-	    }
-	  else if (cxx_dialect < cxx1y)
-	    pedwarn (location_of (type), 0,
-		     "use of %<auto%> in parameter declaration "
-		     "only available with "
-		     "-std=c++1y or -std=gnu++1y");
-	  else
-	    pedwarn (location_of (type), OPT_Wpedantic,
-		     "ISO C++ forbids use of %<auto%> in parameter "
-		     "declaration");
-	}
 
       /* A parameter declared as an array of T is really a pointer to T.
 	 One declared as a function is really a pointer to a function.
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 90c1775..8c8be4c 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -245,6 +245,19 @@ static FILE *cp_lexer_debug_stream;
    sizeof, typeof, or alignof.  */
 int cp_unevaluated_operand;
 
+/* Nonzero if parsing a context where 'auto' in a parameter list should not
+   trigger an implicit template parameter.  Specifically, 'auto' should not
+   introduce a new template type parameter in explicit specializations, trailing
+   return types or exception specifiers.  */
+int cp_disable_auto_as_implicit_function_template_parm;
+
+/* Track the number of implicit template parameters introduced by the
+   current function parameter and, for handling implicit parameter packs, track
+   the most recently synthesized type.  These are reset prior to parsing in
+   cp_parameter_declarator and updated in synthesize_implicit_template_parm.  */
+int cp_num_implicit_template_type_parms;
+tree cp_last_implicit_template_type_parm;
+
 /* Dump up to NUM tokens in BUFFER to FILE starting with token
    START_TOKEN.  If START_TOKEN is NULL, the dump starts with the
    first token in BUFFER.  If NUM is 0, dump all the tokens.  If
@@ -2064,8 +2077,8 @@ static vec<constructor_elt, va_gc> *cp_parser_initializer_list
 static bool cp_parser_ctor_initializer_opt_and_function_body
   (cp_parser *, bool);
 
-static tree add_implicit_template_parms
-  (cp_parser *, size_t, tree);
+static tree synthesize_implicit_template_parm
+  (cp_parser *parser);
 static tree finish_fully_implicit_template
   (cp_parser *, tree);
 
@@ -3393,6 +3406,8 @@ cp_parser_new (void)
 
   /* Not declaring an implicit function template.  */
   parser->fully_implicit_function_template_p = false;
+  parser->implicit_template_parms = 0;
+  parser->implicit_template_scope = 0;
 
   return parser;
 }
@@ -8559,11 +8574,15 @@ cp_parser_lambda_expression (cp_parser* parser)
     unsigned char in_statement = parser->in_statement;
     bool in_switch_statement_p = parser->in_switch_statement_p;
     bool fully_implicit_function_template_p = parser->fully_implicit_function_template_p;
+    tree implicit_template_parms = parser->implicit_template_parms;
+    cp_binding_level* implicit_template_scope = parser->implicit_template_scope;
 
     parser->num_template_parameter_lists = 0;
     parser->in_statement = 0;
     parser->in_switch_statement_p = false;
     parser->fully_implicit_function_template_p = false;
+    parser->implicit_template_parms = 0;
+    parser->implicit_template_scope = 0;
 
     /* By virtue of defining a local class, a lambda expression has access to
        the private variables of enclosing classes.  */
@@ -8588,6 +8607,8 @@ cp_parser_lambda_expression (cp_parser* parser)
     parser->in_statement = in_statement;
     parser->in_switch_statement_p = in_switch_statement_p;
     parser->fully_implicit_function_template_p = fully_implicit_function_template_p;
+    parser->implicit_template_parms = implicit_template_parms;
+    parser->implicit_template_scope = implicit_template_scope;
   }
 
   pop_deferring_access_checks ();
@@ -13978,12 +13999,18 @@ cp_parser_explicit_specialization (cp_parser* parser)
 	cp_parser_explicit_specialization (parser);
     }
   else
+    {
+      ++cp_disable_auto_as_implicit_function_template_parm;
+
       /* Parse the dependent declaration.  */
       cp_parser_single_declaration (parser,
 				    /*checks=*/NULL,
 				    /*member_p=*/false,
 				    /*explicit_specialization_p=*/true,
 				    /*friend_p=*/NULL);
+
+      --cp_disable_auto_as_implicit_function_template_parm;
+    }
   /* We're done with the specialization.  */
   end_specialization ();
   /* For the erroneous case of a template with C linkage, we pushed an
@@ -14287,6 +14314,30 @@ cp_parser_simple_type_specifier (cp_parser* parser,
 
     case RID_AUTO:
       maybe_warn_cpp0x (CPP0X_AUTO);
+      if (!cp_disable_auto_as_implicit_function_template_parm &&
+	  current_binding_level->kind == sk_function_parms)
+	{
+	  type = synthesize_implicit_template_parm (parser);
+
+	  if (current_class_type && LAMBDA_TYPE_P (current_class_type))
+	    {
+	      if (cxx_dialect < cxx1y)
+		pedwarn (location_of (type), 0,
+			 "use of %<auto%> in lambda parameter declaration "
+			 "only available with "
+			 "-std=c++1y or -std=gnu++1y");
+	    }
+	  else if (cxx_dialect < cxx1y)
+	    pedwarn (location_of (type), 0,
+		     "use of %<auto%> in parameter declaration "
+		     "only available with "
+		     "-std=c++1y or -std=gnu++1y");
+	  else
+	    pedwarn (location_of (type), OPT_Wpedantic,
+		     "ISO C++ forbids use of %<auto%> in parameter "
+		     "declaration");
+	}
+      else
 	type = make_auto ();
       break;
 
@@ -17725,7 +17776,10 @@ static tree cp_parser_template_type_arg (cp_parser *parser)
 
 static tree cp_parser_trailing_type_id (cp_parser *parser)
 {
-  return cp_parser_type_id_1 (parser, false, true);
+  ++cp_disable_auto_as_implicit_function_template_parm;
+  tree t = cp_parser_type_id_1 (parser, false, true);
+  --cp_disable_auto_as_implicit_function_template_parm;
+  return t;
 }
 
 /* Parse a type-specifier-seq.
@@ -17934,7 +17988,6 @@ cp_parser_parameter_declaration_list (cp_parser* parser, bool *is_error)
   tree *tail = &parameters; 
   bool saved_in_unbraced_linkage_specification_p;
   int index = 0;
-  int implicit_template_parms = 0;
 
   /* Assume all will go well.  */
   *is_error = false;
@@ -17951,6 +18004,8 @@ cp_parser_parameter_declaration_list (cp_parser* parser, bool *is_error)
       cp_parameter_declarator *parameter;
       tree decl = error_mark_node;
       bool parenthesized_p = false;
+      cp_last_implicit_template_type_parm = 0;
+      cp_num_implicit_template_type_parms = 0;
       /* Parse the parameter.  */
       parameter
 	= cp_parser_parameter_declaration (parser,
@@ -17963,16 +18018,43 @@ cp_parser_parameter_declaration_list (cp_parser* parser, bool *is_error)
 
       if (parameter)
 	{
+	  /* If there is only one generic type in the parameter, tentatively
+	     assume that that it is a parameter pack.  If it turns out, after
+	     grokdeclarator, that the parameter does not contain a pack
+	     expansion, then reset it be a non-pack type.  */
+	  if (cp_num_implicit_template_type_parms == 1)
+	    TEMPLATE_PARM_PARAMETER_PACK
+	      (TEMPLATE_TYPE_PARM_INDEX
+		(cp_last_implicit_template_type_parm)) = true;
+
 	  decl = grokdeclarator (parameter->declarator,
 				 &parameter->decl_specifiers,
 				 PARM,
 				 parameter->default_argument != NULL_TREE,
 				 &parameter->decl_specifiers.attributes);
+	  if (cp_last_implicit_template_type_parm)
+	    {
+	      if (parameter->declarator
+		  && parameter->declarator->parameter_pack_p)
+		{
+		  /* Forbid ambiguous implicit pack expansions by only allowing
+		     a single generic type in such a parameter.
 
-	  if (TREE_TYPE (decl) != error_mark_node
-	      && parameter->decl_specifiers.type
-	      && is_auto_or_concept (parameter->decl_specifiers.type))
-	      ++implicit_template_parms;
+		     XXX: Maybe allow if explicitly specified template
+		     XXX: 'typename...' account for all expansions?  Though this
+		     XXX: could be tricky or slow.
+		  */
+		  if (cp_num_implicit_template_type_parms > 1)
+		    cp_parser_error (parser,
+				     "cannot expand parameter pack "
+				     "with more than one implicit "
+				     "template parameter");
+		}
+	      else if (cp_num_implicit_template_type_parms == 1)
+		TEMPLATE_PARM_PARAMETER_PACK
+		  (TEMPLATE_TYPE_PARM_INDEX
+		    (cp_last_implicit_template_type_parm)) = false;
+	    }
 	}
 
       deprecated_state = DEPRECATED_NORMAL;
@@ -18061,10 +18143,13 @@ cp_parser_parameter_declaration_list (cp_parser* parser, bool *is_error)
   parser->in_unbraced_linkage_specification_p
     = saved_in_unbraced_linkage_specification_p;
 
-  if (parameters != error_mark_node && implicit_template_parms)
-    parameters = add_implicit_template_parms (parser,
-					      implicit_template_parms,
-					      parameters);
+  if (cp_binding_level *its = parser->implicit_template_scope)
+    if (current_binding_level == its
+	|| (current_class_name && current_binding_level->level_chain == its))
+      {
+	parser->implicit_template_parms = 0;
+	parser->implicit_template_scope = 0;
+      }
 
   return parameters;
 }
@@ -20575,6 +20660,8 @@ cp_parser_exception_specification_opt (cp_parser* parser)
   /* Consume the `throw'.  */
   cp_lexer_consume_token (parser->lexer);
 
+  ++cp_disable_auto_as_implicit_function_template_parm;
+
   /* Look for the `('.  */
   cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN);
 
@@ -20598,6 +20685,8 @@ cp_parser_exception_specification_opt (cp_parser* parser)
   /* Look for the `)'.  */
   cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN);
 
+  --cp_disable_auto_as_implicit_function_template_parm;
+
   return type_id_list;
 }
 
@@ -22292,6 +22381,15 @@ cp_parser_function_definition_after_declarator (cp_parser* parser,
   bool saved_in_function_body;
   unsigned saved_num_template_parameter_lists;
   cp_token *token;
+  bool fully_implicit_function_template_p
+    = parser->fully_implicit_function_template_p;
+  parser->fully_implicit_function_template_p = false;
+  tree implicit_template_parms
+    = parser->implicit_template_parms;
+  parser->implicit_template_parms = 0;
+  cp_binding_level* implicit_template_scope
+    = parser->implicit_template_scope;
+  parser->implicit_template_scope = 0;
 
   saved_in_function_body = parser->in_function_body;
   parser->in_function_body = true;
@@ -22364,6 +22462,13 @@ cp_parser_function_definition_after_declarator (cp_parser* parser,
     = saved_num_template_parameter_lists;
   parser->in_function_body = saved_in_function_body;
 
+  parser->fully_implicit_function_template_p
+    = fully_implicit_function_template_p;
+  parser->implicit_template_parms
+    = implicit_template_parms;
+  parser->implicit_template_scope
+    = implicit_template_scope;
+
   if (parser->fully_implicit_function_template_p)
     finish_fully_implicit_template (parser, /*member_decl_opt=*/0);
 
@@ -28920,7 +29025,7 @@ static tree
 make_generic_type_name ()
 {
   char buf[32];
-  sprintf (buf, "<auto%d>", ++generic_parm_count);
+  sprintf (buf, "auto:%d", ++generic_parm_count);
   return get_identifier (buf);
 }
 
@@ -28934,36 +29039,79 @@ tree_type_is_auto_or_concept (const_tree t)
   return TREE_TYPE (t) && is_auto_or_concept (TREE_TYPE (t));
 }
 
-/* Add EXPECT_COUNT implicit template parameters gleaned from the generic
-   type parameters in PARAMETERS to the CURRENT_TEMPLATE_PARMS (creating a new
-   template parameter list if necessary).  Returns PARAMETERS suitably rewritten
-   to reference the newly created types or ERROR_MARK_NODE on failure.  */
+/* Add an implicit template type parameter to the CURRENT_TEMPLATE_PARMS
+   (creating a new template parameter list if necessary).  Returns the newly
+   created template type parm.  */
 
 tree
-add_implicit_template_parms (cp_parser *parser, size_t expect_count,
-			     tree parameters)
+synthesize_implicit_template_parm  (cp_parser *parser)
 {
   gcc_assert (current_binding_level->kind == sk_function_parms);
 
   cp_binding_level *fn_parms_scope = current_binding_level;
 
-  bool become_template =
-    fn_parms_scope->level_chain->kind != sk_template_parms;
+  /* CLASS_SCOPE is set for out-of-line member definitions.  */
+  cp_binding_level *class_scope = 0;
+  if (current_class_type && !LAMBDA_TYPE_P (current_class_type)
+      && parser->num_classes_being_defined == 0)
+    {
+      class_scope = current_binding_level->level_chain;
+      gcc_assert (class_scope->kind == sk_class);
+    }
 
-  size_t synth_count = 0;
+  /* Roll back to the existing impl tmpl scope level or the previous scope and
+     either introduce a new template parameter list or update an existing one.
+     The function scope is added back after template parameter synthesis
+     below.  */
 
-  /* Roll back a scope level and either introduce a new template parameter list
-     or update an existing one.  The function scope is added back after template
-     parameter synthesis below.  */
-  current_binding_level = fn_parms_scope->level_chain;
+  bool become_template = false;
 
-  /* TPARMS tracks the function's template parameter list.  This is either a new
-     chain in the case of a fully implicit function template or an extension of
-     the function's explicitly specified template parameter list.  */
-  tree tparms = NULL_TREE;
+  /* We are either continuing a function template that already contains implicit
+     template parameters, creating a new fully-implicit function template, or
+     extending an existing function template with implicit template parameters.
+   */
 
-  if (become_template)
+  /* XXX: Performance note: I tried to reduce the decomposition and reassembling
+     of current_template_parms and implicit_template_parms but failed; mostly
+     due to the expectations of surrounding code and process_template_parm and
+     end_template_parm_list.  Though the code below is functionally sound, it
+     seems overly complex as it recreates the template parameter list for each
+     new generic type parsed.  I'm sure this can be remedied by a future
+     optimization.  */
+
+  if (parser->implicit_template_scope)
     {
+      gcc_assert (parser->implicit_template_parms);
+
+      current_binding_level = parser->implicit_template_scope->level_chain;
+      tree inner_vec = INNERMOST_TEMPLATE_PARMS (current_template_parms);
+      current_template_parms = TREE_CHAIN (current_template_parms);
+
+      size_t inner_vec_len = TREE_VEC_LENGTH (inner_vec);
+      gcc_assert (inner_vec_len != 0);
+
+      tree t
+	= parser->implicit_template_parms
+	= TREE_VEC_ELT (inner_vec, 0);
+
+      for (size_t n = 1; n < inner_vec_len; ++n)
+	t = TREE_CHAIN (t) = TREE_VEC_ELT (inner_vec, n);
+
+      ++processing_template_parmlist;
+    }
+  else if (fn_parms_scope->level_chain->kind != sk_template_parms)
+    {
+      gcc_assert (!parser->implicit_template_parms);
+      gcc_assert (!parser->implicit_template_scope);
+
+      become_template = true;
+
+      if (class_scope)
+	parser->implicit_template_scope = class_scope;
+      else
+	parser->implicit_template_scope = fn_parms_scope;
+      current_binding_level = parser->implicit_template_scope->level_chain;
+
       push_deferring_access_checks (dk_deferred);
       begin_template_parm_list ();
 
@@ -28977,61 +29125,65 @@ add_implicit_template_parms (cp_parser *parser, size_t expect_count,
 
       gcc_assert (current_template_parms);
 
-      /* Pop the innermost template parms into TPARMS.  */
+      if (class_scope)
+	parser->implicit_template_scope = class_scope;
+      else
+	parser->implicit_template_scope = fn_parms_scope;
+      current_binding_level = parser->implicit_template_scope->level_chain;
+
+      /* Pop the innermost template parms into IMPLICIT_TEMPLATE_PARMS.  */
+
       tree inner_vec = INNERMOST_TEMPLATE_PARMS (current_template_parms);
       current_template_parms = TREE_CHAIN (current_template_parms);
 
       size_t inner_vec_len = TREE_VEC_LENGTH (inner_vec);
-      if (inner_vec_len != 0)
-	{
-	  tree t = tparms = TREE_VEC_ELT (inner_vec, 0);
+      gcc_assert (inner_vec_len != 0);
+
+      tree t
+	= parser->implicit_template_parms
+	= TREE_VEC_ELT (inner_vec, 0);
+
       for (size_t n = 1; n < inner_vec_len; ++n)
 	t = TREE_CHAIN (t) = TREE_VEC_ELT (inner_vec, n);
-	}
 
       ++processing_template_parmlist;
     }
 
-  for (tree p = parameters; p && synth_count < expect_count; p = TREE_CHAIN (p))
-    {
-      tree generic_type_ptr
-	= find_type_usage (TREE_VALUE (p), tree_type_is_auto_or_concept);
-
-      if (!generic_type_ptr)
-	continue;
-
-      ++synth_count;
-
   tree synth_id = make_generic_type_name ();
   tree synth_tmpl_parm = finish_template_type_parm (class_type_node,
 						    synth_id);
-      tparms = process_template_parm (tparms, DECL_SOURCE_LOCATION (TREE_VALUE
-								    (p)),
-				      build_tree_list (NULL_TREE,
-						       synth_tmpl_parm),
+  parser->implicit_template_parms
+    = process_template_parm (parser->implicit_template_parms,
+			     input_location,
+			     build_tree_list (NULL_TREE, synth_tmpl_parm),
 			     /*non_type=*/false,
 			     /*param_pack=*/false);
 
-      /* Rewrite the type of P to be the template_parm added above (getdecls is
-         used to retrieve it since it is the most recent declaration in this
-         scope).  Qualifiers need to be preserved also.  */
-
-      tree& cur_type = TREE_TYPE (generic_type_ptr);
   tree new_type = TREE_TYPE (getdecls ());
 
-      if (TYPE_QUALS (cur_type))
-	cur_type = cp_build_qualified_type (new_type, TYPE_QUALS (cur_type));
-      else
-	cur_type = new_type;
+  /* If introducing a new sk_template_parms scope, then push the existing
+     scopes, otherwise simply return to the calling scope.  */
+  if (become_template)
+    {
+      if (class_scope)
+	push_binding_level (class_scope);
+      push_binding_level (fn_parms_scope);
     }
+  else
+    current_binding_level = fn_parms_scope;
 
-  gcc_assert (synth_count == expect_count);
+  /* XXX: Performance note: Feels like we can save on work here by doing this
+     incrementally rather than building a tree vec and populating with same
+     content each time.  See XXX above.  */
 
-  push_binding_level (fn_parms_scope);
+  end_template_parm_list (parser->implicit_template_parms);
 
-  end_template_parm_list (tparms);
+  /* Track progress to allow for support and diagnostics relating to implicit
+     pack expansions.  */
+  cp_last_implicit_template_type_parm = new_type;
+  ++cp_num_implicit_template_type_parms;
 
-  return parameters;
+  return new_type;
 }
 
 /* Finish the declaration of a fully implicit function template.  Such a
diff --git a/gcc/cp/parser.h b/gcc/cp/parser.h
index ffdddaf..c02d889 100644
--- a/gcc/cp/parser.h
+++ b/gcc/cp/parser.h
@@ -347,6 +347,21 @@ typedef struct GTY(()) cp_parser {
      identifiers) rather than an explicit template parameter list.  */
   bool fully_implicit_function_template_p;
 
+  /* Tracks the function's template parameter list when declaring a function
+     using generic type parameters.  This is either a new chain in the case of a
+     fully implicit function template or an extension of the function's existing
+     template parameter list.  This is tracked to optimize calls subsequent
+     calls to synthesize_implicit_template_parm during
+     cp_parser_parameter_declaration.  */
+  tree implicit_template_parms;
+
+  /* The scope into which an implicit template parameter list has been
+     introduced or an existing template parameter list is being extended with
+     implicit template paramaters.  In most cases this is the sk_function_parms
+     scope containing the use of a generic type.  In the case of an out-of-line
+     member definition using a generic type, it is the sk_class scope.  */
+  cp_binding_level* implicit_template_scope;
+
 } cp_parser;
 
 /* In parser.c  */
diff --git a/gcc/testsuite/g++.dg/cpp1y/pr58534.C b/gcc/testsuite/g++.dg/cpp1y/pr58534.C
new file mode 100644
index 0000000..4aa4f43
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1y/pr58534.C
@@ -0,0 +1,9 @@
+// { dg-do compile }
+// { dg-options "-std=gnu++1y" }
+
+// PR c++/58534
+
+template<typename> void foo(const auto&) {}
+
+template<typename, typename...T> void foo(const auto&, T...) {}
+
diff --git a/gcc/testsuite/g++.dg/cpp1y/pr58536.C b/gcc/testsuite/g++.dg/cpp1y/pr58536.C
new file mode 100644
index 0000000..8050c19
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1y/pr58536.C
@@ -0,0 +1,12 @@
+// { dg-do compile }
+// { dg-options "-std=gnu++1y" }
+
+// PR c++/58536
+
+struct A
+{
+  A(auto);
+};
+
+A::A(auto) {}
+
diff --git a/gcc/testsuite/g++.dg/cpp1y/pr58548.C b/gcc/testsuite/g++.dg/cpp1y/pr58548.C
new file mode 100644
index 0000000..0ac2e1c
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1y/pr58548.C
@@ -0,0 +1,10 @@
+// { dg-do compile }
+// { dg-options "-std=gnu++1y" }
+
+// PR c++/58548
+
+void foo(auto)
+{
+  struct A { int i; };
+}
+
diff --git a/gcc/testsuite/g++.dg/cpp1y/pr58549.C b/gcc/testsuite/g++.dg/cpp1y/pr58549.C
new file mode 100644
index 0000000..b71bac9
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1y/pr58549.C
@@ -0,0 +1,10 @@
+// { dg-do compile }
+// { dg-options "-std=gnu++1y" }
+
+// PR c++/58549
+
+void foo(auto)
+{
+  void bar();
+}
+
diff --git a/gcc/testsuite/g++.dg/cpp1y/pr58637.C b/gcc/testsuite/g++.dg/cpp1y/pr58637.C
new file mode 100644
index 0000000..46200ff
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1y/pr58637.C
@@ -0,0 +1,7 @@
+// { dg-do compile }
+// { dg-options "-std=gnu++1y" }
+
+// PR c++/58637
+
+template<> void foo(auto); // { dg-error "auto|not a template" }
+

Reply via email to