aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorJason Merrill <jason@redhat.com>2017-07-13 09:04:04 -0400
committerJason Merrill <jason@gcc.gnu.org>2017-07-13 09:04:04 -0400
commitf914a1e291319daebae373b3f886c7300dfdeec1 (patch)
treed93616aeb9e1950ddde30a96c0c9cd8e9a552521 /gcc
parent62c1a252aa75de5bf3c44ffa867e761a61279049 (diff)
downloadgcc-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/ChangeLog5
-rw-r--r--gcc/cp/pt.c65
-rw-r--r--gcc/testsuite/g++.dg/cpp1z/class-deduction41.C19
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;