diff mbox series

c++: constraints and explicit instantiation [PR96164]

Message ID 20200713211918.3713282-1-ppalka@redhat.com
State New
Headers show
Series c++: constraints and explicit instantiation [PR96164] | expand

Commit Message

Patrick Palka July 13, 2020, 9:19 p.m. UTC
When considering to instantiate a member of a class template as part of an
explicit instantiation of the class template, we need to first check the
member's constraints before proceeding with the instantiation of the member.

Bootstrapped and regtested on x86_64-pc-linux-gnu, does this look OK to commit
to trunk (and perhaps to the 10 branch)?

gcc/cp/ChangeLog:

	PR c++/96164
	* pt.c (do_type_instantiation): Update a paragraph taken from
	[temp.explicit] to reflect the latest specification.  Don't
	instantiate a member with unsatisfied constraints.

gcc/testsuite/ChangeLog:

	PR c++/96164
	* g++.dg/cpp2a/concepts-explicit-inst5.C: New test.
---
 gcc/cp/pt.c                                   | 23 +++++++++----------
 .../g++.dg/cpp2a/concepts-explicit-inst5.C    | 14 +++++++++++
 2 files changed, 25 insertions(+), 12 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/cpp2a/concepts-explicit-inst5.C

Comments

Jason Merrill July 29, 2020, 7:15 p.m. UTC | #1
On 7/13/20 5:19 PM, Patrick Palka wrote:
> When considering to instantiate a member of a class template as part of an
> explicit instantiation of the class template, we need to first check the
> member's constraints before proceeding with the instantiation of the member.
> 
> Bootstrapped and regtested on x86_64-pc-linux-gnu, does this look OK to commit
> to trunk (and perhaps to the 10 branch)?

Let's change constraints_satisfied_p to return true if !flag_concepts, 
so you don't need to check the flag here.  OK for both with that change.

