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? >.>

Jason

Reply via email to