public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [PATCH 2/1] c++: passing partially inst ttp as ttp [PR110566]
       [not found] <0001-c-passing-partially-inst-ttp-as-ttp-PR110566.patch>
@ 2023-07-21 18:34 ` Patrick Palka
  2023-07-21 20:32   ` Jason Merrill
  0 siblings, 1 reply; 4+ messages in thread
From: Patrick Palka @ 2023-07-21 18:34 UTC (permalink / raw)
  To: gcc-patches; +Cc: jason, Patrick Palka

(This is a follow-up of
https://gcc.gnu.org/pipermail/gcc-patches/2023-July/624951.html)

Bootstrapped and regtested on x86_64-pc-linux-gnu, how does this look?

-- >8 --

The previous fix doesn't work for partially instantiated ttps primarily
because most_general_template doesn't work for them.  This patch fixes
this by giving such ttps a DECL_TEMPLATE_INFO (extending the
r11-734-g2fb595f8348e16 fix) with which we can obtain the original ttp.

This patch additionally makes us be more careful about using the correct
amount of levels from the scope of a ttp argument during
coerce_template_template_parms.

	PR c++/110566

gcc/cp/ChangeLog:

	* pt.cc (reduce_template_parm_level): Set DECL_TEMPLATE_INFO
	on the DECL_TEMPLATE_RESULT of a reduced template template
	parameter.
	(add_defaults_to_ttp): Also update DECL_TEMPLATE_INFO of the
	ttp's DECL_TEMPLATE_RESULT.
	(coerce_template_template_parms): Make sure 'scope_args' has
	the right amount of levels for the ttp argument.
	(most_general_template): Handle template template parameters.

gcc/testsuite/ChangeLog:

	* g++.dg/template/ttp39.C: New test.
---
 gcc/cp/pt.cc                          | 46 ++++++++++++++++++++++++---
 gcc/testsuite/g++.dg/template/ttp39.C | 16 ++++++++++
 2 files changed, 57 insertions(+), 5 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/template/ttp39.C

diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
index e0ed4bc8bbb..be7119dd9a0 100644
--- a/gcc/cp/pt.cc
+++ b/gcc/cp/pt.cc
@@ -4570,8 +4570,14 @@ reduce_template_parm_level (tree index, tree type, int levels, tree args,
 			      TYPE_DECL, DECL_NAME (decl), type);
 	  DECL_TEMPLATE_RESULT (decl) = inner;
 	  DECL_ARTIFICIAL (inner) = true;
-	  DECL_TEMPLATE_PARMS (decl) = tsubst_template_parms
-	    (DECL_TEMPLATE_PARMS (orig_decl), args, complain);
+	  tree parms = tsubst_template_parms (DECL_TEMPLATE_PARMS (orig_decl),
+					      args, complain);
+	  DECL_TEMPLATE_PARMS (decl) = parms;
+	  retrofit_lang_decl (inner);
+	  tree orig_inner = DECL_TEMPLATE_RESULT (orig_decl);
+	  DECL_TEMPLATE_INFO (inner)
+	    = build_template_info (DECL_TI_TEMPLATE (orig_inner),
+				   template_parms_to_args (parms));
 	}
 
       /* Attach the TPI to the decl.  */
@@ -7936,6 +7942,19 @@ add_defaults_to_ttp (tree otmpl)
 	}
     }
 
+  tree oresult = DECL_TEMPLATE_RESULT (otmpl);
+  tree gen_otmpl = DECL_TI_TEMPLATE (oresult);
+  tree gen_ntmpl;
+  if (gen_otmpl == otmpl)
+    gen_ntmpl = ntmpl;
+  else
+    gen_ntmpl = add_defaults_to_ttp (gen_otmpl);
+
+  tree nresult = copy_node (oresult);
+  DECL_TEMPLATE_INFO (nresult) = copy_node (DECL_TEMPLATE_INFO (oresult));
+  DECL_TI_TEMPLATE (nresult) = gen_ntmpl;
+  DECL_TEMPLATE_RESULT (ntmpl) = nresult;
+
   hash_map_safe_put<hm_ggc> (defaulted_ttp_cache, otmpl, ntmpl);
   return ntmpl;
 }
@@ -8121,15 +8140,29 @@ coerce_template_template_parms (tree parm_tmpl,
 	 OUTER_ARGS are not the right outer levels in this case, as they are
 	 the args we're building up for PARM, and for the coercion we want the
 	 args for ARG.  If DECL_CONTEXT isn't set for a template template
-	 parameter, we can assume that it's in the current scope.  In that case
-	 we might end up adding more levels than needed, but that shouldn't be
-	 a problem; any args we need to refer to are at the right level.  */
+	 parameter, we can assume that it's in the current scope.  */
       tree ctx = DECL_CONTEXT (arg_tmpl);
       if (!ctx && DECL_TEMPLATE_TEMPLATE_PARM_P (arg_tmpl))
 	ctx = current_scope ();
       tree scope_args = NULL_TREE;
       if (tree tinfo = get_template_info (ctx))
 	scope_args = TI_ARGS (tinfo);
+      if (DECL_TEMPLATE_TEMPLATE_PARM_P (arg_tmpl))
+	{
+	  int level = TEMPLATE_TYPE_LEVEL (TREE_TYPE (gen_arg_tmpl));
+	  int scope_depth = TMPL_ARGS_DEPTH (scope_args);
+	  if (scope_depth >= level)
+	    /* Only use as many levels from the scope as needed (not
+	       including the level of ARG).  */
+	    scope_args = strip_innermost_template_args
+	      (scope_args, scope_depth - (level - 1));
+
+	  /* Add the arguments that appear at the level of ARG.  */
+	  tree adj_args = DECL_TI_ARGS (DECL_TEMPLATE_RESULT (arg_tmpl));
+	  adj_args = TMPL_ARGS_LEVEL (adj_args, TMPL_ARGS_DEPTH (adj_args) - 1);
+	  scope_args = add_to_template_args (scope_args, adj_args);
+	}
+
       pargs = add_to_template_args (scope_args, pargs);
 
       pargs = coerce_template_parms (gen_arg_parms, pargs, NULL_TREE, tf_none);
@@ -25985,6 +26018,9 @@ most_general_template (tree decl)
 	return NULL_TREE;
     }
 
