summaryrefslogtreecommitdiff
path: root/gcc/cp/call.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/cp/call.c')
-rw-r--r--gcc/cp/call.c58
1 files changed, 50 insertions, 8 deletions
diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index 4ee0eafe81d..e9d6e7ea354 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -429,6 +429,7 @@ struct candidate_warning {
enum rejection_reason_code {
rr_none,
rr_arity,
+ rr_explicit_conversion,
rr_arg_conversion,
rr_bad_arg_conversion
};
@@ -534,15 +535,16 @@ null_ptr_cst_p (tree t)
return false;
}
-/* Returns nonzero if PARMLIST consists of only default parms and/or
- ellipsis. */
+/* Returns nonzero if PARMLIST consists of only default parms,
+ ellipsis, and/or undeduced parameter packs. */
bool
sufficient_parms_p (const_tree parmlist)
{
for (; parmlist && parmlist != void_list_node;
parmlist = TREE_CHAIN (parmlist))
- if (!TREE_PURPOSE (parmlist))
+ if (!TREE_PURPOSE (parmlist)
+ && !PACK_EXPANSION_P (TREE_VALUE (parmlist)))
return false;
return true;
}
@@ -607,6 +609,16 @@ bad_arg_conversion_rejection (tree first_arg, int n_arg, tree from, tree to)
return r;
}
+static struct rejection_reason *
+explicit_conversion_rejection (tree from, tree to)
+{
+ struct rejection_reason *r = alloc_rejection (rr_explicit_conversion);
+ r->u.conversion.n_arg = 0;
+ r->u.conversion.from_type = from;
+ r->u.conversion.to_type = to;
+ return r;
+}
+
/* Dynamically allocate a conversion. */
static conversion *
@@ -1362,6 +1374,8 @@ convert_class_to_reference_1 (tree reference_type, tree s, tree expr, int flags)
/* Don't allow binding of lvalues to rvalue references. */
if (TYPE_REF_IS_RVALUE (reference_type)
+ /* Function lvalues are OK, though. */
+ && TREE_CODE (TREE_TYPE (reference_type)) != FUNCTION_TYPE
&& !TYPE_REF_IS_RVALUE (TREE_TYPE (TREE_TYPE (cand->fn))))
cand->second_conv->bad_p = true;
}
@@ -3150,6 +3164,12 @@ print_z_candidate (const char *msgstr, struct z_candidate *candidate)
case rr_bad_arg_conversion:
print_conversion_rejection (loc, &r->u.bad_conversion);
break;
+ case rr_explicit_conversion:
+ inform (loc, " return type %qT of explicit conversion function "
+ "cannot be converted to %qT with a qualification "
+ "conversion", r->u.conversion.from_type,
+ r->u.conversion.to_type);
+ break;
case rr_none:
default:
/* This candidate didn't have any issues or we failed to
@@ -3426,9 +3446,10 @@ build_user_type_conversion_1 (tree totype, tree expr, int flags)
for (cand = candidates; cand != old_candidates; cand = cand->next)
{
+ tree rettype = TREE_TYPE (TREE_TYPE (cand->fn));
conversion *ics
= implicit_conversion (totype,
- TREE_TYPE (TREE_TYPE (cand->fn)),
+ rettype,
0,
/*c_cast_p=*/false, convflags);
@@ -3450,14 +3471,23 @@ build_user_type_conversion_1 (tree totype, tree expr, int flags)
if (!ics)
{
- tree rettype = TREE_TYPE (TREE_TYPE (cand->fn));
cand->viable = 0;
cand->reason = arg_conversion_rejection (NULL_TREE, -1,
rettype, totype);
}
+ else if (DECL_NONCONVERTING_P (cand->fn)
+ && ics->rank > cr_exact)
+ {
+ /* 13.3.1.5: For direct-initialization, those explicit
+ conversion functions that are not hidden within S and
+ yield type T or a type that can be converted to type T
+ with a qualification conversion (4.4) are also candidate
+ functions. */
+ cand->viable = -1;
+ cand->reason = explicit_conversion_rejection (rettype, totype);
+ }
else if (cand->viable == 1 && ics->bad_p)
{
- tree rettype = TREE_TYPE (TREE_TYPE (cand->fn));
cand->viable = -1;
cand->reason
= bad_arg_conversion_rejection (NULL_TREE, -1,
@@ -5510,7 +5540,18 @@ convert_like_real (conversion *convs, tree expr, tree fn, int argnum,
for (; t; t = convs->u.next)
{
- if (t->kind == ck_user || !t->bad_p)
+ if (t->kind == ck_user && t->cand->reason)
+ {
+ permerror (input_location, "invalid user-defined conversion "
+ "from %qT to %qT", TREE_TYPE (expr), totype);
+ print_z_candidate ("candidate is:", t->cand);
+ expr = convert_like_real (t, expr, fn, argnum, 1,
+ /*issue_conversion_warnings=*/false,
+ /*c_cast_p=*/false,
+ complain);
+ return cp_convert (totype, expr);
+ }
+ else if (t->kind == ck_user || !t->bad_p)
{
expr = convert_like_real (t, expr, fn, argnum, 1,
/*issue_conversion_warnings=*/false,
@@ -8296,7 +8337,8 @@ perform_implicit_conversion_flags (tree type, tree expr, tsubst_flags_t complain
else if (invalid_nonstatic_memfn_p (expr, complain))
/* We gave an error. */;
else
- error ("could not convert %qE to %qT", expr, type);
+ error ("could not convert %qE from %qT to %qT", expr,
+ TREE_TYPE (expr), type);
}
expr = error_mark_node;
}