std::optional of class annotated with clang::trivial_abi is not trivial for purpose of calls
- Dominant language
- LLVM
- Stars
- 40.5k
- Forks
- 18.7k
- PR merge metrics
- PR metrics pending
Description
Consider the following ([godbolt](https://godbolt.org/z/Yd6d4Y3MM)):
```c++
#include
struct TrivialDestructor {
~TrivialDestructor() = default;
int x = 0;
};
struct [[clang::trivial_abi]] NontrivialDestructor {
~NontrivialDestructor() {}
int x = 0;
};
TrivialDestructor trivial() { return {}; }
std::optional trivial_optional() { return {}; }
NontrivialDestructor nontrivial() { return {}; }
std::optional nontrivial_optional() { return {}; }
```
NontrivialDestructor has a nontrivial destructor, but since it is annotated with clang::trivial_abi, nontrivial() is able to return the object in registers instead of on the stack and compiles exactly the same as trivial():
```
trivial():
push rbp
mov rbp, rsp
mov dword ptr [rbp - 4], 0
mov eax, dword ptr [rbp - 4]
pop rbp
ret
nontrivial():
push rbp
mov rbp, rsp
mov dword ptr [rbp - 4], 0
mov eax, dword ptr [rbp - 4]
pop rbp
ret
```
But nontrivial_optional() constructs the object on the stack, even though it could be passed around in registers like trivial_optional() does:
```
trivial_optional():
push rbp
mov rbp, rsp
sub rsp, 16
lea rdi, [rbp - 8]
call std::__1::optional::optional[abi:sqe220000]()
mov rax, qword ptr [rbp - 8]
add rsp, 16
pop rbp
ret
nontrivial_optional():
push rbp
mov rbp, rsp
sub rsp, 16
mov rax, rdi
mov qword ptr [rbp - 16], rax
mov qword ptr [rbp - 8], rdi
call std::__1::optional::optional[abi:sqe220000]()
mov rax, qword ptr [rbp - 16]
add rsp, 16
pop rbp
ret
```
The same issue was also observed for std::variant and std::expected.
Contributor guide
Research direction
Start with the Godbolt reproducer and inspect how std::optional, std::variant, and std::expected determine their call and return ABI when their contained type has clang::trivial_abi. Compare the generated calls for TrivialDestructor and NontrivialDestructor; done means the annotated contained types are passed and returned consistently in registers where applicable, with coverage for the reported cases.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- cpp
- Domain
- compilers
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100