Search code examples
c++cgccintegerclang

"Integer constant is so large that it is unsigned" compiler warning rationale


The following C/C++ code:

    long long foo = -9223372036854775808LL; // -2^63

compiles (g++) with the warning

integer constant is so large that it is unsigned.

clang++ gives a similar warning.

Thanks to this bug report: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=52661. I now understand why GCC gives this warning. Unfortunately, the response to the bug report didn't explain the reason for this behaviour very well.

Questions:

  • Why is no warning given for the equivalent code for a 32/16/8-bit signed integer constant?
  • GCC and Clang both give this warning, so it is clearly intentional behaviour and not just 'to make it easier to parse,' as is suggested in response to the bug report. Why?
  • Is this behaviour mandated by the C/C++ standard? Some other standard?

Solution

  • This has to do with how the type of integer constants is defined.

    First, as mentioned in the gcc bug report, -9223372036854775808LL is actually two tokens: the unary - operator and the integer constant 9223372036854775808LL. So the warning applies only to the latter.

    Section 6.4.4.1p5 of the C standard states:

    The type of an integer constant is the first of the corresponding list in which its value can be represented.

    integer constant table

    Based on this, a decimal integer constant with no suffix will have type int, long, or long long based on the value. These are all signed types. So anything value small enough to fit in an 8 bit or 16 bit type still has type int, and a value too large for a 32 bit signed int will have type long or long long depending on the size of the type on that system. The same goes for a constant with the LL suffix, but only the long long type is tried.

    The warning comes up because the value you're using doesn't fit in the above type list. Any lesser value will result in the value having a signed type meaning there's no conversion to unsigned.