Now that with r14-11-g2245459c85a3f4 made us coerce the template arguments of a bound ttp again after level-lowering, this unfortunately causes a crash from coerce_template_args_for_ttp in the below testcase.
During the level-lowering substitution T=int into the bound ttp TT<int> as part of substitution into the lambda signature, current_template_parms is just U=U rather than the ideal TT=TT, U=U. And because we don't consistently set DECL_CONTEXT for level-lowered ttps (it's kind of a chicken of the egg problem in this case), we attempt to use current_template_parms to obtain the outer arguments during coerce_template_args_for_ttp. But the depth 1 of c_t_p current_template_parms is less than the depth 2 of the level-lowered TT, and we end up segfaulting from there. So for level-lowered ttps it seems we need to get the outer arguments a different way -- namely, we can look at the trailing parms of its DECL_TEMPLATE_PARMS. Bootstrapped and regtested on x86_64-pc-linux-gnu, does this look OK for trunk/13? PR c++/109651 gcc/cp/ChangeLog: * pt.cc (coerce_template_args_for_ttp): For level-lowered ttps with DECL_CONTEXT not set, obtain the outer template arguments via its DECL_TEMPLATE_PARMS. gcc/testsuite/ChangeLog: * g++.dg/template/ttp37.C: New test. --- gcc/cp/pt.cc | 5 +++++ gcc/testsuite/g++.dg/template/ttp37.C | 11 +++++++++++ 2 files changed, 16 insertions(+) create mode 100644 gcc/testsuite/g++.dg/template/ttp37.C diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc index 678cb7930e3..bbde61061f6 100644 --- a/gcc/cp/pt.cc +++ b/gcc/cp/pt.cc @@ -7872,6 +7872,11 @@ coerce_template_args_for_ttp (tree templ, tree arglist, tree outer = DECL_CONTEXT (templ); if (outer) outer = generic_targs_for (outer); + else if (TEMPLATE_TYPE_LEVEL (TREE_TYPE (templ)) + != TEMPLATE_TYPE_ORIG_LEVEL (TREE_TYPE (templ))) + /* This is a level-lowered template template parameter, for which + we don't consistently set DECL_CONTEXT (FIXME). */ + outer = template_parms_to_args (TREE_CHAIN (DECL_TEMPLATE_PARMS (templ))); else if (current_template_parms) { /* This is an argument of the current template, so we haven't set diff --git a/gcc/testsuite/g++.dg/template/ttp37.C b/gcc/testsuite/g++.dg/template/ttp37.C new file mode 100644 index 00000000000..876e5b6232a --- /dev/null +++ b/gcc/testsuite/g++.dg/template/ttp37.C @@ -0,0 +1,11 @@ +// PR c++/109651 +// { dg-do compile { target c++20 } } + +template<class T> +void f() { + []<class U>() { + []<template<class> class TT>(TT<int>) { }; + }; +} + +template void f<int>(); -- 2.40.1.423.g2807bd2c10