jeff@cs.warwick.ac.uk (Jeff Smith) (06/08/89)
In this article, I want to demonstrate a bug in gnu cpp, and a possible bug - certainly a nasty - that can easily be corrected in <limits.h>. I will use this program for discussion: #include <limits.h> #if N < 0 main () { printf ((N < 0) ? "good\n" : "bad\n"); } #else main () { printf ("ugly\n"); } #endif When run through gcc-1.35 with N textually replaced as -2147483647, -2147483648, -2147483649, this program produces "good\n", "bad" and "ugly" respectively. I'm interested in the behaviour of the compiler with N as -2147483648, which is LONG_MIN in gcc's <limits.h>. ansC does not allow numerical constants to be negative, so the -2147483648 has to be parsed as NEGATE 2147483648. Now 2147483648 is greater than LONG_MAX in <limits.h>, and is therefore promoted to unsigned long, so it's subsequent negation will still not produce a number that is less than zero. The behaviour of the compiler proper at this point is therefore correct. However the value of LONG_MIN in <limits.h> is not (assuming <limits.h> is written in the ansC of the compiler it describes). I think LONG_MIN should be defined as (-LONG_MAX-1), rather than -2147483648, and similarly for SCHAR_MIN, CHAR_MIN, SHRT_MIN and INT_MIN. These definitions would still be appropriate for -traditional use. If you believe that -traditional mode should also allow the use of -2147483648 directly, then there are some additional changes to be made to cc1. The behaviour of the preprocessor does not seem to be correct. With the distributed <limits.h>, and the preprocessor and the compiler proper run on the same machine, N as -2147483648 should produce "ugly\n", and N as (-LONG_MAX-1) should produce "good\n". It actually produces "bad\n" and "good\n", which is a bug. -- Jeff Smith jeff@cs.warwick.ac.uk mcvax!warwick!jeff