+  if (DECL_TEMPLATE_TEMPLATE_PARM_P (decl))
+    return DECL_TI_TEMPLATE (DECL_TEMPLATE_RESULT (decl));
+
   /* Look for more and more general templates.  */
   while (DECL_LANG_SPECIFIC (decl) && DECL_TEMPLATE_INFO (decl))
     {
diff --git a/gcc/testsuite/g++.dg/template/ttp39.C b/gcc/testsuite/g++.dg/template/ttp39.C
new file mode 100644
index 00000000000..03d7c505c4a
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/ttp39.C
@@ -0,0 +1,16 @@
+// PR c++/110566
+// { dg-do compile { target c++20 } }
+
+template<template<int N, int M> class>
+struct A;
+
+template<class U>
+struct B {
+  template<class T>
+  struct C {
+    template<template<auto X, auto Y> class TT>
+    using type = A<TT>;
+  };
+};
+
+template struct B<int>::C<int>;
-- 
2.41.0.376.gcba07a324d


^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [PATCH 2/1] c++: passing partially inst ttp as ttp [PR110566]
  2023-07-21 18:34 ` [PATCH 2/1] c++: passing partially inst ttp as ttp [PR110566] Patrick Palka
@ 2023-07-21 20:32   ` Jason Merrill
  2023-07-24 17:03     ` Patrick Palka
  0 siblings, 1 reply; 4+ messages in thread
From: Jason Merrill @ 2023-07-21 20:32 UTC (permalink / raw)
  To: Patrick Palka, gcc-patches

On 7/21/23 14:34, Patrick Palka wrote:
> (This is a follow-up of
> https://gcc.gnu.org/pipermail/gcc-patches/2023-July/624951.html)
> 
> Bootstrapped and regtested on x86_64-pc-linux-gnu, how does this look?
> 
> -- >8 --
> 
> The previous fix doesn't work for partially instantiated ttps primarily
> because most_general_template doesn't work for them.  This patch fixes
> this by giving such ttps a DECL_TEMPLATE_INFO (extending the
> r11-734-g2fb595f8348e16 fix) with which we can obtain the original ttp.
> 
> This patch additionally makes us be more careful about using the correct
> amount of levels from the scope of a ttp argument during
> coerce_template_template_parms.
> 
> 	PR c++/110566
> 
> gcc/cp/ChangeLog:
> 
> 	* pt.cc (reduce_template_parm_level): Set DECL_TEMPLATE_INFO
> 	on the DECL_TEMPLATE_RESULT of a reduced template template
> 	parameter.
> 	(add_defaults_to_ttp): Also update DECL_TEMPLATE_INFO of the
> 	ttp's DECL_TEMPLATE_RESULT.
> 	(coerce_template_template_parms): Make sure 'scope_args' has
> 	the right amount of levels for the ttp argument.
> 	(most_general_template): Handle template template parameters.
> 
> gcc/testsuite/ChangeLog:
> 
> 	* g++.dg/template/ttp39.C: New test.
> ---
>   gcc/cp/pt.cc                          | 46 ++++++++++++++++++++++++---
>   gcc/testsuite/g++.dg/template/ttp39.C | 16 ++++++++++
>   2 files changed, 57 insertions(+), 5 deletions(-)
>   create mode 100644 gcc/testsuite/g++.dg/template/ttp39.C
> 
> diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
> index e0ed4bc8bbb..be7119dd9a0 100644
> --- a/gcc/cp/pt.cc
> +++ b/gcc/cp/pt.cc
> @@ -4570,8 +4570,14 @@ reduce_template_parm_level (tree index, tree type, int levels, tree args,
>   			      TYPE_DECL, DECL_NAME (decl), type);
>   	  DECL_TEMPLATE_RESULT (decl) = inner;
>   	  DECL_ARTIFICIAL (inner) = true;
> -	  DECL_TEMPLATE_PARMS (decl) = tsubst_template_parms
> -	    (DECL_TEMPLATE_PARMS (orig_decl), args, complain);
> +	  tree parms = tsubst_template_parms (DECL_TEMPLATE_PARMS (orig_decl),
> +					      args, complain);
> +	  DECL_TEMPLATE_PARMS (decl) = parms;
> +	  retrofit_lang_decl (inner);
> +	  tree orig_inner = DECL_TEMPLATE_RESULT (orig_decl);
> +	  DECL_TEMPLATE_INFO (inner)
> +	    = build_template_info (DECL_TI_TEMPLATE (orig_inner),
> +				   template_parms_to_args (parms));

Should we assert that orig_inner doesn't have its own 
DECL_TEMPLATE_INFO?  I'm wondering if it's possible to reduce the level 
of a TTP more than once.

>   	}
>   
>         /* Attach the TPI to the decl.  */
> @@ -7936,6 +7942,19 @@ add_defaults_to_ttp (tree otmpl)
>   	}
>       }
>   
> +  tree oresult = DECL_TEMPLATE_RESULT (otmpl);
> +  tree gen_otmpl = DECL_TI_TEMPLATE (oresult);

Hmm, here we're assuming that all TTPs have DECL_TEMPLATE_INFO?

> +  tree gen_ntmpl;
> +  if (gen_otmpl == otmpl)
> +    gen_ntmpl = ntmpl;
> +  else
> +    gen_ntmpl = add_defaults_to_ttp (gen_otmpl);
> +
> +  tree nresult = copy_node (oresult);
> +  DECL_TEMPLATE_INFO (nresult) = copy_node (DECL_TEMPLATE_INFO (oresult));
> +  DECL_TI_TEMPLATE (nresult) = gen_ntmpl;
> +  DECL_TEMPLATE_RESULT (ntmpl) = nresult;
> +
>     hash_map_safe_put<hm_ggc> (defaulted_ttp_cache, otmpl, ntmpl);
>     return ntmpl;
>   }
> @@ -8121,15 +8140,29 @@ coerce_template_template_parms (tree parm_tmpl,
>   	 OUTER_ARGS are not the right outer levels in this case, as they are
>   	 the args we're building up for PARM, and for the coercion we want the
>   	 args for ARG.  If DECL_CONTEXT isn't set for a template template
> -	 parameter, we can assume that it's in the current scope.  In that case
> -	 we might end up adding more levels than needed, but that shouldn't be
> -	 a problem; any args we need to refer to are at the right level.  */
> +	 parameter, we can assume that it's in the current scope.  */
>         tree ctx = DECL_CONTEXT (arg_tmpl);
>         if (!ctx && DECL_TEMPLATE_TEMPLATE_PARM_P (arg_tmpl))
>   	ctx = current_scope ();
>         tree scope_args = NULL_TREE;
>         if (tree tinfo = get_template_info (ctx))
>   	scope_args = TI_ARGS (tinfo);
> +      if (DECL_TEMPLATE_TEMPLATE_PARM_P (arg_tmpl))
> +	{
> +	  int level = TEMPLATE_TYPE_LEVEL (TREE_TYPE (gen_arg_tmpl));
> +	  int scope_depth = TMPL_ARGS_DEPTH (scope_args);
> +	  if (scope_depth >= level)
> +	    /* Only use as many levels from the scope as needed (not
> +	       including the level of ARG).  */
> +	    scope_args = strip_innermost_template_args
> +	      (scope_args, scope_depth - (level - 1));
> +
> +	  /* Add the arguments that appear at the level of ARG.  */
> +	  tree adj_args = DECL_TI_ARGS (DECL_TEMPLATE_RESULT (arg_tmpl));
> +	  adj_args = TMPL_ARGS_LEVEL (adj_args, TMPL_ARGS_DEPTH (adj_args) - 1);
> +	  scope_args = add_to_template_args (scope_args, adj_args);

Maybe we should add an integer parameter to add_to_template_args so we 
can specify adding a certain number of levels without making a temporary 
copy along the way?

> +	}
> +
>         pargs = add_to_template_args (scope_args, pargs);
>   
>         pargs = coerce_template_parms (gen_arg_parms, pargs, NULL_TREE, tf_none);
> @@ -25985,6 +26018,9 @@ most_general_template (tree decl)
>   	return NULL_TREE;
>       }
>   
> +  if (DECL_TEMPLATE_TEMPLATE_PARM_P (decl))
> +    return DECL_TI_TEMPLATE (DECL_TEMPLATE_RESULT (decl));
> +
>     /* Look for more and more general templates.  */
>     while (DECL_LANG_SPECIFIC (decl) && DECL_TEMPLATE_INFO (decl))
>       {
> diff --git a/gcc/testsuite/g++.dg/template/ttp39.C b/gcc/testsuite/g++.dg/template/ttp39.C
> new file mode 100644
> index 00000000000..03d7c505c4a
> --- /dev/null
> +++ b/gcc/testsuite/g++.dg/template/ttp39.C
> @@ -0,0 +1,16 @@
> +// PR c++/110566
> +// { dg-do compile { target c++20 } }
> +
> +template<template<int N, int M> class>
> +struct A;
> +
> +template<class U>
> +struct B {
> +  template<class T>
> +  struct C {
> +    template<template<auto X, auto Y> class TT>
> +    using type = A<TT>;
> +  };
> +};
> +
> +template struct B<int>::C<int>;


^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [PATCH 2/1] c++: passing partially inst ttp as ttp [PR110566]
  2023-07-21 20:32   ` Jason Merrill
@ 2023-07-24 17:03     ` Patrick Palka
  2023-07-25 18:04       ` Jason Merrill
  0 siblings, 1 reply; 4+ messages in thread
From: Patrick Palka @ 2023-07-24 17:03 UTC (permalink / raw)
  To: Jason Merrill; +Cc: Patrick Palka, gcc-patches

On Fri, 21 Jul 2023, Jason Merrill wrote:

> On 7/21/23 14:34, Patrick Palka wrote:
> > (This is a follow-up of
> > https://gcc.gnu.org/pipermail/gcc-patches/2023-July/624951.html)
> > 
> > Bootstrapped and regtested on x86_64-pc-linux-gnu, how does this look?
> > 
> > -- >8 --
> > 
> > The previous fix doesn't work for partially instantiated ttps primarily
> > because most_general_template doesn't work for them.  This patch fixes
> > this by giving such ttps a DECL_TEMPLATE_INFO (extending the
> > r11-734-g2fb595f8348e16 fix) with which we can obtain the original ttp.
> > 
> > This patch additionally makes us be more careful about using the correct
> > amount of levels from the scope of a ttp argument during
> > coerce_template_template_parms.
> > 
> > 	PR c++/110566
> > 
> > gcc/cp/ChangeLog:
> > 
> > 	* pt.cc (reduce_template_parm_level): Set DECL_TEMPLATE_INFO
> > 	on the DECL_TEMPLATE_RESULT of a reduced template template
> > 	parameter.
> > 	(add_defaults_to_ttp): Also update DECL_TEMPLATE_INFO of the
> > 	ttp's DECL_TEMPLATE_RESULT.
> > 	(coerce_template_template_parms): Make sure 'scope_args' has
> > 	the right amount of levels for the ttp argument.
> > 	(most_general_template): Handle template template parameters.
> > 
> > gcc/testsuite/ChangeLog:
> > 
> > 	* g++.dg/template/ttp39.C: New test.
> > ---
> >   gcc/cp/pt.cc                          | 46 ++++++++++++++++++++++++---
> >   gcc/testsuite/g++.dg/template/ttp39.C | 16 ++++++++++
> >   2 files changed, 57 insertions(+), 5 deletions(-)
> >   create mode 100644 gcc/testsuite/g++.dg/template/ttp39.C
> > 
> > diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
> > index e0ed4bc8bbb..be7119dd9a0 100644
> > --- a/gcc/cp/pt.cc
> > +++ b/gcc/cp/pt.cc
> > @@ -4570,8 +4570,14 @@ reduce_template_parm_level (tree index, tree type,
> > int levels, tree args,
> >   			      TYPE_DECL, DECL_NAME (decl), type);
> >   	  DECL_TEMPLATE_RESULT (decl) = inner;
> >   	  DECL_ARTIFICIAL (inner) = true;
> > -	  DECL_TEMPLATE_PARMS (decl) = tsubst_template_parms
> > -	    (DECL_TEMPLATE_PARMS (orig_decl), args, complain);
> > +	  tree parms = tsubst_template_parms (DECL_TEMPLATE_PARMS (orig_decl),
> > +					      args, complain);
> > +	  DECL_TEMPLATE_PARMS (decl) = parms;
> > +	  retrofit_lang_decl (inner);
> > +	  tree orig_inner = DECL_TEMPLATE_RESULT (orig_decl);
> > +	  DECL_TEMPLATE_INFO (inner)
> > +	    = build_template_info (DECL_TI_TEMPLATE (orig_inner),
> > +				   template_parms_to_args (parms));
> 
> Should we assert that orig_inner doesn't have its own DECL_TEMPLATE_INFO?  I'm
> wondering if it's possible to reduce the level of a TTP more than once.

It's possible for a ttp belonging to a nested generic lambda:

  template<class>
  void f() {
    [](auto) {
      []<template<class> class TT>() {
      };
    }(0);
  }

  template void f<int>();

> 
> >   	}
> >           /* Attach the TPI to the decl.  */
> > @@ -7936,6 +7942,19 @@ add_defaults_to_ttp (tree otmpl)
> >   	}
> >       }
> >   +  tree oresult = DECL_TEMPLATE_RESULT (otmpl);
> > +  tree gen_otmpl = DECL_TI_TEMPLATE (oresult);
> 
> Hmm, here we're assuming that all TTPs have DECL_TEMPLATE_INFO?

