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

Reply via email to