Commit e5214479 by Jason Merrill Committed by Jason Merrill

In partial ordering for a call, ignore parms for which we don't have a real argument.

        In partial ordering for a call, ignore parms for which we don't have
        a real argument.
        * call.c (joust): Pass len to more_specialized.
        (add_template_candidate_real): Strip 'this', pass len.
        * pt.c (more_specialized): Pass len down.  Lose explicit_args parm.
        (get_bindings_order): New fn.  Pass len down.
        (get_bindings_real): Strip 'this', pass len.
        (fn_type_unification): Likewise.
        (type_unification_real): Succeed after checking 'len' args.
        (most_specialized_instantiation): Lose explicit_args parm.
        * class.c (resolve_address_of_overloaded_function): Strip 'this',
        pass len.

From-SVN: r38460
parent 83ab3907
2000-12-20 Jason Merrill <jason@redhat.com> 2000-12-22 Jason Merrill <jason@redhat.com>
In partial ordering for a call, ignore parms for which we don't have
a real argument.
* call.c (joust): Pass len to more_specialized.
(add_template_candidate_real): Strip 'this', pass len.
* pt.c (more_specialized): Pass len down. Lose explicit_args parm.
(get_bindings_order): New fn. Pass len down.
(get_bindings_real): Strip 'this', pass len.
(fn_type_unification): Likewise.
(type_unification_real): Succeed after checking 'len' args.
(most_specialized_instantiation): Lose explicit_args parm.
* class.c (resolve_address_of_overloaded_function): Strip 'this',
pass len.
2000-12-21 Jason Merrill <jason@redhat.com>
* pt.c (tsubst_decl): A FUNCTION_DECL has DECL_RESULT, not * pt.c (tsubst_decl): A FUNCTION_DECL has DECL_RESULT, not
DECL_TEMPLATE_RESULT. DECL_TEMPLATE_RESULT.
......
...@@ -2147,26 +2147,24 @@ add_template_candidate_real (candidates, tmpl, ctype, explicit_targs, ...@@ -2147,26 +2147,24 @@ add_template_candidate_real (candidates, tmpl, ctype, explicit_targs,
{ {
int ntparms = DECL_NTPARMS (tmpl); int ntparms = DECL_NTPARMS (tmpl);
tree targs = make_tree_vec (ntparms); tree targs = make_tree_vec (ntparms);
tree args_without_in_chrg; tree args_without_in_chrg = arglist;
struct z_candidate *cand; struct z_candidate *cand;
int i; int i;
tree fn; tree fn;
/* TEMPLATE_DECLs do not have the in-charge parameter, nor the VTT /* We don't do deduction on the in-charge parameter, the VTT
parameter. So, skip it here before attempting to perform parameter or 'this'. */
argument deduction. */ if (DECL_NONSTATIC_MEMBER_FUNCTION_P (tmpl))
args_without_in_chrg = TREE_CHAIN (args_without_in_chrg);
if ((DECL_MAYBE_IN_CHARGE_CONSTRUCTOR_P (tmpl) if ((DECL_MAYBE_IN_CHARGE_CONSTRUCTOR_P (tmpl)
|| DECL_BASE_CONSTRUCTOR_P (tmpl)) || DECL_BASE_CONSTRUCTOR_P (tmpl))
&& TYPE_USES_VIRTUAL_BASECLASSES (DECL_CONTEXT (tmpl))) && TYPE_USES_VIRTUAL_BASECLASSES (DECL_CONTEXT (tmpl)))
args_without_in_chrg = tree_cons (NULL_TREE, args_without_in_chrg = TREE_CHAIN (args_without_in_chrg);
TREE_VALUE (arglist),
TREE_CHAIN (TREE_CHAIN (arglist)));
else
args_without_in_chrg = arglist;
i = fn_type_unification (tmpl, explicit_targs, targs, i = fn_type_unification (tmpl, explicit_targs, targs,
args_without_in_chrg, args_without_in_chrg,
return_type, strict); return_type, strict, -1);
if (i != 0) if (i != 0)
return candidates; return candidates;
...@@ -5156,7 +5154,8 @@ joust (cand1, cand2, warn) ...@@ -5156,7 +5154,8 @@ joust (cand1, cand2, warn)
else if (cand1->template && cand2->template) else if (cand1->template && cand2->template)
winner = more_specialized winner = more_specialized
(TI_TEMPLATE (cand1->template), TI_TEMPLATE (cand2->template), (TI_TEMPLATE (cand1->template), TI_TEMPLATE (cand2->template),
NULL_TREE); /* Never do unification on the 'this' parameter. */
TREE_VEC_LENGTH (cand1->convs) - !DECL_STATIC_FUNCTION_P (cand1->fn));
/* or, if not that, /* or, if not that,
the context is an initialization by user-defined conversion (see the context is an initialization by user-defined conversion (see
......
...@@ -5953,6 +5953,10 @@ resolve_address_of_overloaded_function (target_type, ...@@ -5953,6 +5953,10 @@ resolve_address_of_overloaded_function (target_type,
target_fn_type = TREE_TYPE (target_type); target_fn_type = TREE_TYPE (target_type);
target_arg_types = TYPE_ARG_TYPES (target_fn_type); target_arg_types = TYPE_ARG_TYPES (target_fn_type);
target_ret_type = TREE_TYPE (target_fn_type); target_ret_type = TREE_TYPE (target_fn_type);
/* Never do unification on the 'this' parameter. */
if (TREE_CODE (target_fn_type) == METHOD_TYPE)
target_arg_types = TREE_CHAIN (target_arg_types);
for (fns = overload; fns; fns = OVL_CHAIN (fns)) for (fns = overload; fns; fns = OVL_CHAIN (fns))
{ {
...@@ -5975,7 +5979,7 @@ resolve_address_of_overloaded_function (target_type, ...@@ -5975,7 +5979,7 @@ resolve_address_of_overloaded_function (target_type,
targs = make_tree_vec (DECL_NTPARMS (fn)); targs = make_tree_vec (DECL_NTPARMS (fn));
if (fn_type_unification (fn, explicit_targs, targs, if (fn_type_unification (fn, explicit_targs, targs,
target_arg_types, target_ret_type, target_arg_types, target_ret_type,
DEDUCE_EXACT) != 0) DEDUCE_EXACT, -1) != 0)
/* Argument deduction failed. */ /* Argument deduction failed. */
continue; continue;
...@@ -5999,8 +6003,7 @@ resolve_address_of_overloaded_function (target_type, ...@@ -5999,8 +6003,7 @@ resolve_address_of_overloaded_function (target_type,
/* Now, remove all but the most specialized of the matches. */ /* Now, remove all but the most specialized of the matches. */
if (matches) if (matches)
{ {
tree match = most_specialized_instantiation (matches, tree match = most_specialized_instantiation (matches);
explicit_targs);
if (match != error_mark_node) if (match != error_mark_node)
matches = tree_cons (match, NULL_TREE, NULL_TREE); matches = tree_cons (match, NULL_TREE, NULL_TREE);
......
...@@ -113,13 +113,14 @@ static tree add_outermost_template_args PARAMS ((tree, tree)); ...@@ -113,13 +113,14 @@ static tree add_outermost_template_args PARAMS ((tree, tree));
static void maybe_adjust_types_for_deduction PARAMS ((unification_kind_t, tree*, static void maybe_adjust_types_for_deduction PARAMS ((unification_kind_t, tree*,
tree*)); tree*));
static int type_unification_real PARAMS ((tree, tree, tree, tree, static int type_unification_real PARAMS ((tree, tree, tree, tree,
int, unification_kind_t, int)); int, unification_kind_t, int, int));
static void note_template_header PARAMS ((int)); static void note_template_header PARAMS ((int));
static tree maybe_fold_nontype_arg PARAMS ((tree)); static tree maybe_fold_nontype_arg PARAMS ((tree));
static tree convert_nontype_argument PARAMS ((tree, tree)); static tree convert_nontype_argument PARAMS ((tree, tree));
static tree convert_template_argument PARAMS ((tree, tree, tree, int, static tree convert_template_argument PARAMS ((tree, tree, tree, int,
int , tree)); int , tree));
static tree get_bindings_overload PARAMS ((tree, tree, tree)); static tree get_bindings_overload PARAMS ((tree, tree, tree));
static tree get_bindings_order PARAMS ((tree, tree, int));
static int for_each_template_parm PARAMS ((tree, tree_fn_t, void*)); static int for_each_template_parm PARAMS ((tree, tree_fn_t, void*));
static tree build_template_parm_index PARAMS ((int, int, int, tree, tree)); static tree build_template_parm_index PARAMS ((int, int, int, tree, tree));
static int inline_needs_template_parms PARAMS ((tree)); static int inline_needs_template_parms PARAMS ((tree));
...@@ -134,7 +135,7 @@ static tree build_template_decl PARAMS ((tree, tree)); ...@@ -134,7 +135,7 @@ static tree build_template_decl PARAMS ((tree, tree));
static int mark_template_parm PARAMS ((tree, void *)); static int mark_template_parm PARAMS ((tree, void *));
static tree tsubst_friend_function PARAMS ((tree, tree)); static tree tsubst_friend_function PARAMS ((tree, tree));
static tree tsubst_friend_class PARAMS ((tree, tree)); static tree tsubst_friend_class PARAMS ((tree, tree));
static tree get_bindings_real PARAMS ((tree, tree, tree, int)); static tree get_bindings_real PARAMS ((tree, tree, tree, int, int));
static int template_decl_level PARAMS ((tree)); static int template_decl_level PARAMS ((tree));
static tree maybe_get_template_decl_from_type_decl PARAMS ((tree)); static tree maybe_get_template_decl_from_type_decl PARAMS ((tree));
static int check_cv_quals_for_unify PARAMS ((int, tree, tree)); static int check_cv_quals_for_unify PARAMS ((int, tree, tree));
...@@ -7572,10 +7573,8 @@ overload_template_name (type) ...@@ -7572,10 +7573,8 @@ overload_template_name (type)
all the types, and 1 for complete failure. An error message will be all the types, and 1 for complete failure. An error message will be
printed only for an incomplete match. printed only for an incomplete match.
If FN is a conversion operator, RETURN_TYPE is the type desired as If FN is a conversion operator, or we are trying to produce a specific
the result of the conversion operator. specialization, RETURN_TYPE is the return type desired.
TPARMS is a vector of template parameters.
The EXPLICIT_TARGS are explicit template arguments provided via a The EXPLICIT_TARGS are explicit template arguments provided via a
template-id. template-id.
...@@ -7599,13 +7598,18 @@ overload_template_name (type) ...@@ -7599,13 +7598,18 @@ overload_template_name (type)
[temp.expl.spec], or when taking the address of a function [temp.expl.spec], or when taking the address of a function
template, as in [temp.deduct.funcaddr]. template, as in [temp.deduct.funcaddr].
The other arguments are as for type_unification. */ LEN is the number of parms to consider before returning success, or -1
for all. This is used in partial ordering to avoid comparing parms for
which no actual argument was passed, since they are not considered in
overload resolution (and are explicitly excluded from consideration in
partial ordering in [temp.func.order]/6). */
int int
fn_type_unification (fn, explicit_targs, targs, args, return_type, fn_type_unification (fn, explicit_targs, targs, args, return_type,
strict) strict, len)
tree fn, explicit_targs, targs, args, return_type; tree fn, explicit_targs, targs, args, return_type;
unification_kind_t strict; unification_kind_t strict;
int len;
{ {
tree parms; tree parms;
tree fntype; tree fntype;
...@@ -7653,15 +7657,9 @@ fn_type_unification (fn, explicit_targs, targs, args, return_type, ...@@ -7653,15 +7657,9 @@ fn_type_unification (fn, explicit_targs, targs, args, return_type,
} }
parms = TYPE_ARG_TYPES (fntype); parms = TYPE_ARG_TYPES (fntype);
/* Never do unification on the 'this' parameter. */
if (DECL_CONV_FN_P (fn)) if (DECL_NONSTATIC_MEMBER_FUNCTION_P (fn))
{ parms = TREE_CHAIN (parms);
/* This is a template conversion operator. Remove `this', since
we could be comparing conversions from different classes. */
parms = TREE_CHAIN (parms);
args = TREE_CHAIN (args);
my_friendly_assert (return_type != NULL_TREE, 20000227);
}
if (return_type) if (return_type)
{ {
...@@ -7676,7 +7674,7 @@ fn_type_unification (fn, explicit_targs, targs, args, return_type, ...@@ -7676,7 +7674,7 @@ fn_type_unification (fn, explicit_targs, targs, args, return_type,
event. */ event. */
result = type_unification_real (DECL_INNERMOST_TEMPLATE_PARMS (fn), result = type_unification_real (DECL_INNERMOST_TEMPLATE_PARMS (fn),
targs, parms, args, /*subr=*/0, targs, parms, args, /*subr=*/0,
strict, /*allow_incomplete*/1); strict, /*allow_incomplete*/1, len);
if (result == 0) if (result == 0)
/* All is well so far. Now, check: /* All is well so far. Now, check:
...@@ -7769,7 +7767,7 @@ maybe_adjust_types_for_deduction (strict, parm, arg) ...@@ -7769,7 +7767,7 @@ maybe_adjust_types_for_deduction (strict, parm, arg)
*parm = TREE_TYPE (*parm); *parm = TREE_TYPE (*parm);
} }
/* Like type_unification. /* Most parms like fn_type_unification.
If SUBR is 1, we're being called recursively (to unify the If SUBR is 1, we're being called recursively (to unify the
arguments of a function or method parameter of a function arguments of a function or method parameter of a function
...@@ -7777,11 +7775,11 @@ maybe_adjust_types_for_deduction (strict, parm, arg) ...@@ -7777,11 +7775,11 @@ maybe_adjust_types_for_deduction (strict, parm, arg)
static int static int
type_unification_real (tparms, targs, parms, args, subr, type_unification_real (tparms, targs, parms, args, subr,
strict, allow_incomplete) strict, allow_incomplete, len)
tree tparms, targs, parms, args; tree tparms, targs, parms, args;
int subr; int subr;
unification_kind_t strict; unification_kind_t strict;
int allow_incomplete; int allow_incomplete, len;
{ {
tree parm, arg; tree parm, arg;
int i; int i;
...@@ -7815,6 +7813,9 @@ type_unification_real (tparms, targs, parms, args, subr, ...@@ -7815,6 +7813,9 @@ type_unification_real (tparms, targs, parms, args, subr,
my_friendly_abort (0); my_friendly_abort (0);
} }
if (len == 0)
return 0;
while (parms while (parms
&& parms != void_list_node && parms != void_list_node
&& args && args
...@@ -7887,6 +7888,10 @@ type_unification_real (tparms, targs, parms, args, subr, ...@@ -7887,6 +7888,10 @@ type_unification_real (tparms, targs, parms, args, subr,
if (unify (tparms, targs, parm, arg, sub_strict)) if (unify (tparms, targs, parm, arg, sub_strict))
return 1; return 1;
/* Are we done with the interesting parms? */
if (--len == 0)
return 0;
} }
/* Fail if we've reached the end of the parm list, and more args /* Fail if we've reached the end of the parm list, and more args
are present, and the parm list isn't variadic. */ are present, and the parm list isn't variadic. */
...@@ -8738,7 +8743,7 @@ unify (tparms, targs, parm, arg, strict) ...@@ -8738,7 +8743,7 @@ unify (tparms, targs, parm, arg, strict)
return 1; return 1;
return type_unification_real (tparms, targs, TYPE_ARG_TYPES (parm), return type_unification_real (tparms, targs, TYPE_ARG_TYPES (parm),
TYPE_ARG_TYPES (arg), 1, TYPE_ARG_TYPES (arg), 1,
DEDUCE_EXACT, 0); DEDUCE_EXACT, 0, -1);
case OFFSET_TYPE: case OFFSET_TYPE:
if (TREE_CODE (arg) != OFFSET_TYPE) if (TREE_CODE (arg) != OFFSET_TYPE)
...@@ -8854,27 +8859,30 @@ mark_decl_instantiated (result, extern_p) ...@@ -8854,27 +8859,30 @@ mark_decl_instantiated (result, extern_p)
defer_fn (result); defer_fn (result);
} }
/* Given two function templates PAT1 and PAT2, and explicit template /* Given two function templates PAT1 and PAT2, return:
arguments EXPLICIT_ARGS return:
1 if PAT1 is more specialized than PAT2 as described in [temp.func.order]. 1 if PAT1 is more specialized than PAT2 as described in [temp.func.order].
-1 if PAT2 is more specialized than PAT1. -1 if PAT2 is more specialized than PAT1.
0 if neither is more specialized. */ 0 if neither is more specialized.
LEN is passed through to fn_type_unification. */
int int
more_specialized (pat1, pat2, explicit_args) more_specialized (pat1, pat2, len)
tree pat1, pat2, explicit_args; tree pat1, pat2;
int len;
{ {
tree targs; tree targs;
int winner = 0; int winner = 0;
targs if (len == 0)
= get_bindings_overload (pat1, DECL_TEMPLATE_RESULT (pat2), explicit_args); return 0;
targs = get_bindings_order (pat1, DECL_TEMPLATE_RESULT (pat2), len);
if (targs) if (targs)
--winner; --winner;
targs targs = get_bindings_order (pat2, DECL_TEMPLATE_RESULT (pat1), len);
= get_bindings_overload (pat2, DECL_TEMPLATE_RESULT (pat1), explicit_args);
if (targs) if (targs)
++winner; ++winner;
...@@ -8911,12 +8919,12 @@ more_specialized_class (pat1, pat2) ...@@ -8911,12 +8919,12 @@ more_specialized_class (pat1, pat2)
DECL from the function template FN, with the explicit template DECL from the function template FN, with the explicit template
arguments EXPLICIT_ARGS. If CHECK_RETTYPE is 1, the return type must arguments EXPLICIT_ARGS. If CHECK_RETTYPE is 1, the return type must
also match. Return NULL_TREE if no satisfactory arguments could be also match. Return NULL_TREE if no satisfactory arguments could be
found. */ found. LEN is passed through to fn_type_unification. */
static tree static tree
get_bindings_real (fn, decl, explicit_args, check_rettype) get_bindings_real (fn, decl, explicit_args, check_rettype, len)
tree fn, decl, explicit_args; tree fn, decl, explicit_args;
int check_rettype; int check_rettype, len;
{ {
int ntparms = DECL_NTPARMS (fn); int ntparms = DECL_NTPARMS (fn);
tree targs = make_tree_vec (ntparms); tree targs = make_tree_vec (ntparms);
...@@ -8953,18 +8961,16 @@ get_bindings_real (fn, decl, explicit_args, check_rettype) ...@@ -8953,18 +8961,16 @@ get_bindings_real (fn, decl, explicit_args, check_rettype)
return NULL_TREE; return NULL_TREE;
} }
/* If FN is a static member function, adjust the type of DECL
appropriately. */
decl_arg_types = TYPE_ARG_TYPES (decl_type); decl_arg_types = TYPE_ARG_TYPES (decl_type);
if (DECL_STATIC_FUNCTION_P (fn) /* Never do unification on the 'this' parameter. */
&& DECL_NONSTATIC_MEMBER_FUNCTION_P (decl)) if (DECL_NONSTATIC_MEMBER_FUNCTION_P (decl))
decl_arg_types = TREE_CHAIN (decl_arg_types); decl_arg_types = TREE_CHAIN (decl_arg_types);
i = fn_type_unification (fn, explicit_args, targs, i = fn_type_unification (fn, explicit_args, targs,
decl_arg_types, decl_arg_types,
(check_rettype || DECL_CONV_FN_P (fn) (check_rettype || DECL_CONV_FN_P (fn)
? TREE_TYPE (decl_type) : NULL_TREE), ? TREE_TYPE (decl_type) : NULL_TREE),
DEDUCE_EXACT); DEDUCE_EXACT, len);
if (i != 0) if (i != 0)
return NULL_TREE; return NULL_TREE;
...@@ -8978,16 +8984,27 @@ tree ...@@ -8978,16 +8984,27 @@ tree
get_bindings (fn, decl, explicit_args) get_bindings (fn, decl, explicit_args)
tree fn, decl, explicit_args; tree fn, decl, explicit_args;
{ {
return get_bindings_real (fn, decl, explicit_args, 1); return get_bindings_real (fn, decl, explicit_args, 1, -1);
} }
/* But for more_specialized, we only care about the parameter types. */ /* But for resolve_overloaded_unification, we only care about the parameter
types. */
static tree static tree
get_bindings_overload (fn, decl, explicit_args) get_bindings_overload (fn, decl, explicit_args)
tree fn, decl, explicit_args; tree fn, decl, explicit_args;
{ {
return get_bindings_real (fn, decl, explicit_args, 0); return get_bindings_real (fn, decl, explicit_args, 0, -1);
}
/* And for more_specialized, we want to be able to stop partway. */
static tree
get_bindings_order (fn, decl, len)
tree fn, decl;
int len;
{
return get_bindings_real (fn, decl, NULL_TREE, 0, len);
} }
/* Return the innermost template arguments that, when applied to a /* Return the innermost template arguments that, when applied to a
...@@ -9029,15 +9046,13 @@ get_class_bindings (tparms, parms, args) ...@@ -9029,15 +9046,13 @@ get_class_bindings (tparms, parms, args)
/* In INSTANTIATIONS is a list of <INSTANTIATION, TEMPLATE> pairs. /* In INSTANTIATIONS is a list of <INSTANTIATION, TEMPLATE> pairs.
Pick the most specialized template, and return the corresponding Pick the most specialized template, and return the corresponding
instantiation, or if there is no corresponding instantiation, the instantiation, or if there is no corresponding instantiation, the
template itself. EXPLICIT_ARGS is any template arguments explicitly template itself. If there is no most specialized template,
mentioned in a template-id. If there is no most specialized error_mark_node is returned. If there are no templates at all,
template, error_mark_node is returned. If there are no templates NULL_TREE is returned. */
at all, NULL_TREE is returned. */
tree tree
most_specialized_instantiation (instantiations, explicit_args) most_specialized_instantiation (instantiations)
tree instantiations; tree instantiations;
tree explicit_args;
{ {
tree fn, champ; tree fn, champ;
int fate; int fate;
...@@ -9048,8 +9063,7 @@ most_specialized_instantiation (instantiations, explicit_args) ...@@ -9048,8 +9063,7 @@ most_specialized_instantiation (instantiations, explicit_args)
champ = instantiations; champ = instantiations;
for (fn = TREE_CHAIN (instantiations); fn; fn = TREE_CHAIN (fn)) for (fn = TREE_CHAIN (instantiations); fn; fn = TREE_CHAIN (fn))
{ {
fate = more_specialized (TREE_VALUE (champ), fate = more_specialized (TREE_VALUE (champ), TREE_VALUE (fn), -1);
TREE_VALUE (fn), explicit_args);
if (fate == 1) if (fate == 1)
; ;
else else
...@@ -9066,8 +9080,7 @@ most_specialized_instantiation (instantiations, explicit_args) ...@@ -9066,8 +9080,7 @@ most_specialized_instantiation (instantiations, explicit_args)
for (fn = instantiations; fn && fn != champ; fn = TREE_CHAIN (fn)) for (fn = instantiations; fn && fn != champ; fn = TREE_CHAIN (fn))
{ {
fate = more_specialized (TREE_VALUE (champ), fate = more_specialized (TREE_VALUE (champ), TREE_VALUE (fn), -1);
TREE_VALUE (fn), explicit_args);
if (fate != 1) if (fate != 1)
return error_mark_node; return error_mark_node;
} }
...@@ -9095,7 +9108,7 @@ most_specialized (fns, decl, explicit_args) ...@@ -9095,7 +9108,7 @@ most_specialized (fns, decl, explicit_args)
candidates = tree_cons (NULL_TREE, candidate, candidates); candidates = tree_cons (NULL_TREE, candidate, candidates);
} }
return most_specialized_instantiation (candidates, explicit_args); 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
......
// Test that partial ordering ignores defaulted parms and 'this'.
struct A {
template<class T> int f(T) { return 1; }
template<class T> int f(T*, int=0) { return 0; }
template<class T> int g(T*) { return 0; }
template<class T> static int g(T, int=0) { return 1; }
template<class T> int h(T*) { return 0; }
template<class T> static int h(T, int=0) { return 1; }
template<class T> static int j(T*, short y=0) { return 0; }
template<class T> static int j(T, int=0) { return 1; }
};
int main(void) {
A a;
int *p;
return (a.f(p) || a.g(p) || a.h(p) || a.j(p));
}
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