From b028af11640a2a31c267b73cc40a9b162632a7d0 Mon Sep 17 00:00:00 2001 From: Jason Merrill Date: Mon, 20 Jun 2011 10:40:38 -0400 Subject: [PATCH] re PR c++/47080 ([C++0x] explicit conversion function return conversions not restricted to qualifications) PR c++/47080 * call.c (rejection_reason_code): Add rr_explicit_conversion. (print_z_candidate): Handle it. (explicit_conversion_rejection): New. (build_user_type_conversion_1): Reject an explicit conversion function that requires more than a qualification conversion. From-SVN: r175217 --- gcc/cp/ChangeLog | 7 ++++ gcc/cp/call.c | 46 +++++++++++++++++++++++--- gcc/testsuite/ChangeLog | 3 ++ gcc/testsuite/g++.dg/cpp0x/explicit6.C | 11 ++++++ 4 files changed, 63 insertions(+), 4 deletions(-) create mode 100644 gcc/testsuite/g++.dg/cpp0x/explicit6.C diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 9269a759d34..eff4c8ee81e 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,5 +1,12 @@ 2011-06-20 Jason Merrill + PR c++/47080 + * call.c (rejection_reason_code): Add rr_explicit_conversion. + (print_z_candidate): Handle it. + (explicit_conversion_rejection): New. + (build_user_type_conversion_1): Reject an explicit conversion + function that requires more than a qualification conversion. + PR c++/47635 * decl.c (grokdeclarator): Don't set ctype to an ENUMERAL_TYPE. diff --git a/gcc/cp/call.c b/gcc/cp/call.c index 09d73d0c4c5..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 }; @@ -608,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 * @@ -3153,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 @@ -3429,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); @@ -3453,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, @@ -5513,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, diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 337e5f9a2f4..5590283925f 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,5 +1,8 @@ 2011-06-20 Jason Merrill + PR c++/47080 + * g++.dg/cpp0x/explicit6.C: New. + PR c++/47635 * g++.dg/cpp0x/enum20.C: New. diff --git a/gcc/testsuite/g++.dg/cpp0x/explicit6.C b/gcc/testsuite/g++.dg/cpp0x/explicit6.C new file mode 100644 index 00000000000..0d620be0803 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/explicit6.C @@ -0,0 +1,11 @@ +// PR c++/47080 +// { dg-options -std=c++0x } + +struct A { + explicit operator int(); // { dg-message "qualification conversion" } +}; + +int main() { + bool b((A())); // { dg-error "invalid user-defined" } + !A(); // { dg-error "" } +} -- 2.30.2