[C++ PATCH] Fix xvalue COND_EXPR handling (PR c++/88103)
Jakub Jelinek
jakub@redhat.com
Mon Dec 3 21:36:00 GMT 2018
On Mon, Dec 03, 2018 at 02:44:32PM -0500, Jason Merrill wrote:
> > > Is there a reason not to use the 'move' function here?
> >
> > That doesn't work at all. move doesn't call cp_convert, but
> > build_static_cast (though for the same reference && type).
> > But while cp_convert only adds NOP_EXPR around it, build_static_cast adds
> > a target_expr, addr_expr around that, nop_expr cast to the reference && type
> > and finally indirect_ref that the caller doesn't expect, because it adds it
> > by itself, e.g. in
> > 2424 if (temp)
> > 2425 object = cp_build_fold_indirect_ref (temp);
>
> So the caller is trying to take the address of the COND_EXPR, which should
> have POINTER_TYPE. And then indirecting that gives an lvalue, as it should.
> The bug is in the caller, build_class_member_access_expr.
So like this then (if it passes bootstrap/regtest)? Seems to fix the
testcase.
2018-12-03 Jakub Jelinek <jakub@redhat.com>
PR c++/88103
* typeck.c (build_class_member_access_expr): If unary_complex_lvalue
turned xvalue_p into non-xvalue_p, call move on it.
* g++.dg/cpp0x/rv-cond3.C: New test.
--- gcc/cp/typeck.c.jj 2018-12-02 21:41:09.824475721 +0100
+++ gcc/cp/typeck.c 2018-12-03 22:06:04.425357227 +0100
@@ -2422,7 +2422,13 @@ build_class_member_access_expr (cp_expr
{
tree temp = unary_complex_lvalue (ADDR_EXPR, object);
if (temp)
- object = cp_build_fold_indirect_ref (temp);
+ {
+ temp = cp_build_fold_indirect_ref (temp);
+ if (xvalue_p (object) && !xvalue_p (temp))
+ /* Preserve xvalue kind. */
+ temp = move (temp);
+ object = temp;
+ }
}
/* In [expr.ref], there is an explicit list of the valid choices for
--- gcc/testsuite/g++.dg/cpp0x/rv-cond3.C.jj 2018-12-03 22:04:14.064144468 +0100
+++ gcc/testsuite/g++.dg/cpp0x/rv-cond3.C 2018-12-03 22:04:14.064144468 +0100
@@ -0,0 +1,22 @@
+// PR c++/88103
+// { dg-do compile { target c++11 } }
+
+struct A {
+ A (int);
+ A&& foo () &&;
+ int i;
+};
+void free (A&&);
+
+void test_xvalue (A a){
+ A&& ref = true ? static_cast<A&&> (a) : static_cast<A&&> (a);
+ free (true ? static_cast<A&&> (a) : static_cast<A&&> (a));
+ (true ? static_cast<A&&> (a) : static_cast<A&&> (a)).foo ();
+ int&& k = (true ? static_cast<A&&> (a) : static_cast<A&&> (a)).i;
+}
+void test_prvalue (A a){
+ A&& ref = true ? static_cast<A&&> (a) : 1;
+ free (true ? static_cast<A&&> (a) : 1);
+ (true ? static_cast<A&&> (a) : 1).foo ();
+ int&& k = (true ? static_cast<A&&> (a) : 1).i;
+}
Jakub
More information about the Gcc-patches
mailing list