I finally found the recent discussion I mentioned earlier: http://lists.isocpp.org/core/2018/06/4562.php
which hasn't made it into the issues list yet. This discussion seems to suggest that the standard is likely to change to allow this example and 87109, so fixing G++ to reject them may not be what we want to do right now. On Fri, Sep 7, 2018 at 4:30 AM, Marek Polacek <pola...@redhat.com> wrote: > Another case where we weren't respecting the [class.copy.elision]/3 rule that > "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." In this > case the types differ because of the derived-to-base conversion. As a result, > we chose the wrong ctor. > > It seems that if we set rvaluedness_matches_p for ck_base, build_over_call > then correctly returns error_mark_node for such ctor, because if sees that > the CONVERSION_RANK is unsuitable. > > Bootstrapped/regtested on x86_64-linux, ok for trunk? > > 2018-09-06 Marek Polacek <pola...@redhat.com> > > PR c++/87150 - wrong ctor with maybe-rvalue semantics. > * call.c (struct conversion): Update commentary. > (standard_conversion): Set rvaluedness_matches_p if > LOOKUP_PREFER_RVALUE > for ck_base. > > * g++.dg/cpp0x/move-return2.C: New test. > > diff --git gcc/cp/call.c gcc/cp/call.c > index 942b2c204be..03b4c5ab224 100644 > --- gcc/cp/call.c > +++ gcc/cp/call.c > @@ -102,10 +102,10 @@ struct conversion { > BOOL_BITFIELD base_p : 1; > /* If KIND is ck_ref_bind, true when either an lvalue reference is > being bound to an lvalue expression or an rvalue reference is > - being bound to an rvalue expression. If KIND is ck_rvalue, > + being bound to an rvalue expression. If KIND is ck_rvalue or ck_base, > true when we are treating an lvalue as an rvalue (12.8p33). If > - KIND is ck_base, always false. If ck_identity, we will be > - binding a reference directly or decaying to a pointer. */ > + ck_identity, we will be binding a reference directly or decaying to > + a pointer. */ > BOOL_BITFIELD rvaluedness_matches_p: 1; > BOOL_BITFIELD check_narrowing: 1; > /* Whether check_narrowing should only check TREE_CONSTANTs; used > @@ -1425,6 +1425,9 @@ standard_conversion (tree to, tree from, tree expr, > bool c_cast_p, > type. A temporary object is created to hold the result of > the conversion unless we're binding directly to a reference. */ > conv->need_temporary_p = !(flags & LOOKUP_NO_TEMP_BIND); > + if (flags & LOOKUP_PREFER_RVALUE) > + /* Tell convert_like_real to set LOOKUP_PREFER_RVALUE. */ > + conv->rvaluedness_matches_p = true; > } > else > return NULL; > diff --git gcc/testsuite/g++.dg/cpp0x/move-return2.C > gcc/testsuite/g++.dg/cpp0x/move-return2.C > index e69de29bb2d..681e9ecaca1 100644 > --- gcc/testsuite/g++.dg/cpp0x/move-return2.C > +++ gcc/testsuite/g++.dg/cpp0x/move-return2.C > @@ -0,0 +1,11 @@ > +// PR c++/87150 > +// { dg-do compile { target c++11 } } > + > +struct S1 { S1(S1 &&); }; > +struct S2 : S1 {}; > + > +S1 > +f (S2 s) > +{ > + return s; // { dg-error "use of deleted function" } > +}