Commit eaf0f63a authored by jason's avatar jason
Browse files

* pt.c (resolve_overloaded_unification): New fn.

	(try_one_overload): Likewise.
	(unify): Don't fail on unknown type.
	(type_unification_real): Likewise.  Use resolve_overloaded_unification
	to handle an overloaded argument.
	(template_args_equal): Split out...
	(comp_template_args): From here.
	(determine_specialization): Also allow a template with more
	parms than were explicitly specified.
	* cp-tree.h: Add template_args_equal.
	* call.c (resolve_args): Remove TEMPLATE_ID_EXPR code.


git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@22951 138bc75d-0d04-0410-961f-82ee72b054a4
parent ccd2a2e4
1998-10-08 Jason Merrill <jason@yorick.cygnus.com>
* pt.c (resolve_overloaded_unification): New fn.
(try_one_overload): Likewise.
(unify): Don't fail on unknown type.
(type_unification_real): Likewise. Use resolve_overloaded_unification
to handle an overloaded argument.
(template_args_equal): Split out...
(comp_template_args): From here.
(determine_specialization): Also allow a template with more
parms than were explicitly specified.
* cp-tree.h: Add template_args_equal.
* call.c (resolve_args): Remove TEMPLATE_ID_EXPR code.
Thu Oct 8 15:58:30 1998 Anthony Green <green@cygnus.com>
* semantics.c (finish_asm_stmt): Revert my 1998-09-28
......
......@@ -2255,26 +2255,6 @@ resolve_args (args)
}
else if (TREE_CODE (TREE_VALUE (t)) == OFFSET_REF)
TREE_VALUE (t) = resolve_offset_ref (TREE_VALUE (t));
else if (TREE_CODE (TREE_VALUE (t)) == TEMPLATE_ID_EXPR)
{
tree targs;
tree r;
r = determine_specialization (TREE_VALUE (t), NULL_TREE,
&targs,
/*need_member_template=*/0,
/*complain=*/0);
/* If we figured out what was being specialized, use it.
Otherwise, the function being called may resolve the
choice of specialization, so we don't issue any error
messages here. */
if (r)
{
r = instantiate_template (r, targs);
TREE_VALUE (t) = r;
}
}
}
return args;
}
......
......@@ -2861,6 +2861,7 @@ extern void pop_tinst_level PROTO((void));
extern int more_specialized_class PROTO((tree, tree));
extern void do_pushlevel PROTO((void));
extern int is_member_template PROTO((tree));
extern int template_parms_equal PROTO((tree, tree));
extern int comp_template_parms PROTO((tree, tree));
extern int decl_template_parm_p PROTO((tree));
extern int template_class_depth PROTO((tree));
......
......@@ -76,6 +76,12 @@ static tree saved_trees;
#define UNIFY_ALLOW_LESS_CV_QUAL 2
#define UNIFY_ALLOW_DERIVED 4
static int unify PROTO((tree, tree, tree, tree, int, int*));
static int resolve_overloaded_unification PROTO((tree, tree, tree, tree,
unification_kind_t, int,
int*));
static int try_one_overload PROTO((tree, tree, tree, tree,
unification_kind_t, int, int*));
static int unify PROTO((tree, tree, tree, tree, int, int*));
static void add_pending_template PROTO((tree));
static int push_tinst_level PROTO((tree));
......@@ -905,7 +911,6 @@ determine_specialization (template_id, decl, targs_out,
tree fns, targs_in;
tree templates = NULL_TREE;
tree fn;
int i;
*targs_out = NULL_TREE;
......@@ -949,18 +954,14 @@ determine_specialization (template_id, decl, targs_out,
if (decl == NULL_TREE)
{
tree targs = make_scratch_vec (DECL_NTPARMS (tmpl));
/* We allow incomplete unification here, because we are going to
check all the functions. */
i = type_unification (DECL_INNERMOST_TEMPLATE_PARMS (tmpl),
targs,
NULL_TREE,
NULL_TREE,
targs_in,
DEDUCE_EXACT, 1);
if (i == 0)
/* Unify against ourselves to make sure that the args we have
make sense and there aren't any undeducible parms. It's OK if
not all the parms are specified; they might be deduced
later. */
tree targs = get_bindings_overload (tmpl, DECL_RESULT (tmpl),
targs_in);
if (targs)
/* Unification was successful. */
templates = scratch_tree_cons (targs, tmpl, templates);
}
......@@ -1005,7 +1006,8 @@ determine_specialization (template_id, decl, targs_out,
}
return NULL_TREE;
}
else if (TREE_CHAIN (templates) != NULL_TREE)
else if (TREE_CHAIN (templates) != NULL_TREE
|| uses_template_parms (TREE_PURPOSE (templates)))
{
ambiguous:
if (complain)
......@@ -3045,7 +3047,26 @@ coerce_template_parms (parms, args, in_decl,
return new_inner_args;
}
/* Renturns 1 iff the OLDARGS and NEWARGS are in fact identical sets
/* Returns 1 if template args OT and NT are equivalent. */
int
template_args_equal (ot, nt)
tree ot, nt;
{
if (nt == ot)
return 1;
if (TREE_CODE (nt) != TREE_CODE (ot))
return 0;
if (TREE_CODE (nt) == TREE_VEC)
/* For member templates */
return comp_template_args (ot, nt);
else if (TREE_CODE_CLASS (TREE_CODE (ot)) == 't')
return comptypes (ot, nt, 1);
else
return (cp_tree_equal (ot, nt) > 0);
}
/* Returns 1 iff the OLDARGS and NEWARGS are in fact identical sets
of template arguments. Returns 0 otherwise. */
int
......@@ -3062,26 +3083,8 @@ comp_template_args (oldargs, newargs)
tree nt = TREE_VEC_ELT (newargs, i);
tree ot = TREE_VEC_ELT (oldargs, i);
if (nt == ot)
continue;
else if (!nt || !ot)
if (! template_args_equal (ot, nt))
return 0;
else if (TREE_CODE (nt) != TREE_CODE (ot))
return 0;
else if (TREE_CODE (nt) == TREE_VEC)
{
/* For member templates */
if (comp_template_args (ot, nt))
continue;
}
else if (TREE_CODE_CLASS (TREE_CODE (ot)) == 't')
{
if (comptypes (ot, nt, 1))
continue;
}
else if (cp_tree_equal (ot, nt) > 0)
continue;
return 0;
}
return 1;
}
......@@ -6730,7 +6733,9 @@ type_unification_real (tparms, targs, parms, args, subr,
if (arg == error_mark_node)
return 1;
if (arg == unknown_type_node)
return 1;
/* We can't deduce anything from this, but we might get all the
template args from other function args. */
continue;
/* Conversions will be performed on a function argument that
corresponds with a function parameter that contains only
......@@ -6771,28 +6776,19 @@ type_unification_real (tparms, targs, parms, args, subr,
if (TREE_CODE_CLASS (TREE_CODE (arg)) != 't')
{
my_friendly_assert (TREE_TYPE (arg) != NULL_TREE, 293);
if (TREE_CODE (arg) == OVERLOAD
&& TREE_CODE (OVL_FUNCTION (arg)) == TEMPLATE_DECL)
if (type_unknown_p (arg))
{
tree targs;
tree arg_type;
int r;
/* Have to back unify here */
arg = OVL_FUNCTION (arg);
targs = make_scratch_vec (DECL_NTPARMS (arg));
arg_type = TREE_TYPE (arg);
maybe_adjust_types_for_deduction (strict, &parm, &arg_type);
parm = expr_tree_cons (NULL_TREE, parm, NULL_TREE);
arg_type = scratch_tree_cons (NULL_TREE, arg_type, NULL_TREE);
r = type_unification (DECL_INNERMOST_TEMPLATE_PARMS (arg),
targs, arg_type, parm, NULL_TREE,
DEDUCE_EXACT, allow_incomplete);
if (r)
/* If the back-unification failed, just bail out. */
return r;
else
continue;
/* [temp.deduct.type] A template-argument can be deduced from
a pointer to function or pointer to member function
argument if the set of overloaded functions does not
contain function templates and at most one of a set of
overloaded functions provides a unique match. */
if (resolve_overloaded_unification
(tparms, targs, parm, arg, strict, sub_strict, explicit_mask)
!= 0)
return 1;
continue;
}
arg = TREE_TYPE (arg);
}
......@@ -6829,6 +6825,152 @@ type_unification_real (tparms, targs, parms, args, subr,
return 0;
}
/* Subroutine of type_unification_real. Args are like the variables at the
call site. ARG is an overloaded function (or template-id); we try
deducing template args from each of the overloads, and if only one
succeeds, we go with that. Modifies TARGS and returns 0 on success. */
static int
resolve_overloaded_unification (tparms, targs, parm, arg, strict,
sub_strict, explicit_mask)
tree tparms, targs, parm, arg;
unification_kind_t strict;
int sub_strict;
int* explicit_mask;
{
tree tempargs = copy_node (targs);
int good = 0;
if (TREE_CODE (arg) == ADDR_EXPR)
arg = TREE_OPERAND (arg, 0);
if (TREE_CODE (arg) == TEMPLATE_ID_EXPR)
{
/* If we got some explicit template args, we need to plug them into
the affected templates before we try to unify, in case the
explicit args will completely resolve the templates in question. */
tree expl_subargs = TREE_OPERAND (arg, 1);
arg = TREE_OPERAND (arg, 0);
for (; arg; arg = OVL_NEXT (arg))
{
tree fn = OVL_CURRENT (arg);
tree subargs, elem;
if (TREE_CODE (fn) != TEMPLATE_DECL)
continue;
subargs = get_bindings_overload (fn, DECL_RESULT (fn), expl_subargs);
if (subargs)
{
elem = tsubst (TREE_TYPE (fn), subargs, NULL_TREE);
good += try_one_overload (tparms, tempargs, parm, elem,
strict, sub_strict, explicit_mask);
}
}
}
else if (TREE_CODE (arg) == OVERLOAD)
{
for (; arg; arg = OVL_NEXT (arg))
good += try_one_overload (tparms, tempargs, parm,
TREE_TYPE (OVL_CURRENT (arg)),
strict, sub_strict, explicit_mask);
}
else
my_friendly_abort (981006);
/* [temp.deduct.type] A template-argument can be deduced from a pointer
to function or pointer to member function argument if the set of
overloaded functions does not contain function templates and at most
one of a set of overloaded functions provides a unique match.
So if we found multiple possibilities, we return success but don't
deduce anything. */
if (good == 1)
{
int i = TREE_VEC_LENGTH (targs);
for (; i--; )
if (TREE_VEC_ELT (tempargs, i))
TREE_VEC_ELT (targs, i) = TREE_VEC_ELT (tempargs, i);
}
if (good)
return 0;
return 1;
}
/* Subroutine of resolve_overloaded_unification; does deduction for a single
overload. Fills TARGS with any deduced arguments, or error_mark_node if
different overloads deduce different arguments for a given parm.
Returns 1 on success. */
static int
try_one_overload (tparms, targs, parm, arg, strict,
sub_strict, explicit_mask)
tree tparms, targs, parm, arg;
unification_kind_t strict;
int sub_strict;
int* explicit_mask;
{
int nargs;
tree tempargs;
int i;
/* [temp.deduct.type] A template-argument can be deduced from a pointer
to function or pointer to member function argument if the set of
overloaded functions does not contain function templates and at most
one of a set of overloaded functions provides a unique match.
So if this is a template, just return success. */
if (uses_template_parms (arg))
return 1;
maybe_adjust_types_for_deduction (strict, &parm, &arg);
/* We don't copy orig_targs for this because if we have already deduced
some template args from previous args, unify would complain when we
try to deduce a template parameter for the same argument, even though
there isn't really a conflict. */
nargs = TREE_VEC_LENGTH (targs);
tempargs = make_scratch_vec (nargs);
if (unify (tparms, tempargs, parm, arg, sub_strict, explicit_mask) != 0)
return 0;
/* First make sure we didn't deduce anything that conflicts with
previously deduced/specified args. */
for (i = nargs; i--; )
{
tree elt = TREE_VEC_ELT (tempargs, i);
tree oldelt = TREE_VEC_ELT (targs, i);
if (elt == NULL_TREE)
continue;
else if (uses_template_parms (elt))
{
/* Since we're unifying against ourselves, we will fill in template
args used in the function parm list with our own template parms.
Discard them. */
TREE_VEC_ELT (tempargs, i) = NULL_TREE;
continue;
}
else if (oldelt && ! template_args_equal (oldelt, elt))
return 0;
}
for (i = nargs; i--; )
{
tree elt = TREE_VEC_ELT (tempargs, i);
if (elt)
TREE_VEC_ELT (targs, i) = elt;
}
return 1;
}
/* Returns the level of DECL, which declares a template parameter. */
int
......@@ -6903,7 +7045,10 @@ unify (tparms, targs, parm, arg, strict, explicit_mask)
if (arg == error_mark_node)
return 1;
if (arg == unknown_type_node)
return 1;
/* We can't deduce anything from this, but we might get all the
template args from other function args. */
return 0;
/* If PARM uses template parameters, then we can't bail out here,
even in ARG == PARM, since we won't record unifications for the
template parameters. We might need them if we're trying to
......@@ -8496,5 +8641,3 @@ set_mangled_name_for_template_decl (decl)
/* Restore the previously active namespace. */
current_namespace = saved_namespace;
}
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