Consider the following code: typedef struct { unsigned long A:16; unsigned long B:48; } bits;
int wrong(unsigned long y) { bits *p = (bits *) &y; if (y == 0 || p->A >= 512) { return (1); } return (0); } int right(unsigned long y) { bits *p = (bits *) &y; if (y == 0 || p->A >= 512) { return (-1); } return (0); } The *only* difference between right() and wrong() is the return value in the IF clause. With -O2, the function right() compiles to correct, if suboptimal, code. The function wrong(), however, generates the following: wrong: .prologue .body .mmi cmp.ne p6, p7 = 0, r32 nop 0 addl r14 = 511, r0 .mmi ld2 r15 = [r12] <<<<<< HUH? st8 [r12] = r32 <<<<<< HUH? addl r8 = 1, r0 .mib nop 0 nop 0 (p7) br.ret.dpnt.many rp ;; .mmi cmp4.gtu p6, p7 = r15, r14 ;;wrong: .prologue .body .mmi cmp.ne p6, p7 = 0, r32 nop 0 addl r14 = 511, r0 .mmi ld2 r15 = [r12] st8 [r12] = r32 addl r8 = 1, r0 .mib nop 0 nop 0 (p7) br.ret.dpnt.many rp ;; .mmi cmp4.gtu p6, p7 = r15, r14 ;; (p6) addl r14 = 1, r0 (p7) mov r14 = r0 ;; .mib nop 0 mov r8 = r14 br.ret.sptk.many rp .endp wrong# (p6) addl r14 = 1, r0 (p7) mov r14 = r0 ;; .mib nop 0 mov r8 = r14 br.ret.sptk.many rp .endp wrong# It is clearly wrong to perform the load from the stack before the proper value (r32) has been stored. When run, the value of p->A is the low 16 bits of whatever was stored on the stack before. -- Summary: bitfield alias generates incorrect assembly Product: gcc Version: 4.3.1 Status: UNCONFIRMED Severity: critical Priority: P3 Component: c AssignedTo: unassigned at gcc dot gnu dot org ReportedBy: jsworley at qwest dot net GCC host triplet: i686-linux-gnu GCC target triplet: ia64-linux-gnu http://gcc.gnu.org/bugzilla/show_bug.cgi?id=39255