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?
Bootstrapped and regtested on x86_64-pc-linux-gnu, does this look OK
for trunk and perhaps 11?
PR c++/103706
gcc/cp/ChangeLog:
* constraint.cc (sat_hasher::hash): Look through
ARGUMENT_PACK_SELECT.
(sat_hasher::equal) Likewise.
* cp-tree.h (argument_pack_select_arg): Declare.
* pt.cc (argument_pack_select_arg): No longer static.
gcc/testsuite/ChangeLog:
* g++.dg/cpp2a/concepts-lambda19.C: New test.
---
gcc/cp/constraint.cc | 6 ++++++
gcc/cp/cp-tree.h | 1 +
gcc/cp/pt.cc | 2 +-
gcc/testsuite/g++.dg/cpp2a/concepts-lambda19.C | 11 +++++++++++
4 files changed, 19 insertions(+), 1 deletion(-)
create mode 100644 gcc/testsuite/g++.dg/cpp2a/concepts-lambda19.C
diff --git a/gcc/cp/constraint.cc b/gcc/cp/constraint.cc
index c41ee02b910..ab45988e8bd 100644
--- a/gcc/cp/constraint.cc
+++ b/gcc/cp/constraint.cc
@@ -2484,6 +2484,8 @@ struct sat_hasher : ggc_ptr_hash<sat_entry>
tree parm = TREE_VALUE (target_parms);
template_parm_level_and_index (parm, &level, &index);
tree arg = TMPL_ARG (e->args, level, index);
+ if (TREE_CODE (arg) == ARGUMENT_PACK_SELECT)
+ arg = argument_pack_select_arg (arg);
value = iterative_hash_template_arg (arg, value);
}
return value;
@@ -2515,6 +2517,10 @@ struct sat_hasher : ggc_ptr_hash<sat_entry>
template_parm_level_and_index (parm, &level, &index);
tree arg1 = TMPL_ARG (e1->args, level, index);
tree arg2 = TMPL_ARG (e2->args, level, index);
+ if (TREE_CODE (arg1) == ARGUMENT_PACK_SELECT)
+ arg1 = argument_pack_select_arg (arg1);
+ if (TREE_CODE (arg2) == ARGUMENT_PACK_SELECT)
+ arg2 = argument_pack_select_arg (arg2);
if (!template_args_equal (arg1, arg2))
return false;
}
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 7a7fe5ba599..0bb4d8eb5df 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -7375,6 +7375,7 @@ extern bool primary_template_specialization_p
(const_tree);
extern tree get_primary_template_innermost_parameters (const_tree);
extern tree get_template_innermost_arguments (const_tree);
extern tree get_template_argument_pack_elems (const_tree);
+extern tree argument_pack_select_arg (tree);
extern tree get_function_template_decl (const_tree);
extern tree resolve_nondeduced_context (tree, tsubst_flags_t);
extern tree resolve_nondeduced_context_or_error (tree, tsubst_flags_t);
diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
index c919d2de68f..1ddd36b4413 100644
--- a/gcc/cp/pt.cc
+++ b/gcc/cp/pt.cc
@@ -3718,7 +3718,7 @@ get_template_argument_pack_elems (const_tree t)
/* In an ARGUMENT_PACK_SELECT, the actual underlying argument that the
ARGUMENT_PACK_SELECT represents. */
-static tree
+tree
argument_pack_select_arg (tree t)
{
tree args = ARGUMENT_PACK_ARGS (ARGUMENT_PACK_SELECT_FROM_PACK (t));
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..fcf086248f5
--- /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" }