The following code is compiled incorrectly with -O2: #include <stdlib.h> void f(int x) { if (x < 0) { if (-x > 0) { exit(1); } } } int main() { f(-0x80000000); exit(0); } $ gcc foo.c; ./a.out $ gcc -O2 foo.c; ./a.out zsh: 4407 exit 1 ./a.out $
-0x80000000 is going to overflow and for signed integers overflow is undefined. If you want signed integers to be defined to be wrapping use -fwrapv.
Wait a minute. 0x80000000 is unsigned. So -0x80000000 is well-defined, and is 0x80000000 (unsigned). This is then converted to signed. Since 0x80000000 cannot be represented in signed, the result is implementation specific. We document it to be -0x80000000. So the call is just fine.
It is the -x in f where x = 0x80000000 which is undefined as it overflows.
(In reply to comment #3) > It is the -x in f where x = 0x80000000 which is undefined as it overflows. Oh. I see. Right.
I see your point, but I still think there's a bug. Let me change the code slightly: #include <stdlib.h> #include <stdio.h> void f(int x) { long y; if (x < 0) { y = -x; if (y > 0) { printf("%d\n",y); } } } int main() { f(-0x80000000); exit(0); } $ gcc -O2 foo.c $ ./a.out -2147483648 so, we're in the y > 0 branch, but y is clearly < 0.
Pinskia is right, and this is just as undefined as your previous example (negating INT_MIN is just undefined, however you do it). All you've done is obfuscated things a bit more.
(In reply to comment #5) > I see your point, but I still think there's a bug. Let me change the code > slightly: The code is still undefined, as you are comparing an overflowed variable to something. -x is still undefined for x being 0x80000000 as it overflows and overflow signed integer is undefined runtime code.
Reopening to ...
Mark as a dup of bug 25329. *** This bug has been marked as a duplicate of 25329 ***