Bug 36402 - -0x80000000 (INT_MIN, -2147483648) treated as unsigned
Summary: -0x80000000 (INT_MIN, -2147483648) treated as unsigned
Status: RESOLVED INVALID
Alias: None
Product: gcc
Classification: Unclassified
Component: c (show other bugs)
Version: 4.2.4
: P3 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2008-05-31 19:38 UTC by Andrew Church
Modified: 2008-06-01 13:59 UTC (History)
2 users (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Andrew Church 2008-05-31 19:38:33 UTC
GCC seems to treat the 32-bit integer constant -0x80000000 (INT_MIN) as an unsigned value, when it should be signed.  (I don't think this is a duplicate of bug 25329, since I'm not trying to negate the constant.)  For example:

int a = 1;
int foo(void)
{
    return -0x80000000 < a;
}

improperly returns 0, even though -0x80000000 is less than any positive value.  From the assembly output, it seems as though GCC is treating -0x80000000 as an unsigned value (using the unsigned "seta" instruction to interpret the comparison result):

        movl    a, %eax
        cmpl    $-2147483648, %eax
        seta    %al

Changing the comparison to:
    return (int)-0x80000000 < a;  // Cast to signed
succeeds, as expected (interestingly using "setne" rather than "setg", though certainly either works).
Comment 1 Eric Botcazou 2008-05-31 19:50:00 UTC
> GCC seems to treat the 32-bit integer constant -0x80000000 (INT_MIN) as an
> unsigned value, when it should be signed.

Incorrect.  -0x80000000 is not an integer constant, it's the negation of the
integer constant 0x80000000, which is unsigned (C99 6.4.4.1).
Comment 2 Andrew Church 2008-06-01 04:17:09 UTC
Fair enough, but GCC's documentation explicitly says (gcc.info section 4.5):

   * `Whether signed integer types are represented using sign and
     magnitude, two's complement, or one's complement, and whether the
     extraordinary value is a trap representation or an ordinary value
     (C99 6.2.6.2).'

     GCC supports only two's complement integer types, and all bit
     patterns are ordinary values.

Given that, I think a typical user would assume (as I have) that GCC would treat -0x80000000 as the signed value -2^31; otherwise there would seem to be no way to write a single constant to represent that valid value.  So I'm going to have to argue that this is still a bug, whether in the documentation or in the compiler itself.
Comment 3 Eric Botcazou 2008-06-01 07:25:32 UTC
> Given that, I think a typical user would assume (as I have) that GCC would
> treat -0x80000000 as the signed value -2^31; otherwise there would seem to be
> no way to write a single constant to represent that valid value.

You're confusing the internal representation, described by the paragraph you
quoted, and the syntax of literals.  There is no bug in this case, it's the
well-know limitation of C whereby you need to write INT_MIN as (-INT_MAX - 1).
Comment 4 joseph@codesourcery.com 2008-06-01 12:22:10 UTC
Subject: Re:  -0x80000000 (INT_MIN) erroneously treated as
 unsigned

On Sun, 1 Jun 2008, gcczilla at achurch dot org wrote:

> Fair enough, but GCC's documentation explicitly says (gcc.info section 4.5):

It also explicitly explains, in the section "Incompatibilities", that 
-2147483648 is positive, and why.  (In C99 mode, 2147483648 becomes of 
type long long, but 0x80000000 is still unsigned.)

Comment 5 Andrew Church 2008-06-01 13:59:25 UTC
Thanks for the clarification.  (To be honest, I wouldn't have thought to look in the "Incompatibilities" section--I haven't touched a non-ANSI compiler for over a decade--but either way I guess it's my fault for not searching for "2147483648".)

Touched up the summary line a bit to help future searchers.