> gcc/cp/ChangeLog:
> 
> 	PR c++/96164
> 	* pt.c (do_type_instantiation): Update a paragraph taken from
> 	[temp.explicit] to reflect the latest specification.  Don't
> 	instantiate a member with unsatisfied constraints.
> 
> gcc/testsuite/ChangeLog:
> 
> 	PR c++/96164
> 	* g++.dg/cpp2a/concepts-explicit-inst5.C: New test.
> ---
>   gcc/cp/pt.c                                   | 23 +++++++++----------
>   .../g++.dg/cpp2a/concepts-explicit-inst5.C    | 14 +++++++++++
>   2 files changed, 25 insertions(+), 12 deletions(-)
>   create mode 100644 gcc/testsuite/g++.dg/cpp2a/concepts-explicit-inst5.C
> 
> diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
> index 61f22733858..c518f221f2f 100644
> --- a/gcc/cp/pt.c
> +++ b/gcc/cp/pt.c
> @@ -24902,23 +24902,22 @@ do_type_instantiation (tree t, tree storage, tsubst_flags_t complain)
>   
>   	 [temp.explicit]
>   
> -	 The explicit instantiation of a class template specialization
> -	 implies the instantiation of all of its members not
> -	 previously explicitly specialized in the translation unit
> -	 containing the explicit instantiation.
> -
> -     Of course, we can't instantiate member template classes, since we
> -     don't have any arguments for them.  Note that the standard is
> -     unclear on whether the instantiation of the members are
> -     *explicit* instantiations or not.  However, the most natural
> -     interpretation is that it should be an explicit
> -     instantiation.  */
> +	 An explicit instantiation that names a class template
> +	 specialization is also an explicit instantiation of the same
> +	 kind (declaration or definition) of each of its members (not
> +	 including members inherited from base classes and members
> +	 that are templates) that has not been previously explicitly
> +	 specialized in the translation unit containing the explicit
> +	 instantiation, provided that the associated constraints, if
> +	 any, of that member are satisfied by the template arguments
> +	 of the explicit instantiation.  */
>     for (tree fld = TYPE_FIELDS (t); fld; fld = DECL_CHAIN (fld))
>       if ((VAR_P (fld)
>   	 || (TREE_CODE (fld) == FUNCTION_DECL
>   	     && !static_p
>   	     && user_provided_p (fld)))
> -	&& DECL_TEMPLATE_INSTANTIATION (fld))
> +	&& DECL_TEMPLATE_INSTANTIATION (fld)
> +	&& (!flag_concepts || constraints_satisfied_p (fld)))
>         {
>   	mark_decl_instantiated (fld, extern_p);
>   	if (! extern_p)
> diff --git a/gcc/testsuite/g++.dg/cpp2a/concepts-explicit-inst5.C b/gcc/testsuite/g++.dg/cpp2a/concepts-explicit-inst5.C
> new file mode 100644
> index 00000000000..05959a8972c
> --- /dev/null
> +++ b/gcc/testsuite/g++.dg/cpp2a/concepts-explicit-inst5.C
> @@ -0,0 +1,14 @@
> +// PR c++/96164
> +// { dg-do compile { target concepts } }
> +
> +template <int N>
> +struct A {
> +    void f() requires (N == 3) { static_assert(N == 3); }
> +};
> +template struct A<2>;
> +
> +template <int N>
> +struct B {
> +    void f() requires (N == 2) { static_assert(N == 3); } // { dg-error "assert" }
> +};
> +template struct B<2>;
>
diff mbox series

Patch

diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 61f22733858..c518f221f2f 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -24902,23 +24902,22 @@  do_type_instantiation (tree t, tree storage, tsubst_flags_t complain)
 
 	 [temp.explicit]
 
-	 The explicit instantiation of a class template specialization
-	 implies the instantiation of all of its members not
-	 previously explicitly specialized in the translation unit
-	 containing the explicit instantiation.
-
-     Of course, we can't instantiate member template classes, since we
-     don't have any arguments for them.  Note that the standard is
-     unclear on whether the instantiation of the members are
-     *explicit* instantiations or not.  However, the most natural
-     interpretation is that it should be an explicit
-     instantiation.  */
+	 An explicit instantiation that names a class template
+	 specialization is also an explicit instantiation of the same
+	 kind (declaration or definition) of each of its members (not
+	 including members inherited from base classes and members
+	 that are templates) that has not been previously explicitly
+	 specialized in the translation unit containing the explicit
+	 instantiation, provided that the associated constraints, if
+	 any, of that member are satisfied by the template arguments
+	 of the explicit instantiation.  */
   for (tree fld = TYPE_FIELDS (t); fld; fld = DECL_CHAIN (fld))
     if ((VAR_P (fld)
 	 || (TREE_CODE (fld) == FUNCTION_DECL
 	     && !static_p
 	     && user_provided_p (fld)))
-	&& DECL_TEMPLATE_INSTANTIATION (fld))
+	&& DECL_TEMPLATE_INSTANTIATION (fld)
+	&& (!flag_concepts || constraints_satisfied_p (fld)))
       {
 	mark_decl_instantiated (fld, extern_p);
 	if (! extern_p)
diff --git a/gcc/testsuite/g++.dg/cpp2a/concepts-explicit-inst5.C b/gcc/testsuite/g++.dg/cpp2a/concepts-explicit-inst5.C
new file mode 100644
index 00000000000..05959a8972c
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/concepts-explicit-inst5.C
@@ -0,0 +1,14 @@ 
+// PR c++/96164
+// { dg-do compile { target concepts } }
+
+template <int N>
+struct A {
+    void f() requires (N == 3) { static_assert(N == 3); }
+};
+template struct A<2>;
+
+template <int N>
+struct B {
+    void f() requires (N == 2) { static_assert(N == 3); } // { dg-error "assert" }
+};
+template struct B<2>;