Summary: | compiler optimization | ||
---|---|---|---|
Product: | gcc | Reporter: | Eskil Steenberg <eskil> |
Component: | c | Assignee: | Not yet assigned to anyone <unassigned> |
Status: | RESOLVED INVALID | ||
Severity: | minor | ||
Priority: | P3 | ||
Version: | 4.4.5 | ||
Target Milestone: | --- | ||
Host: | Target: | ||
Build: | Known to work: | ||
Known to fail: | Last reconfirmed: |
Description
Eskil Steenberg
2010-12-12 00:35:47 UTC
There is no integer overflow in the code provided at all. (In reply to comment #1) > There is no integer overflow in the code provided at all. Even if there was, the standard says the behavior is undefined which means anything can happen. Hi > (In reply to comment #1) >> There is no integer overflow in the code provided at all. Sorry it underflows. How about this: void my_func(unsigned short a, unsigned short c) { unsigned int b; b = a * c; .... > Even if there was, the standard says the behavior is undefined which means > anything can happen. Yes, but the doesn't the C spec define the overflow as undefined, rather then the entire program? The behavior is defined, just not by the C spec, its defined by the hardware implementation. The compile time assumption that nothing will ever overflow seams dangerous. My problem is not that C has undefined behavior, but rather that gcc makes assumptions about this behavior that _can_ turn out to be not true. Cheers E >Sorry it underflows. No, conversion does not have any overflow/underflow in it. >void my_func(unsigned short a, unsigned short c) >{ > unsigned int b; > > b = a * c; There is no overflow here since this unsigned integers wrap and don't overflow. > Yes, but the doesn't the C spec define the overflow as undefined, rather > then the entire program? No it is a runtime undefined behavior rather than the result being undefined. > rather that gcc makes assumptions about this behavior that _can_ turn out to > be not true. But assumptions? Since it is undefined behavior, it does not matter because GCC can make different assumptions in when it feels like. Unless you can give a testcase that does not depend on undefined behavior, it is hard to prove GCC is doing something wrong. -fwrapv can be used to define signed integer overflow as wrapping. See http://gcc.gnu.org/onlinedocs/gcc-4.5.1/gcc/Integers-implementation.html for how the conversion is implementation defined behavior: > # The result of, or the signal raised by, converting an integer to a signed > integer type when the value cannot be represented in an object of that type > (C90 6.2.1.2, C99 6.3.1.3). > For conversion to a type of width N, the value is reduced modulo 2^N to be > within range of the type; no signal is raised. Conversions are never causes an overflow rather it causes an implementation defined behavior in some cases. Hi >>void my_func(unsigned short a, unsigned short c) >>{ >> unsigned int b; >> >> b = a * c; > > There is no overflow here since this unsigned integers wrap and don't > overflow. Yes there is since a and c are promoted to signed ints and thats where the multiplication takes place, before they are converted to an unsigned int. A max unsigned short times a max unsigned short will overflow a signed int. (given a 32 bit system at least) >> Yes, but the doesn't the C spec define the overflow as undefined, rather >> then the entire program? > > No it is a runtime undefined behavior rather than the result being > undefined. So how can the compiler make a compile time assumption about the outcome of the behavior since it is undefined at compile time? >> rather that gcc makes assumptions about this behavior that _can_ turn >> out to >> be not true. > > But assumptions? Since it is undefined behavior, it does not matter > because GCC can make different assumptions in when it feels like. Could you clarify this statement? > Unless you can give a testcase that does not depend on undefined behavior, > it is hard to prove GCC is doing something wrong. The very problem I'm addressing is how gcc deals with this, at compile time, undefined behavior. Cheers E >it is undefined at compile time?
No, it is undefined at runtime. This again is not an undefined behavior at compile time but rather at runtime. What that means is the behavior cannot be diagnosed (at least by the C standard definitions) at compile time and has to compile. There is no undefined at compile time behavior here, only at runtime.
Hi
> No, it is undefined at runtime. This again is not an undefined behavior
> at
> compile time but rather at runtime. What that means is the behavior
> cannot be
> diagnosed (at least by the C standard definitions) at compile time and has
> to
> compile. There is no undefined at compile time behavior here, only at
> runtime.
Well the compiler does make assumptions about what the runtime will do.
Have a look at this function:
void my_func(unsigned short a, unsigned short b)
{
unsigned int c;
c = a * b;
printf("c = %u\n", c);
if(f < 3000000000) /* 3 billion */
printf("foo bar\n");
}
using gcc you can get the output (with the input ffff, and ffff):
c = 4294836225
foo bar
This output should not be possible and will be very confusing to the user
(it was to me). My (limited) reading of the C spec should not support this
even though i understand why it happens.
At compile time the compiler decides that c can never be larger then max
singned int, and therefor it thinks that it can optimize away the if
statement.
Cheers
E
PS sorry I dont have a compiler on this machine so excuse any typos.
>This output should not be possible
No, it is possible because the value is undefined so both the if being false and the printout happening can happen.
Hi
> No, it is possible because the value is undefined so both the if being
> false and the printout happening can happen.
But undefined still means that the variable c has a value, just not
something that cant be determined at compile time.
The value c is not undefined, just the operation that produces the value
stored in c. Therefor anything the variable c touches shouldn't become
undefined too.
If i give someone the number 9 and tell them to do a square root of it,
they should produce a 3 even if I dont define where I got the number 9. if
they go ahead and produce the value 4, I'm going to say that they are
wrong, and not buy the argument "Since you dont define where you got the
number, I'm going to assume you really meent 16 and not 9".
I really dislike the idea that something can be undefined, and at the same
time the compiler can make assumptions about what it can be. pick one.
Cheers
E
The execution of an undefined operation produces an undefined value, and any further operation becomes undefined. Hi > The execution of an undefined operation produces an undefined value, and > any further operation becomes undefined. My argument is that, at compile time this isn't known. Just because the C spec doesn't guarantee any behavior to be consistent between runtime environments, doesn't mean that a compiler designer should assume that the programmer doesn't know the behavior of the hardware he or she is programming for. Searching around the net i found this: http://www.groupsrv.com/groups/view.php?c=computer&g=6034&id=62241&p=0 And reading it, it looks like many consider this to be an area of the spec that is perhaps lacking in clarity. What ever side you come down on this, I think its very clear that gcc, does a very poor job here in terms of usability, since it doesn't in any way communicate to the user what it is doing. At least it should put up a warning. Cheers E |