[Bug c++/86521] [8/9 Regression] GCC 8 selects incorrect overload of ref-qualified conversion operator template
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=86521 --- Comment #8 from Jason Merrill --- Author: jason Date: Wed Mar 13 23:34:51 2019 New Revision: 269667 URL: https://gcc.gnu.org/viewcvs?rev=269667=gcc=rev Log: PR c++/86521 - C++17 copy elision in initialization by constructor. This is an overlooked case in C++17 mandatory copy elision: We want overload resolution to reflect that initializing an object from a prvalue does not involve a copy or move constructor even when [over.match.ctor] says that only constructors are candidates. Here I implement that by looking through the copy/move constructor in joust. * call.c (joust_maybe_elide_copy): New. (joust): Call it. Modified: trunk/gcc/cp/ChangeLog trunk/gcc/cp/call.c trunk/gcc/testsuite/g++.dg/cpp0x/overload-conv-3.C trunk/gcc/testsuite/g++.dg/overload/conv-op2.C
[Bug c++/86521] [8/9 Regression] GCC 8 selects incorrect overload of ref-qualified conversion operator template
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=86521 --- Comment #7 from Jason Merrill --- Created attachment 45952 --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=45952=edit patch to prefer copy elision This implements that, but I'm going to hold off a bit before committing it.
[Bug c++/86521] [8/9 Regression] GCC 8 selects incorrect overload of ref-qualified conversion operator template
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=86521 --- Comment #6 from Jason Merrill --- (In reply to Jason Merrill from comment #4) > The cast is ambiguous > > To construct a 'base', we consider the two constructors > > 1) base(const base&); > 2) base(base&&); > > for each of them we could convert the argument by either > > 3) operator U () && > 4) operator U const& () const& > > For #1 we want to convert to const base&. For direct reference binding, #4 > is the only candidate, and it is viable. For #2 we want to convert to > base&&, only #3 is a candidate for direct reference binding, and it is > viable. > > The two user-defined conversion sequences are not comparable because they > use different conversion operators, so the initialization is ambiguous. ...although perhaps the C++17 mandatory copy elision should alter this calculation: initializing the object from the result of #3 doesn't actually use the copy constructor. In that case, we'd just be using #3, making it better than #4+#2. The standard doesn't currently say this, but it probably should.
[Bug c++/86521] [8/9 Regression] GCC 8 selects incorrect overload of ref-qualified conversion operator template
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=86521 --- Comment #5 from Jason Merrill --- Author: jason Date: Tue Mar 12 03:19:22 2019 New Revision: 269602 URL: https://gcc.gnu.org/viewcvs?rev=269602=gcc=rev Log: PR c++/86521 - wrong overload resolution with ref-qualifiers. Here we were wrongly treating binding a const lvalue ref to an xvalue as direct binding, which is wrong under [dcl.init.ref] and [over.match.ref]. * call.c (build_user_type_conversion_1): Don't use a conversion to a reference of the wrong rvalueness for direct binding. Added: trunk/gcc/testsuite/g++.dg/cpp0x/overload-conv-3.C Modified: trunk/gcc/cp/ChangeLog trunk/gcc/cp/call.c trunk/libstdc++-v3/testsuite/20_util/is_constructible/value-2.cc
[Bug c++/86521] [8/9 Regression] GCC 8 selects incorrect overload of ref-qualified conversion operator template
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=86521 --- Comment #4 from Jason Merrill --- The cast is ambiguous To construct a 'base', we consider the two constructors 1) base(const base&); 2) base(base&&); for each of them we could convert the argument by either 3) operator U () && 4) operator U const& () const& For #1 we want to convert to const base&. For direct reference binding, #4 is the only candidate, and it is viable. For #2 we want to convert to base&&, only #3 is a candidate for direct reference binding, and it is viable. The two user-defined conversion sequences are not comparable because they use different conversion operators, so the initialization is ambiguous.
[Bug c++/86521] [8/9 Regression] GCC 8 selects incorrect overload of ref-qualified conversion operator template
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=86521 Jason Merrill changed: What|Removed |Added Status|UNCONFIRMED |ASSIGNED Last reconfirmed||2019-03-11 Assignee|unassigned at gcc dot gnu.org |jason at gcc dot gnu.org Ever confirmed|0 |1
[Bug c++/86521] [8/9 Regression] GCC 8 selects incorrect overload of ref-qualified conversion operator template
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=86521 Matthijs van Duin changed: What|Removed |Added CC||matthijsvanduin at gmail dot com --- Comment #3 from Matthijs van Duin --- First off, your example is more complicated than it needs to be. A more minimal test case would be: #include struct Dest { Dest() = default; Dest( Dest && ) = default; Dest( Dest const & ) = delete; }; struct Source { Dest val; operator Dest () && { return std::move( val ); } operator Dest const & () const & { return val; } }; int main() { Source x; static_cast( std::move( x ) ); } Second, notice that the two conversions are not really directly comparable since one converts to directly Dest while the other converts to an expression used to invoke a constructor of Dest. While it seems desirable for the former to take preference over the latter, I'm not enough of a language lawyer to be able to figure out what the C++ standard actually requires overload resolution to do in this situation. Replacing operator Dest () && { by operator Dest && () && { fixes the problem, and has the additional benefit of avoiding unnecessary temporary materialization in situations like: void foo( Dest && ); int main() { Source x; foo( std::move( x ) ); }
[Bug c++/86521] [8/9 Regression] GCC 8 selects incorrect overload of ref-qualified conversion operator template
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=86521 Jakub Jelinek changed: What|Removed |Added Target Milestone|8.3 |8.4 --- Comment #2 from Jakub Jelinek --- GCC 8.3 has been released.
[Bug c++/86521] [8/9 Regression] GCC 8 selects incorrect overload of ref-qualified conversion operator template
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=86521 Richard Biener changed: What|Removed |Added Priority|P3 |P2
[Bug c++/86521] [8/9 Regression] GCC 8 selects incorrect overload of ref-qualified conversion operator template
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=86521 Jakub Jelinek changed: What|Removed |Added Target Milestone|8.2 |8.3 --- Comment #1 from Jakub Jelinek --- GCC 8.2 has been released.
[Bug c++/86521] [8/9 Regression] GCC 8 selects incorrect overload of ref-qualified conversion operator template
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=86521 Richard Biener changed: What|Removed |Added Keywords||rejects-valid Target Milestone|--- |8.2 Summary|GCC 8 selects incorrect |[8/9 Regression] GCC 8 |overload of ref-qualified |selects incorrect overload |conversion operator |of ref-qualified conversion |template|operator template