* [wwwdocs] porting_to: Two-stage overload resolution for implicit move removed @ 2022-10-12 19:38 Marek Polacek 2022-10-12 20:50 ` Jonathan Wakely 2024-08-19 20:51 ` Gerald Pfeifer 0 siblings, 2 replies; 10+ messages in thread From: Marek Polacek @ 2022-10-12 19:38 UTC (permalink / raw) To: GCC Patches; +Cc: Jason Merrill, Jonathan Wakely As I promised in <https://gcc.gnu.org/pipermail/gcc-patches/2022-October/603189.html>, I'd like to update our GCC 13 porting_to.html with the following note. Does this look OK to commit? Thanks, diff --git a/htdocs/gcc-13/porting_to.html b/htdocs/gcc-13/porting_to.html index 84a00f21..243ed29d 100644 --- a/htdocs/gcc-13/porting_to.html +++ b/htdocs/gcc-13/porting_to.html @@ -42,5 +42,57 @@ be included explicitly when compiled with GCC 13: </li> </ul> +<h3 id="two-stage-or">Two-stage overload resolution for implicit move removed</h3> +<p> +GCC 13 removed the two-stage overload resolution when performing +implicit move, whereby the compiler does two separate overload resolutions: +one treating the operand as an rvalue, and then (if that resolution fails) +another one treating the operand as an lvalue. In the standard this was +introduced in C++11 and implemented in gcc in +<a href="https://gcc.gnu.org/git/?p=gcc.git;a=commitdiff;h=4ce8c5dea53d80736b9c0ba6faa7430ed65ed365"> +r251035</a>. In +<a href="https://gcc.gnu.org/git/?p=gcc.git;a=commitdiff;h=1722e2013f05f1f1f99379dbaa0c0df356da731f"> +r11-2412</a>, the fallback overload resolution was disabled in C++20 (but +not in C++17). Then C++23 <a href="https://wg21.link/p2266">P2266</a> +removed the fallback overload resolution, and changed the implicit move +rules once again. +</p> +<p> +The two overload resolutions approach was complicated and quirky, so users +should transition to the newer model. This change means that code that +previously didn't compile in C++17 will now compile, for example:</p> + +<pre><code> + struct S1 { S1(S1 &&); }; + struct S2 : S1 {}; + + S1 + f (S2 s) + { + return s; // OK, derived-to-base, use S1::S1(S1&&) + } +</code></pre> + +<p> +And conversely, code that used to work in C++17 may not compile anymore: +</p> + +<pre><code> + struct W { + W(); + }; + + struct F { + F(W&); + F(W&&) = delete; + }; + + F fn () + { + W w; + return w; // use w as rvalue -> use of deleted function F::F(W&&) + } +</code></pre> + </body> </html> ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [wwwdocs] porting_to: Two-stage overload resolution for implicit move removed 2022-10-12 19:38 [wwwdocs] porting_to: Two-stage overload resolution for implicit move removed Marek Polacek @ 2022-10-12 20:50 ` Jonathan Wakely 2022-10-12 22:24 ` Marek Polacek 2024-08-19 20:51 ` Gerald Pfeifer 1 sibling, 1 reply; 10+ messages in thread From: Jonathan Wakely @ 2022-10-12 20:50 UTC (permalink / raw) To: Marek Polacek; +Cc: GCC Patches, Jason Merrill On Wed, 12 Oct 2022 at 20:39, Marek Polacek <polacek@redhat.com> wrote: > > As I promised in > <https://gcc.gnu.org/pipermail/gcc-patches/2022-October/603189.html>, > I'd like to update our GCC 13 porting_to.html with the following note. > > Does this look OK to commit? Thanks, > > diff --git a/htdocs/gcc-13/porting_to.html b/htdocs/gcc-13/porting_to.html > index 84a00f21..243ed29d 100644 > --- a/htdocs/gcc-13/porting_to.html > +++ b/htdocs/gcc-13/porting_to.html > @@ -42,5 +42,57 @@ be included explicitly when compiled with GCC 13: > </li> > </ul> > > +<h3 id="two-stage-or">Two-stage overload resolution for implicit move removed</h3> > +<p> > +GCC 13 removed the two-stage overload resolution when performing > +implicit move, whereby the compiler does two separate overload resolutions: > +one treating the operand as an rvalue, and then (if that resolution fails) > +another one treating the operand as an lvalue. In the standard this was > +introduced in C++11 and implemented in gcc in > +<a href="https://gcc.gnu.org/git/?p=gcc.git;a=commitdiff;h=4ce8c5dea53d80736b9c0ba6faa7430ed65ed365"> > +r251035</a>. In > +<a href="https://gcc.gnu.org/git/?p=gcc.git;a=commitdiff;h=1722e2013f05f1f1f99379dbaa0c0df356da731f"> > +r11-2412</a>, the fallback overload resolution was disabled in C++20 (but > +not in C++17). Then C++23 <a href="https://wg21.link/p2266">P2266</a> > +removed the fallback overload resolution, and changed the implicit move > +rules once again. > +</p> > +<p> > +The two overload resolutions approach was complicated and quirky, so users > +should transition to the newer model. This change means that code that > +previously didn't compile in C++17 will now compile, for example:</p> > + > +<pre><code> > + struct S1 { S1(S1 &&); }; > + struct S2 : S1 {}; > + > + S1 > + f (S2 s) > + { > + return s; // OK, derived-to-base, use S1::S1(S1&&) > + } > +</code></pre> > + > +<p> > +And conversely, code that used to work in C++17 may not compile anymore: > +</p> > + > +<pre><code> > + struct W { > + W(); > + }; > + > + struct F { > + F(W&); > + F(W&&) = delete; > + }; > + > + F fn () > + { > + W w; > + return w; // use w as rvalue -> use of deleted function F::F(W&&) Deleted move constructors are an abomination, and should never occur in real code. I'm not sure using one even in an example like this should be encouraged. The example added by P2266 to Annex D is more realistic (and actually broke a libstdc++ test): X& foo(X&& x) { return x; } > + } > +</code></pre> > + > </body> > </html> > ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [wwwdocs] porting_to: Two-stage overload resolution for implicit move removed 2022-10-12 20:50 ` Jonathan Wakely @ 2022-10-12 22:24 ` Marek Polacek 2022-10-12 22:38 ` Jonathan Wakely 0 siblings, 1 reply; 10+ messages in thread From: Marek Polacek @ 2022-10-12 22:24 UTC (permalink / raw) To: Jonathan Wakely; +Cc: GCC Patches, Jason Merrill On Wed, Oct 12, 2022 at 09:50:36PM +0100, Jonathan Wakely wrote: > On Wed, 12 Oct 2022 at 20:39, Marek Polacek <polacek@redhat.com> wrote: > > > > As I promised in > > <https://gcc.gnu.org/pipermail/gcc-patches/2022-October/603189.html>, > > I'd like to update our GCC 13 porting_to.html with the following note. > > > > Does this look OK to commit? Thanks, > > > > diff --git a/htdocs/gcc-13/porting_to.html b/htdocs/gcc-13/porting_to.html > > index 84a00f21..243ed29d 100644 > > --- a/htdocs/gcc-13/porting_to.html > > +++ b/htdocs/gcc-13/porting_to.html > > @@ -42,5 +42,57 @@ be included explicitly when compiled with GCC 13: > > </li> > > </ul> > > > > +<h3 id="two-stage-or">Two-stage overload resolution for implicit move removed</h3> > > +<p> > > +GCC 13 removed the two-stage overload resolution when performing > > +implicit move, whereby the compiler does two separate overload resolutions: > > +one treating the operand as an rvalue, and then (if that resolution fails) > > +another one treating the operand as an lvalue. In the standard this was > > +introduced in C++11 and implemented in gcc in > > +<a href="https://gcc.gnu.org/git/?p=gcc.git;a=commitdiff;h=4ce8c5dea53d80736b9c0ba6faa7430ed65ed365"> > > +r251035</a>. In > > +<a href="https://gcc.gnu.org/git/?p=gcc.git;a=commitdiff;h=1722e2013f05f1f1f99379dbaa0c0df356da731f"> > > +r11-2412</a>, the fallback overload resolution was disabled in C++20 (but > > +not in C++17). Then C++23 <a href="https://wg21.link/p2266">P2266</a> > > +removed the fallback overload resolution, and changed the implicit move > > +rules once again. > > +</p> > > +<p> > > +The two overload resolutions approach was complicated and quirky, so users > > +should transition to the newer model. This change means that code that > > +previously didn't compile in C++17 will now compile, for example:</p> > > + > > +<pre><code> > > + struct S1 { S1(S1 &&); }; > > + struct S2 : S1 {}; > > + > > + S1 > > + f (S2 s) > > + { > > + return s; // OK, derived-to-base, use S1::S1(S1&&) > > + } > > +</code></pre> > > + > > +<p> > > +And conversely, code that used to work in C++17 may not compile anymore: > > +</p> > > + > > +<pre><code> > > + struct W { > > + W(); > > + }; > > + > > + struct F { > > + F(W&); > > + F(W&&) = delete; > > + }; > > + > > + F fn () > > + { > > + W w; > > + return w; // use w as rvalue -> use of deleted function F::F(W&&) > > Deleted move constructors are an abomination, and should never occur > in real code. I'm not sure using one even in an example like this > should be encouraged. The example added by P2266 to Annex D is more > realistic (and actually broke a libstdc++ test): > > X& foo(X&& x) { return x; } Right, but this code still compiles in C++17, it only fails to compile in C++23. The previous example now doesn't compile even in C++17. So how about this improved patch which makes it clear that code with deleted move constructors should never occur in practice, and adds a new note, specifically about P2266 and the code you showed? Thanks for taking a look, diff --git a/htdocs/gcc-13/porting_to.html b/htdocs/gcc-13/porting_to.html index 84a00f21..a9991e8b 100644 --- a/htdocs/gcc-13/porting_to.html +++ b/htdocs/gcc-13/porting_to.html @@ -42,5 +42,71 @@ be included explicitly when compiled with GCC 13: </li> </ul> +<h3 id="P2266">Implicit move rules change</h3> +<p> +GCC 13 implements C++23 <a href="https://wg21.link/p2266">P2266</a> which +simplified the rules for implicit move. As a consequence, valid C++20 +code that relies on a returned <em>id-expression</em>'s being an lvalue +may change behavior or fail to compile in C++23. For example:</p> + +<pre><code> + decltype(auto) f(int&& x) { return (x); } // returns int&&; previously returned int& + int& g(int&& x) { return x; } // ill-formed; previously well-formed +</code></pre> + +<h3 id="two-stage-or">Two-stage overload resolution for implicit move removed</h3> +<p>GCC 13 removed the two-stage overload resolution when performing +implicit move, whereby the compiler does two separate overload resolutions: +one treating the operand as an rvalue, and then (if that resolution fails) +another one treating the operand as an lvalue. In the standard this was +introduced in C++11 and implemented in gcc in +<a href="https://gcc.gnu.org/git/?p=gcc.git;a=commitdiff;h=4ce8c5dea53d80736b9c0ba6faa7430ed65ed365"> +r251035</a>. In +<a href="https://gcc.gnu.org/git/?p=gcc.git;a=commitdiff;h=1722e2013f05f1f1f99379dbaa0c0df356da731f"> +r11-2412</a>, the fallback overload resolution was disabled in C++20 (but +not in C++17). Then C++23 <a href="https://wg21.link/p2266">P2266</a> +removed the fallback overload resolution, and changed the implicit move +rules once again.</p> + +<p>The two overload resolutions approach was complicated and quirky, so users +should transition to the newer model. This change means that code that +previously didn't compile in C++17 will now compile, for example:</p> + +<pre><code> + struct S1 { S1(S1 &&); }; + struct S2 : S1 {}; + + S1 + f (S2 s) + { + return s; // OK, derived-to-base, use S1::S1(S1&&) + } +</code></pre> + +<p>Conversely, code that used to work in C++17 may not compile anymore. +For example, the following example used to compile in C++11...17 because +we performed two separate overload resolutions: one treating the operand +as an rvalue, and then (if that resolution failed) another one treating +the operand as an lvalue.<br> +<strong>NB:</strong> this example is contrived because deleted move +constructors should not occur in real code.</p> + +<pre><code> + struct W { + W(); + }; + + struct F { + F(W&); + F(W&&) = delete; + }; + + F fn () + { + W w; + return w; // use w as rvalue -> use of deleted function F::F(W&&) + } +</code></pre> + </body> </html> ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [wwwdocs] porting_to: Two-stage overload resolution for implicit move removed 2022-10-12 22:24 ` Marek Polacek @ 2022-10-12 22:38 ` Jonathan Wakely 2022-10-12 22:44 ` Marek Polacek 0 siblings, 1 reply; 10+ messages in thread From: Jonathan Wakely @ 2022-10-12 22:38 UTC (permalink / raw) To: Marek Polacek; +Cc: GCC Patches, Jason Merrill On Wed, 12 Oct 2022 at 23:24, Marek Polacek <polacek@redhat.com> wrote: > > On Wed, Oct 12, 2022 at 09:50:36PM +0100, Jonathan Wakely wrote: > > On Wed, 12 Oct 2022 at 20:39, Marek Polacek <polacek@redhat.com> wrote: > > > > > > As I promised in > > > <https://gcc.gnu.org/pipermail/gcc-patches/2022-October/603189.html>, > > > I'd like to update our GCC 13 porting_to.html with the following note. > > > > > > Does this look OK to commit? Thanks, > > > > > > diff --git a/htdocs/gcc-13/porting_to.html b/htdocs/gcc-13/porting_to.html > > > index 84a00f21..243ed29d 100644 > > > --- a/htdocs/gcc-13/porting_to.html > > > +++ b/htdocs/gcc-13/porting_to.html > > > @@ -42,5 +42,57 @@ be included explicitly when compiled with GCC 13: > > > </li> > > > </ul> > > > > > > +<h3 id="two-stage-or">Two-stage overload resolution for implicit move removed</h3> > > > +<p> > > > +GCC 13 removed the two-stage overload resolution when performing > > > +implicit move, whereby the compiler does two separate overload resolutions: > > > +one treating the operand as an rvalue, and then (if that resolution fails) > > > +another one treating the operand as an lvalue. In the standard this was > > > +introduced in C++11 and implemented in gcc in > > > +<a href="https://gcc.gnu.org/git/?p=gcc.git;a=commitdiff;h=4ce8c5dea53d80736b9c0ba6faa7430ed65ed365"> > > > +r251035</a>. In > > > +<a href="https://gcc.gnu.org/git/?p=gcc.git;a=commitdiff;h=1722e2013f05f1f1f99379dbaa0c0df356da731f"> > > > +r11-2412</a>, the fallback overload resolution was disabled in C++20 (but > > > +not in C++17). Then C++23 <a href="https://wg21.link/p2266">P2266</a> > > > +removed the fallback overload resolution, and changed the implicit move > > > +rules once again. > > > +</p> > > > +<p> > > > +The two overload resolutions approach was complicated and quirky, so users > > > +should transition to the newer model. This change means that code that > > > +previously didn't compile in C++17 will now compile, for example:</p> > > > + > > > +<pre><code> > > > + struct S1 { S1(S1 &&); }; > > > + struct S2 : S1 {}; > > > + > > > + S1 > > > + f (S2 s) > > > + { > > > + return s; // OK, derived-to-base, use S1::S1(S1&&) > > > + } > > > +</code></pre> > > > + > > > +<p> > > > +And conversely, code that used to work in C++17 may not compile anymore: > > > +</p> > > > + > > > +<pre><code> > > > + struct W { > > > + W(); > > > + }; > > > + > > > + struct F { > > > + F(W&); > > > + F(W&&) = delete; > > > + }; > > > + > > > + F fn () > > > + { > > > + W w; > > > + return w; // use w as rvalue -> use of deleted function F::F(W&&) > > > > Deleted move constructors are an abomination, and should never occur > > in real code. I'm not sure using one even in an example like this > > should be encouraged. The example added by P2266 to Annex D is more > > realistic (and actually broke a libstdc++ test): > > > > X& foo(X&& x) { return x; } > > Right, but this code still compiles in C++17, it only fails to compile > in C++23. The previous example now doesn't compile even in C++17. So > how about this improved patch which makes it clear that code with > deleted move constructors should never occur in practice, and adds a new > note, specifically about P2266 and the code you showed? Doh, I've just realised that F(W&&) isn't a move ctor at all. For some reason I read the example as F(F&&). I think your original example is fine, and the note would just be confusing (because it's not a deleted move ctor!) > > Thanks for taking a look, > > diff --git a/htdocs/gcc-13/porting_to.html b/htdocs/gcc-13/porting_to.html > index 84a00f21..a9991e8b 100644 > --- a/htdocs/gcc-13/porting_to.html > +++ b/htdocs/gcc-13/porting_to.html > @@ -42,5 +42,71 @@ be included explicitly when compiled with GCC 13: > </li> > </ul> > > +<h3 id="P2266">Implicit move rules change</h3> > +<p> > +GCC 13 implements C++23 <a href="https://wg21.link/p2266">P2266</a> which > +simplified the rules for implicit move. As a consequence, valid C++20 > +code that relies on a returned <em>id-expression</em>'s being an lvalue > +may change behavior or fail to compile in C++23. For example:</p> > + > +<pre><code> > + decltype(auto) f(int&& x) { return (x); } // returns int&&; previously returned int& > + int& g(int&& x) { return x; } // ill-formed; previously well-formed > +</code></pre> > + > +<h3 id="two-stage-or">Two-stage overload resolution for implicit move removed</h3> > +<p>GCC 13 removed the two-stage overload resolution when performing > +implicit move, whereby the compiler does two separate overload resolutions: > +one treating the operand as an rvalue, and then (if that resolution fails) > +another one treating the operand as an lvalue. In the standard this was > +introduced in C++11 and implemented in gcc in > +<a href="https://gcc.gnu.org/git/?p=gcc.git;a=commitdiff;h=4ce8c5dea53d80736b9c0ba6faa7430ed65ed365"> > +r251035</a>. In > +<a href="https://gcc.gnu.org/git/?p=gcc.git;a=commitdiff;h=1722e2013f05f1f1f99379dbaa0c0df356da731f"> > +r11-2412</a>, the fallback overload resolution was disabled in C++20 (but > +not in C++17). Then C++23 <a href="https://wg21.link/p2266">P2266</a> > +removed the fallback overload resolution, and changed the implicit move > +rules once again.</p> > + > +<p>The two overload resolutions approach was complicated and quirky, so users > +should transition to the newer model. This change means that code that > +previously didn't compile in C++17 will now compile, for example:</p> > + > +<pre><code> > + struct S1 { S1(S1 &&); }; > + struct S2 : S1 {}; > + > + S1 > + f (S2 s) > + { > + return s; // OK, derived-to-base, use S1::S1(S1&&) > + } > +</code></pre> > + > +<p>Conversely, code that used to work in C++17 may not compile anymore. > +For example, the following example used to compile in C++11...17 because > +we performed two separate overload resolutions: one treating the operand > +as an rvalue, and then (if that resolution failed) another one treating > +the operand as an lvalue.<br> > +<strong>NB:</strong> this example is contrived because deleted move > +constructors should not occur in real code.</p> > + > +<pre><code> > + struct W { > + W(); > + }; > + > + struct F { > + F(W&); > + F(W&&) = delete; > + }; > + > + F fn () > + { > + W w; > + return w; // use w as rvalue -> use of deleted function F::F(W&&) > + } > +</code></pre> > + > </body> > </html> > ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [wwwdocs] porting_to: Two-stage overload resolution for implicit move removed 2022-10-12 22:38 ` Jonathan Wakely @ 2022-10-12 22:44 ` Marek Polacek 0 siblings, 0 replies; 10+ messages in thread From: Marek Polacek @ 2022-10-12 22:44 UTC (permalink / raw) To: Jonathan Wakely; +Cc: GCC Patches, Jason Merrill On Wed, Oct 12, 2022 at 11:38:01PM +0100, Jonathan Wakely wrote: > On Wed, 12 Oct 2022 at 23:24, Marek Polacek <polacek@redhat.com> wrote: > > > > On Wed, Oct 12, 2022 at 09:50:36PM +0100, Jonathan Wakely wrote: > > > On Wed, 12 Oct 2022 at 20:39, Marek Polacek <polacek@redhat.com> wrote: > > > > > > > > As I promised in > > > > <https://gcc.gnu.org/pipermail/gcc-patches/2022-October/603189.html>, > > > > I'd like to update our GCC 13 porting_to.html with the following note. > > > > > > > > Does this look OK to commit? Thanks, > > > > > > > > diff --git a/htdocs/gcc-13/porting_to.html b/htdocs/gcc-13/porting_to.html > > > > index 84a00f21..243ed29d 100644 > > > > --- a/htdocs/gcc-13/porting_to.html > > > > +++ b/htdocs/gcc-13/porting_to.html > > > > @@ -42,5 +42,57 @@ be included explicitly when compiled with GCC 13: > > > > </li> > > > > </ul> > > > > > > > > +<h3 id="two-stage-or">Two-stage overload resolution for implicit move removed</h3> > > > > +<p> > > > > +GCC 13 removed the two-stage overload resolution when performing > > > > +implicit move, whereby the compiler does two separate overload resolutions: > > > > +one treating the operand as an rvalue, and then (if that resolution fails) > > > > +another one treating the operand as an lvalue. In the standard this was > > > > +introduced in C++11 and implemented in gcc in > > > > +<a href="https://gcc.gnu.org/git/?p=gcc.git;a=commitdiff;h=4ce8c5dea53d80736b9c0ba6faa7430ed65ed365"> > > > > +r251035</a>. In > > > > +<a href="https://gcc.gnu.org/git/?p=gcc.git;a=commitdiff;h=1722e2013f05f1f1f99379dbaa0c0df356da731f"> > > > > +r11-2412</a>, the fallback overload resolution was disabled in C++20 (but > > > > +not in C++17). Then C++23 <a href="https://wg21.link/p2266">P2266</a> > > > > +removed the fallback overload resolution, and changed the implicit move > > > > +rules once again. > > > > +</p> > > > > +<p> > > > > +The two overload resolutions approach was complicated and quirky, so users > > > > +should transition to the newer model. This change means that code that > > > > +previously didn't compile in C++17 will now compile, for example:</p> > > > > + > > > > +<pre><code> > > > > + struct S1 { S1(S1 &&); }; > > > > + struct S2 : S1 {}; > > > > + > > > > + S1 > > > > + f (S2 s) > > > > + { > > > > + return s; // OK, derived-to-base, use S1::S1(S1&&) > > > > + } > > > > +</code></pre> > > > > + > > > > +<p> > > > > +And conversely, code that used to work in C++17 may not compile anymore: > > > > +</p> > > > > + > > > > +<pre><code> > > > > + struct W { > > > > + W(); > > > > + }; > > > > + > > > > + struct F { > > > > + F(W&); > > > > + F(W&&) = delete; > > > > + }; > > > > + > > > > + F fn () > > > > + { > > > > + W w; > > > > + return w; // use w as rvalue -> use of deleted function F::F(W&&) > > > > > > Deleted move constructors are an abomination, and should never occur > > > in real code. I'm not sure using one even in an example like this > > > should be encouraged. The example added by P2266 to Annex D is more > > > realistic (and actually broke a libstdc++ test): > > > > > > X& foo(X&& x) { return x; } > > > > Right, but this code still compiles in C++17, it only fails to compile > > in C++23. The previous example now doesn't compile even in C++17. So > > how about this improved patch which makes it clear that code with > > deleted move constructors should never occur in practice, and adds a new > > note, specifically about P2266 and the code you showed? > > Doh, I've just realised that F(W&&) isn't a move ctor at all. For some > reason I read the example as F(F&&). And so did I while adding the note :[. > I think your original example is fine, and the note would just be > confusing (because it's not a deleted move ctor!) I think I'll go ahead with this, then (I've removed the NB). Thanks! diff --git a/htdocs/gcc-13/porting_to.html b/htdocs/gcc-13/porting_to.html index 84a00f21..ccd3f08f 100644 --- a/htdocs/gcc-13/porting_to.html +++ b/htdocs/gcc-13/porting_to.html @@ -42,5 +42,69 @@ be included explicitly when compiled with GCC 13: </li> </ul> +<h3 id="P2266">Implicit move rules change</h3> +<p> +GCC 13 implements C++23 <a href="https://wg21.link/p2266">P2266</a> which +simplified the rules for implicit move. As a consequence, valid C++20 +code that relies on a returned <em>id-expression</em>'s being an lvalue +may change behavior or fail to compile in C++23. For example:</p> + +<pre><code> + decltype(auto) f(int&& x) { return (x); } // returns int&&; previously returned int& + int& g(int&& x) { return x; } // ill-formed; previously well-formed +</code></pre> + +<h3 id="two-stage-or">Two-stage overload resolution for implicit move removed</h3> +<p>GCC 13 removed the two-stage overload resolution when performing +implicit move, whereby the compiler does two separate overload resolutions: +one treating the operand as an rvalue, and then (if that resolution fails) +another one treating the operand as an lvalue. In the standard this was +introduced in C++11 and implemented in gcc in +<a href="https://gcc.gnu.org/git/?p=gcc.git;a=commitdiff;h=4ce8c5dea53d80736b9c0ba6faa7430ed65ed365"> +r251035</a>. In +<a href="https://gcc.gnu.org/git/?p=gcc.git;a=commitdiff;h=1722e2013f05f1f1f99379dbaa0c0df356da731f"> +r11-2412</a>, the fallback overload resolution was disabled in C++20 (but +not in C++17). Then C++23 <a href="https://wg21.link/p2266">P2266</a> +removed the fallback overload resolution, and changed the implicit move +rules once again.</p> + +<p>The two overload resolutions approach was complicated and quirky, so users +should transition to the newer model. This change means that code that +previously didn't compile in C++17 will now compile, for example:</p> + +<pre><code> + struct S1 { S1(S1 &&); }; + struct S2 : S1 {}; + + S1 + f (S2 s) + { + return s; // OK, derived-to-base, use S1::S1(S1&&) + } +</code></pre> + +<p>Conversely, code that used to work in C++17 may not compile anymore. +For example, the following example used to compile in C++11...17 because +we performed two separate overload resolutions: one treating the operand +as an rvalue, and then (if that resolution failed) another one treating +the operand as an lvalue.<br> + +<pre><code> + struct W { + W(); + }; + + struct F { + F(W&); + F(W&&) = delete; + }; + + F fn () + { + W w; + return w; // use w as rvalue -> use of deleted function F::F(W&&) + } +</code></pre> + </body> </html> ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [wwwdocs] porting_to: Two-stage overload resolution for implicit move removed 2022-10-12 19:38 [wwwdocs] porting_to: Two-stage overload resolution for implicit move removed Marek Polacek 2022-10-12 20:50 ` Jonathan Wakely @ 2024-08-19 20:51 ` Gerald Pfeifer 2024-08-19 20:53 ` Marek Polacek 2024-08-19 21:34 ` Jonathan Wakely 1 sibling, 2 replies; 10+ messages in thread From: Gerald Pfeifer @ 2024-08-19 20:51 UTC (permalink / raw) To: Marek Polacek; +Cc: gcc-patches, Jonathan Wakely On Wed, 12 Oct 2022, Marek Polacek via Gcc-patches wrote: > +<p> > +The two overload resolutions approach was complicated and quirky, so users > +should transition to the newer model. This change means that code that > +previously didn't compile in C++17 will now compile, for example:</p> I looked at this recently and am wondering whether there is a word missing: "two overload" -> "two-stage overload"? If so, the patch below addresses that On the way, I changed "[code] will now compile" to "[code] may now compile", since not every code that failed to compile before will now compile (e.g., syntactically incorrect code). What do you think? Gerald diff --git a/htdocs/gcc-13/porting_to.html b/htdocs/gcc-13/porting_to.html index c727d66f..e595e120 100644 --- a/htdocs/gcc-13/porting_to.html +++ b/htdocs/gcc-13/porting_to.html @@ -82,9 +82,10 @@ not in C++17). Then C++23 <a href="https://wg21.link/p2266">P2266</a> removed the fallback overload resolution, and changed the implicit move rules once again.</p> -<p>The two overload resolutions approach was complicated and quirky, so users -should transition to the newer model. This change means that code that -previously didn't compile in C++17 will now compile, for example:</p> +<p>The two-stage overload resolutions approach was complicated and +quirky, so users should transition to the newer model. This change +means that code that previously didn't compile in C++17 may now +compile, for example:</p> <pre><code> struct S1 { S1(S1 &&); }; ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [wwwdocs] porting_to: Two-stage overload resolution for implicit move removed 2024-08-19 20:51 ` Gerald Pfeifer @ 2024-08-19 20:53 ` Marek Polacek 2024-08-19 21:34 ` Jonathan Wakely 1 sibling, 0 replies; 10+ messages in thread From: Marek Polacek @ 2024-08-19 20:53 UTC (permalink / raw) To: Gerald Pfeifer; +Cc: gcc-patches, Jonathan Wakely On Mon, Aug 19, 2024 at 10:51:28PM +0200, Gerald Pfeifer wrote: > On Wed, 12 Oct 2022, Marek Polacek via Gcc-patches wrote: > > +<p> > > +The two overload resolutions approach was complicated and quirky, so users > > +should transition to the newer model. This change means that code that > > +previously didn't compile in C++17 will now compile, for example:</p> > > I looked at this recently and am wondering whether there is a word > missing: "two overload" -> "two-stage overload"? > > If so, the patch below addresses that > > On the way, I changed "[code] will now compile" to "[code] may now > compile", since not every code that failed to compile before will now > compile (e.g., syntactically incorrect code). > > What do you think? LGTM, thanks. > diff --git a/htdocs/gcc-13/porting_to.html b/htdocs/gcc-13/porting_to.html > index c727d66f..e595e120 100644 > --- a/htdocs/gcc-13/porting_to.html > +++ b/htdocs/gcc-13/porting_to.html > @@ -82,9 +82,10 @@ not in C++17). Then C++23 <a href="https://wg21.link/p2266">P2266</a> > removed the fallback overload resolution, and changed the implicit move > rules once again.</p> > > -<p>The two overload resolutions approach was complicated and quirky, so users > -should transition to the newer model. This change means that code that > -previously didn't compile in C++17 will now compile, for example:</p> > +<p>The two-stage overload resolutions approach was complicated and > +quirky, so users should transition to the newer model. This change > +means that code that previously didn't compile in C++17 may now > +compile, for example:</p> > > <pre><code> > struct S1 { S1(S1 &&); }; > Marek ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [wwwdocs] porting_to: Two-stage overload resolution for implicit move removed 2024-08-19 20:51 ` Gerald Pfeifer 2024-08-19 20:53 ` Marek Polacek @ 2024-08-19 21:34 ` Jonathan Wakely 2024-08-19 21:35 ` Jonathan Wakely 2024-08-19 22:09 ` Marek Polacek 1 sibling, 2 replies; 10+ messages in thread From: Jonathan Wakely @ 2024-08-19 21:34 UTC (permalink / raw) To: Gerald Pfeifer; +Cc: Marek Polacek, gcc-patches On Mon, 19 Aug 2024 at 21:51, Gerald Pfeifer <gerald@pfeifer.com> wrote: > > On Wed, 12 Oct 2022, Marek Polacek via Gcc-patches wrote: > > +<p> > > +The two overload resolutions approach was complicated and quirky, so users > > +should transition to the newer model. This change means that code that > > +previously didn't compile in C++17 will now compile, for example:</p> > > I looked at this recently and am wondering whether there is a word > missing: "two overload" -> "two-stage overload"? > > If so, the patch below addresses that > > On the way, I changed "[code] will now compile" to "[code] may now > compile", since not every code that failed to compile before will now > compile (e.g., syntactically incorrect code). > > What do you think? No, it should either be "two-stage overload resolution" or leave it unchanged. But "two-stage overload resolutions" (plural) is wrong. > > Gerald > > > diff --git a/htdocs/gcc-13/porting_to.html b/htdocs/gcc-13/porting_to.html > index c727d66f..e595e120 100644 > --- a/htdocs/gcc-13/porting_to.html > +++ b/htdocs/gcc-13/porting_to.html > @@ -82,9 +82,10 @@ not in C++17). Then C++23 <a href="https://wg21.link/p2266">P2266</a> > removed the fallback overload resolution, and changed the implicit move > rules once again.</p> > > -<p>The two overload resolutions approach was complicated and quirky, so users > -should transition to the newer model. This change means that code that > -previously didn't compile in C++17 will now compile, for example:</p> > +<p>The two-stage overload resolutions approach was complicated and > +quirky, so users should transition to the newer model. This change > +means that code that previously didn't compile in C++17 may now > +compile, for example:</p> > > <pre><code> > struct S1 { S1(S1 &&); }; > ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [wwwdocs] porting_to: Two-stage overload resolution for implicit move removed 2024-08-19 21:34 ` Jonathan Wakely @ 2024-08-19 21:35 ` Jonathan Wakely 2024-08-19 22:09 ` Marek Polacek 1 sibling, 0 replies; 10+ messages in thread From: Jonathan Wakely @ 2024-08-19 21:35 UTC (permalink / raw) To: Gerald Pfeifer; +Cc: Marek Polacek, gcc-patches On Mon, 19 Aug 2024 at 22:34, Jonathan Wakely <jwakely@redhat.com> wrote: > > On Mon, 19 Aug 2024 at 21:51, Gerald Pfeifer <gerald@pfeifer.com> wrote: > > > > On Wed, 12 Oct 2022, Marek Polacek via Gcc-patches wrote: > > > +<p> > > > +The two overload resolutions approach was complicated and quirky, so users > > > +should transition to the newer model. This change means that code that > > > +previously didn't compile in C++17 will now compile, for example:</p> > > > > I looked at this recently and am wondering whether there is a word > > missing: "two overload" -> "two-stage overload"? > > > > If so, the patch below addresses that > > > > On the way, I changed "[code] will now compile" to "[code] may now > > compile", since not every code that failed to compile before will now > > compile (e.g., syntactically incorrect code). > > > > What do you think? > > No, it should either be "two-stage overload resolution" or leave it > unchanged. But "two-stage overload resolutions" (plural) is wrong. And if I had to choose, I think the original text was better. It wasn't two stages, it really was doing overload resolution twice. So there were two overload resolutions. > > > > > > Gerald > > > > > > diff --git a/htdocs/gcc-13/porting_to.html b/htdocs/gcc-13/porting_to.html > > index c727d66f..e595e120 100644 > > --- a/htdocs/gcc-13/porting_to.html > > +++ b/htdocs/gcc-13/porting_to.html > > @@ -82,9 +82,10 @@ not in C++17). Then C++23 <a href="https://wg21.link/p2266">P2266</a> > > removed the fallback overload resolution, and changed the implicit move > > rules once again.</p> > > > > -<p>The two overload resolutions approach was complicated and quirky, so users > > -should transition to the newer model. This change means that code that > > -previously didn't compile in C++17 will now compile, for example:</p> > > +<p>The two-stage overload resolutions approach was complicated and > > +quirky, so users should transition to the newer model. This change > > +means that code that previously didn't compile in C++17 may now > > +compile, for example:</p> > > > > <pre><code> > > struct S1 { S1(S1 &&); }; > > ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [wwwdocs] porting_to: Two-stage overload resolution for implicit move removed 2024-08-19 21:34 ` Jonathan Wakely 2024-08-19 21:35 ` Jonathan Wakely @ 2024-08-19 22:09 ` Marek Polacek 1 sibling, 0 replies; 10+ messages in thread From: Marek Polacek @ 2024-08-19 22:09 UTC (permalink / raw) To: Jonathan Wakely; +Cc: Gerald Pfeifer, gcc-patches On Mon, Aug 19, 2024 at 10:34:20PM +0100, Jonathan Wakely wrote: > On Mon, 19 Aug 2024 at 21:51, Gerald Pfeifer <gerald@pfeifer.com> wrote: > > > > On Wed, 12 Oct 2022, Marek Polacek via Gcc-patches wrote: > > > +<p> > > > +The two overload resolutions approach was complicated and quirky, so users > > > +should transition to the newer model. This change means that code that > > > +previously didn't compile in C++17 will now compile, for example:</p> > > > > I looked at this recently and am wondering whether there is a word > > missing: "two overload" -> "two-stage overload"? > > > > If so, the patch below addresses that > > > > On the way, I changed "[code] will now compile" to "[code] may now > > compile", since not every code that failed to compile before will now > > compile (e.g., syntactically incorrect code). > > > > What do you think? > > No, it should either be "two-stage overload resolution" or leave it > unchanged. But "two-stage overload resolutions" (plural) is wrong. I hadn't noticed the plural before. I agree that's wrong. Sorry :(. Marek ^ permalink raw reply [flat|nested] 10+ messages in thread
end of thread, other threads:[~2024-08-19 22:09 UTC | newest] Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2022-10-12 19:38 [wwwdocs] porting_to: Two-stage overload resolution for implicit move removed Marek Polacek 2022-10-12 20:50 ` Jonathan Wakely 2022-10-12 22:24 ` Marek Polacek 2022-10-12 22:38 ` Jonathan Wakely 2022-10-12 22:44 ` Marek Polacek 2024-08-19 20:51 ` Gerald Pfeifer 2024-08-19 20:53 ` Marek Polacek 2024-08-19 21:34 ` Jonathan Wakely 2024-08-19 21:35 ` Jonathan Wakely 2024-08-19 22:09 ` Marek Polacek
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).