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:
parent
bea7a39103
commit
dc3d1e1814
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
23
gcc/cp/pt.c
23
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)
|
||||
|
|
|
@ -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>;
|
Loading…
Reference in New Issue