summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorabutcher <abutcher@138bc75d-0d04-0410-961f-82ee72b054a4>2013-11-12 20:17:44 +0000
committerabutcher <abutcher@138bc75d-0d04-0410-961f-82ee72b054a4>2013-11-12 20:17:44 +0000
commit520877fb31003ff8a00dd5f1170849dd15d8f4e8 (patch)
tree87f7a8f525ae28a29777c7a6bfc9ad0639e235df
parent19646b27a9d7436cda1724746425f1eb36499705 (diff)
downloadgcc-520877fb31003ff8a00dd5f1170849dd15d8f4e8.tar.gz
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. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@204715 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r--gcc/cp/ChangeLog10
-rw-r--r--gcc/cp/cp-tree.h1
-rw-r--r--gcc/cp/parser.c36
-rw-r--r--gcc/cp/pt.c52
4 files changed, 92 insertions, 7 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 3f7eb1aa9e2..c85345eb270 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 fd79adbd357..e30922ab43a 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 c48952abbb2..eaad8e44aa7 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 = &parameters;
+ tree *tail = &parameters;
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,
- &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,
+ 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 d066c26dd88..57a9769aecc 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