Refactor implicit function template implementation and fix 58534, 58536, 58548, 58549...
authorabutcher <abutcher@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 12 Nov 2013 20:17:33 +0000 (20:17 +0000)
committerabutcher <abutcher@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 12 Nov 2013 20:17:33 +0000 (20:17 +0000)
gcc/
* tree.c (grow_tree_vec_stat): New function ...
* tree.h (grow_tree_vec_stat) (grow_tree_vec): ... and its declaration
and macro front-end.

gcc/cp/
PR c++/58534
PR c++/58536
PR c++/58548
PR c++/58549
PR c++/58637
* parser.h (struct cp_parser): New members implicit_template_parms,
implicit_template_scope and auto_is_implicit_function_template_parm_p.
* parser.c (add_implicit_template_parms): Refactor as ...
(synthesize_implicit_template_parm): ... this to append a new template
type parm to the current template parameter list (introducing a new list
if necessary).  Removed push_deferring_access_checks.
(finish_fully_implicit_template): Removed pop_deferring_access_checks.
(cp_parser_new): Initialize new cp_parser members.
(cp_parser_parameter_declaration_clause): Consider auto as implicit
template parm when parsing a parameter declaration (unless parsing an
explicit specialization).
(cp_parser_parameter_declaration_list): Remove local
implicit_template_parms counter and reset cp_parser implicit template
state when complete.
(cp_parser_lambda_expression): Reset implicit template cp_parser members
whilst generating lambda class.
(cp_parser_function_definition_after_declarator): Reset implicit
template cp_parser members whilst parsing function definition.
(make_generic_type_name): Respell '<autoN>' as 'auto:N' which works
better with template diagnostics.
(cp_parser_simple_type_specifier): Synthesize implicit template parm on
parsing 'auto' if auto_is_implicit_function_template_parm_p and provide
diagnostics ...
* decl.c (grokdeclarator): ... that were previously done here.

gcc/testsuite/g++.dg/
* cpp1y/pr58534.C: New testcase.
* cpp1y/pr58536.C: New testcase.
* cpp1y/pr58548.C: New testcase.
* cpp1y/pr58549.C: New testcase.
* cpp1y/pr58637.C: New testcase.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@204714 138bc75d-0d04-0410-961f-82ee72b054a4

13 files changed:
gcc/ChangeLog
gcc/cp/ChangeLog
gcc/cp/decl.c
gcc/cp/parser.c
gcc/cp/parser.h
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/cpp1y/pr58534.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp1y/pr58536.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp1y/pr58548.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp1y/pr58549.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp1y/pr58637.C [new file with mode: 0644]
gcc/tree.c
gcc/tree.h

index 94ddbe7..630a082 100644 (file)
@@ -1,3 +1,9 @@
+2013-11-12  Adam Butcher  <adam@jessamine.co.uk>
+
+       * tree.c (grow_tree_vec_stat): New function ...
+       * tree.h (grow_tree_vec_stat) (grow_tree_vec): ... and its declaration
+       and macro front-end.
+
 2013-11-12  Marek Polacek  <polacek@redhat.com>
 
        * final.c (update_alignments): Initialize label to NULL_RTX.
