diff options
author | Jason Merrill <jason@redhat.com> | 2011-06-20 10:40:38 -0400 |
---|---|---|
committer | Jason Merrill <jason@gcc.gnu.org> | 2011-06-20 10:40:38 -0400 |
commit | b028af11640a2a31c267b73cc40a9b162632a7d0 (patch) | |
tree | 5547a21a42cea0d32c973213b19d667cb827c2e9 /gcc | |
parent | de721390198dfc1d1521b315ad96e556d950224a (diff) | |
download | gcc-b028af11640a2a31c267b73cc40a9b162632a7d0.zip gcc-b028af11640a2a31c267b73cc40a9b162632a7d0.tar.gz gcc-b028af11640a2a31c267b73cc40a9b162632a7d0.tar.bz2 |
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
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/cp/ChangeLog | 7 | ||||
-rw-r--r-- | gcc/cp/call.c | 46 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 3 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/cpp0x/explicit6.C | 11 |
4 files changed, 63 insertions, 4 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 9269a75..eff4c8ee 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,5 +1,12 @@ 2011-06-20 Jason Merrill <jason@redhat.com> + 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 09d73d0..e9d6e7e 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 337e5f9..5590283 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,5 +1,8 @@ 2011-06-20 Jason Merrill <jason@redhat.com> + 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 0000000..0d620be --- /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 "" } +} |