Consider struct s { long a : 33; }; long bar(struct s *x) { return (x->a << 16) >> 16; } extern void abort(void); int main() { struct s a = { 1u << 31 };
if (bar(&a) != 0) abort (); return 0; } where we currently (rightfully so, IMHO) abort. There are several problems with how we reach to that conclusion. First of all, a long bitfield is a GCC extension. This extension does not document integer promotion rules for such bitfields, and we indeed do _not_ perform promotion to long for the argument of the shifts, but the gimplifier is handed: return (long int) ((x->a << 16) >> 16); which leads to a GIMPLE intermediate language representation with registers/temporaries of width 31: long int D.1546; <unnamed-signed:33> D.1547; <unnamed-signed:33> D.1548; <unnamed-signed:33> D.1549; D.1547 = x->a; D.1548 = D.1547 << 16; D.1549 = D.1548 >> 16; D.1546 = (long int) D.1549; return D.1546; where this ILs only sane semantics do NOT match the runtime behavior of the program (IMHO the only sane semantics is to truncate the value after D.1548 = D.1547 << 16). Now we go further and expand is handed basically the original IL again if you run TER, or the above if not. But as we do not have modes for registers that have such irregular precision, simply DImode is used for all the temporaries and no bitfield reduction operations are emitted, making the runtime behavior as expected. So, to conclude, the runtime behavior does neither match the C99 standard (which doesn't specify integer promotions for types that do not fit in int, but also leaves bitfields of types with rank bigger than int as implementation defined), nor the only sane semantics of the tree-ssa IL. As a solution I propose to - document how integral promotion is performed on the implementation defined bitfields we allow as a GNU extension. (4.9, "Integer promotion rules are extended for non-standard bit-field types to promote to the smallest integer type that can represent all values of the bit-field type.") - actually perform these integral promotions - disallow GIMPLE registers whose precision does not match the precision of the underlying mode. Note that this requires BIT_FIELD_REF to allow a resulting type that does not match the type of the first operand (but possibly only the same mode). [alternatively only disallow arithmetics on such registers] This all will possibly help to solve PRs 33819 and 33887. Any thoughts? Would any of the C frontend maintainers please try to formulate standards-proof documentation for 4.9? Thanks, Richard.