From: Jason Merrill Date: Mon, 11 May 2020 19:46:59 +0000 (-0400) Subject: c++: Fix specialization of constrained member template. X-Git-Tag: misc/first-auto-changelog~330 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=52c5933f5838adb7bf6035e648b770b4958d137f;p=thirdparty%2Fgcc.git 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 Resolve C++20 NB comment CA104 * pt.c (determine_specialization): Compare constraints for specialization of member template of class instantiation. --- diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 5195a0a043f9..5cf9dda42e2c 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,9 @@ +2020-05-11 Jason Merrill + + 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 PR c++/92583 diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 86f1bb7470df..84864561c258 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -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. */ diff --git a/gcc/testsuite/g++.dg/cpp2a/concepts-spec1.C b/gcc/testsuite/g++.dg/cpp2a/concepts-spec1.C new file mode 100644 index 000000000000..5001813d7b71 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp2a/concepts-spec1.C @@ -0,0 +1,10 @@ +// Example from CA 104 proposal. +// { dg-do compile { target concepts } } + +template concept C = sizeof(T) == 8; +template struct A { + template U f(U) requires C; // #1 + template U f(U) requires C; // #2 +}; + +template <> template U A::f(U) requires C { } // OK, specializes #2 diff --git a/gcc/testsuite/g++.dg/template/nontype18.C b/gcc/testsuite/g++.dg/template/nontype18.C index cbe0a1b5a0d7..b68416dca618 100644 --- a/gcc/testsuite/g++.dg/template/nontype18.C +++ b/gcc/testsuite/g++.dg/template/nontype18.C @@ -5,4 +5,4 @@ template struct A template void foo(); }; -template template void A<0>::foo() {} // { dg-error "template parameter" } +template template void A<0>::foo() {} // { dg-error "" }