This extends the PR93107 fix, which made us do resolve_nondeduced_context on the elements of an initializer list during auto deduction, to happen for CTAD as well.
Bootstrapped and regtested on x86_64-pc-linux-gnu, does this look OK for trunk? PR c++/106214 PR c++/93107 gcc/cp/ChangeLog: * pt.cc (do_auto_deduction): Move up resolve_nondeduced_context calls to happen before do_class_deduction. Add some error_mark_node tests. gcc/testsuite/ChangeLog: * g++.dg/cpp1z/class-deduction114.C: New test. --- gcc/cp/pt.cc | 27 +++++++++--------- .../g++.dg/cpp1z/class-deduction114.C | 28 +++++++++++++++++++ 2 files changed, 41 insertions(+), 14 deletions(-) create mode 100644 gcc/testsuite/g++.dg/cpp1z/class-deduction114.C diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc index 8d66fde9f11..94e1664d00c 100644 --- a/gcc/cp/pt.cc +++ b/gcc/cp/pt.cc @@ -30793,7 +30793,7 @@ do_auto_deduction (tree type, tree init, tree auto_node, int flags /* = LOOKUP_NORMAL */, tree tmpl /* = NULL_TREE */) { - if (init == error_mark_node) + if (type == error_mark_node || init == error_mark_node) return error_mark_node; if (init && type_dependent_expression_p (init) @@ -30827,6 +30827,17 @@ do_auto_deduction (tree type, tree init, tree auto_node, /*return*/true))) init = r; + if (init && BRACE_ENCLOSED_INITIALIZER_P (init)) + { + /* We don't recurse here because we can't deduce from a nested + initializer_list. */ + if (CONSTRUCTOR_ELTS (init)) + for (constructor_elt &elt : CONSTRUCTOR_ELTS (init)) + elt.value = resolve_nondeduced_context (elt.value, complain); + } + else if (init) + init = resolve_nondeduced_context (init, complain); + if (tree ctmpl = CLASS_PLACEHOLDER_TEMPLATE (auto_node)) /* C++17 class template argument deduction. */ return do_class_deduction (type, ctmpl, init, flags, complain); @@ -30861,24 +30872,12 @@ do_auto_deduction (tree type, tree init, tree auto_node, } } - if (type == error_mark_node) + if (type == error_mark_node || init == error_mark_node) return error_mark_node; - if (BRACE_ENCLOSED_INITIALIZER_P (init)) - { - /* We don't recurse here because we can't deduce from a nested - initializer_list. */ - if (CONSTRUCTOR_ELTS (init)) - for (constructor_elt &elt : CONSTRUCTOR_ELTS (init)) - elt.value = resolve_nondeduced_context (elt.value, complain); - } - else - init = resolve_nondeduced_context (init, complain); - tree targs; if (context == adc_decomp_type && auto_node == type - && init != error_mark_node && TREE_CODE (TREE_TYPE (init)) == ARRAY_TYPE) { /* [dcl.struct.bind]/1 - if decomposition declaration has no ref-qualifiers diff --git a/gcc/testsuite/g++.dg/cpp1z/class-deduction114.C b/gcc/testsuite/g++.dg/cpp1z/class-deduction114.C new file mode 100644 index 00000000000..ba6921d1b96 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp1z/class-deduction114.C @@ -0,0 +1,28 @@ +// PR c++/106214 +// { dg-do compile { target c++17 } } +// A version of cpp0x/initlist-deduce3.C using list CTAD instead +// of ordinary auto deduction from std::initializer_list. + +using size_t = decltype(sizeof 0); + +namespace std { + template<typename T> struct initializer_list { + const T *ptr; + size_t n; + initializer_list(const T*, size_t); + }; +} + +template<typename T> +void Task() {} + +template<class T> +struct vector { + vector(std::initializer_list<T>); +}; + +vector a = &Task<int>; // { dg-error "deduction|no match" } +vector b = { &Task<int> }; +vector e{ &Task<int> }; +vector f = { &Task<int>, &Task<int> }; +vector d = { static_cast<void(*)()>(&Task<int>) }; -- 2.40.1.476.g69c786637d