https://gcc.gnu.org/bugzilla/show_bug.cgi?id=89780

            Bug ID: 89780
           Summary: -Wpessimizing-move is too agressive with templates and
                    recommends pessimization
           Product: gcc
           Version: 9.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: c++
          Assignee: unassigned at gcc dot gnu.org
          Reporter: redbeard0531 at gmail dot com
  Target Milestone: ---

https://godbolt.org/z/JA-0Gq

#include <utility>

struct Dest {
    Dest() = default;
    Dest(Dest&&);
    Dest(const Dest&);
};
struct Source : Dest {};

template <typename T>
Dest withMove() {
    T x;
    return std::move(x);
}


template <typename T>
Dest noMove() {
    T x;
    return x;
}


template Dest withMove<Dest>();
template Dest withMove<Source>();

template Dest noMove<Dest>();
template Dest noMove<Source>();

> g++ -O3 -Wall -std=c++17

<source>: In instantiation of 'Dest withMove() [with T = Dest]':
<source>:24:30:   required from here
<source>:13:23: warning: moving a local object in a return statement prevents
copy elision [-Wpessimizing-move]
   13 |     return std::move(x);
      |                       ^
<source>:13:23: note: remove 'std::move' call


Basically, gcc9 recommends changing withMove, where both Source and Dest are
moved from, in to noMove, where Dest is copy-elided but Source is copied. While
this is a minor optimization for the Dest instantiation, it is a potentially
significant pesimization for the Source one.

Amusingly, this code trips a warning in clang that recommends doing the
opposite, adding the std::move to turn noMove into withMove:
https://godbolt.org/z/WONlMN

 <source>:20:12: warning: local variable 'x' will be copied despite being
returned by name [-Wreturn-std-move]
    return x;
           ^
<source>:28:15: note: in instantiation of function template specialization
'noMove<Source>' requested here
template Dest noMove<Source>();
              ^
<source>:20:12: note: call 'std::move' explicitly to avoid copying
    return x;
           ^
           std::move(x)

There is just no winning!

Reply via email to