Commit 5f5babf1 by Jason Merrill Committed by Jason Merrill

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
parent 172d0c86
2009-09-18 Jason Merrill <jason@redhat.com>
* c.opt: Add -fno-deduce-init-list.
2009-09-18 Neil Vachharajani <nvachhar@google.com> 2009-09-18 Neil Vachharajani <nvachhar@google.com>
* value-prof.c (interesting_stringop_to_profile_p): Added output * value-prof.c (interesting_stringop_to_profile_p): Added output
......
...@@ -558,6 +558,10 @@ fconstant-string-class= ...@@ -558,6 +558,10 @@ fconstant-string-class=
ObjC ObjC++ Joined ObjC ObjC++ Joined
-fconst-string-class=<name> Use class <name> for constant strings -fconst-string-class=<name> Use class <name> 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 fdefault-inline
C++ ObjC++ C++ ObjC++
Inline member functions by default Inline member functions by default
......
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> 2009-09-17 Andrew Pinski <pinskia@gcc.gnu.org>
PR c++/39365 PR c++/39365
...@@ -67,7 +75,7 @@ ...@@ -67,7 +75,7 @@
* decl.c (build_init_list_var_init): Check return value of * decl.c (build_init_list_var_init): Check return value of
perform_implicit_conversion. 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 * class.c (currently_open_class): Make sure we're dealing with the
main variant. main variant.
......
...@@ -5568,6 +5568,28 @@ build_over_call (struct z_candidate *cand, int flags, tsubst_flags_t complain) ...@@ -5568,6 +5568,28 @@ build_over_call (struct z_candidate *cand, int flags, tsubst_flags_t complain)
&& !TREE_ADDRESSABLE (type)) && !TREE_ADDRESSABLE (type))
conv = conv->u.next; 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 val = convert_like_with_context
(conv, VEC_index (tree, args, arg_index), fn, i - is_method, (conv, VEC_index (tree, args, arg_index), fn, i - is_method,
complain); complain);
......
...@@ -4646,6 +4646,7 @@ extern tree get_types_needing_access_check (tree); ...@@ -4646,6 +4646,7 @@ extern tree get_types_needing_access_check (tree);
extern int template_class_depth (tree); extern int template_class_depth (tree);
extern int is_specialization_of (tree, tree); extern int is_specialization_of (tree, tree);
extern bool is_specialization_of_friend (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 int comp_template_args (tree, tree);
extern tree maybe_process_partial_specialization (tree); extern tree maybe_process_partial_specialization (tree);
extern tree most_specialized_instantiation (tree); extern tree most_specialized_instantiation (tree);
......
...@@ -192,6 +192,8 @@ static void perform_typedefs_access_check (tree tmpl, tree targs); ...@@ -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 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 hashval_t iterative_hash_template_arg (tree arg, hashval_t val);
static bool primary_template_instantiation_p (const_tree); 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 /* Make the current scope suitable for access checking when we are
processing T. T can be FUNCTION_DECL for instantiated function 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, ...@@ -8033,6 +8035,36 @@ tsubst_pack_expansion (tree t, tree args, tsubst_flags_t complain,
return result; 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. */ /* Substitute ARGS into the vector or list of template arguments T. */
static tree static tree
...@@ -13727,6 +13759,12 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict) ...@@ -13727,6 +13759,12 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict)
{ {
tree elt, elttype; tree elt, elttype;
unsigned i; 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)) if (!is_std_init_list (parm))
/* We can only deduce from an initializer list argument if the /* 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) ...@@ -13752,6 +13790,16 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict)
if (unify (tparms, targs, elttype, elt, elt_strict)) if (unify (tparms, targs, elttype, elt, elt_strict))
return 1; 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; return 0;
} }
...@@ -17446,26 +17494,33 @@ make_auto (void) ...@@ -17446,26 +17494,33 @@ make_auto (void)
return au; return au;
} }
/* Replace auto in TYPE with std::initializer_list<auto>. */ /* Given type ARG, return std::initializer_list<ARG>. */
static tree static tree
listify_autos (tree type, tree auto_node) listify (tree arg)
{ {
tree std_init_list = namespace_binding tree std_init_list = namespace_binding
(get_identifier ("initializer_list"), std_node); (get_identifier ("initializer_list"), std_node);
tree argvec; tree argvec;
tree init_auto;
if (!std_init_list || !DECL_CLASS_TEMPLATE_P (std_init_list)) 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>"); "#include <initializer_list>");
return error_mark_node; return error_mark_node;
} }
argvec = make_tree_vec (1); argvec = make_tree_vec (1);
TREE_VEC_ELT (argvec, 0) = auto_node; TREE_VEC_ELT (argvec, 0) = arg;
init_auto = lookup_template_class (std_init_list, argvec, NULL_TREE, return lookup_template_class (std_init_list, argvec, NULL_TREE,
NULL_TREE, 0, tf_warning_or_error); 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; TREE_VEC_ELT (argvec, 0) = init_auto;
if (processing_template_decl) if (processing_template_decl)
argvec = add_to_template_args (current_template_args (), argvec); argvec = add_to_template_args (current_template_args (), argvec);
......
...@@ -1785,6 +1785,27 @@ two definitions were merged. ...@@ -1785,6 +1785,27 @@ two definitions were merged.
This option is no longer useful on most targets, now that support has This option is no longer useful on most targets, now that support has
been added for putting variables into BSS without making them common. 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 <class T> auto forward(T t) -> decltype (realfn (t))
@{
return realfn (t);
@}
void f()
@{
forward(@{1,2@}); // call forward<std::initializer_list<int>>
@}
@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 @item -ffriend-injection
@opindex ffriend-injection @opindex ffriend-injection
Inject friend functions into the enclosing namespace, so that they are Inject friend functions into the enclosing namespace, so that they are
......
2009-09-18 Jason Merrill <jason@redhat.com>
* g++.dg/cpp0x/initlist-deduce.C: New.
2009-09-18 Janis Johnson <janis187@us.ibm.com> 2009-09-18 Janis Johnson <janis187@us.ibm.com>
* gcc.dg/dfp/dfp.exp: Also run tests in c-c++-common/dfp. * gcc.dg/dfp/dfp.exp: Also run tests in c-c++-common/dfp.
......
// 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 <initializer_list>
struct A
{
A(std::initializer_list<int>) { }
};
void f (A a) { }
template <class T>
auto g (T&& t) -> decltype (f(t)) // { dg-warning "call" }
{
return f(t);
}
int main()
{
g({1}); // { dg-warning "deduc" }
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment