Quantcast

Is this a regression? -r288654 Attn rsmith

classic Classic list List threaded Threaded
2 messages Options
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Is this a regression? -r288654 Attn rsmith

Brian Cain via cfe-dev
TL;DR: Should the example below work as it did before R288654?  If so, can someone hint as to where I can fix this?


Hi All-
Our automated system detected that some old r-value reference tests started failing.  Most simply:

long long x[37] = {37, 47, 59};
int main() {
        const_cast<decltype(x)&&>(x)[2] += 387;
        }

Fails with:  error: expression is not assignable
On the += operator.

Previously, this succeeded.  Interestingly, running this in -std=c++03 mode works (though warns that && is a C++11 feature).

The change in behavior is a result of  the ExprClassification.cpp changes in R288654 (the C+=11 addition to ClassifyInternal in Expr::ArraySubscriptExprClass).

It previously identified as a Cl::CL_LValue, however switched to being a CL_XValue, which SEEMS like the correct classification, as a cast to an rvalue reference of an Object is an XValue.  That said, I would still expect that assignment to be permitted, right?  Is the problem that ExprClassification.cpp's isModifiableLvalue classifies a CL_XValue as an MLV_InvalidExpression?

Or is CheckASignmentOperands checking the wrong thing? That it is a ModifiableLvalue rather than a modifiable GLValue?

Thanks,
Erich
_______________________________________________
cfe-dev mailing list
[hidden email]
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Is this a regression? -r288654 Attn rsmith

Brian Cain via cfe-dev
Ok, I hate to self-respond, but I think I've convinced myself (With Clark's help), that despite GCC and older Clang supporting this case, that it shouldn't be legal by reading of the standard.

Essentially, this is the exact same thing as:
foo().a[2] = 5;
Which, I would expect to fail, since assigning to a temporary is insane and illegal for a good reason.  The GLValue solution I proposed below is incorrect because:

5.18(Assignment and compound assignment operators):
The assignment operator... require a modifiable lvalue as their left operand and return an lvalue referring to the left operand.

Then, the DR that Richard was fixing changed 5.2.1 to say:
5.2.1(Subscripting):
The expression E1[E2] is identical (by definition) to *((E1)+(E2)), except that in the case of an array operand, the result is an lvalue if that operand is an lvalue, and an xvalue otherwise.

AKA, subscripting an xvalue array is still an xvalue, and thus cannot be assigned to.

Finally, a constcast to a rvalue reference of an Object Type is an xvalue:
5.2.11(Const cast):
The result of the expression const_cast<T>(v) is of type T.  If T is an lvalue reference to an object type, the result is an lvalue; if T is an rvalue reference to an object type, the result is an xvalue;...

Meaning that the const cast below is an xvalue, thus subscripting it is an xvalue, thus assigning to it is insane.

I believe the correct response here is for me to fix our tests :)

-----Original Message-----
From: Keane, Erich
Sent: Friday, March 24, 2017 3:20 PM
To: cfe-dev <[hidden email]>
Subject: Is this a regression? -r288654 Attn rsmith

TL;DR: Should the example below work as it did before R288654?  If so, can someone hint as to where I can fix this?


Hi All-
Our automated system detected that some old r-value reference tests started failing.  Most simply:

long long x[37] = {37, 47, 59};
int main() {
        const_cast<decltype(x)&&>(x)[2] += 387;
        }

Fails with:  error: expression is not assignable On the += operator.

Previously, this succeeded.  Interestingly, running this in -std=c++03 mode works (though warns that && is a C++11 feature).

The change in behavior is a result of  the ExprClassification.cpp changes in R288654 (the C+=11 addition to ClassifyInternal in Expr::ArraySubscriptExprClass).

It previously identified as a Cl::CL_LValue, however switched to being a CL_XValue, which SEEMS like the correct classification, as a cast to an rvalue reference of an Object is an XValue.  That said, I would still expect that assignment to be permitted, right?  Is the problem that ExprClassification.cpp's isModifiableLvalue classifies a CL_XValue as an MLV_InvalidExpression?

Or is CheckASignmentOperands checking the wrong thing? That it is a ModifiableLvalue rather than a modifiable GLValue?

Thanks,
Erich
_______________________________________________
cfe-dev mailing list
[hidden email]
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev
Loading...