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,
¶meter->decl_specifiers,
PARM,
parameter->default_argument != NULL_TREE,
¶meter->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