index fc70bbd..3f7eb1a 100644 (file)
@@ -1,3 +1,35 @@
+2013-11-12  Adam Butcher  <adam@jessamine.co.uk>
+
+       PR c++/58534
+       PR c++/58536
+       PR c++/58548
+       PR c++/58549
+       PR c++/58637
+       * parser.h (struct cp_parser): New members implicit_template_parms,
+       implicit_template_scope and auto_is_implicit_function_template_parm_p.
+       * parser.c (add_implicit_template_parms): Refactor as ...
+       (synthesize_implicit_template_parm): ... this to append a new template
+       type parm to the current template parameter list (introducing a new list
+       if necessary).  Removed push_deferring_access_checks.
+       (finish_fully_implicit_template): Removed pop_deferring_access_checks.
+       (cp_parser_new): Initialize new cp_parser members.
+       (cp_parser_parameter_declaration_clause): Consider auto as implicit
+       template parm when parsing a parameter declaration (unless parsing an
+       explicit specialization).
+       (cp_parser_parameter_declaration_list): Remove local
+       implicit_template_parms counter and reset cp_parser implicit template
+       state when complete.
+       (cp_parser_lambda_expression): Reset implicit template cp_parser members
+       whilst generating lambda class.
+       (cp_parser_function_definition_after_declarator): Reset implicit
+       template cp_parser members whilst parsing function definition.
+       (make_generic_type_name): Respell '<autoN>' as 'auto:N' which works
+       better with template diagnostics.
+       (cp_parser_simple_type_specifier): Synthesize implicit template parm on
+       parsing 'auto' if auto_is_implicit_function_template_parm_p and provide
+       diagnostics ...
+       * decl.c (grokdeclarator): ... that were previously done here.
+
 2013-11-12  Paolo Carlini  <paolo.carlini@oracle.com>
 
        PR c++/57734
index 8b7a89f..7d9d5df 100644 (file)
@@ -10381,33 +10381,11 @@ 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%>");
-             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");
+         if (cxx_dialect >= cxx1y)
+           error ("%<auto%> parameter not permitted in this context");
          else
-           pedwarn (location_of (type), OPT_Wpedantic,
-                    "ISO C++ forbids use of %<auto%> in parameter "
-                    "declaration");
+           error ("parameter declared %<auto%>");
+         type = error_mark_node;
        }
 
       /* A parameter declared as an array of T is really a pointer to T.
index 1ff56fe..c48952a 100644 (file)
@@ -2107,8 +2107,8 @@ static bool cp_parser_ctor_initializer_opt_and_function_body
 static tree cp_parser_late_parsing_omp_declare_simd
   (cp_parser *, tree);
 
-static tree add_implicit_template_parms
-  (cp_parser *, size_t, tree);
+static tree synthesize_implicit_template_parm
+  (cp_parser *);
 static tree finish_fully_implicit_template
   (cp_parser *, tree);
 
@@ -3443,7 +3443,10 @@ cp_parser_new (void)
   parser->num_template_parameter_lists = 0;
 
   /* Not declaring an implicit function template.  */
+  parser->auto_is_implicit_function_template_parm_p = false;
   parser->fully_implicit_function_template_p = false;
+  parser->implicit_template_parms = 0;
+  parser->implicit_template_scope = 0;
 
   return parser;
 }
@@ -8660,12 +8663,17 @@ cp_parser_lambda_expression (cp_parser* parser)
         = parser->num_template_parameter_lists;
     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;
+    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.  */
@@ -8689,7 +8697,10 @@ cp_parser_lambda_expression (cp_parser* parser)
     parser->num_template_parameter_lists = saved_num_template_parameter_lists;
     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->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 ();
@@ -14096,7 +14107,7 @@ cp_parser_explicit_specialization (cp_parser* parser)
     cp_parser_single_declaration (parser,
                                  /*checks=*/NULL,
                                  /*member_p=*/false,
-                                  /*explicit_specialization_p=*/true,
+                                 /*explicit_specialization_p=*/true,
                                  /*friend_p=*/NULL);
   /* We're done with the specialization.  */
   end_specialization ();
