#define UNIFY_ALLOW_DERIVED 4
#define UNIFY_ALLOW_INTEGER 8
#define UNIFY_ALLOW_OUTER_LEVEL 16
+#define UNIFY_ALLOW_OUTER_MORE_CV_QUAL 32
+#define UNIFY_ALLOW_OUTER_LESS_CV_QUAL 64
#define GTB_VIA_VIRTUAL 1 /* The base class we are examining is
virtual, or a base class of a virtual
static void tsubst_enum PARAMS ((tree, tree, tree));
static tree add_to_template_args PARAMS ((tree, tree));
static tree add_outermost_template_args PARAMS ((tree, tree));
-static void maybe_adjust_types_for_deduction PARAMS ((unification_kind_t, tree*,
+static int maybe_adjust_types_for_deduction PARAMS ((unification_kind_t, tree*,
tree*));
static int type_unification_real PARAMS ((tree, tree, tree, tree,
int, unification_kind_t, int, int));
static tree convert_template_argument PARAMS ((tree, tree, tree, int,
int , 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 tree build_template_parm_index PARAMS ((int, int, int, tree, tree));
static int inline_needs_template_parms PARAMS ((tree));
static int mark_template_parm PARAMS ((tree, void *));
static tree tsubst_friend_function PARAMS ((tree, tree));
static tree tsubst_friend_class PARAMS ((tree, tree));
-static tree get_bindings_real PARAMS ((tree, tree, tree, int, int));
+static tree get_bindings_real PARAMS ((tree, tree, tree, int, int, int));
static int template_decl_level PARAMS ((tree));
static tree maybe_get_template_decl_from_type_decl PARAMS ((tree));
static int check_cv_quals_for_unify PARAMS ((int, tree, tree));
[temp.deduct.conv].
DEDUCE_EXACT:
+ We are deducing arguments when doing an explicit instantiation
+ as in [temp.explicit], when determining an explicit specialization
+ as in [temp.expl.spec], or when taking the address of a function
+ template, as in [temp.deduct.funcaddr].
+
+ DEDUCE_ORDER:
We are deducing arguments when calculating the partial
ordering between specializations of function or class
- templates, as in [temp.func.order] and [temp.class.order],
- when doing an explicit instantiation as in [temp.explicit],
- when determining an explicit specialization as in
- [temp.expl.spec], or when taking the address of a function
- template, as in [temp.deduct.funcaddr].
+ templates, as in [temp.func.order] and [temp.class.order].
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
the argument passed to the call, or the type of the value
initialized with the result of the conversion function. */
-static void
+static int
maybe_adjust_types_for_deduction (strict, parm, arg)
unification_kind_t strict;
tree* parm;
tree* arg;
{
+ int result = 0;
+
switch (strict)
{
case DEDUCE_CALL:
case DEDUCE_EXACT:
/* There is nothing to do in this case. */
- return;
+ return 0;
+ case DEDUCE_ORDER:
+ /* DR 214. [temp.func.order] is underspecified, and leads to no
+ ordering between things like `T *' and `T const &' for `U *'.
+ The former has T=U and the latter T=U*. The former looks more
+ specialized and John Spicer considers it well-formed (the EDG
+ compiler accepts it).
+
+ John also confirms that deduction should proceed as in a function
+ call. Which implies the usual ARG and PARM bashing as DEDUCE_CALL.
+ However, in ordering, ARG can have REFERENCE_TYPE, but no argument
+ to an actual call can have such a type.
+
+ When deducing against a REFERENCE_TYPE, we can either not change
+ PARM's type, or we can change ARG's type too. The latter, though
+ seemingly more safe, turns out to give the following quirk. Consider
+ deducing a call to a `const int *' with the following template
+ function parameters
+ #1; T const *const & ; T = int
+ #2; T *const & ; T = const int
+ #3; T * ; T = const int
+ It looks like #1 is the more specialized. Taken pairwise, #1 is
+ more specialized than #2 and #2 is more specialized than #3, yet
+ there is no ordering between #1 and #3.
+
+ So, if ARG is a reference, we look though it when PARM is
+ not a refence. When both are references we don't change either. */
+ if (TREE_CODE (*arg) == REFERENCE_TYPE)
+ {
+ if (TREE_CODE (*parm) == REFERENCE_TYPE)
+ return 0;
+ *arg = TREE_TYPE (*arg);
+ result |= UNIFY_ALLOW_OUTER_LESS_CV_QUAL;
+ goto skip_arg;
+ }
+ break;
default:
my_friendly_abort (0);
}
*arg = TYPE_MAIN_VARIANT (*arg);
}
+ skip_arg:;
/* [temp.deduct.call]
If P is a cv-qualified type, the top level cv-qualifiers
type deduction. */
*parm = TYPE_MAIN_VARIANT (*parm);
if (TREE_CODE (*parm) == REFERENCE_TYPE)
- *parm = TREE_TYPE (*parm);
+ {
+ *parm = TREE_TYPE (*parm);
+ result |= UNIFY_ALLOW_OUTER_MORE_CV_QUAL;
+ }
+ return result;
}
/* Most parms like fn_type_unification.
case DEDUCE_EXACT:
sub_strict = UNIFY_ALLOW_NONE;
break;
+
+ case DEDUCE_ORDER:
+ sub_strict = UNIFY_ALLOW_NONE;
+ break;
default:
my_friendly_abort (0);
arg = NULL_TREE;
}
- if (strict == DEDUCE_EXACT)
+ if (strict == DEDUCE_EXACT || strict == DEDUCE_ORDER)
{
if (same_type_p (parm, type))
continue;
}
arg = TREE_TYPE (arg);
}
+
+ {
+ int arg_strict = sub_strict;
+
+ if (!subr)
+ arg_strict |= maybe_adjust_types_for_deduction (strict, &parm, &arg);
- if (!subr)
- maybe_adjust_types_for_deduction (strict, &parm, &arg);
-
- if (unify (tparms, targs, parm, arg, sub_strict))
- return 1;
+ if (unify (tparms, targs, parm, arg, arg_strict))
+ return 1;
+ }
/* Are we done with the interesting parms? */
if (--len == 0)
if (uses_template_parms (arg))
return 1;
- maybe_adjust_types_for_deduction (strict, &parm, &arg);
+ sub_strict |= 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
tree arg;
tree parm;
{
- if (!(strict & UNIFY_ALLOW_MORE_CV_QUAL)
+ if (!(strict & (UNIFY_ALLOW_MORE_CV_QUAL | UNIFY_ALLOW_OUTER_MORE_CV_QUAL))
&& !at_least_as_qualified_p (arg, parm))
return 0;
- if (!(strict & UNIFY_ALLOW_LESS_CV_QUAL)
+ if (!(strict & (UNIFY_ALLOW_LESS_CV_QUAL | UNIFY_ALLOW_OUTER_LESS_CV_QUAL))
&& !at_least_as_qualified_p (parm, arg))
return 0;
have const qualified pointers leading up to the inner type which
requires additional CV quals, except at the outer level, where const
is not required [conv.qual]. It would be normal to set this flag in
- addition to setting UNIFY_ALLOW_MORE_CV_QUAL. */
+ addition to setting UNIFY_ALLOW_MORE_CV_QUAL.
+ UNIFY_ALLOW_OUTER_MORE_CV_QUAL:
+ This is the outermost level of a deduction, and PARM can be more CV
+ qualified at this point.
+ UNIFY_ALLOW_OUTER_LESS_CV_QUAL:
+ This is the outermost level of a deduction, and PARM can be less CV
+ qualified at this point. */
static int
unify (tparms, targs, parm, arg, strict)
strict &= ~UNIFY_ALLOW_MORE_CV_QUAL;
strict &= ~UNIFY_ALLOW_OUTER_LEVEL;
strict &= ~UNIFY_ALLOW_DERIVED;
+ strict &= ~UNIFY_ALLOW_OUTER_MORE_CV_QUAL;
+ strict &= ~UNIFY_ALLOW_OUTER_LESS_CV_QUAL;
switch (TREE_CODE (parm))
{
/* Given two function templates PAT1 and PAT2, return:
+ DEDUCE should be DEDUCE_EXACT or DEDUCE_ORDER.
+
1 if PAT1 is more specialized than PAT2 as described in [temp.func.order].
-1 if PAT2 is more specialized than PAT1.
0 if neither is more specialized.
LEN is passed through to fn_type_unification. */
int
-more_specialized (pat1, pat2, len)
+more_specialized (pat1, pat2, deduce, len)
tree pat1, pat2;
+ int deduce;
int len;
{
tree targs;
int winner = 0;
- targs = get_bindings_order (pat1, DECL_TEMPLATE_RESULT (pat2), len);
+ targs = get_bindings_real (pat1, DECL_TEMPLATE_RESULT (pat2),
+ NULL_TREE, 0, deduce, len);
if (targs)
--winner;
- targs = get_bindings_order (pat2, DECL_TEMPLATE_RESULT (pat1), len);
+ targs = get_bindings_real (pat2, DECL_TEMPLATE_RESULT (pat1),
+ NULL_TREE, 0, deduce, len);
if (targs)
++winner;
DECL from the function template FN, with the explicit template
arguments EXPLICIT_ARGS. If CHECK_RETTYPE is 1, the return type must
also match. Return NULL_TREE if no satisfactory arguments could be
- found. LEN is passed through to fn_type_unification. */
+ found. DEDUCE and LEN are passed through to fn_type_unification. */
static tree
-get_bindings_real (fn, decl, explicit_args, check_rettype, len)
+get_bindings_real (fn, decl, explicit_args, check_rettype, deduce, len)
tree fn, decl, explicit_args;
- int check_rettype, len;
+ int check_rettype, deduce, len;
{
int ntparms = DECL_NTPARMS (fn);
tree targs = make_tree_vec (ntparms);
decl_arg_types,
(check_rettype || DECL_CONV_FN_P (fn)
? TREE_TYPE (decl_type) : NULL_TREE),
- DEDUCE_EXACT, len);
+ deduce, len);
if (i != 0)
return NULL_TREE;
get_bindings (fn, decl, explicit_args)
tree fn, decl, explicit_args;
{
- return get_bindings_real (fn, decl, explicit_args, 1, -1);
+ return get_bindings_real (fn, decl, explicit_args, 1, DEDUCE_EXACT, -1);
}
/* But for resolve_overloaded_unification, we only care about the parameter
get_bindings_overload (fn, decl, explicit_args)
tree fn, decl, explicit_args;
{
- 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 get_bindings_real (fn, decl, explicit_args, 0, DEDUCE_EXACT, -1);
}
/* Return the innermost template arguments that, when applied to a
champ = instantiations;
for (fn = TREE_CHAIN (instantiations); fn; fn = TREE_CHAIN (fn))
{
- fate = more_specialized (TREE_VALUE (champ), TREE_VALUE (fn), -1);
+ fate = more_specialized (TREE_VALUE (champ), TREE_VALUE (fn),
+ DEDUCE_EXACT, -1);
if (fate == 1)
;
else
for (fn = instantiations; fn && fn != champ; fn = TREE_CHAIN (fn))
{
- fate = more_specialized (TREE_VALUE (champ), TREE_VALUE (fn), -1);
+ fate = more_specialized (TREE_VALUE (champ), TREE_VALUE (fn),
+ DEDUCE_EXACT, -1);
if (fate != 1)
return error_mark_node;
}