diff options
author | Jason Merrill <jason@redhat.com> | 2020-05-11 15:46:59 -0400 |
---|---|---|
committer | Jason Merrill <jason@redhat.com> | 2020-05-11 16:19:53 -0400 |
commit | 52c5933f5838adb7bf6035e648b770b4958d137f (patch) | |
tree | 18c8454e7f9ca88cfe88f2eb42b7658ff1d0312c | |
parent | 0f50f6daa140186a048cbf33f54f4591eabf5f12 (diff) |
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.
-rw-r--r-- | gcc/cp/ChangeLog | 6 | ||||
-rw-r--r-- | gcc/cp/pt.c | 28 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/cpp2a/concepts-spec1.C | 10 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/template/nontype18.C | 2 |
4 files changed, 42 insertions, 4 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 5195a0a043f..5cf9dda42e2 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,5 +1,11 @@ 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 PR c++/92654 * tree.c (cp_walk_subtrees): Stop at typedefs. diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 86f1bb7470d..84864561c25 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 00000000000..5001813d7b7 --- /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 <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 diff --git a/gcc/testsuite/g++.dg/template/nontype18.C b/gcc/testsuite/g++.dg/template/nontype18.C index cbe0a1b5a0d..b68416dca61 100644 --- a/gcc/testsuite/g++.dg/template/nontype18.C +++ b/gcc/testsuite/g++.dg/template/nontype18.C @@ -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 "" } |