diff mbox series

c++: more constrained nested partial specialization

Message ID 20200602214550.981432-1-ppalka@redhat.com
State New
Headers show
Series c++: more constrained nested partial specialization | expand

Commit Message

Patrick Palka June 2, 2020, 9:45 p.m. UTC
When checking that a constrained partial specialization is more
constrained than the primary template, we pass only the innermost level
of generic template arguments to strictly_subsumes.  This leads to us
doing a nonsensical substitution from normalize_concept_check if the
full set of template arguments has multiple levels, and it causes
strictly_subsumes to sometimes erroneously return false as in the
testcase below.

Passes 'make check-c++' and also tested by building the testsuites of
cmcstl2 and range-v3.  Does this look OK to commit to mainline and to
the 10 branch after a full bootstrap and regtest?

(We shouldn't need to do any substitution from strictly_subsumes here,
since processing_template_decl would always be non-zero and so
substituting in the complete set of generic template arguments should
always be a no-op I think.  I can propose this as a subsequent patch for
mainline.)

gcc/cp/ChangeLog:

	* pt.c (process_partial_specialization): Pass the full set of
	generic template arguments to strictly_subsumes.

gcc/testsuite/ChangeLog:

	* g++.dg/cpp2a/concepts-partial-spec8.C: New test.
---
 gcc/cp/pt.c                                        |  2 +-
 .../g++.dg/cpp2a/concepts-partial-spec8.C          | 14 ++++++++++++++
 2 files changed, 15 insertions(+), 1 deletion(-)
 create mode 100644 gcc/testsuite/g++.dg/cpp2a/concepts-partial-spec8.C

Comments

Jason Merrill June 3, 2020, 7:20 p.m. UTC | #1
On 6/2/20 5:45 PM, Patrick Palka wrote:
> When checking that a constrained partial specialization is more
> constrained than the primary template, we pass only the innermost level
> of generic template arguments to strictly_subsumes.  This leads to us
> doing a nonsensical substitution from normalize_concept_check if the
> full set of template arguments has multiple levels, and it causes
> strictly_subsumes to sometimes erroneously return false as in the
> testcase below.
> 
> Passes 'make check-c++' and also tested by building the testsuites of
> cmcstl2 and range-v3.  Does this look OK to commit to mainline and to
> the 10 branch after a full bootstrap and regtest?

OK.

> (We shouldn't need to do any substitution from strictly_subsumes here,
> since processing_template_decl would always be non-zero and so
> substituting in the complete set of generic template arguments should
> always be a no-op I think.  I can propose this as a subsequent patch for
> mainline.)

Sounds good.

> gcc/cp/ChangeLog:
> 
> 	* pt.c (process_partial_specialization): Pass the full set of
> 	generic template arguments to strictly_subsumes.
> 
> gcc/testsuite/ChangeLog:
> 
> 	* g++.dg/cpp2a/concepts-partial-spec8.C: New test.
> ---
>   gcc/cp/pt.c                                        |  2 +-
>   .../g++.dg/cpp2a/concepts-partial-spec8.C          | 14 ++++++++++++++
>   2 files changed, 15 insertions(+), 1 deletion(-)
>   create mode 100644 gcc/testsuite/g++.dg/cpp2a/concepts-partial-spec8.C
> 
> diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
> index df92f5584cf..d7f61289621 100644
> --- a/gcc/cp/pt.c
> +++ b/gcc/cp/pt.c
> @@ -5062,7 +5062,7 @@ process_partial_specialization (tree decl)
>     if (comp_template_args (inner_args, INNERMOST_TEMPLATE_ARGS (main_args))
>         && (!flag_concepts
>   	  || !strictly_subsumes (current_template_constraints (),
> -				 inner_args, maintmpl)))
> +				 main_args, maintmpl)))
>       {
>         if (!flag_concepts)
>           error ("partial specialization %q+D does not specialize "
> diff --git a/gcc/testsuite/g++.dg/cpp2a/concepts-partial-spec8.C b/gcc/testsuite/g++.dg/cpp2a/concepts-partial-spec8.C
> new file mode 100644
> index 00000000000..873cf44e407
> --- /dev/null
> +++ b/gcc/testsuite/g++.dg/cpp2a/concepts-partial-spec8.C
> @@ -0,0 +1,14 @@
> +// { dg-do compile { target c++20 } }
> +
> +template<int M, int N>
> +concept equal = M == N;
> +
> +template<int M>
> +struct traits
> +{
> +  template<int N> requires equal<M, N>
> +    struct foo {};
> +
> +  template<int N> requires equal<M, N> && (M >= 0) // { dg-bogus "not more constrained" }
> +    struct foo<N> {};
> +};
>
diff mbox series

Patch

diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index df92f5584cf..d7f61289621 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -5062,7 +5062,7 @@  process_partial_specialization (tree decl)
   if (comp_template_args (inner_args, INNERMOST_TEMPLATE_ARGS (main_args))
       && (!flag_concepts
 	  || !strictly_subsumes (current_template_constraints (),
-				 inner_args, maintmpl)))
+				 main_args, maintmpl)))
     {
       if (!flag_concepts)
         error ("partial specialization %q+D does not specialize "
diff --git a/gcc/testsuite/g++.dg/cpp2a/concepts-partial-spec8.C b/gcc/testsuite/g++.dg/cpp2a/concepts-partial-spec8.C
new file mode 100644
index 00000000000..873cf44e407
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/concepts-partial-spec8.C
@@ -0,0 +1,14 @@ 
+// { dg-do compile { target c++20 } }
+
+template<int M, int N>
+concept equal = M == N;
+
+template<int M>
+struct traits
+{
+  template<int N> requires equal<M, N>
+    struct foo {};
+
+  template<int N> requires equal<M, N> && (M >= 0) // { dg-bogus "not more constrained" }
+    struct foo<N> {};
+};