Re: [PATCH] c++: Don't set DECL_CONTEXT to nested template-template parameters [PR98881]

2024-03-06 Thread Jason Merrill

On 3/5/24 00:24, Nathaniel Shead wrote:

On Mon, Mar 04, 2024 at 10:07:33PM -0500, Patrick Palka wrote:

On Tue, 5 Mar 2024, Nathaniel Shead wrote:


On Mon, Mar 04, 2024 at 09:26:00PM -0500, Patrick Palka wrote:

On Tue, 5 Mar 2024, Nathaniel Shead wrote:


On Mon, Mar 04, 2024 at 07:14:54PM -0500, Patrick Palka wrote:

On Sat, 2 Mar 2024, 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.

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 
---
  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))


IIUC a TEMPLATE_DECL inside a template parameter list always represents
a template template parm, so won't this effectively disable the
DECL_CONTEXT setting logic?


This is only when 'tmpl' (i.e. the containing TEMPLATE_DECL that we're
streaming) is itself a template template parm.


D'oh, makes sense.




{
  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 000..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  struct X {};
+
+template typename TT>
+struct X> {
+  template typename UU>
+  void f (X>&);
+};


I wonder why the partial specialization is relevant here?  I can't
seem to trigger the ICE without the partial specialization.
Slightly further reduced to not use bound ttps:

 template class TT>
 struct X { };

 template class TT> requires true
 struct X {
   template class UU>
   void f(X);
 };

Maybe the expectation is that tpl_parms_fini for UU should be called
with tpl_levels=1 (so that we stream only its own 

Re: [PATCH] c++: Don't set DECL_CONTEXT to nested template-template parameters [PR98881]

2024-03-05 Thread Patrick Palka
On Tue, 5 Mar 2024, Nathaniel Shead wrote:

> On Mon, Mar 04, 2024 at 10:07:33PM -0500, Patrick Palka wrote:
> > On Tue, 5 Mar 2024, Nathaniel Shead wrote:
> > 
> > > On Mon, Mar 04, 2024 at 09:26:00PM -0500, Patrick Palka wrote:
> > > > On Tue, 5 Mar 2024, Nathaniel Shead wrote:
> > > > 
> > > > > On Mon, Mar 04, 2024 at 07:14:54PM -0500, Patrick Palka wrote:
> > > > > > On Sat, 2 Mar 2024, 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.
> > > > > > > 
> > > > > > >   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 
> > > > > > > ---
> > > > > > >  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))
> > > > > > 
> > > > > > IIUC a TEMPLATE_DECL inside a template parameter list always 
> > > > > > represents
> > > > > > a template template parm, so won't this effectively disable the
> > > > > > DECL_CONTEXT setting logic?
> > > > > 
> > > > > This is only when 'tmpl' (i.e. the containing TEMPLATE_DECL that we're
> > > > > streaming) is itself a template template parm.
> > > > 
> > > > D'oh, makes sense.
> > > > 
> > > > > 
> > > > > > >   {
> > > > > > > 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)
> > > > > > >  == 

Re: [PATCH] c++: Don't set DECL_CONTEXT to nested template-template parameters [PR98881]

2024-03-04 Thread Nathaniel Shead
On Mon, Mar 04, 2024 at 10:07:33PM -0500, Patrick Palka wrote:
> On Tue, 5 Mar 2024, Nathaniel Shead wrote:
> 
> > On Mon, Mar 04, 2024 at 09:26:00PM -0500, Patrick Palka wrote:
> > > On Tue, 5 Mar 2024, Nathaniel Shead wrote:
> > > 
> > > > On Mon, Mar 04, 2024 at 07:14:54PM -0500, Patrick Palka wrote:
> > > > > On Sat, 2 Mar 2024, 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.
> > > > > > 
> > > > > > 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 
> > > > > > ---
> > > > > >  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))
> > > > > 
> > > > > IIUC a TEMPLATE_DECL inside a template parameter list always 
> > > > > represents
> > > > > a template template parm, so won't this effectively disable the
> > > > > DECL_CONTEXT setting logic?
> > > > 
> > > > This is only when 'tmpl' (i.e. the containing TEMPLATE_DECL that we're
> > > > streaming) is itself a template template parm.
> > > 
> > > D'oh, makes sense.
> > > 
> > > > 
> > > > > > {
> > > > > >   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)
> > > > > > 

