From: Patrick Palka Date: Thu, 30 Jul 2020 02:06:33 +0000 (-0400) Subject: c++: constraints and explicit instantiation [PR96164] X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=dc3d1e181445fafbbd146eb355a750c41c338794;p=gcc.git c++: constraints and explicit instantiation [PR96164] 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. gcc/cp/ChangeLog: PR c++/96164 * constraint.cc (constraints_satisfied_p): Return true if !flags_concepts. * 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. --- diff --git a/gcc/cp/constraint.cc b/gcc/cp/constraint.cc index d0da2300ba9..e4aace596e7 100644 --- a/gcc/cp/constraint.cc +++ b/gcc/cp/constraint.cc @@ -2864,6 +2864,9 @@ constraint_satisfaction_value (tree t, tree args, tsubst_flags_t complain) bool constraints_satisfied_p (tree t) { + if (!flag_concepts) + return true; + return constraint_satisfaction_value (t, tf_none) == boolean_true_node; } @@ -2873,6 +2876,9 @@ constraints_satisfied_p (tree t) bool constraints_satisfied_p (tree t, tree args) { + if (!flag_concepts) + return true; + return constraint_satisfaction_value (t, args, tf_none) == boolean_true_node; } diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 6a42cf93dcc..9b4e6ce7d89 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -24928,23 +24928,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) + && 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 +struct A { + void f() requires (N == 3) { static_assert(N == 3); } +}; +template struct A<2>; + +template +struct B { + void f() requires (N == 2) { static_assert(N == 3); } // { dg-error "assert" } +}; +template struct B<2>;