Support implicit parameter packs.
authorAdam Butcher <adam@jessamine.co.uk>
Tue, 12 Nov 2013 20:17:44 +0000 (20:17 +0000)
committerAdam Butcher <abutcher@gcc.gnu.org>
Tue, 12 Nov 2013 20:17:44 +0000 (20:17 +0000)
* pt.c (convert_generic_types_to_packs): New function to transform
a range of implicitly introduced non-pack template parms to be parameter
packs.
* cp-tree.h (convert_generic_types_to_packs): Declare.
* parser.c (cp_parser_parameter_declaration_list): If a function
parameter pack contains generic types, convert them to packs prior to
grokdeclarator.

From-SVN: r204715

gcc/cp/ChangeLog
gcc/cp/cp-tree.h
gcc/cp/parser.c
gcc/cp/pt.c

index 3f7eb1a..c85345e 100644 (file)
@@ -1,5 +1,15 @@
 2013-11-12  Adam Butcher  <adam@jessamine.co.uk>
 
+       * pt.c (convert_generic_types_to_packs): New function to transform
+       a range of implicitly introduced non-pack template parms to be parameter
+       packs.
+       * cp-tree.h (convert_generic_types_to_packs): Declare.
+       * parser.c (cp_parser_parameter_declaration_list): If a function
+       parameter pack contains generic types, convert them to packs prior to
+       grokdeclarator.
+
+2013-11-12  Adam Butcher  <adam@jessamine.co.uk>
+
        PR c++/58534
        PR c++/58536
        PR c++/58548
index fd79adb..e30922a 100644 (file)
@@ -5469,6 +5469,7 @@ extern tree type_uses_auto                        (tree);
 extern tree type_uses_auto_or_concept          (tree);
 extern void append_type_to_template_for_access_check (tree, tree, tree,
                                                      location_t);
+extern tree convert_generic_types_to_packs     (tree, int, int);
 extern tree splice_late_return_type            (tree, tree);
 extern bool is_auto                            (const_tree);
 extern bool is_auto_or_concept                 (const_tree);
index c48952a..eaad8e4 100644 (file)
@@ -18112,7 +18112,7 @@ static tree
 cp_parser_parameter_declaration_list (cp_parser* parser, bool *is_error)
 {
   tree parameters = NULL_TREE;
-  tree *tail = &parameters; 
+  tree *tail = &parameters;
   bool saved_in_unbraced_linkage_specification_p;
   int index = 0;
 
@@ -18121,7 +18121,7 @@ cp_parser_parameter_declaration_list (cp_parser* parser, bool *is_error)
   /* The special considerations that apply to a function within an
      unbraced linkage specifications do not apply to the parameters
      to the function.  */
-  saved_in_unbraced_linkage_specification_p 
+  saved_in_unbraced_linkage_specification_p
     = parser->in_unbraced_linkage_specification_p;
   parser->in_unbraced_linkage_specification_p = false;
 
@@ -18131,6 +18131,10 @@ 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 = (parser->num_template_parameter_lists?
+                              TREE_VEC_LENGTH (INNERMOST_TEMPLATE_PARMS
+                                               (current_template_parms)) : 0);
+
       /* Parse the parameter.  */
       parameter
        = cp_parser_parameter_declaration (parser,
@@ -18142,11 +18146,29 @@ 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 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,
+                                parameter->default_argument != NULL_TREE,
+                                &parameter->decl_specifiers.attributes);
+       }
 
       deprecated_state = DEPRECATED_NORMAL;
 
index d066c26..57a9769 100644 (file)
@@ -21630,6 +21630,58 @@ append_type_to_template_for_access_check (tree templ,
                                              scope, location);
 }
 
+/* Convert the generic type parameters in PARM that match the types given in the
+   range [START_IDX, END_IDX) from the current_template_parms into generic type
+   packs.  */
+
+tree
+convert_generic_types_to_packs (tree parm, int start_idx, int end_idx)
+{
+  tree current = current_template_parms;
+  int depth = TMPL_PARMS_DEPTH (current);
+  current = INNERMOST_TEMPLATE_PARMS (current);
+  tree replacement = make_tree_vec (TREE_VEC_LENGTH (current));
+
+  for (int i = 0; i < start_idx; ++i)
+    TREE_VEC_ELT (replacement, i)
+      = TREE_TYPE (TREE_VALUE (TREE_VEC_ELT (current, i)));
+
+  for (int i = start_idx; i < end_idx; ++i)
+    {
+      /* Create a distinct parameter pack type from the current parm and add it
+        to the replacement args to tsubst below into the generic function
+        parameter.  */
+
+      tree o = TREE_TYPE (TREE_VALUE
+                         (TREE_VEC_ELT (current, i)));
+      tree t = copy_type (o);
+      TEMPLATE_TYPE_PARM_INDEX (t)
+       = reduce_template_parm_level (TEMPLATE_TYPE_PARM_INDEX (o),
+                                     o, 0, 0, tf_none);
+      TREE_TYPE (TEMPLATE_TYPE_DECL (t)) = t;
+      TYPE_STUB_DECL (t) = TYPE_NAME (t) = TEMPLATE_TYPE_DECL (t);
+      TYPE_MAIN_VARIANT (t) = t;
+      TEMPLATE_TYPE_PARAMETER_PACK (t) = true;
+      TYPE_CANONICAL (t) = canonical_type_parameter (t);
+      TREE_VEC_ELT (replacement, i) = t;
+      TREE_VALUE (TREE_VEC_ELT (current, i)) = TREE_CHAIN (t);
+    }
+
+  for (int i = end_idx, e = TREE_VEC_LENGTH (current); i < e; ++i)
+    TREE_VEC_ELT (replacement, i)
+      = TREE_TYPE (TREE_VALUE (TREE_VEC_ELT (current, i)));
+
+  /* If there are more levels then build up the replacement with the outer
+     template parms.  */
+  if (depth > 1)
+    replacement = add_to_template_args (template_parms_to_args
+                                       (TREE_CHAIN (current_template_parms)),
+                                       replacement);
+
+  return tsubst (parm, replacement, tf_none, NULL_TREE);
+}
+
+
 /* Set up the hash tables for template instantiations.  */
 
 void