On Tue, 15 Jan 2008, Joseph S. Myers wrote: > On Mon, 14 Jan 2008, Richard Guenther wrote: > > > Can you clarify on the resulting promotions? As I remember the > > standard defines promotions based on the representable values, so > > long : 15 gets promoted to int, but long : 33 doesn't get promoted. > > In the C++ FE at least we promote to the _declared_ type, that is, > > to long in this case. (Which I find more natural, but may be not > > what the standard says). > > Types (including the bit-field width as part of the type) narrower than > int are promoted based on representable values (so to int). Types wider > than int are left unchanged by the promotions. > > > Now, if you assign a rank to long : 15 (is it the same as int : 15?), > > They are the same; we only provide a single signed and a single unsigned > bit-field type of each width. (For int : 32, or other cases where the > width is the full width of the declared type, we used the declared type; > for cases where the width is that of a narrower standard type, we use that > narrower standard type, with c_build_bitfield_integer_type determining > preferences among types of the same width.) > > > would it still promote to int or would it promote to long or neither? > > To int, because int can represent all the values.
Ok, this is all as expected. > > > The question arises when computing the value of say long : 33 i; > > i << 16 >> 16. Is the shift performed in long : 33 type? Is an > > out-of-range value truncated? > > Performed in long : 33, according to the rules for shifts defined in > implement-c.texi (which define some cases ISO C leaves > implementation-defined, and one that's implementation-defined in C90 but > undefined in C99.) > > Arithmetic also follows the usual ISO C rules (e.g. signed overflow > undefined, subject to -fwrapv making it modulo; unsigned overflow modulo). > Arithmetic in narrow bit-field types e.g. int:25 won't appear at the > language level any more than arithmetic in short does, because both get > promoted to int. So this would probably not match behavior of other compilers which seem to do promotion to either the declared type or a non-bitfield type that can hold all the values of the bitfield. To make the example defined, consider an unsigned long : 33 i that is initialized to 1ul << 32. The expression i << 1 >> 1 is evaluated to 1ul << 32 by the compilers I have access to (and also by GCC), not zero. The C++ frontend does in most places promote bitfield operands to the declared type (if it didn't get promoted by integer promotion rules before). > > > * Make the gimplifier (or a later tree-ssa pass) insert whatever > > > conversions / reductions in precision may be needed to produce trees > > > acceptable to expand, if you think expand can't handle the special types > > > reliably. In particular, for arithmetic on such types and on all > > > conversions to such types. (Without special types, special code is still > > > needed for assignments to bit-fields, no longer handled as conversions.) > > > > (The problem is that I'm trying to exactly define what it should mean > > to the middle-end to for example do a NOP conversion to a bitfield - this > > is not at all clear) > > The conversions between integer types should I think be defined in GIMPLE > to follow the same rules as the C language conversions, documented in > implement-c.texi for cases ISO C leaves implemenation-defined: that is, > always reducing modulo 2^N to fit within the range of the type (except for > conversions to _Bool). Right. The middle-end certainly assumes this will happen (and honors these conversions) - apart from expand, where such conversions are either dropped completely (unless they change the mode), or (at least partly) honored if the REDUCE_BIT_FIELD_OPERATIONS langhook is set (which it is for C, but not for C++). Just to state the facts again - I'm back to square one ;) Thanks, Richard.