On 3/21/19 4:55 PM, Marek Polacek wrote:
On Thu, Mar 21, 2019 at 04:13:29PM -0400, Jason Merrill wrote:
On 3/16/19 4:53 PM, Marek Polacek wrote:
Here we have code like
struct X { operator const int(); };
int&& rri = X();
which I think is invalid, because [dcl.init.ref] says that if types T1 and T2
are reference-related, no qualifiers can be dropped, and if the reference is an
rvalue reference, the initializer expression can't be an lvalue. And here the
result of the conversion is "const int", so the "const" would be dropped. A
similar ill-formed test from the standard is
struct X { operator int&(); };
int&& rri = X();
where the result of the conversion is an lvalue of related type. All the
compilers I've tried actually accept the first test, but I think that's wrong.
I don't think it is. g++ and clang++ reject the first test if you change
int to a class type, but prvalues of scalar type have no cv-qualifiers, so
the result of the conversion is a prvalue of type int, which is a perfectly
good initializer for int&&.
This is OK for the same reason:
int&& r = (const int)42;
Oop, this is embarassing, sorry. So I guess we're not handling the (5.3.2)
case in [dcl.init.ref] properly: "If the converted initializer is a prvalue,
its type T4 is adjusted to type “cv1 T4” ([conv.qual]) and the temporary
materialization conversion ([conv.rval]) is applied.
Sure, though I would think it's an issue of the bullet just above:
* has a class type (i.e., T2 is a class type), where T1 is not
reference-related to T2, and can be converted to an rvalue or function
lvalue of type “cv3 T3”, where “cv1 T1” is reference-compatible with
“cv3 T3” (see 11.3.1.6),
where X can be converted to an rvalue of type int, which is
reference-compatible with int.
Jason