C++ Logo

std-proposals

Advanced search

Re: [std-proposals] Stop gap required for NRVO until Anton's paper is assimilated

From: Arthur O'Dwyer <arthur.j.odwyer_at_[hidden]>
Date: Thu, 11 Jul 2024 12:52:56 -0400
On Thu, Jul 11, 2024 at 12:13 PM Tiago Freire via Std-Proposals <
std-proposals_at_[hidden]> wrote:

> The way I see it, any other solution that is not achieving guaranteed nrvo
> extensions without any additional markings (this includes functions) is a
> waste of time.
>

I intuitively agree with that statement; but I believe other participants
have said that RVO without annotation is unattractive to them because it's
not reliable (i.e. "faillure" is not diagnosable); they want markup, so
that they can be alerted when the markup fails.
GCC trunk just recently added something (tentatively?) called "-Wnrvo" that
attempts to diagnose failures of RVO without any markup. I encourage you to
try it out and see if it meets your needs. In practice, I suspect *it will
not *meet your needs.
Related bugs: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=115718


> What you need is quite simple.
> Any named variable X that is returned should guarantee nrvo unless a
> return statement exist that does not return X and X is alive.
>

Let's assume that by "variable" you mean "variable that's not a parameter,
and of automatic lifetime (not static or thread_local), and has the same
type (possibly cv-qualified) as the return type."
And let's assume that the return type is sufficiently non-trivial so that
it does not trigger [class.temporary]/3
<https://eel.is/c++draft/class.temporary#3>.
You'll have to decide whether catch-clause parameters count as
non-parameter local variables (per P2025), or not (per the status quo).
The return statement that "exists" has to be returning from *the current
function* (returns hidden inside lambdas don't interfere).

...None of these sound like showstoppers at all, but at least they show
that the proposal isn't one sentence. It's about as complicated as P2025 —
and not surprising, because P2025 is basically trying to do what you're
asking for, isn't it? What would be the difference between what you're
asking for, and what P2025 proposed?

The one big thing I see your sentence doing differently from P2025 is that
you're talking in terms of "lifetime" rather than in terms of "scope."
That makes some things a lot easier; e.g. you *almost* (not quite) get
correct handling of non-automatic variables for free, since they remain
"alive" even when they're not "in scope".
However, I think your choice makes the *spec* a lot harder, because C++
compilers need a foolproof way to decide whether they're going to do RVO on
a variable *at compile time*, where all that's available to them is
the *lexical
scoping* of things — the dynamic behavioral stuff like lifetime isn't
directly available until runtime, which is too late. So you'll have to
specify a standard heuristic mapping runtime lifetime onto some
compile-time property (like scope) — which, again, is exactly where P2025
ended up.

[...]

> If there are any markings to be added, these would be in terms of
> attributes that have no effect on the generated code, but mark expectations
> on behavior (like [[fallthrough]], or [[maybe_unused]]):
> i.e. you can mark a return statement as [[rvo]] (or something), but that
> only serves to issue a compiler warning in case the return statement cannot
> actually achieve rvo, either or not a variable is rvo is not dependent on
> the attribute.
>

FYI, I have exactly that idea in my Clang fork:
https://godbolt.org/z/fcK1b46c1 (right-hand pane is my P1144 compiler with
my annotated -Wnrvo; left-hand pane shows GCC trunk's different behavior
for unannotated -Wnrvo)

–Arthur

Received on 2024-07-11 16:53:11