Izaron added a comment.

There is a nice proposal (P2025) Guaranteed copy elision for return variables 
<http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2021/p2025r2.html> by 
**Anton Zhilin**. The poll on the proposal showed that its ideas are very 
welcome: link to cplusplus/papers github 
<https://github.com/cplusplus/papers/issues/756#issuecomment-845364557>. 
Although the proposal is not yet accepted into the Standard in its current 
wording, some ideas are still good and can be implemented "in advance".

> This proposal aims to provide guaranteed copy elision for common cases of 
> local variables being returned from a function, a.k.a. "guaranteed NRVO".

С++ сompiler implementations determine by their own rules whether there will be 
a NRVO (since it is not a required optimization). The proposal contains a 
collection of common cases of local variables being returned where copy elision 
is safe and makes senses and therefore is desirable to do.

The main requirement (omitting details for language-lawyers) is that:

> Copy elision is guaranteed for return x; if every return "seen" by x is 
> return x;

"seen by `x`" means here "all non-discarded return statements in `x`'s 
potential scope". There are more details in the proposal.

The collection of common cases contains 20 examples: §4.1. Examples 
<http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2021/p2025r2.html#examples>.
Here is the current status of these examples:

- [OK] 13 out of 20 examples are working in Clang as expected.
- [FAIL] 13th example: should be considered separately (as part of fixing 
consteval code)
- [FAIL] 14th example: should be considered separately (as I haven't looked yet 
how `CXXCatchStmt` works).
- [FAIL] 18th example: is unfixable now because of Clang's architecture: my 
comment on the issue 
<https://github.com/llvm/llvm-project/issues/50297#issuecomment-1033059593>.
- **[OK with the patch]** 7th, 8th, 11th, 15th example: are working with this 
patch.

In order to make the last group of 4 examples working, there is a need to 
rewrite the logic for calculating the NRVO candidate.
The `clang::Scope` class has methods `void AddDecl(Decl *D)`, `void 
addNRVOCandidate(VarDecl *VD)`, `void setNoNRVO()`, that are called in the 
order of the scope's parsing.

- `void AddDecl(Decl *D)` is called when there is a new `Decl *D` in the scope. 
The `D`'s potential scope starts now.
- `void addNRVOCandidate(VarDecl *VD)` is called when there is a `return 
<named-variable>` in the scope or when a children scope has successfully 
calculated its single NRVO candidate.
- `void setNoNRVO()` is called when there is a `return <not-a-named-var>` in 
the scope or when a children scope is telling us to drop our NRVO candidates 
(nevertheless, the children scope now can still succesfully calculated the NRVO 
candidate).

We need to have a set of "unspoiled variables" to find the NRVO candidate 
effectively (yeah, introducing some made up terminology...) A variable is 
"unspoiled" if it is not forbidden to be the NRVO candidate yet. An `AddDecl` 
call adds the variable to this set. An `addNRVOCandidate` call "spoils" every 
variable except `VD`. A `setNoNRVO` "spoils" every variable. Only an "unspoiled 
variable" may be the NRVO candidate.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D119792/new/

https://reviews.llvm.org/D119792

_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to