On Thu, 5 Sep 2024, Jason Merrill wrote:

> On 9/5/24 1:26 PM, Patrick Palka wrote:
> > On Thu, 5 Sep 2024, Jason Merrill wrote:
> > 
> > > On 9/5/24 10:54 AM, Patrick Palka wrote:
> > > > Bootstrapped and regtested on x86_64-pc-linux-gnu, does this look OK
> > > > for trunk/14?
> > > > 
> > > > -- >8 --
> > > > 
> > > > A lambda within a default template argument used in some template-id
> > > > may have a smaller template depth than the context of the template-id.
> > > > For example, the lambda in v1's default template argument has template
> > > > depth 1, and in v2's has template depth 2, but the template-ids v1<0>
> > > > and v2<0> which uses these default arguments appear in a depth 3
> > > > template
> > > > context.  So add_extra_args will ultimately return args with depth 3 --
> > > > too many args for the lambda, leading to a bogus substitution.
> > > > 
> > > > This patch fixes this by trimming the result of add_extra_args to match
> > > > the template depth of the lambda.  A new LAMBDA_EXPR_TEMPLATE_DEPTH
> > > > field
> > > > is added that tracks the template-ness of a lambda;
> > > > 
> > > >         PR c++/116567
> > > > 
> > > > gcc/cp/ChangeLog:
> > > > 
> > > >         * pt.cc (tsubst_lambda_expr): For a deferred-substitution 
> > > > lambda,
> > > >         trim the augmented template arguments to match the template 
> > > > depth
> > > >         of the lambda.
> > > > 
> > > > gcc/testsuite/ChangeLog:
> > > > 
> > > >         * g++.dg/cpp2a/lambda-targ7.C: New test.
> > > > ---
> > > >    gcc/cp/pt.cc                              | 11 +++++++++
> > > >    gcc/testsuite/g++.dg/cpp2a/lambda-targ7.C | 30
> > > > +++++++++++++++++++++++
> > > >    2 files changed, 41 insertions(+)
> > > >    create mode 100644 gcc/testsuite/g++.dg/cpp2a/lambda-targ7.C
> > > > 
> > > > diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
> > > > index 747e627f547..c49a26b4f5e 100644
> > > > --- a/gcc/cp/pt.cc
> > > > +++ b/gcc/cp/pt.cc
> > > > @@ -19699,6 +19699,17 @@ tsubst_lambda_expr (tree t, tree args,
> > > > tsubst_flags_t complain, tree in_decl)
> > > >          LAMBDA_EXPR_EXTRA_ARGS (t) = build_extra_args (t, args,
> > > > complain);
> > > >          return t;
> > > >        }
> > > > +  if (LAMBDA_EXPR_EXTRA_ARGS (t))
> > > > +    {
> > > > +      /* If we deferred substitution into this lambda, then it's
> > > > probably
> > > > from
> > > 
> > > "probably" seems wrong, given that it wasn't implemented for this case.
> > 
> > I said "probably" because in e.g.
> > 
> >      template<int N, auto F = []{}>
> >      bool b = true;
> > 
> >      template<class T>
> >      void f() {
> >        b<0>;
> >      }
> > 
> > the lambda context has the same depth as the template-id context.  But
> > as you point out, the issue is ultimately related vs unrelated
> > parameters rather than depth.
> > 
> > > 
> > > > +        a context (e.g. default template argument context) which may 
> > > > have
> > > > fewer
> > > > +        levels than the current context it's embedded in.  Adjust the 
> > > > result
> > > > of
> > > > +        add_extra_args accordingly.  */
> > > 
> > > Hmm, this looks like a situation of not just fewer levels, but potentially
> > > unrelated levels.  "args" here is for f, which shares no template context
> > > with
> > > v1.  What happens if your templates have non-type template parameters?
> > 
> > Indeed before add_extra_args 'args' will be unrelated, but after doing
> > add_extra_args the innermost levels of 'args' will correspond to the
> > lambda's template context, and so using get_innermost_template_args
> > ought to get rid of the unrelated arguments, keeping only the ones
> > relevant to the original lambda context.
> 
> Will they?  The original function of add_extra_args was to reintroduce outer
> args that we weren't able to substitute the last time through
> tsubst_lambda_expr.  I expect the innermost levels of 'args' to be the same
> before and after.
> 
> Hmm, looking at add_extra_args again, I see that whether the EXTRA_ARGS go on
> the outside or the inside depends on whether they're dependent. How does this
> work other than by accident? >.>

It's kind of a happy accident indeed :P  In the cases this patch is
concerned with, i.e. a template-id using a default argument containing
a lambda, the extra args will always be considered dependent because
during default template argument coercion we substitute an incomplete
set of targs into the default targ (namely the element corresponding to
the default targ is NULL_TREE), which any_dependent_template_arguments_p
considers dependent.  So add_extra_args will reliably put these captured
extra args as the innermost!

> 
> Jason
> 
> 

Reply via email to