This PR points out that we accept
template<typename T> struct tuple { tuple(T); }; // #1
template<typename T> explicit tuple(T t) -> tuple<T>; // #2
tuple t = { 1 };
despite the 'explicit' deduction guide in a copy-list-initialization
context. That's because in deduction_guides_for we first find the
user-defined deduction guide (#2), and then ctor_deduction_guides_for
creates artificial deduction guides: one from the tuple(T) constructor and
a copy guide. So we end up with these three guides:
(1) template<class T> tuple(T) -> tuple<T> [DECL_NONCONVERTING_P]
(2) template<class T> tuple(tuple<T>) -> tuple<T>
(3) template<class T> tuple(T) -> tuple<T>
Then, in do_class_deduction, we prune this set, and get rid of (1).
Then overload resolution selects (3) and we succeed.
But [over.match.list]p1 says "In copy-list-initialization, if an explicit
constructor is chosen, the initialization is ill-formed." It also goes
on to say that this differs from other situations where only converting
constructors are considered for copy-initialization. Therefore for
list-initialization we consider explicit constructors and complain if one
is chosen. E.g. convert_like_internal/ck_user can give an error.
So my logic runs that we should not prune the deduction_guides_for guides
in a copy-list-initialization context, and only complain if we actually
choose an explicit deduction guide. This matches clang++/EDG/msvc++.
Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk?
gcc/cp/ChangeLog:
PR c++/90210
* pt.c (do_class_deduction): Don't prune explicit deduction guides
in copy-list-initialization. In copy-list-initialization, if an
explicit deduction guide was selected, give an error.
gcc/testsuite/ChangeLog:
PR c++/90210
* g++.dg/cpp1z/class-deduction73.C: New test.
---
gcc/cp/pt.c | 49 ++++++++++++++-----
.../g++.dg/cpp1z/class-deduction73.C | 41 ++++++++++++++++
2 files changed, 79 insertions(+), 11 deletions(-)
create mode 100644 gcc/testsuite/g++.dg/cpp1z/class-deduction73.C
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index cfe5ff4a94f..9bcb743dc1d 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -28929,6 +28929,7 @@ do_class_deduction (tree ptype, tree tmpl, tree init,
tree type = TREE_TYPE (tmpl);
bool try_list_ctor = false;
+ bool list_init_p = false;
releasing_vec rv_args = NULL;
vec<tree,va_gc> *&args = *&rv_args;
@@ -28936,6 +28937,7 @@ do_class_deduction (tree ptype, tree tmpl, tree init,
args = make_tree_vector ();
else if (BRACE_ENCLOSED_INITIALIZER_P (init))
{
+ list_init_p = true;
try_list_ctor = TYPE_HAS_LIST_CTOR (type);
if (try_list_ctor && CONSTRUCTOR_NELTS (init) == 1)
{
@@ -28967,9 +28969,10 @@ do_class_deduction (tree ptype, tree tmpl, tree init,
if (cands == error_mark_node)
return error_mark_node;
- /* Prune explicit deduction guides in copy-initialization context. */
+ /* Prune explicit deduction guides in copy-initialization context (but
+ not copy-list-initialization). */
bool elided = false;
- if (flags & LOOKUP_ONLYCONVERTING)
+ if (!list_init_p && (flags & LOOKUP_ONLYCONVERTING))
{
for (lkp_iterator iter (cands); !elided && iter; ++iter)
if (DECL_NONCONVERTING_P (STRIP_TEMPLATE (*iter)))
@@ -29038,18 +29041,42 @@ do_class_deduction (tree ptype, tree tmpl, tree init,
--cp_unevaluated_operand;
}
- if (call == error_mark_node
- && (complain & tf_warning_or_error))
+ if (call == error_mark_node)
{
- error ("class template argument deduction failed:");
+ if (complain & tf_warning_or_error)
+ {
+ error ("class template argument deduction failed:");
- ++cp_unevaluated_operand;
- call = build_new_function_call (cands, &args, complain | tf_decltype);
- --cp_unevaluated_operand;
+ ++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");
+ if (elided)
+ inform (input_location, "explicit deduction guides not considered "
+ "for copy-initialization");
+ }
+ return error_mark_node;
+ }
+ /* [over.match.list]/1: In copy-list-initialization, if an explicit
+ constructor is chosen, the initialization is ill-formed. */
+ else if (flags & LOOKUP_ONLYCONVERTING)
+ {
+ tree fndecl = cp_get_callee_fndecl_nofold (call);
+ if (fndecl && DECL_NONCONVERTING_P (fndecl))
+ {
+ if (complain & tf_warning_or_error)
+ {
+ // TODO: Pass down location from cp_finish_decl.
+ error ("class template argument deduction for %qT failed: "
+ "explicit deduction guide selected in "
+ "copy-list-initialization", type);
+ inform (DECL_SOURCE_LOCATION (fndecl),
+ "explicit deduction guide declared here");
+
+ }
+ return error_mark_node;
+ }
}
return cp_build_qualified_type (TREE_TYPE (call), cp_type_quals (ptype));
diff --git a/gcc/testsuite/g++.dg/cpp1z/class-deduction73.C
b/gcc/testsuite/g++.dg/cpp1z/class-deduction73.C
new file mode 100644
index 00000000000..b37ddedd1bf
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1z/class-deduction73.C
@@ -0,0 +1,41 @@
+// PR c++/90210
+// { dg-do compile { target c++17 } }
+
+template<typename T> struct tuple { tuple(T); };
+template<typename T> explicit tuple(T t) -> tuple<T>;
+tuple t = { 1 }; // { dg-error "explicit deduction guide selected" }
+tuple t1 = tuple{ 1 };
+tuple t2{ 1 };
+
+template<typename T> struct A { A(T, T); };
+template<typename T> explicit A(T, T) -> A<int>;
+A a = {1, 1}; // { dg-error "explicit deduction guide selected" }
+A a1 = A{1, 1};
+A a2{1, 1};
+
+template<typename T, typename U>
+struct B {
+ B(T, U);
+};
+template<typename T, typename U>
+B(T, U) -> B<T, typename U::type>; // SFINAEd-out
+B b = { 1, 2 }; // OK
+B b1 = B{ 1, 2 }; // OK
+B b2{ 1, 2 }; // OK
+
+// Overriden implicit default constructor deduction guide:
+template<typename T>
+struct C { };
+explicit C() -> C<int>;
+C c = {}; // { dg-error "explicit deduction guide selected" }
+C c1 = C{};
+C c2{};
+
+// Overriden copy guide:
+template<typename T>
+struct D { };
+template<typename T> explicit D(D<T>) -> D<T>;
+D<int> d;
+D d1 = {d}; // { dg-error "explicit deduction guide selected" }
+D d2 = D{d};
+D d3{d};
base-commit: 4a5ff2b56bfea0b3e154a15e809c5c42dc3b9e9f