@@ -14398,10 +14409,33 @@ cp_parser_simple_type_specifier (cp_parser* parser,
     case RID_VOID:
       type = void_type_node;
       break;
-      
+
     case RID_AUTO:
       maybe_warn_cpp0x (CPP0X_AUTO);
-      type = make_auto ();
+      if (parser->auto_is_implicit_function_template_parm_p)
+       {
+         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;
 
     case RID_DECLTYPE:
@@ -17980,6 +18014,20 @@ cp_parser_parameter_declaration_clause (cp_parser* parser)
   bool ellipsis_p;
   bool is_error;
 
+  struct cleanup {
+    cp_parser* parser;
+    int auto_is_implicit_function_template_parm_p;
+    ~cleanup() {
+      parser->auto_is_implicit_function_template_parm_p
+       = auto_is_implicit_function_template_parm_p;
+    }
+  } cleanup = { parser, parser->auto_is_implicit_function_template_parm_p };
+
+  (void) cleanup;
+
+  if (!processing_specialization)
+    parser->auto_is_implicit_function_template_parm_p = true;
+
   /* Peek at the next token.  */
   token = cp_lexer_peek_token (parser->lexer);
   /* Check for trivial parameter-declaration-clauses.  */
@@ -18067,7 +18115,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;
@@ -18095,18 +18142,11 @@ cp_parser_parameter_declaration_list (cp_parser* parser, bool *is_error)
       deprecated_state = DEPRECATED_SUPPRESS;
 
       if (parameter)
-       {
-         decl = grokdeclarator (parameter->declarator,
-                                &parameter->decl_specifiers,
-                                PARM,
-                                parameter->default_argument != NULL_TREE,
-                                &parameter->decl_specifiers.attributes);
-
-         if (TREE_TYPE (decl) != error_mark_node
-             && parameter->decl_specifiers.type
-             && is_auto_or_concept (parameter->decl_specifiers.type))
-             ++implicit_template_parms;
-       }
+       decl = grokdeclarator (parameter->declarator,
+                              &parameter->decl_specifiers,
+                              PARM,
+                              parameter->default_argument != NULL_TREE,
+                              &parameter->decl_specifiers.attributes);
 
       deprecated_state = DEPRECATED_NORMAL;
 
@@ -18194,10 +18234,12 @@ 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->level_chain == its)
+      {
+       parser->implicit_template_parms = 0;
+       parser->implicit_template_scope = 0;
+      }
 
   return parameters;
 }
@@ -22461,6 +22503,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;
@@ -22533,6 +22584,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);
 
@@ -31116,7 +31174,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);
 }
 
@@ -31130,110 +31188,138 @@ 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;
-
-  size_t synth_count = 0;
+  /* We are either continuing a function template that already contains implicit
+     template parameters, creating a new fully-implicit function template, or
+     extending an existing explicit function template with implicit template
+     parameters.  */
 
-  /* 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;
+  cp_binding_level *const entry_scope = current_binding_level;
 
-  /* 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;
+  bool become_template = false;
+  cp_binding_level *parent_scope = 0;
 
-  if (become_template)
+  if (parser->implicit_template_scope)
     {
-      push_deferring_access_checks (dk_deferred);
-      begin_template_parm_list ();
+      gcc_assert (parser->implicit_template_parms);
 
-      parser->fully_implicit_function_template_p = true;
-      ++parser->num_template_parameter_lists;
+      current_binding_level = parser->implicit_template_scope;
     }
   else
     {
-      /* Roll back the innermost template parameter list such that it may be
-        extended in the loop below as if it were being explicitly declared.  */
-
-      gcc_assert (current_template_parms);
+      /* Roll back to the existing template parameter scope (in the case of
+        extending an explicit function template) or introduce a new template
+        parameter scope ahead of the function parameter scope (or class scope
+        in the case of out-of-line member definitions).  The function scope is
+        added back after template parameter synthesis below.  */
 
-      /* Pop the innermost template parms into TPARMS.  */
-      tree inner_vec = INNERMOST_TEMPLATE_PARMS (current_template_parms);
-      current_template_parms = TREE_CHAIN (current_template_parms);
+      cp_binding_level *scope = entry_scope;
 
-      size_t inner_vec_len = TREE_VEC_LENGTH (inner_vec);
-      if (inner_vec_len != 0)
+      while (scope->kind == sk_function_parms)
        {
-         tree t = tparms = 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);
+         parent_scope = scope;
+         scope = scope->level_chain;
        }
+      if (current_class_type && !LAMBDA_TYPE_P (current_class_type)
+         && parser->num_classes_being_defined == 0)
+       while (scope->kind == sk_class)
+         {
+           parent_scope = scope;
+           scope = scope->level_chain;
+         }
 
-      ++processing_template_parmlist;
-    }
+      current_binding_level = scope;
 
