On Sun, Nov 7, 2010 at 11:04 PM, Jason Merrill <ja...@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
>

Reply via email to