This testcase demonstrates we can legitimately enter satisfaction with
an ARGUMENT_PACK_SELECT argument, which is problematic because we can't
store such arguments in the satisfaction cache (or any other hash table).

Since this appears to be possible only during constrained auto deduction
for a return-type-requirement, the most appropriate spot to fix this seems
to be from do_auto_deduction, by calling preserve_args to strip A_P_S args
before entering satisfaction.

Bootstrapped and regtested on x86_64-pc-linux-gnu, does this look OK for
trunk/12?

        PR c++/105644

gcc/cp/ChangeLog:

        * pt.cc (do_auto_deduction): Call preserve_args before entering
        satisfaction for adc_requirement contexts.

gcc/testsuite/ChangeLog:

        * g++.dg/cpp2a/concepts-requires36.C: New test.
---
 gcc/cp/pt.cc                                     |  6 ++++++
 gcc/testsuite/g++.dg/cpp2a/concepts-requires36.C | 12 ++++++++++++
 2 files changed, 18 insertions(+)
 create mode 100644 gcc/testsuite/g++.dg/cpp2a/concepts-requires36.C

diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
index 4429ae66b68..821e0035c08 100644
--- a/gcc/cp/pt.cc
+++ b/gcc/cp/pt.cc
@@ -30965,6 +30965,12 @@ do_auto_deduction (tree type, tree init, tree 
auto_node,
            return type;
        }
 
+      /* We can see an ARGUMENT_PACK_SELECT argument when evaluating
+        a return-type-requirement.  Get rid of them before entering
+        satisfaction, since the satisfaction cache can't handle them.  */
+      if (context == adc_requirement)
+       outer_targs = preserve_args (outer_targs);
+
       if (context == adc_return_type
          || context == adc_variable_type
          || context == adc_decomp_type)
diff --git a/gcc/testsuite/g++.dg/cpp2a/concepts-requires36.C 
b/gcc/testsuite/g++.dg/cpp2a/concepts-requires36.C
new file mode 100644
index 00000000000..7d13b9b3e54
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/concepts-requires36.C
@@ -0,0 +1,12 @@
+// PR c++/105644
+// { dg-do compile { target c++20 } }
+
+template<class T, class U>
+concept same_as = __is_same(T, U);
+
+template<class... Ts>
+concept C = (requires { { Ts() } -> same_as<Ts>; } && ...);
+
+static_assert(C<int, char>);
+static_assert(!C<int, const char>);
+static_assert(!C<const int, char>);
-- 
2.40.0.153.g6369acd968

Reply via email to