On Wed, Aug 29, 2018 at 8:03 PM, Marek Polacek <pola...@redhat.com> wrote: > I've now gotten to the point where I question the validity of this PR, so it's > probably a good time to stop and ask for some advice. > > As discussed in <https://gcc.gnu.org/ml/gcc-patches/2018-08/msg01607.html>, we > choose the wrong overload for f1: > > struct C { }; > struct A { > operator C() &; > operator C() &&; > }; > > C f1(A a) > { > return a; // should call operator C()&, but calls operator C()&& > } > > Since we're returning a local variable, we know it's about to be destroyed, > so even though it's got a name, not for very much longer, so we activate move > semantics. So we perform overload resolution with 'a' turned into > *NON_LVALUE_EXPR<(A&) &a>, an xvalue. We need to convert 'a' from A to C, > which is taking place in build_user_type_conversion_1. It will see two > cadidates: > > A::operator C() && > A::operator C() & > > when adding these candidates in add_function_candidate we process the > ref-qualifiers by tweaking the type of the implicit object parameter by > turning > it into a reference type. Then we create an implicit conversion sequence > for converting the type of the argument to the type of the parameter, > so A to A&. That succeeds in the first case (an xvalue binding to an rvalue > reference) but fails in the second case (an xvalue binding to an lvalue > reference). And thus we end up using the first overload. > > But why is this invalid, again? [class.copy.elision] says "or if the type of > the first parameter of the selected constructor is not an rvalue reference to > the object's type (possibly cv-qualified), overload resolution is performed > again, considering the object as an lvalue." but I don't see how that applies > here. (Constructors can't have ref-qualifiers anyway.) > > Thoughts?
Where that rule comes in is when we choose the constructor for C: since we've already called operator C()&&, we choose C(C&&), which does not have a first parameter of "rvalue reference to cv A", so it should be rejected. Jason