I figured it's a reasonable assumption since all "formal" ttps
originally start out with DECL_TEMPLATE_INFO (via process_template_parm).
Though I realized I missed adjusting rewrite_template_parm to set
DECL_TEMPLATE_INFO on the new ttp, which the below patch fixes (and
adds a testcase that we'd otherwise segfualt on).

> 
> > +  tree gen_ntmpl;
> > +  if (gen_otmpl == otmpl)
> > +    gen_ntmpl = ntmpl;
> > +  else
> > +    gen_ntmpl = add_defaults_to_ttp (gen_otmpl);
> > +
> > +  tree nresult = copy_node (oresult);

Another fixed bug: since we build the new DECL_TEMPLATE_RESULT via
copy_node, we need to avoid sharing its DECL_LANG_SPECIFIC with the
old decl.

> > +  DECL_TEMPLATE_INFO (nresult) = copy_node (DECL_TEMPLATE_INFO (oresult));
> > +  DECL_TI_TEMPLATE (nresult) = gen_ntmpl;
> > +  DECL_TEMPLATE_RESULT (ntmpl) = nresult;
> > +
> >     hash_map_safe_put<hm_ggc> (defaulted_ttp_cache, otmpl, ntmpl);
> >     return ntmpl;
> >   }
> > @@ -8121,15 +8140,29 @@ coerce_template_template_parms (tree parm_tmpl,
> >   	 OUTER_ARGS are not the right outer levels in this case, as they are
> >   	 the args we're building up for PARM, and for the coercion we want the
> >   	 args for ARG.  If DECL_CONTEXT isn't set for a template template
> > -	 parameter, we can assume that it's in the current scope.  In that
> > case
> > -	 we might end up adding more levels than needed, but that shouldn't be
> > -	 a problem; any args we need to refer to are at the right level.  */
> > +	 parameter, we can assume that it's in the current scope.  */
> >         tree ctx = DECL_CONTEXT (arg_tmpl);
> >         if (!ctx && DECL_TEMPLATE_TEMPLATE_PARM_P (arg_tmpl))
> >   	ctx = current_scope ();
> >         tree scope_args = NULL_TREE;
> >         if (tree tinfo = get_template_info (ctx))
> >   	scope_args = TI_ARGS (tinfo);
> > +      if (DECL_TEMPLATE_TEMPLATE_PARM_P (arg_tmpl))
> > +	{
> > +	  int level = TEMPLATE_TYPE_LEVEL (TREE_TYPE (gen_arg_tmpl));
> > +	  int scope_depth = TMPL_ARGS_DEPTH (scope_args);
> > +	  if (scope_depth >= level)
> > +	    /* Only use as many levels from the scope as needed (not
> > +	       including the level of ARG).  */
> > +	    scope_args = strip_innermost_template_args
> > +	      (scope_args, scope_depth - (level - 1));
> > +
> > +	  /* Add the arguments that appear at the level of ARG.  */
> > +	  tree adj_args = DECL_TI_ARGS (DECL_TEMPLATE_RESULT (arg_tmpl));
> > +	  adj_args = TMPL_ARGS_LEVEL (adj_args, TMPL_ARGS_DEPTH (adj_args) -
> > 1);
> > +	  scope_args = add_to_template_args (scope_args, adj_args);
> 
> Maybe we should add an integer parameter to add_to_template_args so we can
> specify adding a certain number of levels without making a temporary copy
> along the way?

I ended up building scope_args manually since it turns out we may need
to add empty levels to 'pargs' in the case where ARG is a ttp nested
inside another ttp (g++.old-deja/g++.pt/nttp2.C), in which case the
scope lacks a level for the outer ttp.

Here's the updated patch (bootstrapped and regtested on
x86_64-pc-linux-gnu):


-- >8 --

	PR c++/110566

gcc/cp/ChangeLog:

	* pt.cc (reduce_template_parm_level): Set DECL_TEMPLATE_INFO
	on the DECL_TEMPLATE_RESULT of the new ttp.
	(add_defaults_to_ttp): Use a new DECL_LANG_SPECIFIC for the
	new ttp.  Update DECL_TEMPLATE_INFO on its DECL_TEMPLATE_RESULT.
	(coerce_template_template_parms): Make sure 'scope_args' has
	the right amount of levels for the ttp argument.
	(most_general_template): Handle template template parameters.
	(rewrite_template_parm): Set DECL_TEMPLATE_RESULT on the
	DECL_TEMPLATE_RESULT of the new ttp.

gcc/testsuite/ChangeLog:

	* g++.dg/cpp1z/class-deduction115.C: New test.
	* g++.dg/template/ttp39.C: New test.
---
 gcc/cp/pt.cc                                  | 71 +++++++++++++++----
 .../g++.dg/cpp1z/class-deduction115.C         | 14 ++++
 gcc/testsuite/g++.dg/template/ttp39.C         | 16 +++++
 3 files changed, 89 insertions(+), 12 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/cpp1z/class-deduction115.C
 create mode 100644 gcc/testsuite/g++.dg/template/ttp39.C

diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
index e0ed4bc8bbb..893ef69bb47 100644
--- a/gcc/cp/pt.cc
+++ b/gcc/cp/pt.cc
@@ -4566,12 +4566,17 @@ reduce_template_parm_level (tree index, tree type, int levels, tree args,
       tree inner = decl;
       if (TREE_CODE (decl) == TEMPLATE_DECL)
 	{
-	  inner = build_decl (DECL_SOURCE_LOCATION (decl),
-			      TYPE_DECL, DECL_NAME (decl), type);
+	  inner = build_lang_decl_loc (DECL_SOURCE_LOCATION (decl),
+				       TYPE_DECL, DECL_NAME (decl), type);
 	  DECL_TEMPLATE_RESULT (decl) = inner;
 	  DECL_ARTIFICIAL (inner) = true;
-	  DECL_TEMPLATE_PARMS (decl) = tsubst_template_parms
-	    (DECL_TEMPLATE_PARMS (orig_decl), args, complain);
+	  tree parms = tsubst_template_parms (DECL_TEMPLATE_PARMS (orig_decl),
+					      args, complain);
+	  DECL_TEMPLATE_PARMS (decl) = parms;
+	  tree orig_inner = DECL_TEMPLATE_RESULT (orig_decl);
+	  DECL_TEMPLATE_INFO (inner)
+	    = build_template_info (DECL_TI_TEMPLATE (orig_inner),
+				   template_parms_to_args (parms));
 	}
 
       /* Attach the TPI to the decl.  */
@@ -7936,6 +7941,21 @@ add_defaults_to_ttp (tree otmpl)
 	}
     }
 
