public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [PATCH] c++: optimize unification of class specializations [PR89231]
@ 2023-09-13 17:53 Patrick Palka
  2023-09-16 20:38 ` Jason Merrill
  0 siblings, 1 reply; 2+ messages in thread
From: Patrick Palka @ 2023-09-13 17:53 UTC (permalink / raw)
  To: gcc-patches; +Cc: jason, Patrick Palka

Bootstrapped and regtested on x86_64-pc-linux-gnu, does this look OK for
trunk?

-- >8 --

Since the LHS of a qualified-id is a non-deduced context, it effectively
means we can't deduce from outer template arguments of a class template
specialization.  And checking for equality between the TI_TEMPLATE of a
class specialization parm/arg already implies that the outer template
arguments are the same.  Hence recursing into outer template arguments
during unification of class specializations is redundant, so this patch
makes unify recurse only into innermost arguments.

This incidentally fixes the testcase from PR89231 because there
more_specialized_partial_inst considers the two partial specializations
to be unordered ultimately because unify for identical
parm=arg=A<Ps...>::Collect<N...> gets confused when it recurses into
parm=arg={Ps...} since the level of Ps doesn't match the innermost level
of tparms that we're actually deducing.

	PR c++/89231

gcc/cp/ChangeLog:

	* pt.cc (try_class_unification): Strengthen TI_TEMPLATE equality
	test by not calling most_general_template.  Only unify the
	innermost levels of template arguments.
	(unify) <case CLASS_TYPE>: Only unify the innermost levels of
	template arguments.  Don't unify template arguments if the
	template is not primary.

gcc/testsuite/ChangeLog:

	* g++.dg/cpp0x/variadic-partial3.C: New test.
---
 gcc/cp/pt.cc                                  | 17 +++++++++++------
 .../g++.dg/cpp0x/variadic-partial3.C          | 19 +++++++++++++++++++
 2 files changed, 30 insertions(+), 6 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/cpp0x/variadic-partial3.C

diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
index 838179d5fe3..c88e9cd0fa6 100644
--- a/gcc/cp/pt.cc
+++ b/gcc/cp/pt.cc
@@ -23999,8 +23999,7 @@ try_class_unification (tree tparms, tree targs, tree parm, tree arg,
     return NULL_TREE;
   else if (TREE_CODE (parm) == BOUND_TEMPLATE_TEMPLATE_PARM)
     /* Matches anything.  */;
-  else if (most_general_template (CLASSTYPE_TI_TEMPLATE (arg))
-	   != most_general_template (CLASSTYPE_TI_TEMPLATE (parm)))
+  else if (CLASSTYPE_TI_TEMPLATE (arg) != CLASSTYPE_TI_TEMPLATE (parm))
     return NULL_TREE;
 
   /* We need to make a new template argument vector for the call to
@@ -24041,8 +24040,10 @@ try_class_unification (tree tparms, tree targs, tree parm, tree arg,
   if (TREE_CODE (parm) == BOUND_TEMPLATE_TEMPLATE_PARM)
     err = unify_bound_ttp_args (tparms, targs, parm, arg, explain_p);
   else
-    err = unify (tparms, targs, CLASSTYPE_TI_ARGS (parm),
-		 CLASSTYPE_TI_ARGS (arg), UNIFY_ALLOW_NONE, explain_p);
+    err = unify (tparms, targs,
+		 INNERMOST_TEMPLATE_ARGS (CLASSTYPE_TI_ARGS (parm)),
+		 INNERMOST_TEMPLATE_ARGS (CLASSTYPE_TI_ARGS (arg)),
+		 UNIFY_ALLOW_NONE, explain_p);
 
   return err ? NULL_TREE : arg;
 }
@@ -25167,11 +25168,15 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict,
 	    /* There's no chance of unification succeeding.  */
 	    return unify_type_mismatch (explain_p, parm, arg);
 
-	  return unify (tparms, targs, CLASSTYPE_TI_ARGS (parm),
-			CLASSTYPE_TI_ARGS (t), UNIFY_ALLOW_NONE, explain_p);
+	  if (PRIMARY_TEMPLATE_P (CLASSTYPE_TI_TEMPLATE (t)))
+	    return unify (tparms, targs,
+			  INNERMOST_TEMPLATE_ARGS (CLASSTYPE_TI_ARGS (parm)),
+			  INNERMOST_TEMPLATE_ARGS (CLASSTYPE_TI_ARGS (t)),
+			  UNIFY_ALLOW_NONE, explain_p);
 	}
       else if (!same_type_ignoring_top_level_qualifiers_p (parm, arg))
 	return unify_type_mismatch (explain_p, parm, arg);
+
       return unify_success (explain_p);
 
     case METHOD_TYPE:
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic-partial3.C b/gcc/testsuite/g++.dg/cpp0x/variadic-partial3.C
new file mode 100644
index 00000000000..5af60711320
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/variadic-partial3.C
@@ -0,0 +1,19 @@
+// PR c++/89231
+// { dg-do compile { target c++11 } }
+
+template<class... Ps>
+struct A {
+  template<int... Ns>
+  struct Collect { };
+
+  template<int C, int I = 0, class S = Collect<>>
+  struct Seq;
+
+  template<int C, int I, int... N>
+  struct Seq<C, I, Collect<N...>> : Seq<C - 1, I + 1, Collect<N..., I>> { };
+
+  template<int I, int... N>
+  struct Seq<0, I, Collect<N...>> : Collect<N...> { };
+};
+
+A<int>::Seq<4> test;
-- 
2.42.0.158.g94e83dcf5b


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

* Re: [PATCH] c++: optimize unification of class specializations [PR89231]
  2023-09-13 17:53 [PATCH] c++: optimize unification of class specializations [PR89231] Patrick Palka
@ 2023-09-16 20:38 ` Jason Merrill
  0 siblings, 0 replies; 2+ messages in thread
