diff mbox

[C++,2/3] Support implicit parameter packs.

Message ID 1383212824-5493-3-git-send-email-adam@jessamine.co.uk
State New
Headers show

Commit Message

Adam Butcher Oct. 31, 2013, 9:47 a.m. UTC
* parser.c (convert_generic_types_to_packs): New function to transform
	a range of implicitly introduced non-pack template parms to be parameter
	packs.
	(cp_parser_parameter_declaration_list): If a function parameter pack
	contains generic types, convert them to packs prior to grokdeclarator.
---
 gcc/cp/parser.c | 81 ++++++++++++++++++++++++++++++++++++++++++++++++++++-----
 1 file changed, 74 insertions(+), 7 deletions(-)
diff mbox

Patch

diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index b699ac4..10b9f72 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -2109,6 +2109,8 @@  static tree cp_parser_late_parsing_omp_declare_simd
 
 static tree synthesize_implicit_template_parm
   (cp_parser *);
+static tree convert_generic_types_to_packs
+  (tree, tree, int, int);
 static tree finish_fully_implicit_template
   (cp_parser *, tree);
 
@@ -18069,7 +18071,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;
 
@@ -18078,7 +18080,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;
 
@@ -18088,6 +18090,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,
@@ -18099,11 +18105,30 @@  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,
+		   current_template_parms,
+		   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;
 
@@ -31213,6 +31238,48 @@  synthesize_implicit_template_parm  (cp_parser *parser)
   return new_type;
 }
 
+/* Convert the generic type parameters in PARM that match the types given in the
+   range [START_IDX, END_IDX) from the template parameters CURRENT into generic
+   type packs.  */
+
+tree
+convert_generic_types_to_packs (tree parm,
+				tree current, int start_idx, int end_idx)
+{
+  int depth = TMPL_PARMS_DEPTH (current);
+  current = INNERMOST_TEMPLATE_PARMS (current);
+  tree replacement = make_tree_vec (TREE_VEC_LENGTH (current));
+
+  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 t = copy_type (TREE_TYPE (TREE_VALUE (TREE_VEC_ELT (current, i))));
+      TYPE_STUB_DECL (t) = TYPE_NAME (t) = TEMPLATE_TYPE_DECL (t);
+      TYPE_MAIN_VARIANT (t) = t;
+      TEMPLATE_TYPE_PARAMETER_PACK (t) = true;
+      SET_TYPE_STRUCTURAL_EQUALITY (t);
+      TREE_VEC_ELT (replacement, i) = t;
+    }
+
+  if (depth > 1)
+    {
+      /* Build up a tree vec of empty tree vecs up to the inner substitution
+	 args built above.  */
+
+      tree inner = replacement;
+      replacement = make_tree_vec (depth);
+      int last = depth - 1;
+      for (int i = 0; i < last; ++i)
+	TREE_VEC_ELT (replacement, i) = make_tree_vec (0);
+      TREE_VEC_ELT (replacement, last) = inner;
+    }
+
+  return tsubst (parm, replacement, tf_none, NULL_TREE);
+}
+
 /* 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.  synthesize_implicit_template_parm