summaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authormmitchel <mmitchel@138bc75d-0d04-0410-961f-82ee72b054a4>2006-01-28 19:28:01 +0000
committermmitchel <mmitchel@138bc75d-0d04-0410-961f-82ee72b054a4>2006-01-28 19:28:01 +0000
commitd9db88e121564148b221a34fab10908b13f1b294 (patch)
treecf01e7e1711bb0a24daf243f5df6daba7b5aa587 /gcc
parente0464104c4927c8cd7cb2bf07f157762120df8e0 (diff)
downloadgcc-d9db88e121564148b221a34fab10908b13f1b294.tar.gz
PR c++/25855
* class.c (resolve_address_of_overloaded_function): Adjust use of return value from most_specialized_instantiation. * pt.c (determine_specialization): Avoid multiple calls to get_bindings. (most_specialized_instantiation): When a tie occurs, set the current presumed champion to the next template. Return the TREE_LIST node containing the template, rather than the template itself. (most_specialized): Remove. * name-lookup.c (push_overloaded_decl): When duplicate_decls indicates a failed redeclaration, report that to callers. PR c++/25855 * g++.dg/template/spec29.C: New test. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@110332 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc')
-rw-r--r--gcc/cp/ChangeLog15
-rw-r--r--gcc/cp/class.c4
-rw-r--r--gcc/cp/name-lookup.c8
-rw-r--r--gcc/cp/pt.c70
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/g++.dg/template/spec29.C13
6 files changed, 69 insertions, 46 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 741d3de0a0e..ad3be507d4e 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,18 @@
+2006-01-28 Mark Mitchell <mark@codesourcery.com>
+
+ PR c++/25855
+ * class.c (resolve_address_of_overloaded_function): Adjust use of
+ return value from most_specialized_instantiation.
+ * pt.c (determine_specialization): Avoid multiple calls to
+ get_bindings.
+ (most_specialized_instantiation): When a tie occurs, set the
+ current presumed champion to the next template. Return the
+ TREE_LIST node containing the template, rather than the template
+ itself.
+ (most_specialized): Remove.
+ * name-lookup.c (push_overloaded_decl): When duplicate_decls
+ indicates a failed redeclaration, report that to callers.
+
2006-01-26 Jason Merrill <jason@redhat.com>
PR c++/16021
diff --git a/gcc/cp/class.c b/gcc/cp/class.c
index bcbed7be4d2..b9abaa82ddc 100644
--- a/gcc/cp/class.c
+++ b/gcc/cp/class.c
@@ -5819,7 +5819,9 @@ resolve_address_of_overloaded_function (tree target_type,
tree match = most_specialized_instantiation (matches);
if (match != error_mark_node)
- matches = tree_cons (match, NULL_TREE, NULL_TREE);
+ matches = tree_cons (TREE_PURPOSE (match),
+ NULL_TREE,
+ NULL_TREE);
}
}
diff --git a/gcc/cp/name-lookup.c b/gcc/cp/name-lookup.c
index 2f33b096d4e..ed7dd5361c9 100644
--- a/gcc/cp/name-lookup.c
+++ b/gcc/cp/name-lookup.c
@@ -1892,6 +1892,7 @@ push_overloaded_decl (tree decl, int flags, bool is_friend)
for (tmp = old; tmp; tmp = OVL_NEXT (tmp))
{
tree fn = OVL_CURRENT (tmp);
+ tree dup;
if (TREE_CODE (tmp) == OVERLOAD && OVL_USED (tmp)
&& !(flags & PUSH_USING)
@@ -1901,8 +1902,11 @@ push_overloaded_decl (tree decl, int flags, bool is_friend)
error ("%q#D conflicts with previous using declaration %q#D",
decl, fn);
- if (duplicate_decls (decl, fn, is_friend) == fn)
- POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, fn);
+ dup = duplicate_decls (decl, fn, is_friend);
+ /* If DECL was a redeclaration of FN -- even an invalid
+ one -- pass that information along to our caller. */
+ if (dup == fn || dup == error_mark_node)
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, dup);
}
/* We don't overload implicit built-ins. duplicate_decls()
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index d3d8961cfd0..e02cca47dc0 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -135,7 +135,6 @@ static tree tsubst_template_arg (tree, tree, tsubst_flags_t, tree);
static tree tsubst_template_args (tree, tree, tsubst_flags_t, tree);
static tree tsubst_template_parms (tree, tree, tsubst_flags_t);
static void regenerate_decl_from_template (tree, tree);
-static tree most_specialized (tree, tree, tree);
static tree most_specialized_class (tree, tree);
static tree tsubst_aggr_type (tree, tree, tsubst_flags_t, tree, int);
static tree tsubst_arg_types (tree, tree, tsubst_flags_t, tree);
@@ -1343,6 +1342,11 @@ determine_specialization (tree template_id,
tree targs;
tree explicit_targs;
tree candidates = NULL_TREE;
+ /* A TREE_LIST of templates of which DECL may be a specialization.
+ The TREE_VALUE of each node is a TEMPLATE_DECL. The
+ corresponding TREE_PURPOSE is the set of template arguments that,
+ when used to instantiate the template, would produce a function
+ with the signature of DECL. */
tree templates = NULL_TREE;
int header_count;
struct cp_binding_level *b;
@@ -1547,12 +1551,12 @@ determine_specialization (tree template_id,
the EDG front-end has that behavior, and John Spicer claims
that the committee simply forgot to delete the wording in
[temp.expl.spec]. */
- tree tmpl = most_specialized (templates, decl, explicit_targs);
- if (tmpl && tmpl != error_mark_node)
- {
- targs = get_bindings (tmpl, decl, explicit_targs, /*check_ret=*/true);
- templates = tree_cons (targs, tmpl, NULL_TREE);
- }
+ tree tmpl = most_specialized_instantiation (templates);
+ if (tmpl != error_mark_node)
+ {
+ templates = tmpl;
+ TREE_CHAIN (templates) = NULL_TREE;
+ }
}
if (templates == NULL_TREE && candidates == NULL_TREE)
@@ -10826,25 +10830,26 @@ get_class_bindings (tree tparms, tree parms, tree args)
return vec;
}
-/* In INSTANTIATIONS is a list of <INSTANTIATION, TEMPLATE> pairs.
- Pick the most specialized template, and return the corresponding
- instantiation, or if there is no corresponding instantiation, the
- template itself. If there is no most specialized template,
- error_mark_node is returned. If there are no templates at all,
- NULL_TREE is returned. */
+/* TEMPLATES is a TREE_LIST. Each TREE_VALUE is a TEMPLATE_DECL.
+ Return the TREE_LIST node with the most specialized template, if
+ any. If there is no most specialized template, the error_mark_node
+ is returned.
+
+ Note that this function does not look at, or modify, the
+ TREE_PURPOSE or TREE_TYPE of any of the nodes. Since the node
+ returned is one of the elements of INSTANTIATIONS, callers may
+ store information in the TREE_PURPOSE or TREE_TYPE of the nodes,
+ and retrieve it from the value returned. */
tree
-most_specialized_instantiation (tree instantiations)
+most_specialized_instantiation (tree templates)
{
tree fn, champ;
- if (!instantiations)
- return NULL_TREE;
-
++processing_template_decl;
- champ = instantiations;
- for (fn = TREE_CHAIN (instantiations); fn; fn = TREE_CHAIN (fn))
+ champ = templates;
+ for (fn = TREE_CHAIN (templates); fn; fn = TREE_CHAIN (fn))
{
int fate = 0;
@@ -10865,6 +10870,7 @@ most_specialized_instantiation (tree instantiations)
/* Equally specialized, move to next function. If there
is no next function, nothing's most specialized. */
fn = TREE_CHAIN (fn);
+ champ = fn;
if (!fn)
break;
}
@@ -10873,7 +10879,7 @@ most_specialized_instantiation (tree instantiations)
if (champ)
/* Now verify that champ is better than everything earlier in the
instantiation list. */
- for (fn = instantiations; fn != champ; fn = TREE_CHAIN (fn))
+ for (fn = templates; fn != champ; fn = TREE_CHAIN (fn))
if (get_bindings (TREE_VALUE (champ),
DECL_TEMPLATE_RESULT (TREE_VALUE (fn)),
NULL_TREE, /*check_ret=*/false)
@@ -10890,29 +10896,7 @@ most_specialized_instantiation (tree instantiations)
if (!champ)
return error_mark_node;
- return TREE_PURPOSE (champ) ? TREE_PURPOSE (champ) : TREE_VALUE (champ);
-}
-
-/* Return the most specialized of the list of templates in FNS that can
- produce an instantiation matching DECL, given the explicit template
- arguments EXPLICIT_ARGS. */
-
-static tree
-most_specialized (tree fns, tree decl, tree explicit_args)
-{
- tree candidates = NULL_TREE;
- tree fn, args;
-
- for (fn = fns; fn; fn = TREE_CHAIN (fn))
- {
- tree candidate = TREE_VALUE (fn);
-
- args = get_bindings (candidate, decl, explicit_args, /*check_ret=*/true);
- if (args)
- candidates = tree_cons (NULL_TREE, candidate, candidates);
- }
-
- return most_specialized_instantiation (candidates);
+ return champ;
}
/* If DECL is a specialization of some template, return the most
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 2f2f8c67727..70b6deef740 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,8 @@
+2006-01-28 Mark Mitchell <mark@codesourcery.com>
+
+ PR c++/25855
+ * g++.dg/template/spec29.C: New test.
+
2006-01-28 Kazu Hirata <kazu@codesourcery.com>
PR c/19606.
diff --git a/gcc/testsuite/g++.dg/template/spec29.C b/gcc/testsuite/g++.dg/template/spec29.C
new file mode 100644
index 00000000000..4df00ee7d28
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/spec29.C
@@ -0,0 +1,13 @@
+// PR c++/25855
+// { dg-do run }
+
+template <typename T> int qCompare(const T *t1, const T *t2) { return 1; }
+template <typename T> int qCompare(T *t1, T *t2) { return 2; }
+template <typename T1, typename T2> int qCompare(const T1 *t1, const T2 *t2) {
+ return 3; }
+template<> int qCompare(const char *t1, const char *t2) { return 4; }
+int main()
+{
+ if (qCompare("a", "b") != 4)
+ return 1;
+}