On Thu, Feb 3, 2022 at 3:20 PM Jason Merrill <ja...@redhat.com> wrote: > > 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?
When instantiating the lambda inside the pack expansion, we call tsubst_lambda_expr with args={ARGUMENT_PACK_SELECT}, wherein we add these args to the lambda's LAMBDA_EXPR_REGEN_INFO for use later during satisfaction. And during satisfaction we key the satisfaction cache by those template arguments before any substitution happens. So we didn't get a chance to unwrap the ARGUMENT_PACK_SELECT arguments yet, which IIUC happens transparently during substitution. > > 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" } >