integral overflow and integral conversions
Richard Guenther
richard.guenther@gmail.com
Mon Nov 8 11:20:00 GMT 2010
On Sun, Nov 7, 2010 at 11:04 PM, Jason Merrill <jason@redhat.com> wrote:
> Currently, the middle end seems to use the same rules for handling constant
> overflow of integer arithmetic and conversion between integer types: set
> TREE_OVERFLOW on the INTEGER_CST if the type is signed and the value doesn't
> fit in the target type. But this doesn't seem to match the C/C++ standards.
>
> C99 says,
>
> 6.3.1.3 Signed and unsigned integers
>
> 1 When a value with integer type is converted to another integer type other
> than _Bool, if the value can be represented by the new type, it is
> unchanged.
> 2 Otherwise, if the new type is unsigned, the value is converted by
> repeatedly adding or subtracting one more than the maximum value that can be
> represented in the new type until the value is in the range of the new
> type.49)
> 3 Otherwise, the new type is signed and the value cannot be represented in
> it; either the result is implementation-defined or an implementation-defined
> signal is raised.
>
> 6.5 Expressions
>
> 5 If an exceptional condition occurs during the evaluation of an expression
> (that is, if the result is not mathematically defined or not in the range of
> representable values for its type), the behavior is undefined.
>
> Note the difference. When converting an integer value to another integer
> type that it doesn't fit into, the behavior is either well-defined or
> implementation-defined. When arithmetic produces a value that doesn't fit
> into the type in which the arithmetic is done, the behavior is undefined
> even if the type is unsigned.
>
> So we're setting TREE_OVERFLOW inappropriately for conversion to signed
> integer types (though the front ends unset it again in cast context), and,
> more problematically, failing to set it for unsigned arithmetic overflow:
>
> #include <limits.h>
>
> enum E {
> A = (unsigned char)-1, // OK
> B = (signed char)UCHAR_MAX, // implementation-defined
> C = INT_MAX+1, // undefined (C)/ill-formed (C++)
> D = UINT_MAX+1 // undefined (C)/ill-formed (C++)
> };
>
> Am I missing something?
>
> This is more of a problem for C++, which says that arithmetic overflow in a
> context that requires a constant expression is ill-formed; in C it's merely
> undefined.
The use of TREE_OVERFLOW is largely historical and of not much use
for the middle-end (but it's used extensively by the frontend(s) and so
can't be changed easily).
The middle-end would have use for detecting overflow for both signed
and unsigned arithmetic (in the type that is provided, thus without
implicit promotions). But this should be signalled with a separate
return value, not with flags on INTEGER_CSTs (which eventually
should get deprecated).
I've tried to move us in that direction repeatedly (with some VRP work
and also on the no-undefined-overflow branch) but always run into
interesting issues in the C frontend and stor-layout code. Hum.
Richard.
> Jason
>
More information about the Gcc
mailing list