On 9/5/24 2:28 PM, Patrick Palka wrote:
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!

I see that the testcases you enabled this code to handle in
r12-2222-g2c699fd29829cd were also about lambda/requires in default template arguments. Can we detect this case some other way than uses_template_parms?

Can we do the pruning added by this patch in add_extra_args instead of its caller?

Incidentally, why is having extra outer levels causing trouble? I thought we were generally able to safely ignore them.

Jason

Reply via email to