https://gcc.gnu.org/g:0c80216b7bb0938bff7db230cbefa5bc3e8b3034

commit r14-10652-g0c80216b7bb0938bff7db230cbefa5bc3e8b3034
Author: Patrick Palka <ppa...@redhat.com>
Date:   Sat Sep 7 14:10:09 2024 -0400

    c++: template depth of lambda in default targ [PR116567]
    
    For GCC 14, let's narrowly fix this bug by just pruning the result of
    add_extra_args after the fact to get rid of any unwanted outer levels.
    
            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.
    
    Reviewed-by: Jason Merrill <ja...@redhat.com>

Diff:
---
 gcc/cp/pt.cc                              | 12 +++++++++
 gcc/testsuite/g++.dg/cpp2a/lambda-targ7.C | 42 +++++++++++++++++++++++++++++++
 2 files changed, 54 insertions(+)

diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
index 8e6a7d1a64a4..7135105fc375 100644
--- a/gcc/cp/pt.cc
+++ b/gcc/cp/pt.cc
@@ -19679,6 +19679,18 @@ 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 its original
+        context (e.g. default template argument context) might be unrelated
+        to the current context it's embedded in.  After add_extra_args though,
+        the innermost levels of 'args' will correspond to the lambda context,
+        so get rid of all unrelated levels.  */
+      tree ctx_parms = DECL_TEMPLATE_PARMS (DECL_TI_TEMPLATE (oldfn));
+      if (generic_lambda_fn_p (oldfn))
+       ctx_parms = TREE_CHAIN (ctx_parms);
+      args = get_innermost_template_args (args, TMPL_PARMS_DEPTH (ctx_parms));
+    }
 
   tree r = build_lambda_expr ();
 
diff --git a/gcc/testsuite/g++.dg/cpp2a/lambda-targ7.C 
b/gcc/testsuite/g++.dg/cpp2a/lambda-targ7.C
new file mode 100644
index 000000000000..97b42d6ed0c4
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/lambda-targ7.C
@@ -0,0 +1,42 @@
+// PR c++/116567
+// { dg-do compile { target c++20 } }
+
+struct X { int n; };
+
+template<auto N, auto F = []{ return N; }>
+auto v1 = F;
+
+template<auto N, auto F = [](auto y){ return decltype(N){N.n + y}; }>
+auto v1g = F;
+
+template<class T>
+struct A {
+  template<auto N, auto F = []{ return N; }>
+  static inline auto v2 = F;
+
+  template<auto N, auto F = [](auto y){ return decltype(N){N.n + y}; }>
+  static inline auto v2g = F;
+
+  template<class U>
+  struct B {
+    template<auto N, auto F = []{ return N; }>
+    static inline auto v3 = F;
+
+    template<auto N, auto F = [](auto y){ return decltype(N){N.n + y}; }>
+    static inline auto v3g = F;
+
+    template<class V>
+    static void f() {
+      static_assert(v1<X{1}>().n == 1);
+      static_assert(v1g<X{1}>(42).n == 1 + 42);
+      static_assert(v2<X{2}>().n == 2);
+      static_assert(v2g<X{2}>(42).n == 2 + 42);
+      static_assert(v3<X{3}>().n == 3);
+      static_assert(v3g<X{3}>(42).n == 3 + 42);
+    }
+  };
+};
+
+int main() {
+  A<int>::B<int>::f<int>();
+}

Reply via email to