diff options
author | Jason Merrill <jason@redhat.com> | 2014-01-27 23:31:39 -0500 |
---|---|---|
committer | Jason Merrill <jason@gcc.gnu.org> | 2014-01-27 23:31:39 -0500 |
commit | 63a18c8e46063cb7912d98ccb9131e481f3dbb09 (patch) | |
tree | 12a5917a842eff94ff7c70361836f0795759d066 /gcc | |
parent | b89cc12b9962ea4b8a01d51e506348e3933106c6 (diff) | |
download | gcc-63a18c8e46063cb7912d98ccb9131e481f3dbb09.zip gcc-63a18c8e46063cb7912d98ccb9131e481f3dbb09.tar.gz gcc-63a18c8e46063cb7912d98ccb9131e481f3dbb09.tar.bz2 |
re PR c++/59823 (conversion operator to const X& causes copy-construction of temporary)
PR c++/59823
Core DR 1138
* call.c (reference_binding): Pass LOOKUP_NO_TEMP_BIND for
list-initialization. A conversion to rvalue ref that involves
an lvalue-rvalue conversion is bad.
(convert_like_real): Give helpful error message.
From-SVN: r207170
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/cp/ChangeLog | 7 | ||||
-rw-r--r-- | gcc/cp/call.c | 24 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/cpp0x/overload3.C | 17 |
3 files changed, 41 insertions, 7 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 214cb57..66e5cb5 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,5 +1,12 @@ 2014-01-27 Jason Merrill <jason@redhat.com> + PR c++/59823 + Core DR 1138 + * call.c (reference_binding): Pass LOOKUP_NO_TEMP_BIND for + list-initialization. A conversion to rvalue ref that involves + an lvalue-rvalue conversion is bad. + (convert_like_real): Give helpful error message. + PR c++/54652 * decl.c (duplicate_decls): Always use oldtype for TYPE_DECL. diff --git a/gcc/cp/call.c b/gcc/cp/call.c index b3db840..f6566cf 100644 --- a/gcc/cp/call.c +++ b/gcc/cp/call.c @@ -1484,7 +1484,7 @@ reference_binding (tree rto, tree rfrom, tree expr, bool c_cast_p, int flags, direct-list-initialized, depending on the kind of initialization for the reference, and the reference is bound to that temporary. */ conv = implicit_conversion (to, from, expr, c_cast_p, - flags, complain); + flags|LOOKUP_NO_TEMP_BIND, complain); skip:; } @@ -1637,9 +1637,9 @@ reference_binding (tree rto, tree rfrom, tree expr, bool c_cast_p, int flags, /* [dcl.init.ref] - Otherwise, the reference shall be to a non-volatile const type. - - Under C++0x, [8.5.3/5 dcl.init.ref] it may also be an rvalue reference */ + Otherwise, the reference shall be an lvalue reference to a + non-volatile const type, or the reference shall be an rvalue + reference. */ if (!CP_TYPE_CONST_NON_VOLATILE_P (to) && !TYPE_REF_IS_RVALUE (rto)) return NULL; @@ -1677,7 +1677,16 @@ reference_binding (tree rto, tree rfrom, tree expr, bool c_cast_p, int flags, /* 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; } @@ -5881,7 +5890,7 @@ convert_like_real (conversion *convs, tree expr, tree fn, int argnum, && convs->kind != ck_list && convs->kind != ck_ambig && (convs->kind != ck_ref_bind - || convs->user_conv_p) + || (convs->user_conv_p && next_conversion (convs)->bad_p)) && (convs->kind != ck_rvalue || SCALAR_TYPE_P (totype)) && convs->kind != ck_base) @@ -6173,7 +6182,8 @@ 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) - && real_lvalue_p (expr)); + && (real_lvalue_p (expr) + || next_conversion(convs)->kind == ck_rvalue)); error_at (loc, "cannot bind %qT lvalue to %qT", TREE_TYPE (expr), totype); diff --git a/gcc/testsuite/g++.dg/cpp0x/overload3.C b/gcc/testsuite/g++.dg/cpp0x/overload3.C new file mode 100644 index 0000000..e521b35 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/overload3.C @@ -0,0 +1,17 @@ +// PR c++/59823 +// { dg-options "-std=c++11" } + +struct X { }; + +void f(X&&); + +struct wrap +{ + operator const X&() const; +}; + +int main() +{ + wrap w; + f(w); // { dg-error "lvalue" } +} |