Commit 7ca383e6 by Mark Mitchell Committed by Mark Mitchell

re PR c++/25855 (template specialisation not always found (partial ordering))

	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.

From-SVN: r110332
parent e94aab95
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> 2006-01-26 Jason Merrill <jason@redhat.com>
PR c++/16021 PR c++/16021
......
...@@ -5819,7 +5819,9 @@ resolve_address_of_overloaded_function (tree target_type, ...@@ -5819,7 +5819,9 @@ resolve_address_of_overloaded_function (tree target_type,
tree match = most_specialized_instantiation (matches); tree match = most_specialized_instantiation (matches);
if (match != error_mark_node) if (match != error_mark_node)
matches = tree_cons (match, NULL_TREE, NULL_TREE); matches = tree_cons (TREE_PURPOSE (match),
NULL_TREE,
NULL_TREE);
} }
} }
......
...@@ -1892,6 +1892,7 @@ push_overloaded_decl (tree decl, int flags, bool is_friend) ...@@ -1892,6 +1892,7 @@ push_overloaded_decl (tree decl, int flags, bool is_friend)
for (tmp = old; tmp; tmp = OVL_NEXT (tmp)) for (tmp = old; tmp; tmp = OVL_NEXT (tmp))
{ {
tree fn = OVL_CURRENT (tmp); tree fn = OVL_CURRENT (tmp);
tree dup;
if (TREE_CODE (tmp) == OVERLOAD && OVL_USED (tmp) if (TREE_CODE (tmp) == OVERLOAD && OVL_USED (tmp)
&& !(flags & PUSH_USING) && !(flags & PUSH_USING)
...@@ -1901,8 +1902,11 @@ push_overloaded_decl (tree decl, int flags, bool is_friend) ...@@ -1901,8 +1902,11 @@ push_overloaded_decl (tree decl, int flags, bool is_friend)
error ("%q#D conflicts with previous using declaration %q#D", error ("%q#D conflicts with previous using declaration %q#D",
decl, fn); decl, fn);
if (duplicate_decls (decl, fn, is_friend) == fn) dup = duplicate_decls (decl, fn, is_friend);
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, fn); /* 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() /* We don't overload implicit built-ins. duplicate_decls()
......
...@@ -135,7 +135,6 @@ static tree tsubst_template_arg (tree, tree, tsubst_flags_t, tree); ...@@ -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_args (tree, tree, tsubst_flags_t, tree);
static tree tsubst_template_parms (tree, tree, tsubst_flags_t); static tree tsubst_template_parms (tree, tree, tsubst_flags_t);
static void regenerate_decl_from_template (tree, tree); static void regenerate_decl_from_template (tree, tree);
static tree most_specialized (tree, tree, tree);
static tree most_specialized_class (tree, tree); static tree most_specialized_class (tree, tree);
static tree tsubst_aggr_type (tree, tree, tsubst_flags_t, tree, int); static tree tsubst_aggr_type (tree, tree, tsubst_flags_t, tree, int);
static tree tsubst_arg_types (tree, tree, tsubst_flags_t, tree); static tree tsubst_arg_types (tree, tree, tsubst_flags_t, tree);
...@@ -1343,6 +1342,11 @@ determine_specialization (tree template_id, ...@@ -1343,6 +1342,11 @@ determine_specialization (tree template_id,
tree targs; tree targs;
tree explicit_targs; tree explicit_targs;
tree candidates = NULL_TREE; 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; tree templates = NULL_TREE;
int header_count; int header_count;
struct cp_binding_level *b; struct cp_binding_level *b;
...@@ -1547,12 +1551,12 @@ determine_specialization (tree template_id, ...@@ -1547,12 +1551,12 @@ determine_specialization (tree template_id,
the EDG front-end has that behavior, and John Spicer claims the EDG front-end has that behavior, and John Spicer claims
that the committee simply forgot to delete the wording in that the committee simply forgot to delete the wording in
[temp.expl.spec]. */ [temp.expl.spec]. */
tree tmpl = most_specialized (templates, decl, explicit_targs); tree tmpl = most_specialized_instantiation (templates);
if (tmpl && tmpl != error_mark_node) if (tmpl != error_mark_node)
{ {
targs = get_bindings (tmpl, decl, explicit_targs, /*check_ret=*/true); templates = tmpl;
templates = tree_cons (targs, tmpl, NULL_TREE); TREE_CHAIN (templates) = NULL_TREE;
} }
} }
if (templates == NULL_TREE && candidates == NULL_TREE) if (templates == NULL_TREE && candidates == NULL_TREE)
...@@ -10826,25 +10830,26 @@ get_class_bindings (tree tparms, tree parms, tree args) ...@@ -10826,25 +10830,26 @@ get_class_bindings (tree tparms, tree parms, tree args)
return vec; return vec;
} }
/* In INSTANTIATIONS is a list of <INSTANTIATION, TEMPLATE> pairs. /* TEMPLATES is a TREE_LIST. Each TREE_VALUE is a TEMPLATE_DECL.
Pick the most specialized template, and return the corresponding Return the TREE_LIST node with the most specialized template, if
instantiation, or if there is no corresponding instantiation, the any. If there is no most specialized template, the error_mark_node
template itself. If there is no most specialized template, is returned.
error_mark_node is returned. If there are no templates at all,
NULL_TREE 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 tree
most_specialized_instantiation (tree instantiations) most_specialized_instantiation (tree templates)
{ {
tree fn, champ; tree fn, champ;
if (!instantiations)
return NULL_TREE;
++processing_template_decl; ++processing_template_decl;
champ = instantiations; champ = templates;
for (fn = TREE_CHAIN (instantiations); fn; fn = TREE_CHAIN (fn)) for (fn = TREE_CHAIN (templates); fn; fn = TREE_CHAIN (fn))
{ {
int fate = 0; int fate = 0;
...@@ -10865,6 +10870,7 @@ most_specialized_instantiation (tree instantiations) ...@@ -10865,6 +10870,7 @@ most_specialized_instantiation (tree instantiations)
/* Equally specialized, move to next function. If there /* Equally specialized, move to next function. If there
is no next function, nothing's most specialized. */ is no next function, nothing's most specialized. */
fn = TREE_CHAIN (fn); fn = TREE_CHAIN (fn);
champ = fn;
if (!fn) if (!fn)
break; break;
} }
...@@ -10873,7 +10879,7 @@ most_specialized_instantiation (tree instantiations) ...@@ -10873,7 +10879,7 @@ most_specialized_instantiation (tree instantiations)
if (champ) if (champ)
/* Now verify that champ is better than everything earlier in the /* Now verify that champ is better than everything earlier in the
instantiation list. */ 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), if (get_bindings (TREE_VALUE (champ),
DECL_TEMPLATE_RESULT (TREE_VALUE (fn)), DECL_TEMPLATE_RESULT (TREE_VALUE (fn)),
NULL_TREE, /*check_ret=*/false) NULL_TREE, /*check_ret=*/false)
...@@ -10890,29 +10896,7 @@ most_specialized_instantiation (tree instantiations) ...@@ -10890,29 +10896,7 @@ most_specialized_instantiation (tree instantiations)
if (!champ) if (!champ)
return error_mark_node; return error_mark_node;
return TREE_PURPOSE (champ) ? TREE_PURPOSE (champ) : TREE_VALUE (champ); return 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);
} }
/* If DECL is a specialization of some template, return the most /* If DECL is a specialization of some template, return the most
......
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> 2006-01-28 Kazu Hirata <kazu@codesourcery.com>
PR c/19606. PR c/19606.
// 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;
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment