| Issue |
175018
|
| Summary |
[clang] Miscompilation at -O1 with std::optional return value comparison
|
| Labels |
clang
|
| Assignees |
|
| Reporter |
kazikame
|
**Description:** Function that returns `std::nullopt` based on a range check is miscompiled with clang-21 at `-O1` and above, causing the function to incorrectly return a value instead of `std::nullopt`
**Reproducer:**
```c++
#include <iostream>
#include <cstring>
#include <optional>
#include <array>
#include <stdint.h>
using s64 = int64_t;
using u8 = uint8_t;
constexpr static s64 convert(s64 in) {
return in / 10000;
}
std::optional<std::array<u8, 6>> __attribute__((noinline)) f(s64 x) {
if (x < 0) {
return std::nullopt;
}
if (x % 10000 != 0) {
return std::nullopt;
}
auto y = convert(x);
if (y > 0xFFFFFFFFFFFF) {
return std::nullopt;
}
std::array<u8, 6> z{};
std::memcpy(z.data(), &y, 6);
return z;
}
int main() {
auto res = f((0xFFFFFFFFFFFF + 1) * 10000);
std::cerr << &res << " " << res.has_value() << std::endl;
}
```
Flags: `-Wall -Wextra -std=c++20 -O1 -g3`
**Environment:**
- Ubuntu 22.04.5 LTS, x86_64
- Ubuntu clang version 21.1.0 (++20250811123346+6f5c887e557f-1~exp1~20250811123522.21)
- fetched from http://apt.llvm.org/jammy/
- Also reproduces on clang-20 (20.1.8); works correctly on clang-15 through clang-19
**Additional information:**
Bisecting with `-mllvm -opt-bisect-limit=N` points to SimplifyCFGPass:
```
$ clang++-21 -mllvm -opt-bisect-limit=1132 -Wall -Wextra -std=c++20 -O1 -g3 test.cpp -o test21 2> /tmp/o0_1132 && ./test21
0x7ffd0b9affb1 0
$ clang++-21 -mllvm -opt-bisect-limit=1133 -Wall -Wextra -std=c++20 -O1 -g3 test.cpp -o test21 2> /tmp/o0_1133 && ./test21
0x7fff07badad1 1
$ grep 'running pass \(1133\)' /tmp/o0_1133
1133:BISECT: running pass (1133) SimplifyCFGPass on _Z1fl
```
_______________________________________________
llvm-bugs mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-bugs