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.
This commit is contained in:
Patrick Palka 2020-07-29 22:06:33 -04:00
parent bea7a39103
commit dc3d1e1814
3 changed files with 31 additions and 12 deletions

View File

@ -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;
}

View File

@ -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)

View File

@ -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>;