aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorGiovanni Bajo <giovannibajo@gcc.gnu.org>2004-07-21 00:06:45 +0000
committerGiovanni Bajo <giovannibajo@gcc.gnu.org>2004-07-21 00:06:45 +0000
commit5fe7b6549e1d588e3b0ae4015d61080bac3dbf37 (patch)
tree1312c53d8cf381419e2804cabd75d2dfe5541a6a /gcc
parent66e4969bb93f7012d6cc11131132424ea336cd4e (diff)
downloadgcc-5fe7b6549e1d588e3b0ae4015d61080bac3dbf37.zip
gcc-5fe7b6549e1d588e3b0ae4015d61080bac3dbf37.tar.gz
gcc-5fe7b6549e1d588e3b0ae4015d61080bac3dbf37.tar.bz2
re PR c++/509 (G++ forbids template specialization as ambiguous)
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. From-SVN: r84982
Diffstat (limited to 'gcc')
-rw-r--r--gcc/cp/ChangeLog9
-rw-r--r--gcc/cp/pt.c54
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/g++.dg/template/spec15.C34
4 files changed, 98 insertions, 4 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 3038907..5883b7e 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 86f945e..3971b6d 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;
}
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 39601de..b939e33 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,8 @@
+2004-07-21 Giovanni Bajo <giovannibajo@gcc.gnu.org>
+
+ PR c++/509
+ * g++.dg/template/spec15.C: New test.
+
2004-07-21 David Billinghurst (David.Billinghurst@riotinto.com)
Copy cases from g77.f-torture/execute and add dg-run
diff --git a/gcc/testsuite/g++.dg/template/spec15.C b/gcc/testsuite/g++.dg/template/spec15.C
new file mode 100644
index 0000000..fcf4ecb
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/spec15.C
@@ -0,0 +1,34 @@
+// { dg-do compile }
+// Contributed by Wolfgang Bangerth <bangerth at ticam dot utexas dot edu>
+// PR c++/509: Make sure specializations of member templates match correctly
+// between template and non-template overloads.
+
+template <class T>
+struct A {
+ template <class U> void f (U);
+ void f2 (int);
+
+ template <class U> void h (U);
+ void h (long);
+};
+
+template <>
+struct A<float> {
+ template <class U> void g (U);
+ void g2 (float);
+};
+
+template <> void A<int>::f (int); // { dg-error "" }
+template <> template <> void A<int>::f (int);
+
+template <> void A<int>::f2 (int);
+template <> template <> void A<int>::f2 (int); // { dg-error "" }
+
+template <> void A<float>::g (float);
+template <> template <> void A<float>::g(float); // { dg-error "" }
+
+template <> void A<float>::g2 (float); // { dg-error "" }
+template <> template <> void A<float>::g2(float); // { dg-error "" }
+
+template <> void A<long>::h (long);
+template <> template <> void A<long>::h(long);