| Issue |
174179
|
| Summary |
std::optional of class annotated with clang::trivial_abi is not trivial for purpose of calls
|
| Labels |
clang
|
| Assignees |
|
| Reporter |
es1024
|
Consider the following ([godbolt](https://godbolt.org/z/Yd6d4Y3MM)):
```c++
#include <optional>
struct TrivialDestructor {
~TrivialDestructor() = default;
int x = 0;
};
struct [[clang::trivial_abi]] NontrivialDestructor {
~NontrivialDestructor() {}
int x = 0;
};
TrivialDestructor trivial() { return {}; }
std::optional<TrivialDestructor> trivial_optional() { return {}; }
NontrivialDestructor nontrivial() { return {}; }
std::optional<NontrivialDestructor> 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<TrivialDestructor>::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<NontrivialDestructor>::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.
_______________________________________________
llvm-bugs mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-bugs