With GCC6 and the code snippet below, this test
if (i > 31 || i < 0) {
is false, and this printf is executed
printf("i > 31 || i < 0 is FALSE, where i=%d", i);
and produces this very weird output (GCC6):
i > 31 || i < 0 is FALSE, where i=32 /* weird result with GCC6 !!! */
whereas with GCC4 I get:
i > 31 || i < 0 is true, where i=32 /* result Ok with GCC4 */
which looks perfectly alright.
How can this be??
Code snippet (broken legacy code!):
static int check_params(... input parameters ...) {
/* Note that value can be 0 (zero) */
uint32_t value = ....
int i;
i = __builtin_ctz(value);
if (i > 31 || i < 0) {
printf("i > 31 || i < 0 is true, where i=%d", i);
/* No 1 found */
return 0;
} else {
printf("i > 31 || i < 0 is FALSE, where i=%d", i);
}
return i;
}
According to the documentation about GCC builtin functions, calling __builtin_ctz(0) must be avoided:
Built-in Function: int __builtin_ctz (unsigned int x) Returns the number of trailing 0-bits in x, starting at the least significant bit position. If x is 0, the result is undefined.
So obviously, a solution to the coding error is to simply check the value before calling __builtin_ctz(value). This is clear and understood.
I could just stop there and move to other topics...but still, I don't understand how I could possibly (with the broken code), get the following output:
i > 31 || i < 0 is FALSE, where i=32 /* weird result with GCC6 !!! */
A weird GCC6 optimization or something?
Just in case it matters at all:
Cross-compiler: arm-linux-gcc
Architecture: -march=armv7-a
Any idea?