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

Reply via email to