From 29a1da1c303b0bca58faf0963ae250eb460c66ba Mon Sep 17 00:00:00 2001 From: Mark Mitchell Date: Tue, 23 May 2006 20:45:44 +0000 Subject: [PATCH] re PR c++/20173 (gcc accepts invalid partial specialization attempt of member function) PR c++/20173 * pt.c (determine_specialization): Disallow partial specializations of templates. PR c++/20173 * g++.dg/template/error21.C: New test. From-SVN: r114023 --- gcc/cp/ChangeLog | 6 +++++ gcc/cp/pt.c | 39 ++++++++++++++++++++++++++------- gcc/testsuite/ChangeLog | 5 +++++ gcc/testsuite/g++.dg/template/error21.C | 15 +++++++++++++ 4 files changed, 57 insertions(+), 8 deletions(-) create mode 100644 gcc/testsuite/g++.dg/template/error21.C diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 4cfa827..f6bcf57 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,9 @@ +2006-05-23 Mark Mitchell + + PR c++/20173 + * pt.c (determine_specialization): Disallow partial + specializations of templates. + 2006-05-22 Volker Reichelt PR c++/27716 diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 8db24ca..ca57676 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -150,7 +150,6 @@ static tree get_template_base (tree, tree, tree, tree); static tree try_class_unification (tree, tree, tree, tree); static int coerce_template_template_parms (tree, tree, tsubst_flags_t, tree, tree); -static tree determine_specialization (tree, tree, tree *, int, int); static int template_args_equal (tree, tree); static void tsubst_default_arguments (tree); static tree for_each_template_parm_r (tree *, int *, void *); @@ -1321,6 +1320,11 @@ print_candidates (tree fns) template classes that appeared in the name of the function. See check_explicit_specialization for a more accurate description. + TSK indicates what kind of template declaration (if any) is being + declared. TSK_TEMPLATE indicates that the declaration given by + DECL, though a FUNCTION_DECL, has template parameters, and is + therefore a template function. + The template args (those explicitly specified and those deduced) are output in a newly created vector *TARGS_OUT. @@ -1332,7 +1336,8 @@ determine_specialization (tree template_id, tree decl, tree* targs_out, int need_member_template, - int template_count) + int template_count, + tmpl_spec_kind tsk) { tree fns; tree targs; @@ -1450,6 +1455,18 @@ determine_specialization (tree template_id, (current_template_parms)))) continue; + /* Function templates cannot be specializations; there are + no partial specializations of functions. Therefore, if + the type of DECL does not match FN, there is no + match. */ + if (tsk == tsk_template) + { + if (compparms (TYPE_ARG_TYPES (TREE_TYPE (fn)), + decl_arg_types)) + candidates = tree_cons (NULL_TREE, fn, candidates); + continue; + } + /* See whether this function might be a specialization of this template. */ targs = get_bindings (fn, decl, explicit_targs, /*check_ret=*/true); @@ -1576,10 +1593,14 @@ determine_specialization (tree template_id, /* We have one, and exactly one, match. */ if (candidates) { + tree fn = TREE_VALUE (candidates); + /* DECL is a re-declaration of a template function. */ + if (TREE_CODE (fn) == TEMPLATE_DECL) + return fn; /* It was a specialization of an ordinary member function in a template class. */ - *targs_out = copy_node (DECL_TI_ARGS (TREE_VALUE (candidates))); - return DECL_TI_TEMPLATE (TREE_VALUE (candidates)); + *targs_out = copy_node (DECL_TI_ARGS (fn)); + return DECL_TI_TEMPLATE (fn); } /* It was a specialization of a template. */ @@ -2042,7 +2063,8 @@ check_explicit_specialization (tree declarator, tmpl = determine_specialization (declarator, decl, &targs, member_specialization, - template_count); + template_count, + tsk); if (!tmpl || tmpl == error_mark_node) /* We couldn't figure out what this declaration was @@ -2088,8 +2110,8 @@ check_explicit_specialization (tree declarator, revert_static_member_fn (decl); /* If this is a specialization of a member template of a - template class. In we want to return the TEMPLATE_DECL, - not the specialization of it. */ + template class, we want to return the TEMPLATE_DECL, not + the specialization of it. */ if (tsk == tsk_template) { SET_DECL_TEMPLATE_SPECIALIZATION (tmpl); @@ -5163,7 +5185,8 @@ tsubst_friend_function (tree decl, tree args) tmpl = determine_specialization (template_id, new_friend, &new_args, /*need_member_template=*/0, - TREE_VEC_LENGTH (args)); + TREE_VEC_LENGTH (args), + tsk_none); return instantiate_template (tmpl, new_args, tf_error); } diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index bb4451d..eea1b80 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2006-05-23 Mark Mitchell + + PR c++/20173 + * g++.dg/template/error21.C: New test. + 2006-05-23 Kazu Hirata PR target/27696 diff --git a/gcc/testsuite/g++.dg/template/error21.C b/gcc/testsuite/g++.dg/template/error21.C new file mode 100644 index 0000000..c5f04f0 --- /dev/null +++ b/gcc/testsuite/g++.dg/template/error21.C @@ -0,0 +1,15 @@ +// PR c++/20173 + +template +struct A{ + template + void function(T){} +}; + +template<> +template +void A::function(T){} + +template<> +template +void A::function(T*){} // { dg-error "match" } -- 2.7.4