From f914a1e291319daebae373b3f886c7300dfdeec1 Mon Sep 17 00:00:00 2001 From: Jason Merrill Date: Thu, 13 Jul 2017 09:04:04 -0400 Subject: [PATCH] P0512R0 - Deduction from an initializer list. * pt.c (do_class_deduction): Do list deduction in two phases. From-SVN: r250183 --- gcc/cp/ChangeLog | 5 ++ gcc/cp/pt.c | 65 +++++++++++++++---- .../g++.dg/cpp1z/class-deduction41.C | 19 ++++++ 3 files changed, 78 insertions(+), 11 deletions(-) create mode 100644 gcc/testsuite/g++.dg/cpp1z/class-deduction41.C diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 178b2626098..02214c9953b 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,8 @@ +2017-07-12 Jason Merrill + + P0512R0 - Deduction from an initializer list. + * pt.c (do_class_deduction): Do list deduction in two phases. + 2017-07-12 Nathan Sidwell * cp-tree.h (DECL_CONSTRUCTOR_P, DECL_MAYBE_IN_CHARGE_CONSTRUCTOR, diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index bd02951cb85..0df6854f648 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 *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 00000000000..5e7fa3a2c51 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp1z/class-deduction41.C @@ -0,0 +1,19 @@ +// { dg-options -std=c++1z } + +#include + +struct B { }; + +template +struct A +{ + A(std::initializer_list); + A(T, B); +}; + +A a { 1, B() }; + +template struct same; +template struct same { }; + +same> s; -- 2.30.2