From: Jason Merrill @ 2023-09-16 20:38 UTC (permalink / raw)
  To: Patrick Palka, gcc-patches

On 9/13/23 13:53, Patrick Palka wrote:
> Bootstrapped and regtested on x86_64-pc-linux-gnu, does this look OK for
> trunk?

OK.

> -- >8 --
> 
> Since the LHS of a qualified-id is a non-deduced context, it effectively
> means we can't deduce from outer template arguments of a class template
> specialization.  And checking for equality between the TI_TEMPLATE of a
> class specialization parm/arg already implies that the outer template
> arguments are the same.  Hence recursing into outer template arguments
> during unification of class specializations is redundant, so this patch
> makes unify recurse only into innermost arguments.
> 
> This incidentally fixes the testcase from PR89231 because there
> more_specialized_partial_inst considers the two partial specializations
> to be unordered ultimately because unify for identical
> parm=arg=A<Ps...>::Collect<N...> gets confused when it recurses into
> parm=arg={Ps...} since the level of Ps doesn't match the innermost level
> of tparms that we're actually deducing.
> 
> 	PR c++/89231
> 
> gcc/cp/ChangeLog:
> 
> 	* pt.cc (try_class_unification): Strengthen TI_TEMPLATE equality
> 	test by not calling most_general_template.  Only unify the
> 	innermost levels of template arguments.
> 	(unify) <case CLASS_TYPE>: Only unify the innermost levels of
> 	template arguments.  Don't unify template arguments if the
> 	template is not primary.
> 
> gcc/testsuite/ChangeLog:
> 
> 	* g++.dg/cpp0x/variadic-partial3.C: New test.
> ---
>   gcc/cp/pt.cc                                  | 17 +++++++++++------
>   .../g++.dg/cpp0x/variadic-partial3.C          | 19 +++++++++++++++++++
>   2 files changed, 30 insertions(+), 6 deletions(-)
>   create mode 100644 gcc/testsuite/g++.dg/cpp0x/variadic-partial3.C
> 
> diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
> index 838179d5fe3..c88e9cd0fa6 100644
> --- a/gcc/cp/pt.cc
> +++ b/gcc/cp/pt.cc
> @@ -23999,8 +23999,7 @@ try_class_unification (tree tparms, tree targs, tree parm, tree arg,
>       return NULL_TREE;
>     else if (TREE_CODE (parm) == BOUND_TEMPLATE_TEMPLATE_PARM)
>       /* Matches anything.  */;
> -  else if (most_general_template (CLASSTYPE_TI_TEMPLATE (arg))
> -	   != most_general_template (CLASSTYPE_TI_TEMPLATE (parm)))
> +  else if (CLASSTYPE_TI_TEMPLATE (arg) != CLASSTYPE_TI_TEMPLATE (parm))
>       return NULL_TREE;
>   
>     /* We need to make a new template argument vector for the call to
> @@ -24041,8 +24040,10 @@ try_class_unification (tree tparms, tree targs, tree parm, tree arg,
>     if (TREE_CODE (parm) == BOUND_TEMPLATE_TEMPLATE_PARM)
>       err = unify_bound_ttp_args (tparms, targs, parm, arg, explain_p);
>     else
> -    err = unify (tparms, targs, CLASSTYPE_TI_ARGS (parm),
> -		 CLASSTYPE_TI_ARGS (arg), UNIFY_ALLOW_NONE, explain_p);
> +    err = unify (tparms, targs,
> +		 INNERMOST_TEMPLATE_ARGS (CLASSTYPE_TI_ARGS (parm)),
> +		 INNERMOST_TEMPLATE_ARGS (CLASSTYPE_TI_ARGS (arg)),
> +		 UNIFY_ALLOW_NONE, explain_p);
>   
>     return err ? NULL_TREE : arg;
>   }
> @@ -25167,11 +25168,15 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict,
>   	    /* There's no chance of unification succeeding.  */
>   	    return unify_type_mismatch (explain_p, parm, arg);
>   
> -	  return unify (tparms, targs, CLASSTYPE_TI_ARGS (parm),
> -			CLASSTYPE_TI_ARGS (t), UNIFY_ALLOW_NONE, explain_p);
> +	  if (PRIMARY_TEMPLATE_P (CLASSTYPE_TI_TEMPLATE (t)))
> +	    return unify (tparms, targs,
> +			  INNERMOST_TEMPLATE_ARGS (CLASSTYPE_TI_ARGS (parm)),
> +			  INNERMOST_TEMPLATE_ARGS (CLASSTYPE_TI_ARGS (t)),
> +			  UNIFY_ALLOW_NONE, explain_p);
>   	}
>         else if (!same_type_ignoring_top_level_qualifiers_p (parm, arg))
>   	return unify_type_mismatch (explain_p, parm, arg);
> +
>         return unify_success (explain_p);
>   
>       case METHOD_TYPE:
> diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic-partial3.C b/gcc/testsuite/g++.dg/cpp0x/variadic-partial3.C
> new file mode 100644
> index 00000000000..5af60711320
> --- /dev/null
> +++ b/gcc/testsuite/g++.dg/cpp0x/variadic-partial3.C
> @@ -0,0 +1,19 @@
> +// PR c++/89231
> +// { dg-do compile { target c++11 } }
> +
> +template<class... Ps>
> +struct A {
> +  template<int... Ns>
> +  struct Collect { };
> +
> +  template<int C, int I = 0, class S = Collect<>>
> +  struct Seq;
> +
> +  template<int C, int I, int... N>
> +  struct Seq<C, I, Collect<N...>> : Seq<C - 1, I + 1, Collect<N..., I>> { };
> +
> +  template<int I, int... N>
> +  struct Seq<0, I, Collect<N...>> : Collect<N...> { };
> +};
> +
> +A<int>::Seq<4> test;


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

end of thread, other threads:[~2023-09-16 20:38 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-09-13 17:53 [PATCH] c++: optimize unification of class specializations [PR89231] Patrick Palka
2023-09-16 20:38 ` 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).