diff options
author | Adam Butcher <adam@jessamine.co.uk> | 2013-11-12 20:17:44 +0000 |
---|---|---|
committer | Adam Butcher <abutcher@gcc.gnu.org> | 2013-11-12 20:17:44 +0000 |
commit | 91f1c208261de87fb75bba8124474feba91dd91b (patch) | |
tree | 87f7a8f525ae28a29777c7a6bfc9ad0639e235df /gcc | |
parent | 0dca5025f02ad920b12cede50c7968768decee19 (diff) | |
download | gcc-91f1c208261de87fb75bba8124474feba91dd91b.zip gcc-91f1c208261de87fb75bba8124474feba91dd91b.tar.gz gcc-91f1c208261de87fb75bba8124474feba91dd91b.tar.bz2 |
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.
From-SVN: r204715
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/cp/ChangeLog | 10 | ||||
-rw-r--r-- | gcc/cp/cp-tree.h | 1 | ||||
-rw-r--r-- | gcc/cp/parser.c | 36 | ||||
-rw-r--r-- | gcc/cp/pt.c | 52 |
4 files changed, 92 insertions, 7 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 3f7eb1a..c85345e 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -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 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 @@ -18112,7 +18112,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; @@ -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, - ¶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, + 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 d066c26..57a9769 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -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 |