c++: CTAD from initializer list [PR106366]
During CTAD, we currently perform the first phase of overload resolution from [over.match.list] only if the class template has a list constructor. But according to [over.match.class.deduct]/4 it should be enough to just have a guide that looks like a list constructor (which is a more general criterion in light of user-defined guides). PR c++/106366 gcc/cp/ChangeLog: * pt.cc (do_class_deduction): Don't consider TYPE_HAS_LIST_CTOR when setting try_list_ctor. Reset args even when try_list_ctor is true and there are no list candidates. Call resolve_args on the reset args. Rename try_list_ctor to try_list_cand. gcc/testsuite/ChangeLog: * g++.dg/cpp1z/class-deduction112.C: New test.
This commit is contained in:
parent
b585af38a1
commit
f77bbc8f86
2 changed files with 29 additions and 16 deletions
31
gcc/cp/pt.cc
31
gcc/cp/pt.cc
|
@ -30240,7 +30240,7 @@ do_class_deduction (tree ptype, tree tmpl, tree init,
|
|||
|
||||
tree type = TREE_TYPE (tmpl);
|
||||
|
||||
bool try_list_ctor = false;
|
||||
bool try_list_cand = false;
|
||||
bool list_init_p = false;
|
||||
|
||||
releasing_vec rv_args = NULL;
|
||||
|
@ -30250,8 +30250,8 @@ do_class_deduction (tree ptype, tree tmpl, tree init,
|
|||
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
|
||||
try_list_cand = true;
|
||||
if (CONSTRUCTOR_NELTS (init) == 1
|
||||
&& !CONSTRUCTOR_IS_DESIGNATED_INIT (init))
|
||||
{
|
||||
/* As an exception, the first phase in 16.3.1.7 (considering the
|
||||
|
@ -30261,9 +30261,9 @@ do_class_deduction (tree ptype, tree tmpl, tree init,
|
|||
specialization of C. */
|
||||
tree elt = CONSTRUCTOR_ELT (init, 0)->value;
|
||||
if (is_spec_or_derived (TREE_TYPE (elt), tmpl))
|
||||
try_list_ctor = false;
|
||||
try_list_cand = false;
|
||||
}
|
||||
if (try_list_ctor || is_std_init_list (type))
|
||||
if (try_list_cand || is_std_init_list (type))
|
||||
args = make_tree_vector_single (init);
|
||||
else
|
||||
args = make_tree_vector_from_ctor (init);
|
||||
|
@ -30310,26 +30310,25 @@ do_class_deduction (tree ptype, tree tmpl, tree init,
|
|||
|
||||
tree fndecl = error_mark_node;
|
||||
|
||||
/* If this is list-initialization and the class has a list constructor, first
|
||||
/* If this is list-initialization and the class has a list guide, 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 (try_list_cand)
|
||||
{
|
||||
tree list_cands = NULL_TREE;
|
||||
for (tree dg : lkp_range (cands))
|
||||
if (is_list_ctor (dg))
|
||||
list_cands = lookup_add (dg, list_cands);
|
||||
}
|
||||
if (list_cands)
|
||||
{
|
||||
fndecl = perform_dguide_overload_resolution (list_cands, args, tf_none);
|
||||
|
||||
if (list_cands)
|
||||
fndecl = perform_dguide_overload_resolution (list_cands, args, tf_none);
|
||||
if (fndecl == 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);
|
||||
args = resolve_args (args, complain);
|
||||
if (args == NULL)
|
||||
return error_mark_node;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
14
gcc/testsuite/g++.dg/cpp1z/class-deduction112.C
Normal file
14
gcc/testsuite/g++.dg/cpp1z/class-deduction112.C
Normal file
|
@ -0,0 +1,14 @@
|
|||
// PR c++/106366
|
||||
// { dg-do compile { target c++17 } }
|
||||
|
||||
#include <initializer_list>
|
||||
|
||||
template<class T>
|
||||
struct A { A(...); };
|
||||
|
||||
template<typename T>
|
||||
A(std::initializer_list<T>) -> A<T>;
|
||||
|
||||
A a{1,2,3};
|
||||
using type = decltype(a);
|
||||
using type = A<int>;
|
Loading…
Add table
Reference in a new issue