diff options
author | giovannibajo <giovannibajo@138bc75d-0d04-0410-961f-82ee72b054a4> | 2004-07-21 00:06:45 +0000 |
---|---|---|
committer | giovannibajo <giovannibajo@138bc75d-0d04-0410-961f-82ee72b054a4> | 2004-07-21 00:06:45 +0000 |
commit | 05a677c71ece39cae12ce541570b6cd3ffab0a5c (patch) | |
tree | 1312c53d8cf381419e2804cabd75d2dfe5541a6a /gcc/cp | |
parent | d6f7df3a44d2d1a43b2128558157e26b8282d835 (diff) | |
download | gcc-05a677c71ece39cae12ce541570b6cd3ffab0a5c.tar.gz |
PR c++/509
* pt.c (determine_specialization): New parameter template_count.
Disambiguate between member templates and member functions counting
the template headers.
(check_explicit_specialization): Update caller.
(tsubst_friend_function): Likewise.
PR c++/509
* g++.dg/template/spec15.C: New test.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@84982 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/cp')
-rw-r--r-- | gcc/cp/ChangeLog | 9 | ||||
-rw-r--r-- | gcc/cp/pt.c | 54 |
2 files changed, 59 insertions, 4 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 3038907545c..5883b7e26de 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,12 @@ +2004-07-21 Giovanni Bajo <giovannibajo@gcc.gnu.org> + + PR c++/509 + * pt.c (determine_specialization): New parameter template_count. + Disambiguate between member templates and member functions counting + the template headers. + (check_explicit_specialization): Update caller. + (tsubst_friend_function): Likewise. + 2004-07-20 Steven Bosscher <stevenb@suse.de> * cp-tree.def (TINST_LEVEL): Make it an 'x' node. diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 86f945e7f8f..3971b6d37d2 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -155,7 +155,7 @@ static int verify_class_unification (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); +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 *); @@ -1205,6 +1205,10 @@ print_candidates (tree fns) If NEED_MEMBER_TEMPLATE is nonzero the function is known to be a specialization of a member template. + The TEMPLATE_COUNT is the number of references to qualifying + template classes that appeared in the name of the function. See + check_explicit_specialization for a more accurate description. + The template args (those explicitly specified and those deduced) are output in a newly created vector *TARGS_OUT. @@ -1215,13 +1219,16 @@ static tree determine_specialization (tree template_id, tree decl, tree* targs_out, - int need_member_template) + int need_member_template, + int template_count) { tree fns; tree targs; tree explicit_targs; tree candidates = NULL_TREE; tree templates = NULL_TREE; + int header_count; + struct cp_binding_level *b; *targs_out = NULL_TREE; @@ -1244,6 +1251,14 @@ determine_specialization (tree template_id, return error_mark_node; } + /* Count the number of template headers specified for this + specialization. */ + header_count = 0; + for (b = current_binding_level; + b->kind == sk_template_parms || b->kind == sk_template_spec; + b = b->level_chain) + ++header_count; + for (; fns; fns = OVL_NEXT (fns)) { tree fn = OVL_CURRENT (fns); @@ -1280,6 +1295,35 @@ determine_specialization (tree template_id, TREE_VALUE (decl_arg_types))) continue; + /* In case of explicit specialization, we need to check if + the number of template headers appearing in the specialization + is correct. This is usually done in check_explicit_specialization, + but the check done there cannot be exhaustive when specializing + member functions. Consider the following code: + + template <> void A<int>::f(int); + template <> template <> void A<int>::f(int); + + Assuming that A<int> is not itself an explicit specialization + already, the first line specializes "f" which is a non-template + member function, whilst the second line specializes "f" which + is a template member function. So both lines are syntactically + correct, and check_explicit_specialization does not reject + them. + + Here, we can do better, as we are matching the specialization + against the declarations. We count the number of template + headers, and we check if they match TEMPLATE_COUNT + 1 + (TEMPLATE_COUNT is the number of qualifying template classes, + plus there must be another header for the member template + itself). + + Notice that if header_count is zero, this is not a + specialization but rather a template instantiation, so there + is no check we can perform here. */ + if (header_count && header_count != template_count + 1) + continue; + /* See whether this function might be a specialization of this template. */ targs = get_bindings (fn, decl, explicit_targs); @@ -1872,7 +1916,8 @@ check_explicit_specialization (tree declarator, declaration. */ tmpl = determine_specialization (declarator, decl, &targs, - member_specialization); + member_specialization, + template_count); if (!tmpl || tmpl == error_mark_node) /* We couldn't figure out what this declaration was @@ -4980,7 +5025,8 @@ tsubst_friend_function (tree decl, tree args) new_friend = tsubst (decl, args, tf_error | tf_warning, NULL_TREE); tmpl = determine_specialization (template_id, new_friend, &new_args, - /*need_member_template=*/0); + /*need_member_template=*/0, + TREE_VEC_LENGTH (args)); new_friend = instantiate_template (tmpl, new_args, tf_error); goto done; } |