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

            Bug ID: 115718
           Summary: Deficiencies in -Wnrvo
           Product: gcc
           Version: unknown
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: c++
          Assignee: unassigned at gcc dot gnu.org
          Reporter: arthur.j.odwyer at gmail dot com
  Target Milestone: ---

Jason Turner recently did a video on `-Wnrvo`
https://www.youtube.com/watch?v=PTCFddZfnXc and I noticed some deficiencies in
GCC's handling of his very first example. Here's the example in Godbolt:

https://godbolt.org/z/7z6naEhhK

S f(bool b) {
    S s = S(1);
    S t = S(2);
    if (b) {
        return s;
    } else {
        return t;
    }
}

GCC complains: "not eliding copy on return in 'S f(bool)' [-Wnrvo]"

Trivial defect #1: The message should say "move", not "copy".

Bigger defect #2: No message is emitted for "return s", but in fact GCC doesn't
elide the move on "return s" either! This is significant, because GCC *could*
have elided the move on "return s" (by hoisting the test of the non-escaped
bool `b` above the constructions of `s` and `t`); GCC simply chose not to elide
it. So I would expect a warning there.
Especially considering that the warning is disable-able:
https://godbolt.org/z/56anKj4d3

Point #3: My Clang fork also implements something I've tentatively named
"-Wnrvo", but it diagnoses only those situations where the programmer
*specifically requested* NRVO via the [[clang::nrvo]] attribute on a return
statement, and the compiler couldn't grant their request. This makes it
feasible to turn on by default; although of course it also makes it far less
discoverable/applicable, because it won't trigger on un-annotated codebases at
all. Here's a side-by-side example: https://godbolt.org/z/fcK1b46c1

Point #4: Consider whether the point of this diagnostic is just to "debug"
GCC's elision heuristic, or to be pedagogical. E.g. should it diagnose
    auto [s] = std::make_tuple(S(1));
    return s; // this is a copy, no elision is possible
or
    ChildOfS c;
    return c; // this is slicing, no elision is possible
? (Right now it does not diagnose either of these. But an average programmer
might *think* that elision should apply to either or both of these cases, and
appreciate the information that it does not.)

Reply via email to