On Thu, Apr 27, 2023 at 4:46 PM Patrick Palka <ppa...@redhat.com> wrote: > > 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.
Note this is not an ideal solution because TREE_CHAIN of DECL_TEMPLATE_PARMS in this case is just "2 <empty>, 1 U", so we're missing tparm information for the level that the ttp belongs to :/ So the only difference compared to using current_template_parms in this case is the extra empty level of args corresponding to the ttp's level. > > 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 >