-  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 (scope->kind != sk_template_parms)
+       {
+         /* Introduce a new template parameter list for implicit template
+            parameters.  */
 
-      if (!generic_type_ptr)
-       continue;
+         become_template = true;
+
+         parser->implicit_template_scope
+             = begin_scope (sk_template_parms, NULL);
 
-      ++synth_count;
+         ++processing_template_decl;
 
-      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),
-                                     /*non_type=*/false,
-                                     /*param_pack=*/false);
+         parser->fully_implicit_function_template_p = true;
+         ++parser->num_template_parameter_lists;
+       }
+      else
+       {
+         /* Synthesize implicit template parameters at the end of the explicit
+            template parameter list.  */
 
-      /* 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.  */
+         gcc_assert (current_template_parms);
 
-      tree& cur_type = TREE_TYPE (generic_type_ptr);
-      tree new_type = TREE_TYPE (getdecls ());
+         parser->implicit_template_scope = scope;
 
-      if (TYPE_QUALS (cur_type))
-       cur_type = cp_build_qualified_type (new_type, TYPE_QUALS (cur_type));
-      else
-       cur_type = new_type;
+         tree v = INNERMOST_TEMPLATE_PARMS (current_template_parms);
+         parser->implicit_template_parms
+           = TREE_VEC_ELT (v, TREE_VEC_LENGTH (v) - 1);
+       }
     }
 
-  gcc_assert (synth_count == expect_count);
+  /* Synthesize a new template parameter and track the current template
+     parameter chain with implicit_template_parms.  */
 
-  push_binding_level (fn_parms_scope);
+  tree synth_id = make_generic_type_name ();
+  tree synth_tmpl_parm = finish_template_type_parm (class_type_node,
+                                                   synth_id);
+  tree new_parm
+    = process_template_parm (parser->implicit_template_parms,
+                            input_location,
+                            build_tree_list (NULL_TREE, synth_tmpl_parm),
+                            /*non_type=*/false,
+                            /*param_pack=*/false);
 
-  end_template_parm_list (tparms);
 
-  return parameters;
+  if (parser->implicit_template_parms)
+    parser->implicit_template_parms
+      = TREE_CHAIN (parser->implicit_template_parms);
+  else
+    parser->implicit_template_parms = new_parm;
+
+  tree new_type = TREE_TYPE (getdecls ());
+
+  /* If creating a fully implicit function template, start the new implicit
+     template parameter list with this synthesized type, otherwise grow the
+     current template parameter list.  */
+
+  if (become_template)
+    {
+      parent_scope->level_chain = current_binding_level;
+
+      tree new_parms = make_tree_vec (1);
+      TREE_VEC_ELT (new_parms, 0) = parser->implicit_template_parms;
+      current_template_parms = tree_cons (size_int (processing_template_decl),
+                                         new_parms, current_template_parms);
+    }
+  else
+    {
+      tree& new_parms = INNERMOST_TEMPLATE_PARMS (current_template_parms);
+      int new_parm_idx = TREE_VEC_LENGTH (new_parms);
+      new_parms = grow_tree_vec_stat (new_parms, new_parm_idx + 1);
+      TREE_VEC_ELT (new_parms, new_parm_idx) = parser->implicit_template_parms;
+    }
+
+  current_binding_level = entry_scope;
+
+  return new_type;
 }
 
 /* Finish the declaration of a fully implicit function template.  Such a
    template has no explicit template parameter list so has not been through the
-   normal template head and tail processing.  add_implicit_template_parms tries
-   to do the head; this tries to do the tail.  MEMBER_DECL_OPT should be
+   normal template head and tail processing.  synthesize_implicit_template_parm
+   tries to do the head; this tries to do the tail.  MEMBER_DECL_OPT should be
    provided if the declaration is a class member such that its template
    declaration can be completed.  If MEMBER_DECL_OPT is provided the finished
    form is returned.  Otherwise NULL_TREE is returned. */
@@ -31251,7 +31337,6 @@ finish_fully_implicit_template (cp_parser *parser, tree member_decl_opt)
       DECL_VIRTUAL_P (member_decl_opt) = false;
     }
 
