public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [PATCH] c++: explicit specialization and trailing requirements [PR107864]
@ 2022-11-28 20:16 Patrick Palka
  2022-11-28 23:31 ` Jason Merrill
  0 siblings, 1 reply; 2+ messages in thread
From: Patrick Palka @ 2022-11-28 20:16 UTC (permalink / raw)
  To: gcc-patches; +Cc: jason, Patrick Palka

Here we're crashing when using an explicit specialization of a function
template with trailing requirements ultimately because decls_match
(called indirectly from register_specialization) returns false since the
template has trailing requirements whereas the specialization doesn't.

In r12-2230-gddd25bd1a7c8f4, we fixed a similar issue concerning
template requirements instead of trailing requirements.  We could just
extend this fix to ignore trailing requirement mismatches for
explicit specializations as well, but it seems cleaner to just propagate
constraints from the specialized template to the explicit specialization
so that decls_match will naturally return true.  And it looks like
determine_specialization already does this, albeit inconsistently (only
for non-template member functions of a class template as in
cpp2a/concepts-explicit-spec4.C).

So this patch makes determine_specialization consistently propagate
constraints from the specialized template to the specialization, which
obviates the function_requirements_equivalent_p special case added by
r12-2230.  In passing use add_outermost_template_args instead of open
coding it.

Bootstrapped and regtested on x86_64-pc-linux-gnu, does this look OK for
trunk?  Also tested on range-v3 and cmcstl2.

	PR c++/107864

gcc/cp/ChangeLog:

	* decl.cc (function_requirements_equivalent_p): Don't check
	DECL_TEMPLATE_SPECIALIZATION.
	* pt.cc (determine_specialization): Propagate constraints when
	specializing a function template too.  Simplify by using
	add_outermost_template_args.

gcc/testsuite/ChangeLog:

	* g++.dg/concepts/explicit-spec1a.C: New test.
---
 gcc/cp/decl.cc                                |  4 +---
 gcc/cp/pt.cc                                  | 21 +++++++++----------
 .../g++.dg/concepts/explicit-spec1a.C         | 11 ++++++++++
 3 files changed, 22 insertions(+), 14 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/concepts/explicit-spec1a.C

diff --git a/gcc/cp/decl.cc b/gcc/cp/decl.cc
index 544efdc9914..238e72f90da 100644
--- a/gcc/cp/decl.cc
+++ b/gcc/cp/decl.cc
@@ -956,9 +956,7 @@ static bool
 function_requirements_equivalent_p (tree newfn, tree oldfn)
 {
   /* In the concepts TS, the combined constraints are compared.  */
-  if (cxx_dialect < cxx20
-      && (DECL_TEMPLATE_SPECIALIZATION (newfn)
-	  <= DECL_TEMPLATE_SPECIALIZATION (oldfn)))
+  if (cxx_dialect < cxx20)
     {
       tree ci1 = get_constraints (oldfn);
       tree ci2 = get_constraints (newfn);
diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
index fbf498ad16a..e677e9d1b38 100644
--- a/gcc/cp/pt.cc
+++ b/gcc/cp/pt.cc
@@ -2482,17 +2482,16 @@ determine_specialization (tree template_id,
     }
 
   /* It was a specialization of a template.  */
-  targs = DECL_TI_ARGS (DECL_TEMPLATE_RESULT (TREE_VALUE (templates)));
-  if (TMPL_ARGS_HAVE_MULTIPLE_LEVELS (targs))
-    {
-      *targs_out = copy_node (targs);
-      SET_TMPL_ARGS_LEVEL (*targs_out,
-			   TMPL_ARGS_DEPTH (*targs_out),
-			   TREE_PURPOSE (templates));
-    }
-  else
-    *targs_out = TREE_PURPOSE (templates);
-  return TREE_VALUE (templates);
+  tree tmpl = TREE_VALUE (templates);
+  targs = DECL_TI_ARGS (DECL_TEMPLATE_RESULT (tmpl));
+  targs = add_outermost_template_args (targs, TREE_PURPOSE (templates));
+  *targs_out = targs;
+
+  /* Propagate the template's constraints to the declaration.  */
+  if (tsk != tsk_template)
+    set_constraints (decl, get_constraints (tmpl));
+
+  return tmpl;
 }
 
 /* Returns a chain of parameter types, exactly like the SPEC_TYPES,
diff --git a/gcc/testsuite/g++.dg/concepts/explicit-spec1a.C b/gcc/testsuite/g++.dg/concepts/explicit-spec1a.C
new file mode 100644
index 00000000000..ec678740cb8
--- /dev/null
+++ b/gcc/testsuite/g++.dg/concepts/explicit-spec1a.C
@@ -0,0 +1,11 @@
+// A version of explicit-spec1.C where the template g has trailing instead of
+// template requirements.
+// PR c++/107864
+// { dg-do compile { target concepts } }
+
+template<typename T> concept C = __is_class(T);
+struct Y { int n; } y;
+template<class T> void g(T) requires C<T> { }
+int called;
+template<> void g(Y) { called = 3; }
+int main() { g(y); }
-- 
2.39.0.rc0.33.g815c1e8202


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

* Re: [PATCH] c++: explicit specialization and trailing requirements [PR107864]
  2022-11-28 20:16 [PATCH] c++: explicit specialization and trailing requirements [PR107864] Patrick Palka
@ 2022-11-28 23:31 ` Jason Merrill
  0 siblings, 0 replies; 2+ messages in thread
