Bug 20019 - incorrect overflow warning
Summary: incorrect overflow warning
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: c++ (show other bugs)
Version: 3.4.0
: P2 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords: diagnostic
Depends on:
Blocks:
 
Reported: 2005-02-17 02:59 UTC by Ivan Godard
Modified: 2007-01-13 02:23 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 Ivan Godard 2005-02-17 02:59:13 UTC
The code:
#include <cstddef>

static const char lwb = 0x80;
static const char upb = 0x7f;
static const size_t cnt = upb - lwb + 1;

static const char lwba = 0x80;
static const char upba = 0x01;
static const size_t cnta = upba - lwba + 1;

static const char lwbb = 0xff;
static const char upbb = 0x7f;
static const size_t cntb = upbb - lwbb + 1;

static const char lwbc = 0x00;
static const char upbc = 0x7f;
static const size_t cntc = upbc - lwbc + 1;

int main() {
    return 0;
    }

gets you:
~/ootbc/common/src$ c++ foo.cc
foo.cc:5: warning: integer overflow in expression
foo.cc:9: warning: integer overflow in expression
foo.cc:13: warning: integer overflow in expression

which (as I read the promotion rules) is incorrect. First lwb and upb should be
promoted to int, then subtraction is done, and then the addition. This gives no
overflow. However, it appears that the subtraction is actually being done in
char, not int, because the results actually do overflow 127 on all but the last
case.

Have the promotion rules changed?

Ivan
Comment 1 Ivan Godard 2005-02-17 03:09:19 UTC
Turns out that the promotion rules aren't the problem, because you still get the
same message even with *explicit* promotion - the code:

#include <cstddef>

static const char lwb = 0x80;
static const char upb = 0x7f;
static const size_t cnt = int(upb) - int(lwb) + 1;

int main() {
    return 0;
    }

gets you:

~/ootbc/common/src$ c++ foo.cc
foo.cc:5: warning: integer overflow in expression

which *has* to be wrong regardless of the promotion rules.

Ivan

Comment 2 Andrew Pinski 2005-02-17 03:14:23 UTC
No the warning is correct as char on a lot of targets is signed by default so promoting (char)0x80 to int 
will give 0xFFFFFF80.
Comment 3 Ivan Godard 2005-02-17 03:37:57 UTC
WADR, but "char" on my (x86 Linux) machine in fact signed. So I tried:
#include <cstddef>

static const char lwb = 0x80;
static const char upb = 0x7f;
static const int lwbi = lwb;
static const int upbi = upb;
static const size_t cnt = upb - lwb;
static const size_t cnti = upbi - lwbi;

int main() {
    return 0;
    }

Now I get:
~/ootbc/common/src$ c++ foo.cc
foo.cc:7: warning: integer overflow in expression
foo.cc:8: warning: integer overflow in expression

Surely after I have assigned the chars to ints and done the arithmetic in int
there cannot be an overflow, but I'm still getting a warning. And the result of
the subtraction is positive on a machine with signed chars, so it can't be the
assignment to the size_t.

Reopened - please look again.

Ivan
Comment 4 Andrew Pinski 2005-02-17 03:43:32 UTC
static const int lwbi = lwb;

lwb = 0x80

lwbi is the signed extended version of lwb to the size of int so you will still get 0xFFFFFF80.

So this is still not a bug.
Comment 5 Ivan Godard 2005-02-17 04:10:11 UTC
Please: 

yes, the int value lwbi arising from the conversion of char(0x80) is the int 
value 0xffffff80, i.e. int(-128); you are quite right about that. That value is 
being *subtracted* from the int value upbi arising from the conversion of 
char(0x7f) which is the value 0x0000007f, i.e. 127. If you subtract -128 from 
127, i.e (127 - (-128)), the result is 255, a positive number and there is NO 
overflow. This is signed subtract and it is permitted to subtract a negative 
from a positive. The result is exact.

The result of the subtract is the positive number int(255). That can be 
converted to size_t (which is unsigned in in this case) also without overflow.

Yet there is still a warning message.

If the problem here is not clear, please pass this report on to your other 
colleagues for a second opinion. Thank you.

Ivan
Comment 6 Neil Booth 2005-02-17 11:34:34 UTC
Subject: Re:  incorrect overflow warning

pinskia at gcc dot gnu dot org wrote:-

