https://gcc.gnu.org/bugzilla/show_bug.cgi?id=71700
Bug ID: 71700 Summary: [4.9/5/6/7 Regression] wrong code with struct assignment with sub-word signed bitfields Product: gcc Version: 7.0 Status: UNCONFIRMED Keywords: wrong-code Severity: normal Priority: P3 Component: middle-end Assignee: unassigned at gcc dot gnu.org Reporter: ktkachov at gcc dot gnu.org Target Milestone: --- Target: arm The testcase below fails: struct S { signed f0 : 16; unsigned f1 : 1; }; int b; static struct S c[] = { { -1, 0 }, { -1, 0 } }; struct S d; int main() { struct S e = c[0]; d = e; if (d.f1 != 0) __builtin_abort (); return 0; } on arm targets with optimisation. At -O0 it doesn't abort. The wrong code is at statement: struct S e = c[0]; The constructor initialisation RTL emitted is: ;; e = c[0]; (insn 5 4 6 (set (reg/v:SI 112 [ e ]) (const_int 0 [0])) (nil)) (insn 6 5 7 (set (reg/v:SI 112 [ e ]) (const_int -1 [0xffffffffffffffff])) (nil)) The second SET clobbers the whole word rather than just the 16 bits it was supposed to. The problem is in store_constructor in expr.c where it widens the first store to word mode by sign-extending the value but then tries to avoid storing the zero bitfield because it had initially cleared out the word (the first set). This testcase works for me for GCC 4.8.5 but fails on 4.9 and later