This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [C++ PATCH] Refactor implicit function template implementation and fix 58534, 58536, 58548, 58549 and 58637.


On 2013-11-10 10:38, Adam Butcher wrote:
On 2013-11-10 6:10, Jason Merrill wrote:

Hmm, actually I think messing with the non-pack's decl is dangerous,
and we should come up with a new decl for the pack instead.  I think
you can use reduce_template_parm_level with a "levels" argument of 0
to build a new decl and parm index.

I actually did this in one of my experiments and it worked fine.
Although I also had to update the template parm list with new decl:

  TREE_VALUE (TREE_VEC_ELT (current, i)) = TREE_CHAIN (t);

At that point I had the convert function in pt.c an operating directly on current_template_parms (also having direct access to the two statics
required; reduce_template_parm_level and canonical_type_parameter).

I can't think of a case where we'd want to make this substitution in
anything but the current_template_parms so maybe moving the convert
function back into to pt.c and removing the 'current' parm from it
might be best?

And if we're doing that, setting TYPE_STUB_DECL and TYPE_NAME is
indeed necessary.

Only for the sake of not exposing this (currently static) function from pt.c (or moving the pack convert function into pt.c). My original impl did extern canonical_type_parameter and use that and I think it worked
as expected.  Would that be preferred?

Yes. Please declare it in cp-tree.h rather than within the function.

Will do.  Unless, as suggested above, we go for moving
convert_generic_types_to_packs into pt.c in which case exposing these
internals won't be necessary.


With the convert function in pt.c, PATCH 2/3 now looks as follows:


    Support implicit parameter packs.
    
    	* 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.

diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index fd79adb..e30922a 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -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);
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index c48952a..eaad8e4 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -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)
+	{
+	  /* 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;
 
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 8c1553f..360d8a3 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -21629,6 +21629,56 @@ 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 = 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);
+    }
+
+  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);
+}
+
+
 /* Set up the hash tables for template instantiations.  */
 
 void

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]