On Thu, Sep 20, 2018 at 11:53 AM, Marek Polacek <pola...@redhat.com> wrote: > On Thu, Sep 20, 2018 at 11:25:38AM -0400, Jason Merrill wrote: >> On Wed, Sep 19, 2018 at 9:50 PM, Marek Polacek <pola...@redhat.com> wrote: >> > Aaaand this addresses >> > <https://gcc.gnu.org/bugzilla/show_bug.cgi?id=87150#c11>, >> > as I promised earlier. I hope I got it right. >> > >> > Bootstrapped/regtested on x86_64-linux, ok for trunk? >> > >> > 2018-09-19 Marek Polacek <pola...@redhat.com> >> > >> > PR c++/87109 - wrong ctor with maybe-rvalue semantics. >> > * call.c (build_user_type_conversion_1): Refine the maybe-rvalue >> > check to only return if we're converting from a base class. >> > >> > * g++.dg/cpp0x/ref-qual19.C: Adjust the expected results. >> > * g++.dg/cpp0x/ref-qual20.C: New test. >> > >> > diff --git gcc/cp/call.c gcc/cp/call.c >> > index ddf0ed044a0..4bbd77b9cef 100644 >> > --- gcc/cp/call.c >> > +++ gcc/cp/call.c >> > @@ -4034,9 +4034,13 @@ build_user_type_conversion_1 (tree totype, tree >> > expr, int flags, >> > conv->bad_p = true; >> > >> > /* We're performing the maybe-rvalue overload resolution and >> > - a conversion function is in play. This isn't going to work >> > - because we would not end up with a suitable constructor. */ >> > - if ((flags & LOOKUP_PREFER_RVALUE) && !DECL_CONSTRUCTOR_P (cand->fn)) >> > + a conversion function is in play. If we're converting from >> > + a base class to a derived class, reject the conversion. */ >> > + if ((flags & LOOKUP_PREFER_RVALUE) >> > + && !DECL_CONSTRUCTOR_P (cand->fn) >> > + && CLASS_TYPE_P (fromtype) >> > + && CLASS_TYPE_P (totype) >> > + && DERIVED_FROM_P (fromtype, totype)) >> >> Here fromtype is the type we're converting from, and what we want to >> reject is converting the return value of the conversion op to a base >> class. CLASS_TYPE_P (fromtype) will always be true, since it has a >> conversion op. And I think we also want to handle the case of totype >> being a reference. > > I think I totally misunderstood what this was about. It's actually about > this case > > struct Y { int y; }; > struct X : public Y { int x; }; > > struct A { > operator X(); > }; > > Y > fn (A a) > { > return a; > } > > where we want to avoid slicing of X when converting X to Y, yes?
Yes. Jason