tree, tsubst_flags_t);
static struct z_candidate *add_function_candidate
(struct z_candidate **, tree, tree, tree, const vec<tree, va_gc> *, tree,
- tree, int, tsubst_flags_t);
+ tree, int, conversion**, tsubst_flags_t);
static conversion *implicit_conversion (tree, tree, tree, bool, int,
tsubst_flags_t);
static conversion *reference_binding (tree, tree, tree, bool, int,
return NULL;
}
+/* Like implicit_conversion, but return NULL if the conversion is bad.
+
+ This is not static so that check_non_deducible_conversion can call it within
+ add_template_candidate_real as part of overload resolution; it should not be
+ called outside of overload resolution. */
+
+conversion *
+good_conversion (tree to, tree from, tree expr,
+ int flags, tsubst_flags_t complain)
+{
+ conversion *c = implicit_conversion (to, from, expr, /*cast*/false,
+ flags, complain);
+ if (c && c->bad_p)
+ c = NULL;
+ return c;
+}
+
/* Add a new entry to the list of candidates. Used by the add_*_candidate
functions. ARGS will not be changed until a single candidate is
selected. */
return n;
}
+/* [over.match.copy]: When initializing a temporary object (12.2) to be bound
+ to the first parameter of a constructor where the parameter is of type
+ "reference to possibly cv-qualified T" and the constructor is called with a
+ single argument in the context of direct-initialization of an object of type
+ "cv2 T", explicit conversion functions are also considered.
+
+ So set LOOKUP_COPY_PARM to let reference_binding know that
+ it's being called in that context. */
+
+int
+conv_flags (int i, int nargs, tree fn, tree arg, int flags)
+{
+ int lflags = flags;
+ tree t;
+ if (i == 0 && nargs == 1 && DECL_CONSTRUCTOR_P (fn)
+ && (t = FUNCTION_FIRST_USER_PARMTYPE (fn))
+ && (same_type_ignoring_top_level_qualifiers_p
+ (non_reference (TREE_VALUE (t)), DECL_CONTEXT (fn))))
+ {
+ if (!(flags & LOOKUP_ONLYCONVERTING))
+ lflags |= LOOKUP_COPY_PARM;
+ if ((flags & LOOKUP_LIST_INIT_CTOR)
+ && BRACE_ENCLOSED_INITIALIZER_P (arg))
+ lflags |= LOOKUP_NO_CONVERSION;
+ }
+ else
+ lflags |= LOOKUP_ONLYCONVERTING;
+
+ return lflags;
+}
+
/* Create an overload candidate for the function or method FN called
with the argument list FIRST_ARG/ARGS and add it to CANDIDATES.
FLAGS is passed on to implicit_conversion.
tree fn, tree ctype, tree first_arg,
const vec<tree, va_gc> *args, tree access_path,
tree conversion_path, int flags,
+ conversion **convs,
tsubst_flags_t complain)
{
tree parmlist = TYPE_ARG_TYPES (TREE_TYPE (fn));
int i, len;
- conversion **convs;
tree parmnode;
tree orig_first_arg = first_arg;
int skip;
skip = 0;
len = vec_safe_length (args) - skip + (first_arg != NULL_TREE ? 1 : 0);
- convs = alloc_conversions (len);
+ if (!convs)
+ convs = alloc_conversions (len);
/* 13.3.2 - Viable functions [over.match.viable]
First, to be a viable function, a candidate function shall have enough
if (parmnode == void_list_node)
break;
+ if (convs[i])
+ {
+ /* Already set during deduction. */
+ parmnode = TREE_CHAIN (parmnode);
+ continue;
+ }
+
if (i == 0 && first_arg != NULL_TREE)
arg = first_arg;
else
if (parmnode)
{
tree parmtype = TREE_VALUE (parmnode);
- int lflags = flags;
parmnode = TREE_CHAIN (parmnode);
}
}
- /* Core issue 899: When [copy-]initializing a temporary to be bound
- to the first parameter of a copy constructor (12.8) called with
- a single argument in the context of direct-initialization,
- explicit conversion functions are also considered.
-
- So set LOOKUP_COPY_PARM to let reference_binding know that
- it's being called in that context. We generalize the above
- to handle move constructors and template constructors as well;
- the standardese should soon be updated similarly. */
- if (ctype && i == 0 && (len-skip == 1)
- && DECL_CONSTRUCTOR_P (fn)
- && parmtype != error_mark_node
- && (same_type_ignoring_top_level_qualifiers_p
- (non_reference (parmtype), ctype)))
- {
- if (!(flags & LOOKUP_ONLYCONVERTING))
- lflags |= LOOKUP_COPY_PARM;
- /* We allow user-defined conversions within init-lists, but
- don't list-initialize the copy parm, as that would mean
- using two levels of braces for the same type. */
- if ((flags & LOOKUP_LIST_INIT_CTOR)
- && BRACE_ENCLOSED_INITIALIZER_P (arg))
- lflags |= LOOKUP_NO_CONVERSION;
- }
- else
- lflags |= LOOKUP_ONLYCONVERTING;
+ int lflags = conv_flags (i, len-skip, fn, arg, flags);
t = implicit_conversion (parmtype, argtype, arg,
/*c_cast_p=*/false, lflags, complain);
tree fn;
struct rejection_reason *reason = NULL;
int errs;
+ conversion **convs = NULL;
/* We don't do deduction on the in-charge parameter, the VTT
parameter or 'this'. */
gcc_assert (ia == nargs_without_in_chrg);
errs = errorcount+sorrycount;
+ if (!obj)
+ convs = alloc_conversions (nargs);
fn = fn_type_unification (tmpl, explicit_targs, targs,
args_without_in_chrg,
nargs_without_in_chrg,
- return_type, strict, flags, false,
- complain & tf_decltype);
+ return_type, strict, flags, convs,
+ false, complain & tf_decltype);
if (fn == error_mark_node)
{
else
cand = add_function_candidate (candidates, fn, ctype,
first_arg, arglist, access_path,
- conversion_path, flags, complain);
+ conversion_path, flags, convs, complain);
if (DECL_TI_TEMPLATE (fn) != tmpl)
/* This situation can occur if a member template of a template
class is specialized. Then, instantiate_template might return
r->u.template_unification.return_type,
r->u.template_unification.strict,
r->u.template_unification.flags,
- true, false);
+ NULL, true, false);
break;
case rr_invalid_copy:
inform (cloc,
access_path,
conversion_path,
flags,
+ NULL,
complain);
}
}
static tree add_to_template_args (tree, tree);
static tree add_outermost_template_args (tree, tree);
static bool check_instantiated_args (tree, tree, tsubst_flags_t);
+static int check_non_deducible_conversion (tree, tree, int, int,
+ struct conversion **, bool);
static int maybe_adjust_types_for_deduction (unification_kind_t, tree*, tree*,
tree);
static int type_unification_real (tree, tree, tree, const tree *,
- unsigned int, int, unification_kind_t, int,
+ unsigned int, int, unification_kind_t,
vec<deferred_access_check, va_gc> **,
bool);
static void note_template_header (int);
return true;
}
+/* Subroutine of fn_type_unification: check non-dependent parms for
+ convertibility. */
+
+static int
+check_non_deducible_conversions (tree parms, const tree *args, unsigned nargs,
+ tree fn, unification_kind_t strict, int flags,
+ struct conversion **convs, bool explain_p)
+{
+ /* Non-constructor methods need to leave a conversion for 'this', which
+ isn't included in nargs here. */
+ unsigned offset = (DECL_NONSTATIC_MEMBER_FUNCTION_P (fn)
+ && !DECL_CONSTRUCTOR_P (fn));
+
+ for (unsigned ia = 0;
+ parms && parms != void_list_node && ia < nargs; )
+ {
+ tree parm = TREE_VALUE (parms);
+
+ if (TREE_CODE (parm) == TYPE_PACK_EXPANSION
+ && (!TREE_CHAIN (parms)
+ || TREE_CHAIN (parms) == void_list_node))
+ /* For a function parameter pack that occurs at the end of the
+ parameter-declaration-list, the type A of each remaining
+ argument of the call is compared with the type P of the
+ declarator-id of the function parameter pack. */
+ break;
+
+ parms = TREE_CHAIN (parms);
+
+ if (TREE_CODE (parm) == TYPE_PACK_EXPANSION)
+ /* For a function parameter pack that does not occur at the
+ end of the parameter-declaration-list, the type of the
+ parameter pack is a non-deduced context. */
+ continue;
+
+ if (!uses_template_parms (parm))
+ {
+ tree arg = args[ia];
+ conversion **conv_p = convs ? &convs[ia+offset] : NULL;
+ int lflags = conv_flags (ia, nargs, fn, arg, flags);
+
+ if (check_non_deducible_conversion (parm, arg, strict, lflags,
+ conv_p, explain_p))
+ return 1;
+ }
+
+ ++ia;
+ }
+
+ return 0;
+}
+
/* The FN is a TEMPLATE_DECL for a function. ARGS is an array with
NARGS elements of the arguments that are being used when calling
it. TARGS is a vector into which the deduced template arguments
tree return_type,
unification_kind_t strict,
int flags,
+ struct conversion **convs,
bool explain_p,
bool decltype_p)
{
ok = !type_unification_real (DECL_INNERMOST_TEMPLATE_PARMS (fn),
full_targs, parms, args, nargs, /*subr=*/0,
- strict, flags, &checks, explain_p);
+ strict, &checks, explain_p);
if (!explain_p)
pop_tinst_level ();
if (!ok)
goto fail;
}
+ /* DR 1391: All parameters have args, now check non-dependent parms for
+ convertibility. */
+ if (check_non_deducible_conversions (parms, args, nargs, fn, strict, flags,
+ convs, explain_p))
+ goto fail;
+
/* All is well so far. Now, check:
[temp.deduct]
return result;
}
-/* Subroutine of unify_one_argument. PARM is a function parameter of a
- template which does contain any deducible template parameters; check if
+/* Subroutine of fn_type_unification. PARM is a function parameter of a
+ template which doesn't contain any deducible template parameters; check if
ARG is a suitable match for it. STRICT, FLAGS and EXPLAIN_P are as in
unify_one_argument. */
static int
check_non_deducible_conversion (tree parm, tree arg, int strict,
- int flags, bool explain_p)
+ int flags, struct conversion **conv_p,
+ bool explain_p)
{
tree type;
if (same_type_p (parm, type))
return unify_success (explain_p);
+ tsubst_flags_t complain = (explain_p ? tf_warning_or_error : tf_none);
if (strict == DEDUCE_CONV)
{
- if (can_convert_arg (type, parm, NULL_TREE, flags,
- explain_p ? tf_warning_or_error : tf_none))
+ if (can_convert_arg (type, parm, NULL_TREE, flags, complain))
return unify_success (explain_p);
}
else if (strict != DEDUCE_EXACT)
{
- if (can_convert_arg (parm, type,
- TYPE_P (arg) ? NULL_TREE : arg,
- flags, explain_p ? tf_warning_or_error : tf_none))
+ bool ok = false;
+ tree conv_arg = TYPE_P (arg) ? NULL_TREE : arg;
+ if (conv_p)
+ /* Avoid recalculating this in add_function_candidate. */
+ ok = (*conv_p
+ = good_conversion (parm, type, conv_arg, flags, complain));
+ else
+ ok = can_convert_arg (parm, type, conv_arg, flags, complain);
+ if (ok)
return unify_success (explain_p);
}
unsigned int xnargs,
int subr,
unification_kind_t strict,
- int flags,
vec<deferred_access_check, va_gc> **checks,
bool explain_p)
{
return unify_parameter_deduction_failure (explain_p, tparm);
}
- /* DR 1391: All parameters have args, now check non-dependent parms for
- convertibility. */
- if (saw_undeduced < 2)
- for (ia = 0, parms = xparms, args = xargs, nargs = xnargs;
- parms && parms != void_list_node && ia < nargs; )
- {
- parm = TREE_VALUE (parms);
-
- if (TREE_CODE (parm) == TYPE_PACK_EXPANSION
- && (!TREE_CHAIN (parms)
- || TREE_CHAIN (parms) == void_list_node))
- /* For a function parameter pack that occurs at the end of the
- parameter-declaration-list, the type A of each remaining
- argument of the call is compared with the type P of the
- declarator-id of the function parameter pack. */
- break;
-
- parms = TREE_CHAIN (parms);
-
- if (TREE_CODE (parm) == TYPE_PACK_EXPANSION)
- /* For a function parameter pack that does not occur at the
- end of the parameter-declaration-list, the type of the
- parameter pack is a non-deduced context. */
- continue;
-
- arg = args[ia];
- ++ia;
-
- if (uses_template_parms (parm))
- continue;
- if (check_non_deducible_conversion (parm, arg, strict, flags,
- explain_p))
- return 1;
-
- if (BRACE_ENCLOSED_INITIALIZER_P (arg)
- && (TREE_CODE (parm) == ARRAY_TYPE || is_std_init_list (parm)))
- {
- tree elt, elttype;
- unsigned int i;
-
- if (TREE_CODE (parm) == ARRAY_TYPE)
- elttype = TREE_TYPE (parm);
- else
- elttype = TREE_VEC_ELT (CLASSTYPE_TI_ARGS (parm), 0);
- FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (arg), i, elt)
- if (check_non_deducible_conversion (elttype, elt, strict,
- flags, explain_p))
- return 1;
- }
- }
-
/* Now substitute into the default template arguments. */
for (i = 0; i < ntparms; i++)
{
if (type_unification_real (tparms, targs, TYPE_ARG_TYPES (parm),
args, nargs, 1, DEDUCE_EXACT,
- LOOKUP_NORMAL, NULL, explain_p))
+ NULL, explain_p))
return 1;
if (flag_noexcept_type)
args, ix,
(check_rettype || DECL_CONV_FN_P (fn)
? TREE_TYPE (decl_type) : NULL_TREE),
- DEDUCE_EXACT, LOOKUP_NORMAL, /*explain_p=*/false,
+ DEDUCE_EXACT, LOOKUP_NORMAL, NULL,
+ /*explain_p=*/false,
/*decltype*/false)
== error_mark_node)
return NULL_TREE;
targs = make_tree_vec (TREE_VEC_LENGTH (tparms));
int val = type_unification_real (tparms, targs, parms, &init, 1, 0,
- DEDUCE_CALL, LOOKUP_NORMAL,
+ DEDUCE_CALL,
NULL, /*explain_p=*/false);
if (val > 0)
{
else
error ("unable to deduce %qT from %qE", type, init);
type_unification_real (tparms, targs, parms, &init, 1, 0,
- DEDUCE_CALL, LOOKUP_NORMAL,
+ DEDUCE_CALL,
NULL, /*explain_p=*/true);
}
return error_mark_node;