On 4/8/25 10:29 AM, Patrick Palka wrote:
Bootstrapped and regtested on x86_64-pc-linux-gnu, does this look
OK for trunk?

OK.

-- >8 --

Here we substitute into the inner lambda twice, first during default
argument substitution for the outer template parameters, then during
that for the inner template parameters.

For the second testcase (which is easier to follow/debug), the first
substitution into the inner lambda is with the template arguments
{0, NULL_TREE}, which we defer because it's an incremental substitution.
For the second and final substitution we have the template arguments
{1, NULL_TREE}, which we try combining via add_extra_args and ICE on
the checking assert because TREE_STATIC isn't set on the deferred
arguments but the template arguments are considered dependent.

Incidentally, in a separate change let's add a macro with a more informative name that we can use instead of TREE_STATIC. EXTRA_ARGS_TF_PARTIAL?

Though perhaps we also want to rename tf_partial to something like tf_preserve_level?

The template arguments aren't dependent however -- they're just
incomplete because when we deferred them we were in the middle
deduction, and we consider a NULL_TREE template argument as dependent.

I wonder what would break if that changed?

I also wonder about trying to distinguish between things that actually involve a template parameter and things that are instantiation-dependent for other reasons...

If we remove this checking assert, we go on to correctly merge the
template arguments into {{0, NULL_TREE}, {1, NULL_TREE}}.  So this
patch just removes this imprecise assert.

        PR c++/119574

gcc/cp/ChangeLog:

        * pt.cc (add_extra_args): Remove checking assert.

gcc/testsuite/ChangeLog:

        * g++.dg/cpp2a/lambda-targ13.C: New test.
        * g++.dg/cpp2a/lambda-targ13a.C: New test.
        * g++.dg/cpp2a/lambda-targ13b.C: New test.
---
  gcc/cp/pt.cc                                | 1 -
  gcc/testsuite/g++.dg/cpp2a/lambda-targ13.C  | 7 +++++++
  gcc/testsuite/g++.dg/cpp2a/lambda-targ13a.C | 8 ++++++++
  gcc/testsuite/g++.dg/cpp2a/lambda-targ13b.C | 8 ++++++++
  4 files changed, 23 insertions(+), 1 deletion(-)
  create mode 100644 gcc/testsuite/g++.dg/cpp2a/lambda-targ13.C
  create mode 100644 gcc/testsuite/g++.dg/cpp2a/lambda-targ13a.C
  create mode 100644 gcc/testsuite/g++.dg/cpp2a/lambda-targ13b.C

diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
index 95b89f1281ba..ffd23d9cd13b 100644
--- a/gcc/cp/pt.cc
+++ b/gcc/cp/pt.cc
@@ -13740,7 +13740,6 @@ add_extra_args (tree extra, tree args, tsubst_flags_t 
complain, tree in_decl)
        gcc_assert (!TREE_PURPOSE (extra));
        extra = TREE_VALUE (extra);
      }
-  gcc_checking_assert (TREE_STATIC (extra) == uses_template_parms (extra));
    if (TREE_STATIC (extra))
      /* This is a partial substitution into e.g. a requires-expr or lambda-expr
         inside a default template argument; we expect 'extra' to be a full set
diff --git a/gcc/testsuite/g++.dg/cpp2a/lambda-targ13.C 
b/gcc/testsuite/g++.dg/cpp2a/lambda-targ13.C
new file mode 100644
index 000000000000..8fd0a311e056
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/lambda-targ13.C
@@ -0,0 +1,7 @@
+// PR c++/119574
+// { dg-do compile { target c++20 } }
+
+template <class F = decltype([] <auto G = [] {}> () {})>
+void f(F op = {}) { op(); }
+
+int main() { f(); }
diff --git a/gcc/testsuite/g++.dg/cpp2a/lambda-targ13a.C 
b/gcc/testsuite/g++.dg/cpp2a/lambda-targ13a.C
new file mode 100644
index 000000000000..8aaefd93356c
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/lambda-targ13a.C
@@ -0,0 +1,8 @@
+// PR c++/119574
+// A version of lambda-targ13.C with extra template parameters.
+// { dg-do compile { target c++20 } }
+
+template <int = 0, class F = decltype([] <int = 1, auto G = [] {}> () {})>
+void f(F op = {}) { op(); }
+
+int main() { f(); }
diff --git a/gcc/testsuite/g++.dg/cpp2a/lambda-targ13b.C 
b/gcc/testsuite/g++.dg/cpp2a/lambda-targ13b.C
new file mode 100644
index 000000000000..952c44761357
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/lambda-targ13b.C
@@ -0,0 +1,8 @@
+// PR c++/119574
+// A version of lambda-targ13.C where the inner lambda returns non-void.
+// { dg-do compile { target c++20 } }
+
+template <class F = decltype([] <auto G = [] { return 42; }> () { return G(); 
})>
+int f(F op = {}) { return op(); }
+
+int main() { f(); }

Reply via email to