Demonstrating GCC's signed int overflow optimization bug is non-conforming

// When compiled in GCC with -O2, this causes an infinite loop

#include <limits>
int main()
  if( std::numeric_limits<signed int>::is_modulo )
  for( int ii=1 ; ii<0 ; ++ii ) { }
  return 0;

This has been heavily debated as to whether it's actually a defect, with many claiming it is not a defect due to the following line in the C++ spec:

"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."

However, std::numeric_limits<signed int>::is_modulo clearly changes the argument, and is defined in the spec as:

True if the type is modulo. A type is modulo if, for any operation involving +, -, or * on values of that type whose result would fall outside the range [min(),max()], the value returned differs from the true value by an integer multiple of max() – min() + 1.

By signed int being a modulo type in gcc's implementation of C++, it has a clear mathmatical definition and is required to wrap on overflow as most developers expect.

I tested the following compilers (all targeting x86):
- g++ (Ubuntu/Linaro 4.6.3-1ubuntu5) 4.6.3
- Ubuntu clang version 3.0-6ubuntu3 (tags/RELEASE_30/final) (based on LLVM 3.0)
- Visual Studio 2013

GCC and Clang tests were compiled using standard 'safe' optimization level of -O2. Visual Studio test was compiled using the default optimization options for a Release build.

All three compilers report signed int to be modulo in their implementation. Only GCC causes an infinite loop in the test code. (It is unknown whether Clang or VisualStudio can be made to exhibit similar bugs with non-trivial code). Visual Studio optimized out the entire loop initially; a printf was added in the loop for the Visual Studio test to prevent the loop from being removed in entirety.

I believe this clearly demonstrates a bug in GCC. Either the oft quoted "signed int overflow is undefined" is incorrect due to signed int being modulo and GCC's optimizer is exhibiting incorrect behavior, or GCC's std::numeric_limits is incorrectly reporting signed int as being modulo. */

No comments:

Post a Comment