diff options
Diffstat (limited to 'gcc/cp/call.c')
-rw-r--r-- | gcc/cp/call.c | 58 |
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; } |