* 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 --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 = ¶meters; + tree *tail = ¶meters; 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, - ¶meter->decl_specifiers, - PARM, - parameter->default_argument != NULL_TREE, - ¶meter->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, + ¶meter->decl_specifiers, + PARM, + parameter->default_argument != NULL_TREE, + ¶meter->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 -- 1.8.4