On 5/5/23 13:36, Patrick Palka wrote:
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.
Maybe move them even higher? I suppose it shouldn't actually make a
difference, but this seems to make sense right after the early returns.
OK either way.
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>) };