aboutsummaryrefslogtreecommitdiff
path: root/gcc/cp
diff options
context:
space:
mode:
authorJason Merrill <jason@redhat.com>2009-09-18 17:25:10 -0400
committerJason Merrill <jason@gcc.gnu.org>2009-09-18 17:25:10 -0400
commit5f5babf18b5bede638a67406cbd3ebf480cd4b8f (patch)
tree6aa179508e77386b7ac3dfbb8cfab78bd7ff3486 /gcc/cp
parent172d0c86838196561037b8766f231da85c7bd45c (diff)
downloadgcc-5f5babf18b5bede638a67406cbd3ebf480cd4b8f.zip
gcc-5f5babf18b5bede638a67406cbd3ebf480cd4b8f.tar.gz
gcc-5f5babf18b5bede638a67406cbd3ebf480cd4b8f.tar.bz2
c.opt: Add -fno-deduce-init-list.
* c.opt: Add -fno-deduce-init-list. * pt.c (get_pattern_parm): New. (listify): Split out from... (listify_autos): ...here. (unify): Deduce std::initializer_list for T. * call.c (build_over_call): Warn about it. From-SVN: r151867
Diffstat (limited to 'gcc/cp')
-rw-r--r--gcc/cp/ChangeLog10
-rw-r--r--gcc/cp/call.c22
-rw-r--r--gcc/cp/cp-tree.h1
-rw-r--r--gcc/cp/pt.c69
4 files changed, 94 insertions, 8 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 8bf0dde..350aa3e 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,11 @@
+2009-09-18 Jason Merrill <jason@redhat.com>
+
+ * pt.c (get_pattern_parm): New.
+ (listify): Split out from...
+ (listify_autos): ...here.
+ (unify): Deduce std::initializer_list for T.
+ * call.c (build_over_call): Warn about it.
+
2009-09-17 Andrew Pinski <pinskia@gcc.gnu.org>
PR c++/39365
@@ -67,7 +75,7 @@
* decl.c (build_init_list_var_init): Check return value of
perform_implicit_conversion.
-2009-09-03 Jason Merrill <jason@redhat.com>
+2009-09-08 Jason Merrill <jason@redhat.com>
* class.c (currently_open_class): Make sure we're dealing with the
main variant.
diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index f4b0497..8c1bb0e 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -5568,6 +5568,28 @@ build_over_call (struct z_candidate *cand, int flags, tsubst_flags_t complain)
&& !TREE_ADDRESSABLE (type))
conv = conv->u.next;
+ /* Warn about initializer_list deduction that isn't currently in the
+ working draft. */
+ if (cxx_dialect > cxx98
+ && flag_deduce_init_list
+ && cand->template_decl
+ && is_std_init_list (non_reference (type)))
+ {
+ tree tmpl = TI_TEMPLATE (cand->template_decl);
+ tree realparm = chain_index (j, DECL_ARGUMENTS (cand->fn));
+ tree patparm = get_pattern_parm (realparm, tmpl);
+
+ if (!is_std_init_list (non_reference (TREE_TYPE (patparm))))
+ {
+ pedwarn (input_location, 0, "deducing %qT as %qT",
+ non_reference (TREE_TYPE (patparm)),
+ non_reference (type));
+ pedwarn (input_location, 0, " in call to %q+D", cand->fn);
+ pedwarn (input_location, 0,
+ " (you can disable this with -fno-deduce-init-list)");
+ }
+ }
+
val = convert_like_with_context
(conv, VEC_index (tree, args, arg_index), fn, i - is_method,
complain);
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index e8db635..7801f98 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -4646,6 +4646,7 @@ extern tree get_types_needing_access_check (tree);
extern int template_class_depth (tree);
extern int is_specialization_of (tree, tree);
extern bool is_specialization_of_friend (tree, tree);
+extern tree get_pattern_parm (tree, tree);
extern int comp_template_args (tree, tree);
extern tree maybe_process_partial_specialization (tree);
extern tree most_specialized_instantiation (tree);
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 9f094a3..7e3a545 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -192,6 +192,8 @@ static void perform_typedefs_access_check (tree tmpl, tree targs);
static void append_type_to_template_for_access_check_1 (tree, tree, tree);
static hashval_t iterative_hash_template_arg (tree arg, hashval_t val);
static bool primary_template_instantiation_p (const_tree);
+static tree listify (tree);
+static tree listify_autos (tree, tree);
/* Make the current scope suitable for access checking when we are
processing T. T can be FUNCTION_DECL for instantiated function
@@ -8033,6 +8035,36 @@ tsubst_pack_expansion (tree t, tree args, tsubst_flags_t complain,
return result;
}
+/* Given PARM_DECL PARM, find the corresponding PARM_DECL in the template
+ TMPL. We do this using DECL_PARM_INDEX, which should work even with
+ parameter packs; all parms generated from a function parameter pack will
+ have the same DECL_PARM_INDEX. */
+
+tree
+get_pattern_parm (tree parm, tree tmpl)
+{
+ tree pattern = DECL_TEMPLATE_RESULT (tmpl);
+ tree patparm;
+
+ if (DECL_ARTIFICIAL (parm))
+ {
+ for (patparm = DECL_ARGUMENTS (pattern);
+ patparm; patparm = TREE_CHAIN (patparm))
+ if (DECL_ARTIFICIAL (patparm)
+ && DECL_NAME (parm) == DECL_NAME (patparm))
+ break;
+ }
+ else
+ {
+ patparm = FUNCTION_FIRST_USER_PARM (DECL_TEMPLATE_RESULT (tmpl));
+ patparm = chain_index (DECL_PARM_INDEX (parm)-1, patparm);
+ gcc_assert (DECL_PARM_INDEX (patparm)
+ == DECL_PARM_INDEX (parm));
+ }
+
+ return patparm;
+}
+
/* Substitute ARGS into the vector or list of template arguments T. */
static tree
@@ -13727,6 +13759,12 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict)
{
tree elt, elttype;
unsigned i;
+ tree orig_parm = parm;
+
+ /* Replace T with std::initializer_list<T> for deduction. */
+ if (TREE_CODE (parm) == TEMPLATE_TYPE_PARM
+ && flag_deduce_init_list)
+ parm = listify (parm);
if (!is_std_init_list (parm))
/* We can only deduce from an initializer list argument if the
@@ -13752,6 +13790,16 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict)
if (unify (tparms, targs, elttype, elt, elt_strict))
return 1;
}
+
+ /* If the std::initializer_list<T> deduction worked, replace the
+ deduced A with std::initializer_list<A>. */
+ if (orig_parm != parm)
+ {
+ idx = TEMPLATE_TYPE_IDX (orig_parm);
+ targ = TREE_VEC_ELT (INNERMOST_TEMPLATE_ARGS (targs), idx);
+ targ = listify (targ);
+ TREE_VEC_ELT (INNERMOST_TEMPLATE_ARGS (targs), idx) = targ;
+ }
return 0;
}
@@ -17446,26 +17494,33 @@ make_auto (void)
return au;
}
-/* Replace auto in TYPE with std::initializer_list<auto>. */
+/* Given type ARG, return std::initializer_list<ARG>. */
static tree
-listify_autos (tree type, tree auto_node)
+listify (tree arg)
{
tree std_init_list = namespace_binding
(get_identifier ("initializer_list"), std_node);
tree argvec;
- tree init_auto;
if (!std_init_list || !DECL_CLASS_TEMPLATE_P (std_init_list))
{
- error ("deducing auto from brace-enclosed initializer list requires "
+ error ("deducing from brace-enclosed initializer list requires "
"#include <initializer_list>");
return error_mark_node;
}
argvec = make_tree_vec (1);
- TREE_VEC_ELT (argvec, 0) = auto_node;
- init_auto = lookup_template_class (std_init_list, argvec, NULL_TREE,
- NULL_TREE, 0, tf_warning_or_error);
+ TREE_VEC_ELT (argvec, 0) = arg;
+ return lookup_template_class (std_init_list, argvec, NULL_TREE,
+ NULL_TREE, 0, tf_warning_or_error);
+}
+
+/* Replace auto in TYPE with std::initializer_list<auto>. */
+static tree
+listify_autos (tree type, tree auto_node)
+{
+ tree init_auto = listify (auto_node);
+ tree argvec = make_tree_vec (1);
TREE_VEC_ELT (argvec, 0) = init_auto;
if (processing_template_decl)
argvec = add_to_template_args (current_template_args (), argvec);