-  pop_deferring_access_checks ();
   if (member_decl_opt)
     member_decl_opt = finish_member_template_decl (member_decl_opt);
   end_template_decl ();
index 75f327b..1024024 100644 (file)
@@ -360,11 +360,30 @@ typedef struct GTY(()) cp_parser {
      data structure with everything needed for parsing the clauses.  */
   cp_omp_declare_simd_data * GTY((skip)) omp_declare_simd;
 
+  /* Nonzero if parsing a parameter list where 'auto' should trigger an implicit
+     template parameter.  */
+  bool auto_is_implicit_function_template_parm_p;
+
   /* TRUE if the function being declared was made a template due to its
      parameter list containing generic type specifiers (`auto' or concept
      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  */
index d3be7aa..f4cf0ae 100644 (file)
@@ -1,3 +1,16 @@
+2013-11-12  Adam Butcher  <adam@jessamine.co.uk>
+
+       PR c++/58534
+       PR c++/58536
+       PR c++/58548
+       PR c++/58549
+       PR c++/58637
+       * g++.dg/cpp1y/pr58534.C: New testcase.
+       * g++.dg/cpp1y/pr58536.C: New testcase.
+       * g++.dg/cpp1y/pr58548.C: New testcase.
+       * g++.dg/cpp1y/pr58549.C: New testcase.
+       * g++.dg/cpp1y/pr58637.C: New testcase.
+
 2013-11-12  Joseph Myers  <joseph@codesourcery.com>
 
        * gcc.dg/c90-thread-local-1.c, gcc.dg/c99-thread-local-1.c,
diff --git a/gcc/testsuite/g++.dg/cpp1y/pr58534.C b/gcc/testsuite/g++.dg/cpp1y/pr58534.C
new file mode 100644 (file)
index 0000000..4aa4f43
--- /dev/null
@@ -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 (file)
index 0000000..8050c19
--- /dev/null
@@ -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 (file)
index 0000000..0ac2e1c
--- /dev/null
@@ -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 (file)
index 0000000..b71bac9
--- /dev/null
@@ -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 (file)
index 0000000..46200ff
--- /dev/null
@@ -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" }
+
index 686a680..dd0371d 100644 (file)
@@ -1864,6 +1864,28 @@ make_tree_vec_stat (int len MEM_STAT_DECL)
 
   return t;
 }
+
+/* Grow a TREE_VEC node to new length LEN.  */
+
+tree
+grow_tree_vec_stat (tree v, int len MEM_STAT_DECL)
+{
+  gcc_assert (TREE_CODE (v) == TREE_VEC);
+
+  int oldlen = TREE_VEC_LENGTH (v);
+  gcc_assert (len > oldlen);
+
+  int oldlength = (oldlen - 1) * sizeof (tree) + sizeof (struct tree_vec);
+  int length = (len - 1) * sizeof (tree) + sizeof (struct tree_vec);
+
+  record_node_allocation_statistics (TREE_VEC, length - oldlength);
+
+  v = (tree) ggc_realloc_stat (v, length PASS_MEM_STAT);
+
+  TREE_VEC_LENGTH (v) = len;
+
+  return v;
+}
 \f
 /* Return 1 if EXPR is the integer constant zero or a complex constant
    of zero.  */
index 3633caf..9c2f2d0 100644 (file)
@@ -3430,6 +3430,11 @@ extern tree make_tree_binfo_stat (unsigned MEM_STAT_DECL);
 extern tree make_tree_vec_stat (int MEM_STAT_DECL);
 #define make_tree_vec(t) make_tree_vec_stat (t MEM_STAT_INFO)
 
+/* Grow a TREE_VEC.  */
+
+extern tree grow_tree_vec_stat (tree v, int MEM_STAT_DECL);
+#define grow_tree_vec(v, t) grow_tree_vec_stat (v, t MEM_STAT_INFO)
+
 /* Return the (unique) IDENTIFIER_NODE node for a given name.
    The name is supplied as a char *.  */