On 3/22/19 5:29 PM, Marek Polacek wrote:
On Thu, Mar 21, 2019 at 07:41:37PM -0400, Jason Merrill wrote:
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.

Thanks.  I wonder if you think that the following makes sense.

The gist of the patch is that if a conversion function returns a prvalue of
non-class type, get rid of the cv-quals.  Then reference_binding won't mark it
as bad here:
  1890   if (related_p && !at_least_as_qualified_p (to, from))
  1891     conv->bad_p = true;
so we accept the code.

Bootstrapped/regtested on x86_64-linux, ok for trunk/8?

2019-03-22  Marek Polacek  <pola...@redhat.com>

        PR c++/89705 - ICE with reference binding with conversion function.
        * call.c (reference_binding): If the result of the conversion function
        is a prvalue of non-class type, use the cv-unqualified type.

OK.

Jason

Reply via email to