c++: Fix specialization of constrained member template.

The resolution of comment CA104 clarifies that we need to do direct
substitution of constraints in order to determine which member template
corresponds to an explicit specialization.

gcc/cp/ChangeLog
2020-05-11  Jason Merrill  <jason@redhat.com>

	Resolve C++20 NB comment CA104
	* pt.c (determine_specialization): Compare constraints for
	specialization of member template of class instantiation.
This commit is contained in:
Jason Merrill 2020-05-11 15:46:59 -04:00
parent 0f50f6daa1
commit 52c5933f58
4 changed files with 42 additions and 4 deletions

View File

@ -1,3 +1,9 @@
2020-05-11 Jason Merrill <jason@redhat.com>
Resolve C++20 NB comment CA104
* pt.c (determine_specialization): Compare constraints for
specialization of member template of class instantiation.
2020-05-11 Jason Merrill <jason@redhat.com>
PR c++/92583

View File

@ -2282,8 +2282,29 @@ determine_specialization (tree template_id,
below. */
if (tsk == tsk_template)
{
if (compparms (fn_arg_types, decl_arg_types))
candidates = tree_cons (NULL_TREE, fn, candidates);
if (!comp_template_parms (DECL_TEMPLATE_PARMS (fn),
current_template_parms))
continue;
if (!same_type_p (TREE_TYPE (TREE_TYPE (decl)),
TREE_TYPE (TREE_TYPE (fn))))
continue;
if (!compparms (fn_arg_types, decl_arg_types))
continue;
tree freq = get_trailing_function_requirements (fn);
tree dreq = get_trailing_function_requirements (decl);
if (!freq != !dreq)
continue;
if (freq)
{
tree fargs = DECL_TI_ARGS (fn);
tsubst_flags_t complain = tf_none;
freq = tsubst_constraint (freq, fargs, complain, fn);
if (!cp_tree_equal (freq, dreq))
continue;
}
candidates = tree_cons (NULL_TREE, fn, candidates);
continue;
}
@ -2472,7 +2493,8 @@ determine_specialization (tree template_id,
*targs_out = copy_node (DECL_TI_ARGS (fn));
/* Propagate the candidate's constraints to the declaration. */
set_constraints (decl, get_constraints (fn));
if (tsk != tsk_template)
set_constraints (decl, get_constraints (fn));
/* DECL is a re-declaration or partial instantiation of a template
function. */

View File

@ -0,0 +1,10 @@
// Example from CA 104 proposal.
// { dg-do compile { target concepts } }
template <class T> concept C = sizeof(T) == 8;
template <class T> struct A {
template <class U> U f(U) requires C<typename T::type>; // #1
template <class U> U f(U) requires C<T>; // #2
};
template <> template <class U> U A<int>::f(U) requires C<int> { } // OK, specializes #2

View File

@ -5,4 +5,4 @@ template<int I> struct A
template<typename T> void foo();
};
template<int I> template<typename T> void A<0>::foo() {} // { dg-error "template parameter" }
template<int I> template<typename T> void A<0>::foo() {} // { dg-error "" }