[cfe-users] Boost.GIL test failing with clang 5.x while pass with 15 gcc/clang versions
Jan Korous via cfe-users
cfe-users at lists.llvm.org
Mon May 21 10:27:06 PDT 2018
Hi Mateusz,
You are hitting UB because of signed integer overflow.
ISO/IEC 14882:2011 clause 5 paragraph 4 and ISO/IEC 14882:2017 clause 8 paragraph 4
“If during the evaluation of an expression, the result is not mathematically defined or not in the range of representable values for its type, the behavior is undefined. [...]"
With the exception of unsigned integers:
ISO/IEC 14882:2011 clause 3.9.1 footnote 46 and ISO/IEC 14882:2017 clause 6.9.1 footnote 49
"This implies that unsigned arithmetic does not overflow because a result that cannot be represented by the resulting unsigned integer type is reduced modulo the number that is one greater than the largest value that can be represented by the resulting unsigned integer type."
This code
int x = std::numeric_limits<int>::min();
template <typename C>
inline C channel_invert1(C x)
{
return std::numeric_limits<C>::max() - x + std::numeric_limits<C>::min();
}
contains (left-to-right operator precedence):
numeric_limits<int>::max() - numeric_limits<int>::min() ...
Where min() is < 0 so it's an overflow.
This code:
int x = std::numeric_limits<int>::min();
template <typename C>
inline C channel_invert2(C x)
{
return (x - std::numeric_limits<C>::max()) * (-1) +
std::numeric_limits<C>::min();
}
contains
numeric_limits<int>::min() - numeric_limits<int>::max()
Where max() is > 0 so it's an underflow.
BTW This is a perfect opportunity to try out UndefinedBehaviorSanitizer!
https://clang.llvm.org/docs/UndefinedBehaviorSanitizer.html
> clang++ -fsanitize=signed-integer-overflow overflow.cpp
> ./a.out
-2147483648
overflow.cpp:24:52: runtime error: signed integer overflow: 2147483647 - -2147483648 cannot be represented in type 'int'
...
Hope this helps.
Jan
> On 19 May 2018, at 20:38, Mateusz Loskot via cfe-users <cfe-users at lists.llvm.org> wrote:
>
> Hi,
>
> While testing Boost.GIL library [1] with gcc and clang, I noticed a
> peculiar issue.
> One particular test is failing with lang 5.x while passing with total of 15-17
> other versions of clang and GCC (total workflow of CircleCI with at [2]).
>
> Below is extracted minimal program equivalent to Boost.GIL
> channel_invert algorithm. It includes two variants: plain expression
> and the same expression wrapped with a function template:
>
> #include <limits>
> #include <iostream>
> #include <typeinfo>
>
> template <typename C>
> inline C channel_invert1(C x)
> {
> return std::numeric_limits<C>::max() - x + std::numeric_limits<C>::min();
> }
>
> template <typename C>
> inline C channel_invert2(C x)
> {
> return (x - std::numeric_limits<C>::max()) * (-1) +
> std::numeric_limits<C>::min();
> }
>
> int main()
> {
> int x = std::numeric_limits<int>::min();
> std::cout << x << std::endl;
>
> // plain expressions
> int x_invert1 = std::numeric_limits<int>::max() - x +
> std::numeric_limits<int>::min();
> int x_invert2 = (x - std::numeric_limits<int>::max()) * (-1) +
> std::numeric_limits<int>::min();
> std::cout << x_invert1 << std::endl;
> std::cout << x_invert2 << std::endl;
>
> // the same expressions wrapped in function template
> std::cout << channel_invert1<int>(x) << std::endl;
> std::cout << channel_invert2<int>(x) << std::endl;
> }
>
> If compiled as optimised variant (-O2 or -O3) with clang 5.x outputs
> the following:
>
> -2147483648
> 2147483647
> 2147483647
> -1
> -1
>
> The last two negative one is not expected.
>
> If compiled with clang 3.9, 4.0 or gcc from 5.1 to 7.3 it outputs
>
> -2147483648
> 2147483647
> 2147483647
> 2147483647
> 2147483647
>
> Could anyone help me to understand what is going on in the clang 5 case?
> Or, what UB is this hitting?
>
> [1] https://github.com/boostorg/gil/issues/89
> [2] https://circleci.com/workflow-run/3a14dd64-6c38-46b2-a6da-678c0075ca27
>
> Best regards,
> --
> Mateusz Loskot, http://mateusz.loskot.net
> _______________________________________________
> cfe-users mailing list
> cfe-users at lists.llvm.org
> http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-users
More information about the cfe-users
mailing list