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.

Reply via email to