On 2/3/22 12:04, Patrick Palka wrote:
On Wed, 2 Feb 2022, Jason Merrill wrote:
On 2/2/22 12:09, Patrick Palka wrote:
The satisfaction cache needs to look through ARGUMENT_PACK_SELECT
template arguments before calling iterative_hash_template_arg and
template_args_equal, which would otherwise crash.
Maybe we should handle ARGUMENT_PACK_SELECT in iterative_hash_template_arg and
template_args_equal, rather than their callers?
Like so? I can't think of a good reason not to handle ARGUMENT_PACK_SELECT
ther, but FWIW it looks like we had such handling in the past, until it
was removed in r7-2082.
Ah, right. That came after my fix for 67164,
https://gcc.gnu.org/pipermail/gcc-patches/2016-March/443660.html
with that PR, we were seeing ARGUMENT_PACK_SELECT unexpectedly because
of excessive sharing of template argument lists. Why are we seeing it
in satisfaction?
I should have commented the gcc_unreachables better.
-- >8 --
Subject: [PATCH] c++: lambda in pack expansion using outer pack in constraint
[PR103706]
Here when expanding the pack expansion pattern, the template argument
for T is an ARGUMENT_PACK_SELECT, which during satisfaction of C<T> the
satisfaction cache passes to iterative_hash_template_arg and
template_args_equal, which don't handle ARGUMENT_PACK_SELECT presumably
because at some point it became unnecessary to do so. Since it now
appears necessary again, this patch reinstates the ARGUMENT_PACK_SELECT
handling that was removed by r7-2082.
PR c++/103706
gcc/cp/ChangeLog:
* pt.cc (iterative_hash_template_arg): Handle ARGUMENT_PACK_SELECT.
(template_args_equal): Likewise.
gcc/testsuite/ChangeLog:
* g++.dg/cpp2a/concepts-lambda19.C: New test.
---
gcc/cp/pt.cc | 10 ++++++----
gcc/testsuite/g++.dg/cpp2a/concepts-lambda19.C | 11 +++++++++++
2 files changed, 17 insertions(+), 4 deletions(-)
create mode 100644 gcc/testsuite/g++.dg/cpp2a/concepts-lambda19.C
diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
index c62822d65f8..644f24b7c09 100644
--- a/gcc/cp/pt.cc
+++ b/gcc/cp/pt.cc
@@ -220,6 +220,7 @@ static tree make_argument_pack (tree);
static void register_parameter_specializations (tree, tree);
static tree enclosing_instantiation_of (tree tctx);
static void instantiate_body (tree pattern, tree args, tree d, bool nested);
+static tree argument_pack_select_arg (tree t);
/* Make the current scope suitable for access checking when we are
processing T. T can be FUNCTION_DECL for instantiated function
@@ -1783,6 +1784,9 @@ iterative_hash_template_arg (tree arg, hashval_t val)
if (arg == NULL_TREE)
return iterative_hash_object (arg, val);
+ if (TREE_CODE (arg) == ARGUMENT_PACK_SELECT)
+ arg = argument_pack_select_arg (arg);
+
if (!TYPE_P (arg))
/* Strip nop-like things, but not the same as STRIP_NOPS. */
while (CONVERT_EXPR_P (arg)
@@ -1796,9 +1800,6 @@ iterative_hash_template_arg (tree arg, hashval_t val)
switch (code)
{
- case ARGUMENT_PACK_SELECT:
- gcc_unreachable ();
-
case ERROR_MARK:
return val;
@@ -9246,7 +9247,8 @@ template_args_equal (tree ot, tree nt, bool partial_order /* = false */)
else if (ARGUMENT_PACK_P (ot) || ARGUMENT_PACK_P (nt))
return cp_tree_equal (ot, nt);
else if (TREE_CODE (ot) == ARGUMENT_PACK_SELECT)
- gcc_unreachable ();
+ return template_args_equal (argument_pack_select_arg (ot),
+ argument_pack_select_arg (nt));
else if (TYPE_P (nt) || TYPE_P (ot))
{
if (!(TYPE_P (nt) && TYPE_P (ot)))
diff --git a/gcc/testsuite/g++.dg/cpp2a/concepts-lambda19.C
b/gcc/testsuite/g++.dg/cpp2a/concepts-lambda19.C
new file mode 100644
index 00000000000..570e3596f1b
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/concepts-lambda19.C
@@ -0,0 +1,11 @@
+// PR c++/103706
+// { dg-do compile { target c++20 } }
+
+template<class T> concept C = __is_same(T, int);
+
+template<class... T> void f() {
+ ([]() requires C<T> { return T(); }(), ...); // { dg-error "no match" }
+}
+
+template void f<int, int, int>(); // { dg-bogus "" }
+template void f<int, int, char>(); // { dg-message "required from here" }