Search code examples
c++gccg++c++20internal-compiler-error

Why does g++-11 '-O2' contain a bug while '-O0' is ok?


#include <limits>
#include <cstdint>
#include <iostream>

template<typename T>
T f(T const a = std::numeric_limits<T>::min(),
    T const b = std::numeric_limits<T>::max())
{
    if (a >= b)
    {
        throw 1;
    }

    auto n = static_cast<std::uint64_t>(b - a + 1);
    if (0 == n)
    {
        n = 1;
    }

    return n;
}

int main()
{
    std::cout << f<int>() << std::endl;
}

g++-11 -std=c++20 -O2 should output 0 other than 1!

clang++ is ok as expected. If I change -O2 to -O0, g++-11 is also ok.

See: online demo

Why does g++ -O2 contain a bug while -O0 is ok?


Solution

  • b - a + 1 is clearly UB when the type of a and b are int and a is INT_MIN and b is INT_MAX as signed overflow is undefined behavior.

    From cppreference:

    When signed integer arithmetic operation overflows (the result does not fit in the result type), the behavior is undefined

    You are not converting to int64_t until after the calculation has already been executed.