From: Jason Merrill @ 2022-11-28 23:31 UTC (permalink / raw)
  To: Patrick Palka, gcc-patches

On 11/28/22 15:16, Patrick Palka wrote:
> Here we're crashing when using an explicit specialization of a function
> template with trailing requirements ultimately because decls_match
> (called indirectly from register_specialization) returns false since the
> template has trailing requirements whereas the specialization doesn't.
> 
> In r12-2230-gddd25bd1a7c8f4, we fixed a similar issue concerning
> template requirements instead of trailing requirements.  We could just
> extend this fix to ignore trailing requirement mismatches for
> explicit specializations as well, but it seems cleaner to just propagate
> constraints from the specialized template to the explicit specialization
> so that decls_match will naturally return true.  And it looks like
> determine_specialization already does this, albeit inconsistently (only
> for non-template member functions of a class template as in
> cpp2a/concepts-explicit-spec4.C).
> 
> So this patch makes determine_specialization consistently propagate
> constraints from the specialized template to the specialization, which
> obviates the function_requirements_equivalent_p special case added by
> r12-2230.  In passing use add_outermost_template_args instead of open
> coding it.
> 
> Bootstrapped and regtested on x86_64-pc-linux-gnu, does this look OK for
> trunk?  Also tested on range-v3 and cmcstl2.
> 
> 	PR c++/107864
> 
> gcc/cp/ChangeLog:
> 
> 	* decl.cc (function_requirements_equivalent_p): Don't check
> 	DECL_TEMPLATE_SPECIALIZATION.
> 	* pt.cc (determine_specialization): Propagate constraints when
> 	specializing a function template too.  Simplify by using
> 	add_outermost_template_args.
> 
> gcc/testsuite/ChangeLog:
> 
> 	* g++.dg/concepts/explicit-spec1a.C: New test.
> ---
>   gcc/cp/decl.cc                                |  4 +---
>   gcc/cp/pt.cc                                  | 21 +++++++++----------
>   .../g++.dg/concepts/explicit-spec1a.C         | 11 ++++++++++
>   3 files changed, 22 insertions(+), 14 deletions(-)
>   create mode 100644 gcc/testsuite/g++.dg/concepts/explicit-spec1a.C
> 
> diff --git a/gcc/cp/decl.cc b/gcc/cp/decl.cc
> index 544efdc9914..238e72f90da 100644
> --- a/gcc/cp/decl.cc
> +++ b/gcc/cp/decl.cc
> @@ -956,9 +956,7 @@ static bool
>   function_requirements_equivalent_p (tree newfn, tree oldfn)
>   {
>     /* In the concepts TS, the combined constraints are compared.  */
> -  if (cxx_dialect < cxx20
> -      && (DECL_TEMPLATE_SPECIALIZATION (newfn)
> -	  <= DECL_TEMPLATE_SPECIALIZATION (oldfn)))
> +  if (cxx_dialect < cxx20)

This should probably check flag_concepts_ts instead of cxx_dialect.

OK with that change.

>       {
>         tree ci1 = get_constraints (oldfn);
>         tree ci2 = get_constraints (newfn);
> diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
> index fbf498ad16a..e677e9d1b38 100644
> --- a/gcc/cp/pt.cc
> +++ b/gcc/cp/pt.cc
> @@ -2482,17 +2482,16 @@ determine_specialization (tree template_id,
>       }
>   
>     /* It was a specialization of a template.  */
> -  targs = DECL_TI_ARGS (DECL_TEMPLATE_RESULT (TREE_VALUE (templates)));
> -  if (TMPL_ARGS_HAVE_MULTIPLE_LEVELS (targs))
> -    {
> -      *targs_out = copy_node (targs);
> -      SET_TMPL_ARGS_LEVEL (*targs_out,
> -			   TMPL_ARGS_DEPTH (*targs_out),
> -			   TREE_PURPOSE (templates));
> -    }
> -  else
> -    *targs_out = TREE_PURPOSE (templates);
> -  return TREE_VALUE (templates);
> +  tree tmpl = TREE_VALUE (templates);
> +  targs = DECL_TI_ARGS (DECL_TEMPLATE_RESULT (tmpl));
> +  targs = add_outermost_template_args (targs, TREE_PURPOSE (templates));
> +  *targs_out = targs;
> +
> +  /* Propagate the template's constraints to the declaration.  */
> +  if (tsk != tsk_template)
> +    set_constraints (decl, get_constraints (tmpl));
> +
> +  return tmpl;
>   }
>   
>   /* Returns a chain of parameter types, exactly like the SPEC_TYPES,
> diff --git a/gcc/testsuite/g++.dg/concepts/explicit-spec1a.C b/gcc/testsuite/g++.dg/concepts/explicit-spec1a.C
> new file mode 100644
> index 00000000000..ec678740cb8
> --- /dev/null
> +++ b/gcc/testsuite/g++.dg/concepts/explicit-spec1a.C
> @@ -0,0 +1,11 @@
> +// A version of explicit-spec1.C where the template g has trailing instead of
> +// template requirements.
> +// PR c++/107864
> +// { dg-do compile { target concepts } }
> +
> +template<typename T> concept C = __is_class(T);
> +struct Y { int n; } y;
> +template<class T> void g(T) requires C<T> { }
> +int called;
> +template<> void g(Y) { called = 3; }
> +int main() { g(y); }


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

end of thread, other threads:[~2022-11-28 23:31 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-11-28 20:16 [PATCH] c++: explicit specialization and trailing requirements [PR107864] Patrick Palka
2022-11-28 23:31 ` 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).