Message ID | 20200713211918.3713282-1-ppalka@redhat.com |
---|---|
State | New |
Headers | show |
Series | c++: constraints and explicit instantiation [PR96164] | expand |
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 --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>;