Re: [PATCH] c++: Don't set DECL_CONTEXT to nested template-template parameters [PR98881]

2024-03-04 Thread Patrick Palka
On Tue, 5 Mar 2024, Nathaniel Shead wrote:

> On Mon, Mar 04, 2024 at 09:26:00PM -0500, Patrick Palka wrote:
> > On Tue, 5 Mar 2024, Nathaniel Shead wrote:
> > 
> > > On Mon, Mar 04, 2024 at 07:14:54PM -0500, Patrick Palka wrote:
> > > > On Sat, 2 Mar 2024, 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.
> > > > > 
> > > > >   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 
> > > > > ---
> > > > >  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))
> > > > 
> > > > IIUC a TEMPLATE_DECL inside a template parameter list always represents
> > > > a template template parm, so won't this effectively disable the
> > > > DECL_CONTEXT setting logic?
> > > 
> > > This is only when 'tmpl' (i.e. the containing TEMPLATE_DECL that we're
> > > streaming) is itself a template template parm.
> > 
> > D'oh, makes sense.
> > 
> > > 
> > > > >   {
> > > > > 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

Re: [PATCH] c++: Don't set DECL_CONTEXT to nested template-template parameters [PR98881]

2024-03-04 Thread Nathaniel Shead
On Mon, Mar 04, 2024 at 09:26:00PM -0500, Patrick Palka wrote:
> On Tue, 5 Mar 2024, Nathaniel Shead wrote:
> 
> > On Mon, Mar 04, 2024 at 07:14:54PM -0500, Patrick Palka wrote:
> > > On Sat, 2 Mar 2024, 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.
> > > > 
> > > > 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 
> > > > ---
> > > >  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))
> > > 
> > > IIUC a TEMPLATE_DECL inside a template parameter list always represents
> > > a template template parm, so won't this effectively disable the
> > > DECL_CONTEXT setting logic?
> > 
> > This is only when 'tmpl' (i.e. the containing TEMPLATE_DECL that we're
> > streaming) is itself a template template parm.
> 
> D'oh, makes sense.
> 
> > 
> > > > {
> > > >   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 000..21bbc054fa3
> > > > --- /dev/null
> > > > +++ b/gcc/testsuite/g++.dg/modules/tpl-tpl-parm-3_a.H
> > > > @@ -0,0 +1,11 @@
> > > > +// PR c++/98881

Re: [PATCH] c++: Don't set DECL_CONTEXT to nested template-template parameters [PR98881]

2024-03-04 Thread Patrick Palka
On Tue, 5 Mar 2024, Nathaniel Shead wrote:

> On Mon, Mar 04, 2024 at 07:14:54PM -0500, Patrick Palka wrote:
> > On Sat, 2 Mar 2024, 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.
> > > 
> > >   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 
> > > ---
> > >  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))
> > 
> > IIUC a TEMPLATE_DECL inside a template parameter list always represents
> > a template template parm, so won't this effectively disable the
> > DECL_CONTEXT setting logic?
> 
> This is only when 'tmpl' (i.e. the containing TEMPLATE_DECL that we're
> streaming) is itself a template template parm.

D'oh, makes sense.

> 
> > >   {
> > > 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 000..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  struct X {};
> > > +
> > > +template typename TT>
> > > +struct X> {
> > > +  template typename UU>
> > > +  void f (X>&);
> > > +};
> > 
> > I wonder why the partial specialization is relevant here?  I can't
> > seem to trigger the ICE without the partial specialization.
> > Slightly further reduced to not use bound ttps:
> > 
> > template class TT>
> > struct X { };
> > 
> > template class TT> requires true
> > 

Re: [PATCH] c++: Don't set DECL_CONTEXT to nested template-template parameters [PR98881]

2024-03-04 Thread Nathaniel Shead
On Mon, Mar 04, 2024 at 07:14:54PM -0500, Patrick Palka wrote:
> On Sat, 2 Mar 2024, 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.
> > 
> > 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 
> > ---
> >  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))
> 
> IIUC a TEMPLATE_DECL inside a template parameter list always represents
> a template template parm, so won't this effectively disable the
> DECL_CONTEXT setting logic?

