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

Reply via email to