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 >