How does gcc handle -Wtype-limits?

c, gcc, types

Solution

GCC does take into account the actual known limits of the types. It knows that `int` is more than 16 bits wide in your case, so it warns.

You get no warning for

#include <assert.h>
#include <limits.h>
#include <stdint.h>

int main(void)
{
    assert((unsigned int)INT_MAX < (unsigned int)UINT16_MAX);
    return 0;
}

because the standard says in 7.20.2 (2):

Each instance of any defined macro shall be replaced by a constant expression suitable for use in `#if` preprocessing directives, and this expression shall have the same type as would an expression that is an object of the corresponding type converted according to the integer promotions.

so with 32-bit wide `int`s, the macro `UINT16_MAX` is an `int`, hence the limits of the involved types don't guarantee that the comparison is always false (or true).

Problem

I'm testing a small code snippet with gcc 4.4.5 and `-Wtype-limits` option on. ``` #include <assert.h> #include <limits.h> #include <stdint.h> int main(void) { /* With other values of v, the behavior of the compiler is the same. */ uint16_t v = 0; assert((unsigned int)INT_MAX < (unsigned int)v); /* l. 7 */ return 0; } ``` Then, the compiler throws me the following warning: `main.c:7: warning: comparison is always false due to limited range of data type` However, as far as I know, `INT_MAX` may be equal to `+32767` (from C11 (n1570), § 5.2.4.2.1 Sizes of integer types `<limits.h>`). In that case, the variable `v` would be able to hold the value `INT_MAX+1`, and the expression in `assert` would be evaluated to `1`. Therefore, I can see two issues: - GCC takes in account my architecture, because, in fact, `INT_MAX` is not equal to `+32767`. In that case, it would reduce the benefits of `-Wtype-limits` for me. - It is a bug. What it makes me think about the second option is the following code, which doesn't produce any warning with the same options. ``` #include <assert.h> #include <limits.h> #include <stdint.h> int main(void) { assert((unsigned int)INT_MAX < (unsigned int)UINT16_MAX); return 0; } ``` So, what is the correct answer? PS: By the way, I have to apologize because of my old version of gcc. Maybe the behavior of the next releases is different.

Original source