> 
> ------- Additional Comments From pinskia at gcc dot gnu dot org  2005-02-17 03:14 -------
> No the warning is correct as char on a lot of targets is signed by default so promoting (char)0x80 to int 
> will give 0xFFFFFF80.

This explanation just doesn't make sense.

What should get a warning is the assignment of 0x80 to a char.

Neil.
Comment 7 Paul Schlie 2005-02-17 13:20:29 UTC
(In reply to comment #6)
> What should get a warning is the assignment of 0x80 to a char.

Not that either, as although the two differ in sign, the value does not exceed the type's precision.
Comment 8 Neil Booth 2005-02-17 14:00:46 UTC
Subject: Re:  incorrect overflow warning

schlie at comcast dot net wrote:-

> 
> ------- Additional Comments From schlie at comcast dot net  2005-02-17 13:20 -------
> (In reply to comment #6)
> > What should get a warning is the assignment of 0x80 to a char.
> 
> Not that either, as although the two differ in sign, the value does not exceed the type's precision.

I disagree.  Like so:

"/tmp/foo.c", line 1: warning: value changes sign during integer type
        conversion
char x = 0x80;
         ^
Comment 9 Paul Schlie 2005-02-17 14:33:06 UTC
(In reply to comment #8)
> char x = 0x80; warning: value changes sign during integer type conversion

Implying an analogous warning for all assignments between dissimilarly
signed variables (i.e. signed x; unsigned y; x = y;) which I believe are
considered "compatible"; and half of all unsigned hex constants being
assigned to signed types even if cast, as it's arguably the cast which
produces the virtual numerical over/underflow.

(where although you're numerically correct, seems like a lot of noise?)

Comment 10 Neil Booth 2005-02-17 15:12:03 UTC
Subject: Re:  incorrect overflow warning

schlie at comcast dot net wrote:-

> 
> ------- Additional Comments From schlie at comcast dot net  2005-02-17 14:33 -------
> (In reply to comment #8)
> > char x = 0x80; warning: value changes sign during integer type conversion
> 
> Implying an analogous warning for all assignments between dissimilarly
> signed variables (i.e. signed x; unsigned y; x = y;) which I believe are
> considered "compatible"; and half of all unsigned hex constants being
> assigned to signed types even if cast, as it's arguably the cast which
> produces the virtual numerical over/underflow.
> 
> (where although you're numerically correct, seems like a lot of noise?)

Well it's certainly a matter of taste.  char is arguably a special
case as you cannot assign a value with the high bit set without
creating the warning on some targets.  But if you are assigning
values with the high bit set then arguably you have in mind whether
you are dealing with signed or unsigned values and should be explicit
about signedness.  As such like any warning it tends to expose sloppy
thinking.

Your x=y example is of course not the same; whether a value is
changing sign or not is not knowable at compile time and probably
rarely the case, so I agree complaining about that would be annoying.

Some people have in the past requested command-line switches to
generate warnings for any implicit integer conversion.  I agree a
singed <-> unsigned should not be on by default, though potentially
narrowing conversions are debatably more appropriate to have on by
default.

Neil.
Comment 11 Manuel López-Ibáñez 2006-11-25 13:51:07 UTC
I don't get the warning with current mainline (revision 119143).

Still, I would like to keep this bug around since it may be interesting that Wconversion emits a warning for the int->char conversion. I would like to hear some opinions about this. My current patch does the following:

manuel@gcc05:~$ local/bin/g++ -fsigned-char pr20019.cpp
manuel@gcc05:~$ local/bin/g++ -fno-signed-char pr20019.cpp
manuel@gcc05:~$ local/bin/g++ -fno-signed-char -Wconversion pr20019.cpp
pr20019.cpp:9: warning: negative integer implicitly converted to unsigned type
pr20019.cpp:13: warning: negative integer implicitly converted to unsigned type
manuel@gcc05:~$ local/bin/g++ -fsigned-char -Wconversion pr20019.cpp
pr20019.cpp:3: warning: conversion to ‘char’ alters ‘int’ constant value
pr20019.cpp:7: warning: conversion to ‘char’ alters ‘int’ constant value
pr20019.cpp:11: warning: conversion to ‘char’ alters ‘int’ constant value

Does this seem correct to all of you?

Comment 12 Manuel López-Ibáñez 2007-01-13 02:23:28 UTC
There is no warning with GCC 4.3 and you can get a warning for the int->char conversion by using -Wconversion. So I am going to close this. Please, feel free to reopen if you think there is some unresolved issue.