From 2f75f5154f05bd9ebc4e582ec5b4aca9f1d8bbac Mon Sep 17 00:00:00 2001 From: Jason Merrill Date: Wed, 26 Feb 2014 11:48:22 -0500 Subject: [PATCH] re PR c++/60345 (r208159 causes Firefox build error) PR c++/60345 Revert: DR 1571 * call.c (reference_binding): Recurse on user-defined conversion. (convert_like_real) [ck_ref_bind]: Explain cv-qual mismatch. From-SVN: r208175 --- gcc/cp/ChangeLog | 8 +++++ gcc/cp/call.c | 64 +++++++++------------------------- gcc/testsuite/g++.dg/cpp0x/overload3.C | 2 +- gcc/testsuite/g++.dg/cpp0x/rv-init1.C | 26 -------------- 4 files changed, 26 insertions(+), 74 deletions(-) delete mode 100644 gcc/testsuite/g++.dg/cpp0x/rv-init1.C diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index a27643e..ce6085d 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,11 @@ +2014-02-26 Jason Merrill + + PR c++/60345 + Revert: + DR 1571 + * call.c (reference_binding): Recurse on user-defined conversion. + (convert_like_real) [ck_ref_bind]: Explain cv-qual mismatch. + 2014-02-25 Jason Merrill DR 1571 diff --git a/gcc/cp/call.c b/gcc/cp/call.c index 32767ec..700099d 100644 --- a/gcc/cp/call.c +++ b/gcc/cp/call.c @@ -1677,37 +1677,20 @@ reference_binding (tree rto, tree rfrom, tree expr, bool c_cast_p, int flags, if (!conv) return NULL; - /* Limit this to C++11 mode for GCC 4.9, to be safe. */ - if (cxx_dialect >= cxx11 && conv->user_conv_p) - { - /* If initializing the temporary used a conversion function, - recalculate the second conversion sequence. */ - for (conversion *t = conv; t; t = next_conversion (t)) - if (t->kind == ck_user - && DECL_CONV_FN_P (t->cand->fn)) - { - tree ftype = TREE_TYPE (TREE_TYPE (t->cand->fn)); - if (TREE_CODE (ftype) != REFERENCE_TYPE) - /* Pretend we start from an xvalue to avoid trouble from - LOOKUP_NO_TEMP_BIND. */ - ftype = cp_build_reference_type (ftype, true); - conversion *new_second - = reference_binding (rto, ftype, NULL_TREE, c_cast_p, - flags|LOOKUP_NO_CONVERSION, complain); - if (!new_second) - return NULL; - conv = merge_conversion_sequences (t, new_second); - break; - } - } - - if (conv->kind != ck_ref_bind) - conv = build_conv (ck_ref_bind, rto, conv); - + conv = build_conv (ck_ref_bind, rto, conv); /* This reference binding, unlike those above, requires the creation of a temporary. */ conv->need_temporary_p = true; - conv->rvaluedness_matches_p = TYPE_REF_IS_RVALUE (rto); + if (TYPE_REF_IS_RVALUE (rto)) + { + conv->rvaluedness_matches_p = 1; + /* In the second case, if the reference is an rvalue reference and + the second standard conversion sequence of the user-defined + conversion sequence includes an lvalue-to-rvalue conversion, the + program is ill-formed. */ + if (conv->user_conv_p && next_conversion (conv)->kind == ck_rvalue) + conv->bad_p = 1; + } return conv; } @@ -6230,25 +6213,12 @@ convert_like_real (conversion *convs, tree expr, tree fn, int argnum, if (convs->bad_p && !next_conversion (convs)->bad_p) { - gcc_assert (TYPE_REF_IS_RVALUE (ref_type)); - - if (real_lvalue_p (expr) - || next_conversion(convs)->kind == ck_rvalue) - error_at (loc, "cannot bind %qT lvalue to %qT", - TREE_TYPE (expr), totype); - else if (!reference_compatible_p (totype, TREE_TYPE (expr))) - error_at (loc, "binding %qT to reference of type %qT " - "discards qualifiers", TREE_TYPE (expr),totype); - else - gcc_unreachable (); - if (convs->user_conv_p) - for (conversion *t = convs; t; t = next_conversion (t)) - if (t->kind == ck_user) - { - print_z_candidate (loc, "after user-defined conversion:", - t->cand); - break; - } + gcc_assert (TYPE_REF_IS_RVALUE (ref_type) + && (real_lvalue_p (expr) + || next_conversion(convs)->kind == ck_rvalue)); + + error_at (loc, "cannot bind %qT lvalue to %qT", + TREE_TYPE (expr), totype); if (fn) inform (input_location, "initializing argument %P of %q+D", argnum, fn); diff --git a/gcc/testsuite/g++.dg/cpp0x/overload3.C b/gcc/testsuite/g++.dg/cpp0x/overload3.C index b8f781a..e521b35 100644 --- a/gcc/testsuite/g++.dg/cpp0x/overload3.C +++ b/gcc/testsuite/g++.dg/cpp0x/overload3.C @@ -13,5 +13,5 @@ struct wrap int main() { wrap w; - f(w); // { dg-error "" } + f(w); // { dg-error "lvalue" } } diff --git a/gcc/testsuite/g++.dg/cpp0x/rv-init1.C b/gcc/testsuite/g++.dg/cpp0x/rv-init1.C deleted file mode 100644 index 2e8d4f7..0000000 --- a/gcc/testsuite/g++.dg/cpp0x/rv-init1.C +++ /dev/null @@ -1,26 +0,0 @@ -// Core DR 1604/1571/1572 -// { dg-require-effective-target c++11 } - -struct Banana { }; -struct Enigma { operator const Banana(); }; -struct Doof { operator Banana&(); }; -void enigmatic() { - typedef const Banana ConstBanana; - Banana &&banana1 = ConstBanana(); // { dg-error "" } - Banana &&banana2 = Enigma(); // { dg-error "" } - Banana &&banana3 = Doof(); // { dg-error "" } -} - -class A { -public: - operator volatile int &(); -}; -A a; - -const int & ir1a = a.operator volatile int&(); // { dg-error "" } -const int & ir2a = a; // { dg-error "" } - -struct X { - operator int&(); -} x; -int&& rri2 = X(); // { dg-error "" } -- 2.7.4