aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorJason Merrill <jason@redhat.com>2014-01-27 23:31:39 -0500
committerJason Merrill <jason@gcc.gnu.org>2014-01-27 23:31:39 -0500
commit63a18c8e46063cb7912d98ccb9131e481f3dbb09 (patch)
tree12a5917a842eff94ff7c70361836f0795759d066 /gcc
parentb89cc12b9962ea4b8a01d51e506348e3933106c6 (diff)
downloadgcc-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/ChangeLog7
-rw-r--r--gcc/cp/call.c24
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/overload3.C17
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" }
+}