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

Reply via email to