+  tree oresult = DECL_TEMPLATE_RESULT (otmpl);
+  tree gen_otmpl = DECL_TI_TEMPLATE (oresult);
+  tree gen_ntmpl;
+  if (gen_otmpl == otmpl)
+    gen_ntmpl = ntmpl;
+  else
+    gen_ntmpl = add_defaults_to_ttp (gen_otmpl);
+
+  tree nresult = copy_node (oresult);
+  DECL_LANG_SPECIFIC (nresult) = nullptr;
+  retrofit_lang_decl (nresult);
+  DECL_TEMPLATE_INFO (nresult)
+    = build_template_info (gen_ntmpl, TI_ARGS (DECL_TEMPLATE_INFO (oresult)));
+  DECL_TEMPLATE_RESULT (ntmpl) = nresult;
+
   hash_map_safe_put<hm_ggc> (defaulted_ttp_cache, otmpl, ntmpl);
   return ntmpl;
 }
@@ -8121,16 +8141,37 @@ coerce_template_template_parms (tree parm_tmpl,
 	 OUTER_ARGS are not the right outer levels in this case, as they are
 	 the args we're building up for PARM, and for the coercion we want the
 	 args for ARG.  If DECL_CONTEXT isn't set for a template template
-	 parameter, we can assume that it's in the current scope.  In that case
-	 we might end up adding more levels than needed, but that shouldn't be
-	 a problem; any args we need to refer to are at the right level.  */
+	 parameter, we can assume that it's in the current scope.  */
       tree ctx = DECL_CONTEXT (arg_tmpl);
       if (!ctx && DECL_TEMPLATE_TEMPLATE_PARM_P (arg_tmpl))
 	ctx = current_scope ();
       tree scope_args = NULL_TREE;
       if (tree tinfo = get_template_info (ctx))
 	scope_args = TI_ARGS (tinfo);
-      pargs = add_to_template_args (scope_args, pargs);
+      if (DECL_TEMPLATE_TEMPLATE_PARM_P (arg_tmpl))
+	{
+	  int levels = TEMPLATE_TYPE_LEVEL (TREE_TYPE (gen_arg_tmpl));
+	  int scope_depth = TMPL_ARGS_DEPTH (scope_args);
+	  tree full_pargs = make_tree_vec (levels + 1);
+
+	/* Only use as many levels from the scope as needed
+	   (excluding the level of ARG).  */
+	  for (int i = 0; i < levels - 1; ++i)
+	    if (i < scope_depth)
+	      TREE_VEC_ELT (full_pargs, i) = TMPL_ARGS_LEVEL (scope_args, i + 1);
+	    else
+	      TREE_VEC_ELT (full_pargs, i) = make_tree_vec (0);
+
+	  /* Add the arguments that appear at the levels of ARG.  */
+	  tree adjacent = DECL_TI_ARGS (DECL_TEMPLATE_RESULT (arg_tmpl));
+	  adjacent = TMPL_ARGS_LEVEL (adjacent, TMPL_ARGS_DEPTH (adjacent) - 1);
+	  TREE_VEC_ELT (full_pargs, levels - 1) = adjacent;
+
+	  TREE_VEC_ELT (full_pargs, levels) = pargs;
+	  pargs = full_pargs;
+	}
+      else
+	pargs = add_to_template_args (scope_args, pargs);
 
       pargs = coerce_template_parms (gen_arg_parms, pargs, NULL_TREE, tf_none);
       if (pargs != error_mark_node)
@@ -25985,6 +26026,9 @@ most_general_template (tree decl)
 	return NULL_TREE;
     }
 
