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.
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" } -- 2.35.0