From: Jason Merrill Date: Fri, 18 Sep 2009 21:25:10 +0000 (-0400) Subject: c.opt: Add -fno-deduce-init-list. X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=5f5babf18b5bede638a67406cbd3ebf480cd4b8f;p=gcc.git 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 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index a3602abb810..16ee1d69a1f 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,7 @@ +2009-09-18 Jason Merrill + + * c.opt: Add -fno-deduce-init-list. + 2009-09-18 Neil Vachharajani * value-prof.c (interesting_stringop_to_profile_p): Added output diff --git a/gcc/c.opt b/gcc/c.opt index 5ee9a1348d4..21f7ab71246 100644 --- a/gcc/c.opt +++ b/gcc/c.opt @@ -558,6 +558,10 @@ fconstant-string-class= ObjC ObjC++ Joined -fconst-string-class= Use class for constant strings +fdeduce-init-list +C++ ObjC++ Var(flag_deduce_init_list) Init(1) +-fno-deduce-init-list disable deduction of std::initializer_list for a template type parameter from a brace-enclosed initializer-list + fdefault-inline C++ ObjC++ Inline member functions by default diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 8bf0dde4226..350aa3ee8cd 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,11 @@ +2009-09-18 Jason Merrill + + * 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 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 +2009-09-08 Jason Merrill * 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 f4b0497b7f9..8c1bb0edd47 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 e8db635fda7..7801f987e51 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 9f094a3959e..7e3a54540ec 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 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 deduction worked, replace the + deduced A with std::initializer_list. */ + 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. */ +/* Given type ARG, return std::initializer_list. */ 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 "); 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. */ +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); diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi index 5a96820ba14..ad8e51cfe97 100644 --- a/gcc/doc/invoke.texi +++ b/gcc/doc/invoke.texi @@ -1785,6 +1785,27 @@ two definitions were merged. This option is no longer useful on most targets, now that support has been added for putting variables into BSS without making them common. +@item -fno-deduce-init-list +@opindex fno-deduce-init-list +Disable deduction of a template type parameter as +std::initializer_list from a brace-enclosed initializer list, i.e. + +@smallexample +template auto forward(T t) -> decltype (realfn (t)) +@{ + return realfn (t); +@} + +void f() +@{ + forward(@{1,2@}); // call forward> +@} +@end smallexample + +This option is present because this deduction is an extension to the +current specification in the C++0x working draft, and there was +some concern about potential overload resolution problems. + @item -ffriend-injection @opindex ffriend-injection Inject friend functions into the enclosing namespace, so that they are diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index e4e7a21af78..43f42b5e5fe 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2009-09-18 Jason Merrill + + * g++.dg/cpp0x/initlist-deduce.C: New. + 2009-09-18 Janis Johnson * gcc.dg/dfp/dfp.exp: Also run tests in c-c++-common/dfp. diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist-deduce.C b/gcc/testsuite/g++.dg/cpp0x/initlist-deduce.C new file mode 100644 index 00000000000..e422132afc3 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/initlist-deduce.C @@ -0,0 +1,26 @@ +// Test for deduction of T as std::initializer_list. This isn't currently +// supported by the working draft, but is necessary for perfect forwarding +// of initializer-lists to things that can take a std::initializer_list. + +// { dg-options -std=c++0x } +// { dg-do run } + +#include + +struct A +{ + A(std::initializer_list) { } +}; + +void f (A a) { } + +template +auto g (T&& t) -> decltype (f(t)) // { dg-warning "call" } +{ + return f(t); +} + +int main() +{ + g({1}); // { dg-warning "deduc" } +}