PR c++/86439
gcc/cp/ChangeLog:
* call.c (print_error_for_call_failure): Constify 'args'
parameter.
(perform_dguide_overload_resolution): Define.
* cp-tree.h: (perform_dguide_overload_resolution): Declare.
* pt.c (do_class_deduction): Use perform_dguide_overload_resolution
instead of build_new_function_call. Don't use tf_decltype or
set cp_unevaluated_operand. Remove unnecessary NULL_TREE tests.
libstdc++-v3/ChangeLog:
* testsuite/23_containers/map/cons/deduction.cc: Remove
ambiguous CTAD constructs.
* testsuite/23_containers/multimap/cons/deduction.cc: Likewise.
* testsuite/23_containers/multiset/cons/deduction.cc: Likewise.
* testsuite/23_containers/set/cons/deduction.cc: Likewise.
* testsuite/23_containers/unordered_map/cons/deduction.cc: Likewise.
* testsuite/23_containers/unordered_multimap/cons/deduction.cc:
Likewise.
* testsuite/23_containers/unordered_multiset/cons/deduction.cc:
Likewise.
* testsuite/23_containers/unordered_set/cons/deduction.cc: Likewise.
gcc/testsuite/ChangeLog:
* g++.dg/cpp1z/class-deduction88.C: New test.
* g++.dg/cpp1z/class-deduction89.C: New test.
* g++.dg/cpp1z/class-deduction90.C: New test.
---
gcc/cp/call.c | 36 +++++++++++++++-
gcc/cp/cp-tree.h | 2 +
gcc/cp/pt.c | 41 +++++++------------
.../g++.dg/cpp1z/class-deduction88.C | 20 +++++++++
.../g++.dg/cpp1z/class-deduction89.C | 15 +++++++
.../g++.dg/cpp1z/class-deduction90.C | 16 ++++++++
.../23_containers/map/cons/deduction.cc | 19 ---------
.../23_containers/multimap/cons/deduction.cc | 20 ---------
.../23_containers/multiset/cons/deduction.cc | 14 -------
.../23_containers/set/cons/deduction.cc | 15 -------
.../unordered_map/cons/deduction.cc | 16 --------
.../unordered_multimap/cons/deduction.cc | 16 --------
.../unordered_multiset/cons/deduction.cc | 10 -----
.../unordered_set/cons/deduction.cc | 10 -----
14 files changed, 102 insertions(+), 148 deletions(-)
create mode 100644 gcc/testsuite/g++.dg/cpp1z/class-deduction88.C
create mode 100644 gcc/testsuite/g++.dg/cpp1z/class-deduction89.C
create mode 100644 gcc/testsuite/g++.dg/cpp1z/class-deduction90.C
diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index 9f03534c20c..aafc7acca24 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -4629,7 +4629,7 @@ perform_overload_resolution (tree fn,
functions. */
static void
-print_error_for_call_failure (tree fn, vec<tree, va_gc> *args,
+print_error_for_call_failure (tree fn, const vec<tree, va_gc> *args,
struct z_candidate *candidates)
{
tree targs = NULL_TREE;
@@ -4654,6 +4654,40 @@ print_error_for_call_failure (tree fn, vec<tree, va_gc>
*args,
print_z_candidates (loc, candidates);
}
+/* Perform overload resolution on the set of deduction guides DGUIDES
+ using ARGS. Returns the selected deduction guide, or error_mark_node
+ if overload resolution fails. */
+
+tree
+perform_dguide_overload_resolution (tree dguides, const vec<tree, va_gc> *args,
+ tsubst_flags_t complain)
+{
+ z_candidate *candidates;
+ bool any_viable_p;
+ tree result;
+
+ gcc_assert (deduction_guide_p (OVL_FIRST (dguides)));
+
+ /* Get the high-water mark for the CONVERSION_OBSTACK. */
+ void *p = conversion_obstack_alloc (0);
+
+ z_candidate *cand = perform_overload_resolution (dguides, args, &candidates,
+ &any_viable_p, complain);
+ if (!cand)
+ {
+ if (complain & tf_error)
+ print_error_for_call_failure (dguides, args, candidates);
+ result = error_mark_node;
+ }
+ else
+ result = cand->fn;
+
+ /* Free all the conversions we allocated. */
+ obstack_free (&conversion_obstack, p);
+
+ return result;
+}
+
/* Return an expression for a call to FN (a namespace-scope function,
or a static member function) with the ARGS. This may change
ARGS. */
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 36f99ccf189..6f713719589 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -6437,6 +6437,8 @@ extern void complain_about_bad_argument (location_t
arg_loc,
tree from_type, tree to_type,
tree fndecl, int parmnum);
extern void maybe_inform_about_fndecl_for_bogus_argument_init (tree, int);
+extern tree perform_dguide_overload_resolution (tree, const vec<tree, va_gc> *,
+ tsubst_flags_t);
/* A class for recording information about access failures (e.g. private
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 15947b2c812..732fb405adf 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -29382,7 +29382,7 @@ do_class_deduction (tree ptype, tree tmpl, tree init,
if (tree guide = maybe_aggr_guide (tmpl, init, args))
cands = lookup_add (guide, cands);
- tree call = error_mark_node;
+ tree fndecl = 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].
*/
@@ -29396,11 +29396,9 @@ do_class_deduction (tree ptype, tree tmpl, tree init,
}
if (list_cands)
{
- ++cp_unevaluated_operand;
- call = build_new_function_call (list_cands, &args, tf_decltype);
- --cp_unevaluated_operand;
+ fndecl = perform_dguide_overload_resolution (list_cands, args, tf_none);
- if (call == error_mark_node)
+ if (fndecl == error_mark_node)
{
/* That didn't work, now try treating the list as a sequence of
arguments. */
@@ -29416,31 +29414,22 @@ do_class_deduction (tree ptype, tree tmpl, tree init,
"user-declared constructors", type);
return error_mark_node;
}
- else if (!cands && call == error_mark_node)
+ else if (!cands && fndecl == error_mark_node)
{
error ("cannot deduce template arguments of %qT, as it has no viable "
"deduction guides", type);
return error_mark_node;
}
- if (call == error_mark_node)
- {
- ++cp_unevaluated_operand;
- call = build_new_function_call (cands, &args, tf_decltype);
- --cp_unevaluated_operand;
- }
+ if (fndecl == error_mark_node)
+ fndecl = perform_dguide_overload_resolution (cands, args, tf_none);
- if (call == error_mark_node)
+ if (fndecl == error_mark_node)
{
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;
-
+ perform_dguide_overload_resolution (cands, args, complain);
if (elided)
inform (input_location, "explicit deduction guides not considered "
"for copy-initialization");
@@ -29451,8 +29440,7 @@ do_class_deduction (tree ptype, tree tmpl, tree init,
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 (DECL_NONCONVERTING_P (fndecl))
{
if (complain & tf_warning_or_error)
{
@@ -29470,12 +29458,10 @@ do_class_deduction (tree ptype, tree tmpl, tree init,
/* If CTAD succeeded but the type doesn't have any explicit deduction
guides, this deduction might not be what the user intended. */
- if (call != error_mark_node && !any_dguides_p)
+ if (fndecl != error_mark_node && !any_dguides_p)
{
- tree fndecl = cp_get_callee_fndecl_nofold (call);
- if (fndecl != NULL_TREE
- && (!DECL_IN_SYSTEM_HEADER (fndecl)
- || global_dc->dc_warn_system_headers)
+ if ((!DECL_IN_SYSTEM_HEADER (fndecl)
+ || global_dc->dc_warn_system_headers)
&& warning (OPT_Wctad_maybe_unsupported,
"%qT may not intend to support class template argument "
"deduction", type))
@@ -29483,7 +29469,8 @@ do_class_deduction (tree ptype, tree tmpl, tree init,
"warning");
}
- return cp_build_qualified_type (TREE_TYPE (call), cp_type_quals (ptype));
+ return cp_build_qualified_type (TREE_TYPE (TREE_TYPE (fndecl)),
+ cp_type_quals (ptype));
}
/* Replace occurrences of 'auto' in TYPE with the appropriate type deduced
diff --git a/gcc/testsuite/g++.dg/cpp1z/class-deduction88.C
b/gcc/testsuite/g++.dg/cpp1z/class-deduction88.C
new file mode 100644
index 00000000000..f8fea966696
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1z/class-deduction88.C
@@ -0,0 +1,20 @@
+// PR c++/86439
+// { dg-do compile { target c++17 } }
+
+struct NC {
+ NC() = default;
+ NC(NC const&) = delete;
+ NC& operator=(NC const&) = delete;
+};
+
+template <int>
+struct C {
+ C(NC const&);
+};
+
+C(NC) -> C<0>;
+
+int main() {
+ NC nc;
+ C c(nc);
+}
diff --git a/gcc/testsuite/g++.dg/cpp1z/class-deduction89.C
b/gcc/testsuite/g++.dg/cpp1z/class-deduction89.C
new file mode 100644
index 00000000000..dd898573022
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1z/class-deduction89.C
@@ -0,0 +1,15 @@
+// PR c++/86439
+// { dg-do compile { target c++17 } }
+
+struct B { };
+struct C { };
+
+template<class T>
+struct A {
+ A(T, B);
+};
+
+template<class T>
+A(T, C) -> A<T>;
+
+A a(0, {});
diff --git a/gcc/testsuite/g++.dg/cpp1z/class-deduction90.C
b/gcc/testsuite/g++.dg/cpp1z/class-deduction90.C
new file mode 100644
index 00000000000..8b93193c7b0
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1z/class-deduction90.C
@@ -0,0 +1,16 @@
+// PR c++/86439
+// { dg-do compile { target c++17 } }
+
+struct less { };
+struct allocator { };
+
+template<class T, class U = less, class V = allocator>
+struct A {
+ A(T, U);
+ A(T, V);
+};
+
+template<class T, class U = less>
+A(T, U) -> A<T>;
+
+A a(0, {}); // { dg-error "ambiguous" }
diff --git a/libstdc++-v3/testsuite/23_containers/map/cons/deduction.cc
b/libstdc++-v3/testsuite/23_containers/map/cons/deduction.cc
index e9628c4ac32..8def11ed574 100644
--- a/libstdc++-v3/testsuite/23_containers/map/cons/deduction.cc
+++ b/libstdc++-v3/testsuite/23_containers/map/cons/deduction.cc
@@ -39,10 +39,6 @@ static_assert(std::is_same_v<
std::map<int, double>>);
*/
-static_assert(std::is_same_v<
- decltype(std::map{{std::pair{1, 2.0}, {2, 3.0}, {3, 4.0}}, {}}),
- std::map<int, double>>);
-
/* This is not deducible, ambiguous candidates:
* map(initializer_list<value_type>, const Compare&, const _Allocator& = {})
* map(initializer_list<value_type>, const _Allocator&)
@@ -90,11 +86,6 @@ void f()
std::less<int>{}, {}}),
std::map<int, double>>);
- static_assert(std::is_same_v<
- decltype(std::map(x.begin(), x.end(),
- {})),
- std::map<int, double>>);
-
static_assert(std::is_same_v<
decltype(std::map{x.begin(), x.end(),
std::allocator<value_type>{}}),
@@ -143,11 +134,6 @@ void g()
std::less<int>{}, {}}),
std::map<int, double>>);
- static_assert(std::is_same_v<
- decltype(std::map(x.begin(), x.end(),
- {})),
- std::map<int, double>>);
-
static_assert(std::is_same_v<
decltype(std::map{x.begin(), x.end(),
std::allocator<value_type>{}}),
@@ -193,11 +179,6 @@ void h()
std::less<int>{}, {}}),
std::map<int, double>>);
- static_assert(std::is_same_v<
- decltype(std::map(x.begin(), x.end(),
- {})),
- std::map<int, double>>);
-
static_assert(std::is_same_v<
decltype(std::map{x.begin(), x.end(),
std::allocator<value_type>{}}),
diff --git a/libstdc++-v3/testsuite/23_containers/multimap/cons/deduction.cc
b/libstdc++-v3/testsuite/23_containers/multimap/cons/deduction.cc
index 791cc963479..ff855081ab3 100644
--- a/libstdc++-v3/testsuite/23_containers/multimap/cons/deduction.cc
+++ b/libstdc++-v3/testsuite/23_containers/multimap/cons/deduction.cc
@@ -40,11 +40,6 @@ static_assert(std::is_same_v<
std::multimap<int, double>>);
*/
-static_assert(std::is_same_v<
- decltype(std::multimap{{std::pair{1, 2.0}, {2, 3.0}, {3, 4.0}},
- {}}),
- std::multimap<int, double>>);
-
static_assert(std::is_same_v<
decltype(std::multimap{{value_type{1, 2.0}, {2, 3.0}, {3, 4.0}},
{}, SimpleAllocator<value_type>{}}),
@@ -75,11 +70,6 @@ void f()
std::less<int>{}, {}}),
std::multimap<int, double>>);
- static_assert(std::is_same_v<
- decltype(std::multimap(x.begin(), x.end(),
- {})),
- std::multimap<int, double>>);
-
static_assert(std::is_same_v<
decltype(std::multimap{x.begin(), x.end(),
{},
@@ -117,11 +107,6 @@ void g()
std::less<int>{}, {}}),
std::multimap<int, double>>);
- static_assert(std::is_same_v<
- decltype(std::multimap(x.begin(), x.end(),
- {})),
- std::multimap<int, double>>);
-
static_assert(std::is_same_v<
decltype(std::multimap{x.begin(), x.end(),
{},
@@ -156,11 +141,6 @@ void h()
std::less<int>{}, {}}),
std::multimap<int, double>>);
- static_assert(std::is_same_v<
- decltype(std::multimap(x.begin(), x.end(),
- {})),
- std::multimap<int, double>>);
-
static_assert(std::is_same_v<
decltype(std::multimap{x.begin(), x.end(),
{},
diff --git a/libstdc++-v3/testsuite/23_containers/multiset/cons/deduction.cc
b/libstdc++-v3/testsuite/23_containers/multiset/cons/deduction.cc
index ad12755ccc6..be7ca237e78 100644
--- a/libstdc++-v3/testsuite/23_containers/multiset/cons/deduction.cc
+++ b/libstdc++-v3/testsuite/23_containers/multiset/cons/deduction.cc
@@ -19,10 +19,6 @@ static_assert(std::is_same_v<
decltype(std::multiset{{1, 2, 3}, std::less<int>{}, {}}),
std::multiset<int>>);
-static_assert(std::is_same_v<
- decltype(std::multiset{{1, 2, 3}, {}}),
- std::multiset<int>>);
-
static_assert(std::is_same_v<
decltype(std::multiset{{1, 2, 3}, SimpleAllocator<int>{}}),
std::multiset<int, std::less<int>, SimpleAllocator<int>>>);
@@ -50,11 +46,6 @@ void f()
std::less<int>{}, {}}),
std::multiset<int>>);
- static_assert(std::is_same_v<
- decltype(std::multiset(x.begin(), x.end(),
- {})),
- std::multiset<int>>);
-
static_assert(std::is_same_v<
decltype(std::multiset{x.begin(), x.end(),
std::allocator<int>{}}),
@@ -101,11 +92,6 @@ void g()
std::less<int>{}, {}}),
std::multiset<int>>);
- static_assert(std::is_same_v<
- decltype(std::multiset(x.begin(), x.end(),
- {})),
- std::multiset<int>>);
-
static_assert(std::is_same_v<
decltype(std::multiset{x.begin(), x.end(),
std::allocator<value_type>{}}),
diff --git a/libstdc++-v3/testsuite/23_containers/set/cons/deduction.cc
b/libstdc++-v3/testsuite/23_containers/set/cons/deduction.cc
index 89a2c43b937..48d1a3ebbe2 100644
--- a/libstdc++-v3/testsuite/23_containers/set/cons/deduction.cc
+++ b/libstdc++-v3/testsuite/23_containers/set/cons/deduction.cc
@@ -20,11 +20,6 @@ static_assert(std::is_same_v<
std::less<int>{}, {}}),
std::set<int>>);
-static_assert(std::is_same_v<
- decltype(std::set{{1, 2, 3},
- {}}),
- std::set<int>>);
-
static_assert(std::is_same_v<
decltype(std::set{{1, 2, 3},
SimpleAllocator<int>{}}),
@@ -56,11 +51,6 @@ void f()
std::less<int>{}, {}}),
std::set<int>>);
- static_assert(std::is_same_v<
- decltype(std::set(x.begin(), x.end(),
- {})),
- std::set<int>>);
-
static_assert(std::is_same_v<
decltype(std::set{x.begin(), x.end(),
{},
@@ -102,11 +92,6 @@ void g()
std::less<int>{}, {}}),
std::set<int>>);
- static_assert(std::is_same_v<
- decltype(std::set(x.begin(), x.end(),
- {})),
- std::set<int>>);
-
static_assert(std::is_same_v<
decltype(std::set{x.begin(), x.end(),
std::allocator<value_type>{}}),
diff --git
a/libstdc++-v3/testsuite/23_containers/unordered_map/cons/deduction.cc
b/libstdc++-v3/testsuite/23_containers/unordered_map/cons/deduction.cc
index d8489b23f8a..bd266492b2a 100644
--- a/libstdc++-v3/testsuite/23_containers/unordered_map/cons/deduction.cc
+++ b/libstdc++-v3/testsuite/23_containers/unordered_map/cons/deduction.cc
@@ -21,12 +21,6 @@ static_assert(std::is_same_v<
1}),
std::unordered_map<int, double>>);
-static_assert(std::is_same_v<
- decltype(std::unordered_map{{std::pair{1, 2.0},
- {2, 3.0}, {3, 4.0}},
- {}, std::hash<int>{}, {}}),
- std::unordered_map<int, double>>);
-
static_assert(std::is_same_v<
decltype(std::unordered_map{{std::pair{1, 2.0},
{2, 3.0}, {3, 4.0}},
@@ -57,16 +51,6 @@ void f()
std::allocator<std::pair<const int, double>>{}}),
std::unordered_map<int, double>>);
- static_assert(std::is_same_v<
- decltype(std::unordered_map{x.begin(), x.end(),
- {}, std::hash<int>{}, {}}),
- std::unordered_map<int, double>>);
-
- static_assert(std::is_same_v<
- decltype(std::unordered_map(x.begin(), x.end(),
- {})),
- std::unordered_map<int, double>>);
-
static_assert(std::is_same_v<
decltype(std::unordered_map{x.begin(), x.end(), 1}),
std::unordered_map<int, double>>);
diff --git
a/libstdc++-v3/testsuite/23_containers/unordered_multimap/cons/deduction.cc
b/libstdc++-v3/testsuite/23_containers/unordered_multimap/cons/deduction.cc
index 13f54d43451..74a0165574d 100644
--- a/libstdc++-v3/testsuite/23_containers/unordered_multimap/cons/deduction.cc
+++ b/libstdc++-v3/testsuite/23_containers/unordered_multimap/cons/deduction.cc
@@ -15,12 +15,6 @@ static_assert(std::is_same_v<
{2, 3.0}, {3, 4.0}}}),
std::unordered_multimap<int, double>>);
-static_assert(std::is_same_v<
- decltype(std::unordered_multimap{{std::pair{1, 2.0},
- {2, 3.0}, {3, 4.0}},
- {}, std::hash<int>{}, {}}),
- std::unordered_multimap<int, double>>);
-
static_assert(std::is_same_v<
decltype(std::unordered_multimap{{std::pair{1, 2.0},
{2, 3.0}, {3, 4.0}},
@@ -66,16 +60,6 @@ void f()
std::allocator<std::pair<const int, double>>{}}),
std::unordered_multimap<int, double>>);
- static_assert(std::is_same_v<
- decltype(std::unordered_multimap{x.begin(), x.end(),
- {}, std::hash<int>{}, {}}),
- std::unordered_multimap<int, double>>);
-
- static_assert(std::is_same_v<
- decltype(std::unordered_multimap(x.begin(), x.end(),
- {})),
- std::unordered_multimap<int, double>>);
-
static_assert(std::is_same_v<
decltype(std::unordered_multimap(x.begin(), x.end(), 1)),
std::unordered_multimap<int, double>>);
diff --git
a/libstdc++-v3/testsuite/23_containers/unordered_multiset/cons/deduction.cc
b/libstdc++-v3/testsuite/23_containers/unordered_multiset/cons/deduction.cc
index 1850237e44c..e3006fdbfe3 100644
--- a/libstdc++-v3/testsuite/23_containers/unordered_multiset/cons/deduction.cc
+++ b/libstdc++-v3/testsuite/23_containers/unordered_multiset/cons/deduction.cc
@@ -9,11 +9,6 @@ static_assert(std::is_same_v<
decltype(std::unordered_multiset{1, 2, 3}),
std::unordered_multiset<int>>);
-static_assert(std::is_same_v<
- decltype(std::unordered_multiset{{1, 2, 3},
- 0, std::hash<int>{}, {}}),
- std::unordered_multiset<int>>);
-
static_assert(std::is_same_v<
decltype(std::unordered_multiset{{1, 2, 3},
{}}),
@@ -76,11 +71,6 @@ void f()
std::allocator<int>{}}),
std::unordered_multiset<int>>);
- static_assert(std::is_same_v<
- decltype(std::unordered_multiset{x.begin(), x.end(),
- {}, std::hash<int>{}, {}}),
- std::unordered_multiset<int>>);
-
static_assert(std::is_same_v<
decltype(std::unordered_multiset(x.begin(), x.end(),
{})),
diff --git
a/libstdc++-v3/testsuite/23_containers/unordered_set/cons/deduction.cc
b/libstdc++-v3/testsuite/23_containers/unordered_set/cons/deduction.cc
index a745dce0fba..69922cd92e7 100644
--- a/libstdc++-v3/testsuite/23_containers/unordered_set/cons/deduction.cc
+++ b/libstdc++-v3/testsuite/23_containers/unordered_set/cons/deduction.cc
@@ -9,11 +9,6 @@ static_assert(std::is_same_v<
decltype(std::unordered_set{1, 2, 3}),
std::unordered_set<int>>);
-static_assert(std::is_same_v<
- decltype(std::unordered_set{{1, 2, 3},
- 0, std::hash<int>{}, {}}),
- std::unordered_set<int>>);
-
static_assert(std::is_same_v<
decltype(std::unordered_set{{1, 2, 3},
{}}),
@@ -71,11 +66,6 @@ void f()
std::allocator<int>{}}),
std::unordered_set<int>>);
- static_assert(std::is_same_v<
- decltype(std::unordered_set{x.begin(), x.end(),
- {}, std::hash<int>{}, {}}),
- std::unordered_set<int>>);
-
static_assert(std::is_same_v<
decltype(std::unordered_set(x.begin(), x.end(),
{})),