+  if (DECL_TEMPLATE_TEMPLATE_PARM_P (decl))
+    return DECL_TI_TEMPLATE (DECL_TEMPLATE_RESULT (decl));
+
   /* Look for more and more general templates.  */
   while (DECL_LANG_SPECIFIC (decl) && DECL_TEMPLATE_INFO (decl))
     {
@@ -29700,10 +29744,11 @@ rewrite_template_parm (tree olddecl, unsigned index, unsigned level,
 
       if (TREE_CODE (olddecl) == TEMPLATE_DECL)
 	{
-	  DECL_TEMPLATE_RESULT (newdecl)
-	    = build_decl (DECL_SOURCE_LOCATION (olddecl), TYPE_DECL,
-			  DECL_NAME (olddecl), newtype);
-	  DECL_ARTIFICIAL (DECL_TEMPLATE_RESULT (newdecl)) = true;
+	  tree newresult
+	    = build_lang_decl_loc (DECL_SOURCE_LOCATION (olddecl), TYPE_DECL,
+				   DECL_NAME (olddecl), newtype);
+	  DECL_ARTIFICIAL (newresult) = true;
+	  DECL_TEMPLATE_RESULT (newdecl) = newresult;
 	  // First create a copy (ttargs) of tsubst_args with an
 	  // additional level for the template template parameter's own
 	  // template parameters (ttparms).
@@ -29737,6 +29782,8 @@ rewrite_template_parm (tree olddecl, unsigned index, unsigned level,
 	  TREE_VALUE (TREE_CHAIN (ttparms)) = make_tree_vec (0);
 	  // All done.
 	  DECL_TEMPLATE_PARMS (newdecl) = ttparms;
+	  DECL_TEMPLATE_INFO (newresult)
+	    = build_template_info (newdecl, template_parms_to_args (ttparms));
 	}
 
       if (TYPE_STRUCTURAL_EQUALITY_P (TREE_TYPE (olddecl)))
diff --git a/gcc/testsuite/g++.dg/cpp1z/class-deduction115.C b/gcc/testsuite/g++.dg/cpp1z/class-deduction115.C
new file mode 100644
index 00000000000..7b690e465d9
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1z/class-deduction115.C
@@ -0,0 +1,14 @@
+// { dg-do compile { target c++17 } }
+
+template<template<class> class> struct C { };
+
+template<class T>
+struct A {
+  template<template<class> class TT, C<TT>* = nullptr>
+  A(TT<T>);
+};
+
+template<class T>
+struct B { };
+
+A a = B<int>();
diff --git a/gcc/testsuite/g++.dg/template/ttp39.C b/gcc/testsuite/g++.dg/template/ttp39.C
new file mode 100644
index 00000000000..03d7c505c4a
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/ttp39.C
@@ -0,0 +1,16 @@
+// PR c++/110566
+// { dg-do compile { target c++20 } }
+
+template<template<int N, int M> class>
+struct A;
+
+template<class U>
+struct B {
+  template<class T>
+  struct C {
+    template<template<auto X, auto Y> class TT>
+    using type = A<TT>;
+  };
+};
+
+template struct B<int>::C<int>;
-- 
2.41.0.394.ge43f4fd0bd


^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [PATCH 2/1] c++: passing partially inst ttp as ttp [PR110566]
  2023-07-24 17:03     ` Patrick Palka
@ 2023-07-25 18:04       ` Jason Merrill
  0 siblings, 0 replies; 4+ messages in thread
From: Jason Merrill @ 2023-07-25 18:04 UTC (permalink / raw)
  To: Patrick Palka; +Cc: gcc-patches

On 7/24/23 13:03, Patrick Palka wrote:
> On Fri, 21 Jul 2023, Jason Merrill wrote:
>> On 7/21/23 14:34, Patrick Palka wrote:
>>> (This is a follow-up of
>>> https://gcc.gnu.org/pipermail/gcc-patches/2023-July/624951.html)
>>>
>>> Bootstrapped and regtested on x86_64-pc-linux-gnu, how does this look?
>>>
>>> -- >8 --
>>>
>>> The previous fix doesn't work for partially instantiated ttps primarily
>>> because most_general_template doesn't work for them.  This patch fixes
>>> this by giving such ttps a DECL_TEMPLATE_INFO (extending the
>>> r11-734-g2fb595f8348e16 fix) with which we can obtain the original ttp.
>>>
>>> This patch additionally makes us be more careful about using the correct
>>> amount of levels from the scope of a ttp argument during
>>> coerce_template_template_parms.
>>>
>>> 	PR c++/110566
>>>
>>> gcc/cp/ChangeLog:
>>>
>>> 	* pt.cc (reduce_template_parm_level): Set DECL_TEMPLATE_INFO
>>> 	on the DECL_TEMPLATE_RESULT of a reduced template template
>>> 	parameter.
>>> 	(add_defaults_to_ttp): Also update DECL_TEMPLATE_INFO of the
>>> 	ttp's DECL_TEMPLATE_RESULT.
>>> 	(coerce_template_template_parms): Make sure 'scope_args' has
>>> 	the right amount of levels for the ttp argument.
>>> 	(most_general_template): Handle template template parameters.
>>>
>>> gcc/testsuite/ChangeLog:
>>>
>>> 	* g++.dg/template/ttp39.C: New test.
>>> ---
>>>    gcc/cp/pt.cc                          | 46 ++++++++++++++++++++++++---
>>>    gcc/testsuite/g++.dg/template/ttp39.C | 16 ++++++++++
>>>    2 files changed, 57 insertions(+), 5 deletions(-)
>>>    create mode 100644 gcc/testsuite/g++.dg/template/ttp39.C
>>>
>>> diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
>>> index e0ed4bc8bbb..be7119dd9a0 100644
>>> --- a/gcc/cp/pt.cc
>>> +++ b/gcc/cp/pt.cc
>>> @@ -4570,8 +4570,14 @@ reduce_template_parm_level (tree index, tree type,
>>> int levels, tree args,
>>>    			      TYPE_DECL, DECL_NAME (decl), type);
>>>    	  DECL_TEMPLATE_RESULT (decl) = inner;
>>>    	  DECL_ARTIFICIAL (inner) = true;
>>> -	  DECL_TEMPLATE_PARMS (decl) = tsubst_template_parms
>>> -	    (DECL_TEMPLATE_PARMS (orig_decl), args, complain);
>>> +	  tree parms = tsubst_template_parms (DECL_TEMPLATE_PARMS (orig_decl),
>>> +					      args, complain);
>>> +	  DECL_TEMPLATE_PARMS (decl) = parms;
>>> +	  retrofit_lang_decl (inner);
>>> +	  tree orig_inner = DECL_TEMPLATE_RESULT (orig_decl);
>>> +	  DECL_TEMPLATE_INFO (inner)
>>> +	    = build_template_info (DECL_TI_TEMPLATE (orig_inner),
>>> +				   template_parms_to_args (parms));
>>
>> Should we assert that orig_inner doesn't have its own DECL_TEMPLATE_INFO?  I'm
>> wondering if it's possible to reduce the level of a TTP more than once.
> 
> It's possible for a ttp belonging to a nested generic lambda:
> 
>    template<class>
>    void f() {
>      [](auto) {
>        []<template<class> class TT>() {
>        };
>      }(0);
>    }
> 
>    template void f<int>();
> 
>>
>>>    	}
>>>            /* Attach the TPI to the decl.  */
>>> @@ -7936,6 +7942,19 @@ add_defaults_to_ttp (tree otmpl)
>>>    	}
>>>        }
>>>    +  tree oresult = DECL_TEMPLATE_RESULT (otmpl);
>>> +  tree gen_otmpl = DECL_TI_TEMPLATE (oresult);
>>
>> Hmm, here we're assuming that all TTPs have DECL_TEMPLATE_INFO?
> 
> I figured it's a reasonable assumption since all "formal" ttps
> originally start out with DECL_TEMPLATE_INFO (via process_template_parm).
> Though I realized I missed adjusting rewrite_template_parm to set
> DECL_TEMPLATE_INFO on the new ttp, which the below patch fixes (and
> adds a testcase that we'd otherwise segfualt on).
> 
>>
>>> +  tree gen_ntmpl;
>>> +  if (gen_otmpl == otmpl)
>>> +    gen_ntmpl = ntmpl;
>>> +  else
>>> +    gen_ntmpl = add_defaults_to_ttp (gen_otmpl);
>>> +
>>> +  tree nresult = copy_node (oresult);
> 
> Another fixed bug: since we build the new DECL_TEMPLATE_RESULT via
> copy_node, we need to avoid sharing its DECL_LANG_SPECIFIC with the
> old decl.
> 
>>> +  DECL_TEMPLATE_INFO (nresult) = copy_node (DECL_TEMPLATE_INFO (oresult));
>>> +  DECL_TI_TEMPLATE (nresult) = gen_ntmpl;
>>> +  DECL_TEMPLATE_RESULT (ntmpl) = nresult;
>>> +
>>>      hash_map_safe_put<hm_ggc> (defaulted_ttp_cache, otmpl, ntmpl);
>>>      return ntmpl;
>>>    }
>>> @@ -8121,15 +8140,29 @@ coerce_template_template_parms (tree parm_tmpl,
>>>    	 OUTER_ARGS are not the right outer levels in this case, as they are
>>>    	 the args we're building up for PARM, and for the coercion we want the
>>>    	 args for ARG.  If DECL_CONTEXT isn't set for a template template
>>> -	 parameter, we can assume that it's in the current scope.  In that
>>> case
>>> -	 we might end up adding more levels than needed, but that shouldn't be
>>> -	 a problem; any args we need to refer to are at the right level.  */
>>> +	 parameter, we can assume that it's in the current scope.  */
>>>          tree ctx = DECL_CONTEXT (arg_tmpl);
>>>          if (!ctx && DECL_TEMPLATE_TEMPLATE_PARM_P (arg_tmpl))
>>>    	ctx = current_scope ();
>>>          tree scope_args = NULL_TREE;
>>>          if (tree tinfo = get_template_info (ctx))
>>>    	scope_args = TI_ARGS (tinfo);
>>> +      if (DECL_TEMPLATE_TEMPLATE_PARM_P (arg_tmpl))
>>> +	{
>>> +	  int level = TEMPLATE_TYPE_LEVEL (TREE_TYPE (gen_arg_tmpl));
>>> +	  int scope_depth = TMPL_ARGS_DEPTH (scope_args);
>>> +	  if (scope_depth >= level)
>>> +	    /* Only use as many levels from the scope as needed (not
>>> +	       including the level of ARG).  */
>>> +	    scope_args = strip_innermost_template_args
>>> +	      (scope_args, scope_depth - (level - 1));
>>> +
>>> +	  /* Add the arguments that appear at the level of ARG.  */
>>> +	  tree adj_args = DECL_TI_ARGS (DECL_TEMPLATE_RESULT (arg_tmpl));
>>> +	  adj_args = TMPL_ARGS_LEVEL (adj_args, TMPL_ARGS_DEPTH (adj_args) -
>>> 1);
>>> +	  scope_args = add_to_template_args (scope_args, adj_args);
>>
>> Maybe we should add an integer parameter to add_to_template_args so we can
>> specify adding a certain number of levels without making a temporary copy
>> along the way?
> 
> I ended up building scope_args manually since it turns out we may need
> to add empty levels to 'pargs' in the case where ARG is a ttp nested
> inside another ttp (g++.old-deja/g++.pt/nttp2.C), in which case the
> scope lacks a level for the outer ttp.
> 
> Here's the updated patch (bootstrapped and regtested on
> x86_64-pc-linux-gnu):
> 
> 
> -- >8 --
> 
> 	PR c++/110566
> 
> gcc/cp/ChangeLog:
> 
> 	* pt.cc (reduce_template_parm_level): Set DECL_TEMPLATE_INFO
> 	on the DECL_TEMPLATE_RESULT of the new ttp.
> 	(add_defaults_to_ttp): Use a new DECL_LANG_SPECIFIC for the
> 	new ttp.  Update DECL_TEMPLATE_INFO on its DECL_TEMPLATE_RESULT.
> 	(coerce_template_template_parms): Make sure 'scope_args' has
> 	the right amount of levels for the ttp argument.
> 	(most_general_template): Handle template template parameters.
> 	(rewrite_template_parm): Set DECL_TEMPLATE_RESULT on the
> 	DECL_TEMPLATE_RESULT of the new ttp.
> 
> gcc/testsuite/ChangeLog:
> 
> 	* g++.dg/cpp1z/class-deduction115.C: New test.
> 	* g++.dg/template/ttp39.C: New test.
> ---
>   gcc/cp/pt.cc                                  | 71 +++++++++++++++----
>   .../g++.dg/cpp1z/class-deduction115.C         | 14 ++++
>   gcc/testsuite/g++.dg/template/ttp39.C         | 16 +++++
>   3 files changed, 89 insertions(+), 12 deletions(-)
>   create mode 100644 gcc/testsuite/g++.dg/cpp1z/class-deduction115.C
>   create mode 100644 gcc/testsuite/g++.dg/template/ttp39.C
> 
> diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
> index e0ed4bc8bbb..893ef69bb47 100644
> --- a/gcc/cp/pt.cc
> +++ b/gcc/cp/pt.cc
> @@ -4566,12 +4566,17 @@ reduce_template_parm_level (tree index, tree type, int levels, tree args,
>         tree inner = decl;
>         if (TREE_CODE (decl) == TEMPLATE_DECL)
>   	{
> -	  inner = build_decl (DECL_SOURCE_LOCATION (decl),
> -			      TYPE_DECL, DECL_NAME (decl), type);
> +	  inner = build_lang_decl_loc (DECL_SOURCE_LOCATION (decl),
> +				       TYPE_DECL, DECL_NAME (decl), type);
>   	  DECL_TEMPLATE_RESULT (decl) = inner;
>   	  DECL_ARTIFICIAL (inner) = true;
> -	  DECL_TEMPLATE_PARMS (decl) = tsubst_template_parms
> -	    (DECL_TEMPLATE_PARMS (orig_decl), args, complain);
> +	  tree parms = tsubst_template_parms (DECL_TEMPLATE_PARMS (orig_decl),
> +					      args, complain);
> +	  DECL_TEMPLATE_PARMS (decl) = parms;
> +	  tree orig_inner = DECL_TEMPLATE_RESULT (orig_decl);
> +	  DECL_TEMPLATE_INFO (inner)
> +	    = build_template_info (DECL_TI_TEMPLATE (orig_inner),
> +				   template_parms_to_args (parms));
>   	}
>   
>         /* Attach the TPI to the decl.  */
> @@ -7936,6 +7941,21 @@ add_defaults_to_ttp (tree otmpl)
>   	}
>       }
>   
> +  tree oresult = DECL_TEMPLATE_RESULT (otmpl);
> +  tree gen_otmpl = DECL_TI_TEMPLATE (oresult);
> +  tree gen_ntmpl;
> +  if (gen_otmpl == otmpl)
> +    gen_ntmpl = ntmpl;
> +  else
> +    gen_ntmpl = add_defaults_to_ttp (gen_otmpl);
> +
> +  tree nresult = copy_node (oresult);
> +  DECL_LANG_SPECIFIC (nresult) = nullptr;
> +  retrofit_lang_decl (nresult);

Maybe copy_decl instead of these three lines?  OK with that change.

> +  DECL_TEMPLATE_INFO (nresult)
> +    = build_template_info (gen_ntmpl, TI_ARGS (DECL_TEMPLATE_INFO (oresult)));
> +  DECL_TEMPLATE_RESULT (ntmpl) = nresult;
> +
>     hash_map_safe_put<hm_ggc> (defaulted_ttp_cache, otmpl, ntmpl);
>     return ntmpl;
>   }
> @@ -8121,16 +8141,37 @@ coerce_template_template_parms (tree parm_tmpl,
>   	 OUTER_ARGS are not the right outer levels in this case, as they are
>   	 the args we're building up for PARM, and for the coercion we want the
>   	 args for ARG.  If DECL_CONTEXT isn't set for a template template
> -	 parameter, we can assume that it's in the current scope.  In that case
> -	 we might end up adding more levels than needed, but that shouldn't be
> -	 a problem; any args we need to refer to are at the right level.  */
> +	 parameter, we can assume that it's in the current scope.  */
>         tree ctx = DECL_CONTEXT (arg_tmpl);
>         if (!ctx && DECL_TEMPLATE_TEMPLATE_PARM_P (arg_tmpl))
>   	ctx = current_scope ();
>         tree scope_args = NULL_TREE;
>         if (tree tinfo = get_template_info (ctx))
>   	scope_args = TI_ARGS (tinfo);
> -      pargs = add_to_template_args (scope_args, pargs);
> +      if (DECL_TEMPLATE_TEMPLATE_PARM_P (arg_tmpl))
> +	{
> +	  int levels = TEMPLATE_TYPE_LEVEL (TREE_TYPE (gen_arg_tmpl));
> +	  int scope_depth = TMPL_ARGS_DEPTH (scope_args);
> +	  tree full_pargs = make_tree_vec (levels + 1);
> +
> +	/* Only use as many levels from the scope as needed
> +	   (excluding the level of ARG).  */
> +	  for (int i = 0; i < levels - 1; ++i)
> +	    if (i < scope_depth)
> +	      TREE_VEC_ELT (full_pargs, i) = TMPL_ARGS_LEVEL (scope_args, i + 1);
> +	    else
> +	      TREE_VEC_ELT (full_pargs, i) = make_tree_vec (0);
> +
> +	  /* Add the arguments that appear at the levels of ARG.  */
> +	  tree adjacent = DECL_TI_ARGS (DECL_TEMPLATE_RESULT (arg_tmpl));
> +	  adjacent = TMPL_ARGS_LEVEL (adjacent, TMPL_ARGS_DEPTH (adjacent) - 1);
> +	  TREE_VEC_ELT (full_pargs, levels - 1) = adjacent;
> +
> +	  TREE_VEC_ELT (full_pargs, levels) = pargs;
> +	  pargs = full_pargs;
> +	}
> +      else
> +	pargs = add_to_template_args (scope_args, pargs);
>   
>         pargs = coerce_template_parms (gen_arg_parms, pargs, NULL_TREE, tf_none);
>         if (pargs != error_mark_node)
> @@ -25985,6 +26026,9 @@ most_general_template (tree decl)
>   	return NULL_TREE;
>       }
>   
> +  if (DECL_TEMPLATE_TEMPLATE_PARM_P (decl))
> +    return DECL_TI_TEMPLATE (DECL_TEMPLATE_RESULT (decl));
> +
>     /* Look for more and more general templates.  */
>     while (DECL_LANG_SPECIFIC (decl) && DECL_TEMPLATE_INFO (decl))
>       {
> @@ -29700,10 +29744,11 @@ rewrite_template_parm (tree olddecl, unsigned index, unsigned level,
>   
>         if (TREE_CODE (olddecl) == TEMPLATE_DECL)
>   	{
> -	  DECL_TEMPLATE_RESULT (newdecl)
> -	    = build_decl (DECL_SOURCE_LOCATION (olddecl), TYPE_DECL,
> -			  DECL_NAME (olddecl), newtype);
> -	  DECL_ARTIFICIAL (DECL_TEMPLATE_RESULT (newdecl)) = true;
> +	  tree newresult
> +	    = build_lang_decl_loc (DECL_SOURCE_LOCATION (olddecl), TYPE_DECL,
> +				   DECL_NAME (olddecl), newtype);
> +	  DECL_ARTIFICIAL (newresult) = true;
> +	  DECL_TEMPLATE_RESULT (newdecl) = newresult;
>   	  // First create a copy (ttargs) of tsubst_args with an
>   	  // additional level for the template template parameter's own
>   	  // template parameters (ttparms).
> @@ -29737,6 +29782,8 @@ rewrite_template_parm (tree olddecl, unsigned index, unsigned level,
>   	  TREE_VALUE (TREE_CHAIN (ttparms)) = make_tree_vec (0);
>   	  // All done.
>   	  DECL_TEMPLATE_PARMS (newdecl) = ttparms;
> +	  DECL_TEMPLATE_INFO (newresult)
> +	    = build_template_info (newdecl, template_parms_to_args (ttparms));
>   	}
>   
>         if (TYPE_STRUCTURAL_EQUALITY_P (TREE_TYPE (olddecl)))
> diff --git a/gcc/testsuite/g++.dg/cpp1z/class-deduction115.C b/gcc/testsuite/g++.dg/cpp1z/class-deduction115.C
> new file mode 100644
> index 00000000000..7b690e465d9
> --- /dev/null
> +++ b/gcc/testsuite/g++.dg/cpp1z/class-deduction115.C
> @@ -0,0 +1,14 @@
> +// { dg-do compile { target c++17 } }
> +
> +template<template<class> class> struct C { };
> +
> +template<class T>
> +struct A {
> +  template<template<class> class TT, C<TT>* = nullptr>
> +  A(TT<T>);
> +};
> +
> +template<class T>
> +struct B { };
> +
> +A a = B<int>();
> diff --git a/gcc/testsuite/g++.dg/template/ttp39.C b/gcc/testsuite/g++.dg/template/ttp39.C
> new file mode 100644
> index 00000000000..03d7c505c4a
> --- /dev/null
> +++ b/gcc/testsuite/g++.dg/template/ttp39.C
> @@ -0,0 +1,16 @@
> +// PR c++/110566
> +// { dg-do compile { target c++20 } }
> +
> +template<template<int N, int M> class>
> +struct A;
> +
> +template<class U>
> +struct B {
> +  template<class T>
> +  struct C {
> +    template<template<auto X, auto Y> class TT>
> +    using type = A<TT>;
> +  };
> +};
> +
> +template struct B<int>::C<int>;


^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2023-07-25 18:04 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
     [not found] <0001-c-passing-partially-inst-ttp-as-ttp-PR110566.patch>
2023-07-21 18:34 ` [PATCH 2/1] c++: passing partially inst ttp as ttp [PR110566] Patrick Palka
2023-07-21 20:32   ` Jason Merrill
2023-07-24 17:03     ` Patrick Palka
2023-07-25 18:04       ` Jason Merrill

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).