Issue
#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.
Answered By - Mestkon