On Mon, Mar 04, 2024 at 06:01:48PM -0500, Jason Merrill wrote:
> On 3/2/24 01:54, Nathaniel Shead wrote:
> > Bootstrapped and regtested on x86_64-pc-linux-gnu, OK for trunk?
> > 
> > -- >8 --
> > 
> > When streaming in a nested template-template parameter as in the
> > attached testcase, we end up reaching the containing template-template
> > parameter in 'tpl_parms_fini'. We should not set the DECL_CONTEXT to
> > this (nested) template-template parameter, as it should already be the
> > struct that the outer template-template parameter is declared on.
> 
> So in the case where tmpl is a template template parameter we want
> DECL_CONTEXT (parm) to be the same as DECL_CONTEXT (tmpl)?  Let's check that
> instead of ignoring it.

No, I don't think so. I guess the closest is that we if we keep
iterating through all the nested 'DECL_CONTEXT's of tmpl we should
eventually reach the template result of parm's context, if we find
enough template infos etc.? I'm not entirely sure how to go about this.

But in particular, in the current test case we have:

- tmpl = <template_decl 0x7ffff7ffa300 UU>
- DECL_CONTEXT (tmpl) = <template_decl 0x7ffff7ffa500 f>

- decl = <template_decl 0x7ffff7ffa180 TT>
- DECL_CONTEXT (decl) = <template_decl 0x7ffff7ffa200 X> 

('decl' is the declaration associated with 'parm', a tree_list.)
And it's not immediately obvious to me how to unify these.

> >     PR c++/98881
> > 
> > gcc/cp/ChangeLog:
> > 
> >     * module.cc (trees_out::tpl_parms_fini): Clarify logic purely
> >     for checking purposes. Don't consider a template template
> >     parameter as the owning template.
> >     (trees_in::tpl_parms_fini): Don't consider a template template
> >     parameter as the owning template.
> > 
> > gcc/testsuite/ChangeLog:
> > 
> >     * g++.dg/modules/tpl-tpl-parm-3_a.H: New test.
> >     * g++.dg/modules/tpl-tpl-parm-3_b.C: New test.
> > 
> > Signed-off-by: Nathaniel Shead <nathanielosh...@gmail.com>
> > ---
> >   gcc/cp/module.cc                                | 17 ++++++++++++-----
> >   gcc/testsuite/g++.dg/modules/tpl-tpl-parm-3_a.H | 11 +++++++++++
> >   gcc/testsuite/g++.dg/modules/tpl-tpl-parm-3_b.C | 13 +++++++++++++
> >   3 files changed, 36 insertions(+), 5 deletions(-)
> >   create mode 100644 gcc/testsuite/g++.dg/modules/tpl-tpl-parm-3_a.H
> >   create mode 100644 gcc/testsuite/g++.dg/modules/tpl-tpl-parm-3_b.C
> > 
> > diff --git a/gcc/cp/module.cc b/gcc/cp/module.cc
> > index 67f132d28d7..5663d01ed9c 100644
> > --- a/gcc/cp/module.cc
> > +++ b/gcc/cp/module.cc
> > @@ -10126,10 +10126,14 @@ trees_out::tpl_parms_fini (tree tmpl, unsigned 
> > tpl_levels)
> >       tree dflt = TREE_PURPOSE (parm);
> >       tree_node (dflt);
> > -     if (streaming_p ())
> > +     if (CHECKING_P && streaming_p ())
> >         {
> > +         /* Sanity check that the DECL_CONTEXT we'll infer when
> > +            streaming in is correct.  */
> >           tree decl = TREE_VALUE (parm);
> > -         if (TREE_CODE (decl) == TEMPLATE_DECL)
> > +         if (TREE_CODE (decl) == TEMPLATE_DECL
> > +             /* A template template parm is not the owning template.  */
> > +             && !DECL_TEMPLATE_TEMPLATE_PARM_P (tmpl))
> >             {
> >               tree ctx = DECL_CONTEXT (decl);
> >               tree inner = DECL_TEMPLATE_RESULT (decl);
> > @@ -10164,8 +10168,13 @@ trees_in::tpl_parms_fini (tree tmpl, unsigned 
> > tpl_levels)
> >         return false;
> >       TREE_PURPOSE (parm) = dflt;
> > +     /* Original template template parms have a context
> > +        of their owning template.  Reduced ones do not.
> > +        But if TMPL is itself a template template parm
> > +        then it cannot be the owning template.  */
> >       tree decl = TREE_VALUE (parm);
> > -     if (TREE_CODE (decl) == TEMPLATE_DECL)
> > +     if (TREE_CODE (decl) == TEMPLATE_DECL
> > +         && !DECL_TEMPLATE_TEMPLATE_PARM_P (tmpl))
> >         {
> >           tree inner = DECL_TEMPLATE_RESULT (decl);
> >           tree tpi = (TREE_CODE (inner) == TYPE_DECL
> > @@ -10173,8 +10182,6 @@ trees_in::tpl_parms_fini (tree tmpl, unsigned 
> > tpl_levels)
> >                       : DECL_INITIAL (inner));
> >           bool original = (TEMPLATE_PARM_LEVEL (tpi)
> >                            == TEMPLATE_PARM_ORIG_LEVEL (tpi));
> > -         /* Original template template parms have a context
> > -            of their owning template.  Reduced ones do not.  */
> >           if (original)
> >             DECL_CONTEXT (decl) = tmpl;
> >         }
> > diff --git a/gcc/testsuite/g++.dg/modules/tpl-tpl-parm-3_a.H 
> > b/gcc/testsuite/g++.dg/modules/tpl-tpl-parm-3_a.H
> > new file mode 100644
> > index 00000000000..21bbc054fa3
> > --- /dev/null
> > +++ b/gcc/testsuite/g++.dg/modules/tpl-tpl-parm-3_a.H
> > @@ -0,0 +1,11 @@
> > +// PR c++/98881
> > +// { dg-additional-options "-fmodule-header" }
> > +// { dg-module-cmi {} }
> > +
> > +template <typename P> struct X {};
> > +
> > +template<template <typename> typename TT>
> > +struct X<TT<int>> {
> > +  template<template <typename> typename UU>
> > +  void f (X<UU<int>>&);
> > +};
> > diff --git a/gcc/testsuite/g++.dg/modules/tpl-tpl-parm-3_b.C 
> > b/gcc/testsuite/g++.dg/modules/tpl-tpl-parm-3_b.C
> > new file mode 100644
> > index 00000000000..234e822faa9
> > --- /dev/null
> > +++ b/gcc/testsuite/g++.dg/modules/tpl-tpl-parm-3_b.C
> > @@ -0,0 +1,13 @@
> > +// PR c++/98881
> > +// { dg-additional-options "-fmodules-ts" }
> > +
> > +import "tpl-tpl-parm-3_a.H";
> > +
> > +template <typename T> struct Y {};
> > +template <typename T> struct Z {};
> > +
> > +void foo() {
> > +  X<Y<int>> y;
> > +  X<Z<int>> z;
> > +  y.f(z);
> > +}
> 

Reply via email to