diff options
author | Jason Merrill <jason@redhat.com> | 2017-07-13 09:04:04 -0400 |
---|---|---|
committer | Jason Merrill <jason@gcc.gnu.org> | 2017-07-13 09:04:04 -0400 |
commit | f914a1e291319daebae373b3f886c7300dfdeec1 (patch) | |
tree | d93616aeb9e1950ddde30a96c0c9cd8e9a552521 /gcc | |
parent | 62c1a252aa75de5bf3c44ffa867e761a61279049 (diff) | |
download | gcc-f914a1e291319daebae373b3f886c7300dfdeec1.zip gcc-f914a1e291319daebae373b3f886c7300dfdeec1.tar.gz gcc-f914a1e291319daebae373b3f886c7300dfdeec1.tar.bz2 |
P0512R0 - Deduction from an initializer list.
* pt.c (do_class_deduction): Do list deduction in two phases.
From-SVN: r250183
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/cp/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/cp/pt.c | 65 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/cpp1z/class-deduction41.C | 19 |
3 files changed, 78 insertions, 11 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 178b262..02214c9 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,8 @@ +2017-07-12 Jason Merrill <jason@redhat.com> + + P0512R0 - Deduction from an initializer list. + * pt.c (do_class_deduction): Do list deduction in two phases. + 2017-07-12 Nathan Sidwell <nathan@acm.org> * cp-tree.h (DECL_CONSTRUCTOR_P, DECL_MAYBE_IN_CHARGE_CONSTRUCTOR, diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index bd02951..0df6854 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -25329,14 +25329,20 @@ do_class_deduction (tree ptype, tree tmpl, tree init, int flags, tree type = TREE_TYPE (tmpl); + bool try_list_ctor = false; + vec<tree,va_gc> *args; if (init == NULL_TREE || TREE_CODE (init) == TREE_LIST) args = make_tree_vector_from_list (init); - else if (BRACE_ENCLOSED_INITIALIZER_P (init) - && !TYPE_HAS_LIST_CTOR (type) - && !is_std_init_list (type)) - args = make_tree_vector_from_ctor (init); + else if (BRACE_ENCLOSED_INITIALIZER_P (init)) + { + try_list_ctor = TYPE_HAS_LIST_CTOR (type); + if (try_list_ctor || is_std_init_list (type)) + args = make_tree_vector_single (init); + else + args = make_tree_vector_from_ctor (init); + } else args = make_tree_vector_single (init); @@ -25391,13 +25397,43 @@ do_class_deduction (tree ptype, tree tmpl, tree init, int flags, saw_ctor = true; } - if (args->length () < 2) + tree call = error_mark_node; + + /* If this is list-initialization and the class has a list constructor, first + try deducing from the list as a single argument, as [over.match.list]. */ + tree list_cands = NULL_TREE; + if (try_list_ctor && cands) + for (lkp_iterator iter (cands); iter; ++iter) + { + tree dg = *iter; + if (is_list_ctor (dg)) + list_cands = lookup_add (dg, list_cands); + } + if (list_cands) + { + ++cp_unevaluated_operand; + call = build_new_function_call (list_cands, &args, tf_decltype); + --cp_unevaluated_operand; + + if (call == error_mark_node) + { + /* That didn't work, now try treating the list as a sequence of + arguments. */ + release_tree_vector (args); + args = make_tree_vector_from_ctor (init); + } + } + + /* Maybe generate an implicit deduction guide. */ + if (call == error_mark_node && args->length () < 2) { tree gtype = NULL_TREE; if (args->length () == 1) + /* Generate a copy guide. */ gtype = build_reference_type (type); else if (!saw_ctor) + /* Generate a default guide. */ gtype = type; if (gtype) @@ -25419,22 +25455,29 @@ do_class_deduction (tree ptype, tree tmpl, tree init, int flags, return error_mark_node; } - ++cp_unevaluated_operand; - tree t = build_new_function_call (cands, &args, tf_decltype); + if (call == error_mark_node) + { + ++cp_unevaluated_operand; + call = build_new_function_call (cands, &args, tf_decltype); + --cp_unevaluated_operand; + } - if (t == error_mark_node && (complain & tf_warning_or_error)) + if (call == error_mark_node && (complain & tf_warning_or_error)) { error ("class template argument deduction failed:"); - t = build_new_function_call (cands, &args, complain | tf_decltype); + + ++cp_unevaluated_operand; + call = build_new_function_call (cands, &args, complain | tf_decltype); + --cp_unevaluated_operand; + if (elided) inform (input_location, "explicit deduction guides not considered " "for copy-initialization"); } - --cp_unevaluated_operand; release_tree_vector (args); - return cp_build_qualified_type (TREE_TYPE (t), cp_type_quals (ptype)); + return cp_build_qualified_type (TREE_TYPE (call), cp_type_quals (ptype)); } /* Replace occurrences of 'auto' in TYPE with the appropriate type deduced diff --git a/gcc/testsuite/g++.dg/cpp1z/class-deduction41.C b/gcc/testsuite/g++.dg/cpp1z/class-deduction41.C new file mode 100644 index 0000000..5e7fa3a --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp1z/class-deduction41.C @@ -0,0 +1,19 @@ +// { dg-options -std=c++1z } + +#include <initializer_list> + +struct B { }; + +template <class T> +struct A +{ + A(std::initializer_list<T>); + A(T, B); +}; + +A a { 1, B() }; + +template <class,class> struct same; +template <class T> struct same<T,T> { }; + +same<decltype(a), A<int>> s; |