This is only when 'tmpl' (i.e. the containing TEMPLATE_DECL that we're
streaming) is itself a template template parm.

> > {
> >   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 000..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  struct X {};
> > +
> > +template typename TT>
> > +struct X> {
> > +  template typename UU>
> > +  void f (X>&);
> > +};
> 
> I wonder why the partial specialization is relevant here?  I can't
> seem to trigger the ICE without the partial specialization.
> Slightly further reduced to not use bound ttps:
> 
> template class TT>
> struct X { };
> 
> template class TT> requires true
> struct X {
>   template class UU>
>   void f(X);
> };
> 
> Maybe the expectation is that tpl_parms_fini for UU should be called
> with tpl_levels=1 (so that we stream only its own template parameters)
> but it's 

Re: [PATCH] c++: Don't set DECL_CONTEXT to nested template-template parameters [PR98881]

2024-03-04 Thread Patrick Palka
On Sat, 2 Mar 2024, 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.
> 
>   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 
> ---
>  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))

IIUC a TEMPLATE_DECL inside a template parameter list always represents
a template template parm, so won't this effectively disable the
DECL_CONTEXT setting logic?

>   {
> 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 000..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  struct X {};
> +
> +template typename TT>
> +struct X> {
> +  template typename UU>
> +  void f (X>&);
> +};

I wonder why the partial specialization is relevant here?  I can't
seem to trigger the ICE without the partial specialization.
Slightly further reduced to not use bound ttps:

template class TT>
struct X { };

template class TT> requires true
struct X {
  template class UU>
  void f(X);
};

Maybe the expectation is that tpl_parms_fini for UU should be called
with tpl_levels=1 (so that we stream only its own template parameters)
but it's instead called with tpl_levels=3 for some reason?

IIUC that assert should always hold in the first iteration of the loop
(for the ttp's own template parameters).  Perhaps for subsequent
iterations we need to actually stream the contexts?

Ah, but we also ICE in the same spot with:

  template class TT> struct X;  // #1
  template 

Re: [PATCH] c++: Don't set DECL_CONTEXT to nested template-template parameters [PR98881]

2024-03-04 Thread Nathaniel Shead
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 = 
- DECL_CONTEXT (tmpl) = 

- decl = 
- DECL_CONTEXT (decl) =  

('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 
> > ---
> >   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 000..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  struct X {};
> > +
> > +template typename TT>
> > +struct X> {
> > +  template typename UU>
> > +  void f (X>&);
> > +};
> > diff --git a/gcc/testsuite/g++.dg/modules/tpl-tpl-parm-3_b.C 
> > 

Re: [PATCH] c++: Don't set DECL_CONTEXT to nested template-template parameters [PR98881]

2024-03-04 Thread Jason Merrill

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.



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 
---
  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 000..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  struct X {};
+
+template typename TT>
+struct X> {
+  template typename UU>
+  void f (X>&);
+};
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 000..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  struct Y {};
+template  struct Z {};
+
+void foo() {
+  X> y;
+  X> z;
+  y.f(z);
+}




[PATCH] c++: Don't set DECL_CONTEXT to nested template-template parameters [PR98881]

2024-03-01 Thread Nathaniel Shead
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.

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 
---
 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 000..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  struct X {};
+
+template typename TT>
+struct X> {
+  template typename UU>
+  void f (X>&);
+};
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 000..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  struct Y {};
+template  struct Z {};
+
+void foo() {
+  X> y;
+  X> z;
+  y.f(z);
+}
-- 
2.43.2