]> gcc.gnu.org Git - gcc.git/commit
c++: Remove maybe-rvalue OR in implicit move
authorMarek Polacek <polacek@redhat.com>
Wed, 28 Sep 2022 14:37:34 +0000 (10:37 -0400)
committerMarek Polacek <polacek@redhat.com>
Wed, 12 Oct 2022 18:37:52 +0000 (14:37 -0400)
commitbc0d700b574a22f12db7f7587ce885f64ebcbfb0
tree8c4ce2f50e04ceea8dc2b9dcb986c2ade856aa50
parenta0c1a059101a3067d96211cbc4fae5905796d1db
c++: Remove maybe-rvalue OR in implicit move

This patch removes 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 via CWG 1579 and implemented in gcc in r251035.  In r11-2412,
we disabled the fallback OR in C++20 (but not in C++17).  Then C++23 P2266
removed the fallback overload resolution, and changed the implicit move rules
once again.  So we wound up with three different behaviors.

The two overload resolutions approach was complicated and quirky, so
users should transition to the newer model.  Removing the maybe-rvalue
OR also allows us to simplify our code, for instance, now we can get
rid of LOOKUP_PREFER_RVALUE altogether.

This change means that code that previously didn't compile in C++17 will
now compile, for example:

  struct S1 { S1(S1 &&); };
  struct S2 : S1 {};

  S1
  f (S2 s)
  {
    return s; // OK, derived-to-base, use S1::S1(S1&&)
  }

And conversely, code that used to work in C++17 may not compile anymore:

  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&&)
  }

I plan to add a note to porting_to.html.

gcc/cp/ChangeLog:

* call.cc (standard_conversion): Remove LOOKUP_PREFER_RVALUE code.
(reference_binding): Honor clk_implicit_rval even pre-C++20.
(implicit_conversion_1): Remove LOOKUP_PREFER_RVALUE code.
(build_user_type_conversion_1): Likewise.
(convert_like_internal): Likewise.
(build_over_call): Likewise.
* cp-tree.h (LOOKUP_PREFER_RVALUE): Remove.
(LOOKUP_NO_NARROWING): Adjust definition.
* except.cc (build_throw): Don't perform two overload resolutions.
* typeck.cc (maybe_warn_pessimizing_move): Don't use
LOOKUP_PREFER_RVALUE.
(check_return_expr): Don't perform two overload resolutions.

gcc/testsuite/ChangeLog:

* g++.dg/cpp0x/Wredundant-move10.C: Adjust dg-warning.
* g++.dg/cpp0x/Wredundant-move7.C: Likewise.
* g++.dg/cpp0x/move-return2.C: Remove dg-error.
* g++.dg/cpp0x/move-return4.C: Likewise.
* g++.dg/cpp0x/ref-qual20.C: Adjust expected return value.
* g++.dg/cpp0x/move-return5.C: New test.
gcc/cp/call.cc
gcc/cp/cp-tree.h
gcc/cp/except.cc
gcc/cp/typeck.cc
gcc/testsuite/g++.dg/cpp0x/Wredundant-move10.C
gcc/testsuite/g++.dg/cpp0x/Wredundant-move7.C
gcc/testsuite/g++.dg/cpp0x/move-return2.C
gcc/testsuite/g++.dg/cpp0x/move-return4.C
gcc/testsuite/g++.dg/cpp0x/move-return5.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp0x/ref-qual20.C
This page took 0.063662 seconds and 6 git commands to generate.