static bool any_strictly_viable (struct z_candidate *);
static struct z_candidate *add_template_candidate
(struct z_candidate **, tree, tree, tree, tree, const vec<tree, va_gc> *,
- tree, tree, tree, int, unification_kind_t, tsubst_flags_t);
+ tree, tree, tree, int, unification_kind_t, bool, tsubst_flags_t);
static struct z_candidate *add_template_candidate_real
(struct z_candidate **, tree, tree, tree, tree, const vec<tree, va_gc> *,
- tree, tree, tree, int, tree, unification_kind_t, tsubst_flags_t);
+ tree, tree, tree, int, tree, unification_kind_t, bool, tsubst_flags_t);
static bool is_complete (tree);
static struct z_candidate *add_conv_candidate
(struct z_candidate **, tree, tree, const vec<tree, va_gc> *, tree,
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, conversion**, tsubst_flags_t);
+ tree, int, conversion**, bool, 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 lflags;
}
+/* Build an appropriate 'this' conversion for the method FN and class
+ type CTYPE from the value ARG (having type ARGTYPE) to the type PARMTYPE.
+ This function modifies PARMTYPE, ARGTYPE and ARG. */
+
+static conversion *
+build_this_conversion (tree fn, tree ctype,
+ tree& parmtype, tree& argtype, tree& arg,
+ int flags, tsubst_flags_t complain)
+{
+ gcc_assert (DECL_NONSTATIC_MEMBER_FUNCTION_P (fn)
+ && !DECL_CONSTRUCTOR_P (fn));
+
+ /* The type of the implicit object parameter ('this') for
+ overload resolution is not always the same as for the
+ function itself; conversion functions are considered to
+ be members of the class being converted, and functions
+ introduced by a using-declaration are considered to be
+ members of the class that uses them.
+
+ Since build_over_call ignores the ICS for the `this'
+ parameter, we can just change the parm type. */
+ parmtype = cp_build_qualified_type (ctype,
+ cp_type_quals (TREE_TYPE (parmtype)));
+ bool this_p = true;
+ if (FUNCTION_REF_QUALIFIED (TREE_TYPE (fn)))
+ {
+ /* If the function has a ref-qualifier, the implicit
+ object parameter has reference type. */
+ bool rv = FUNCTION_RVALUE_QUALIFIED (TREE_TYPE (fn));
+ parmtype = cp_build_reference_type (parmtype, rv);
+ /* The special handling of 'this' conversions in compare_ics
+ does not apply if there is a ref-qualifier. */
+ this_p = false;
+ }
+ else
+ {
+ parmtype = build_pointer_type (parmtype);
+ /* We don't use build_this here because we don't want to
+ capture the object argument until we've chosen a
+ non-static member function. */
+ arg = build_address (arg);
+ argtype = lvalue_type (arg);
+ }
+ flags |= LOOKUP_ONLYCONVERTING;
+ conversion *t = implicit_conversion (parmtype, argtype, arg,
+ /*c_cast_p=*/false, flags, complain);
+ t->this_p = this_p;
+ return t;
+}
+
/* 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.
This does not change ARGS.
CTYPE, if non-NULL, is the type we want to pretend this function
- comes from for purposes of overload resolution. */
+ comes from for purposes of overload resolution.
+
+ SHORTCUT_BAD_CONVS controls how we handle "bad" argument conversions.
+ If true, we stop computing conversions upon seeing the first bad
+ conversion. This is used by add_candidates to avoid computing
+ more conversions than necessary in the presence of a strictly viable
+ candidate, while preserving the defacto behavior of overload resolution
+ when it turns out there are only non-strictly viable candidates. */
static struct z_candidate *
add_function_candidate (struct z_candidate **candidates,
const vec<tree, va_gc> *args, tree access_path,
tree conversion_path, int flags,
conversion **convs,
+ bool shortcut_bad_convs,
tsubst_flags_t complain)
{
tree parmlist = TYPE_ARG_TYPES (TREE_TYPE (fn));
{
tree argtype, to_type;
tree arg;
- conversion *t;
- int is_this;
if (parmnode == void_list_node)
break;
(*args)[i + skip - (first_arg != NULL_TREE ? 1 : 0)]);
argtype = lvalue_type (arg);
- is_this = (i == 0 && DECL_NONSTATIC_MEMBER_FUNCTION_P (fn)
- && ! DECL_CONSTRUCTOR_P (fn));
-
+ conversion *t;
if (parmnode)
{
tree parmtype = TREE_VALUE (parmnode);
-
- parmnode = TREE_CHAIN (parmnode);
-
- /* The type of the implicit object parameter ('this') for
- overload resolution is not always the same as for the
- function itself; conversion functions are considered to
- be members of the class being converted, and functions
- introduced by a using-declaration are considered to be
- members of the class that uses them.
-
- Since build_over_call ignores the ICS for the `this'
- parameter, we can just change the parm type. */
- if (ctype && is_this)
+ if (i == 0
+ && DECL_NONSTATIC_MEMBER_FUNCTION_P (fn)
+ && !DECL_CONSTRUCTOR_P (fn))
+ t = build_this_conversion (fn, ctype, parmtype, argtype, arg,
+ flags, complain);
+ else
{
- parmtype = cp_build_qualified_type
- (ctype, cp_type_quals (TREE_TYPE (parmtype)));
- if (FUNCTION_REF_QUALIFIED (TREE_TYPE (fn)))
- {
- /* If the function has a ref-qualifier, the implicit
- object parameter has reference type. */
- bool rv = FUNCTION_RVALUE_QUALIFIED (TREE_TYPE (fn));
- parmtype = cp_build_reference_type (parmtype, rv);
- /* The special handling of 'this' conversions in compare_ics
- does not apply if there is a ref-qualifier. */
- is_this = false;
- }
- else
- {
- parmtype = build_pointer_type (parmtype);
- /* We don't use build_this here because we don't want to
- capture the object argument until we've chosen a
- non-static member function. */
- arg = build_address (arg);
- argtype = lvalue_type (arg);
- }
+ int lflags = conv_flags (i, len-skip, fn, arg, flags);
+ t = implicit_conversion (parmtype, argtype, arg,
+ /*c_cast_p=*/false, lflags, complain);
}
-
- int lflags = conv_flags (i, len-skip, fn, arg, flags);
-
- t = implicit_conversion (parmtype, argtype, arg,
- /*c_cast_p=*/false, lflags, complain);
to_type = parmtype;
+ parmnode = TREE_CHAIN (parmnode);
}
else
{
to_type = argtype;
}
- if (t && is_this)
- t->this_p = true;
-
convs[i] = t;
if (! t)
{
viable = -1;
reason = bad_arg_conversion_rejection (first_arg, i, arg, to_type,
EXPR_LOCATION (arg));
-
+ if (shortcut_bad_convs)
+ break;
}
}
This does not change ARGLIST. The RETURN_TYPE is the desired type
for conversion operators. If OBJ is NULL_TREE, FLAGS and CTYPE are
as for add_function_candidate. If an OBJ is supplied, FLAGS and
- CTYPE are ignored, and OBJ is as for add_conv_candidate. */
+ CTYPE are ignored, and OBJ is as for add_conv_candidate.
+
+ SHORTCUT_BAD_CONVS is as in add_function_candidate. */
static struct z_candidate*
add_template_candidate_real (struct z_candidate **candidates, tree tmpl,
const vec<tree, va_gc> *arglist, tree return_type,
tree access_path, tree conversion_path,
int flags, tree obj, unification_kind_t strict,
- tsubst_flags_t complain)
+ bool shortcut_bad_convs, tsubst_flags_t complain)
{
int ntparms = DECL_NTPARMS (tmpl);
tree targs = make_tree_vec (ntparms);
errs = errorcount+sorrycount;
if (!obj)
- convs = alloc_conversions (nargs);
+ {
+ convs = alloc_conversions (nargs);
+
+ if (shortcut_bad_convs
+ && DECL_NONSTATIC_MEMBER_FUNCTION_P (tmpl)
+ && !DECL_CONSTRUCTOR_P (tmpl))
+ {
+ /* Check the 'this' conversion before proceeding with deduction.
+ This is effectively an extension of the DR 1391 resolution
+ that we perform in check_non_deducible_conversions, though it's
+ convenient to do this extra check here instead of there. */
+ tree parmtype = TREE_VALUE (TYPE_ARG_TYPES (TREE_TYPE (tmpl)));
+ tree argtype = lvalue_type (first_arg);
+ tree arg = first_arg;
+ conversion *t = build_this_conversion (tmpl, ctype,
+ parmtype, argtype, arg,
+ flags, complain);
+ convs[0] = t;
+ if (t->bad_p)
+ {
+ reason = bad_arg_conversion_rejection (first_arg, 0,
+ arg, parmtype,
+ EXPR_LOCATION (arg));
+ goto fail;
+ }
+ }
+ }
fn = fn_type_unification (tmpl, explicit_targs, targs,
args_without_in_chrg,
nargs_without_in_chrg,
else
cand = add_function_candidate (candidates, fn, ctype,
first_arg, arglist, access_path,
- conversion_path, flags, convs, complain);
+ conversion_path, flags, convs,
+ shortcut_bad_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
return cand;
fail:
- return add_candidate (candidates, tmpl, first_arg, arglist, nargs, NULL,
- access_path, conversion_path, 0, reason, flags);
+ int viable = (reason->code == rr_bad_arg_conversion ? -1 : 0);
+ return add_candidate (candidates, tmpl, first_arg, arglist, nargs, convs,
+ access_path, conversion_path, viable, reason, flags);
}
tree explicit_targs, tree first_arg,
const vec<tree, va_gc> *arglist, tree return_type,
tree access_path, tree conversion_path, int flags,
- unification_kind_t strict, tsubst_flags_t complain)
+ unification_kind_t strict, bool shortcut_bad_convs,
+ tsubst_flags_t complain)
{
return
add_template_candidate_real (candidates, tmpl, ctype,
explicit_targs, first_arg, arglist,
return_type, access_path, conversion_path,
- flags, NULL_TREE, strict, complain);
+ flags, NULL_TREE, strict, shortcut_bad_convs,
+ complain);
}
/* Create an overload candidate for the conversion function template TMPL,
add_template_candidate_real (candidates, tmpl, NULL_TREE, NULL_TREE,
NULL_TREE, arglist, return_type, access_path,
conversion_path, 0, obj, DEDUCE_CALL,
- complain);
+ /*shortcut_bad_convs=*/false, complain);
}
/* The CANDS are the set of candidates that were considered for
/* Delay creating the implicit this parameter until it is needed. */
non_static_args = NULL;
+ bool seen_strictly_viable = any_strictly_viable (*candidates);
/* If there's a non-template perfect match, we don't need to consider
templates. So check non-templates first. This optimization is only
really needed for the defaulted copy constructor of tuple and the like
else /*if (flags & LOOKUP_DEFAULTED)*/
which = non_templates;
+ /* During overload resolution, we first consider each function under the
+ assumption that we'll eventually find a strictly viable candidate.
+ This allows us to circumvent our defacto behavior when checking
+ argument conversions and shortcut consideration of the candidate
+ upon encountering the first bad conversion. If this assumption
+ turns out to be false, and all candidates end up being non-strictly
+ viable, then we reconsider such candidates under the defacto behavior.
+ This trick is important for pruning member function overloads according
+ to their const/ref-qualifiers (since all 'this' conversions are at
+ worst bad) without breaking -fpermissive. */
+ tree bad_fns = NULL_TREE;
+ bool shortcut_bad_convs = true;
+
again:
for (tree fn : lkp_range (fns))
{
}
if (TREE_CODE (fn) == TEMPLATE_DECL)
- add_template_candidate (candidates,
- fn,
- ctype,
- explicit_targs,
- fn_first_arg,
- fn_args,
- return_type,
- access_path,
- conversion_path,
- flags,
- strict,
- complain);
+ {
+ if (!add_template_candidate (candidates,
+ fn,
+ ctype,
+ explicit_targs,
+ fn_first_arg,
+ fn_args,
+ return_type,
+ access_path,
+ conversion_path,
+ flags,
+ strict,
+ shortcut_bad_convs,
+ complain))
+ continue;
+ }
else
{
add_function_candidate (candidates,
conversion_path,
flags,
NULL,
+ shortcut_bad_convs,
complain);
if (perfect_candidate_p (*candidates))
seen_perfect = true;
}
+
+ z_candidate *cand = *candidates;
+ if (cand->viable == 1)
+ seen_strictly_viable = true;
+
+ if (cand->viable == -1
+ && shortcut_bad_convs
+ && !cand->convs[cand->reversed () ? 0 : cand->num_convs - 1])
+ {
+ /* This candidate has been tentatively marked non-strictly viable,
+ and we didn't compute all argument conversions for it (having
+ stopped at the first bad conversion). Add the function to BAD_FNS
+ to fully reconsider later if we don't find any strictly viable
+ candidates. */
+ bad_fns = lookup_add (fn, bad_fns);
+ *candidates = (*candidates)->next;
+ }
}
if (which == non_templates && !seen_perfect)
{
which = templates;
goto again;
}
+ else if (which == templates
+ && !seen_strictly_viable
+ && shortcut_bad_convs
+ && bad_fns)
+ {
+ /* None of the candidates are strictly viable, so consider again those
+ functions in BAD_FNS, this time without shortcutting bad conversions
+ so that all their argument conversions are computed. */
+ which = either;
+ fns = bad_fns;
+ shortcut_bad_convs = false;
+ goto again;
+ }
}
/* Returns 1 if P0145R2 says that the LHS of operator CODE is evaluated first,