Thomas Preud'homme writes: > In the code dealing with folding of structure and union initialization, > there is a > check that the size of the constructor is the same as the field being read. > However, in the case of bitfield this test can be wrong because it relies on > TYPE_SIZE to get the size of the field being read but TYPE_SIZE returns the > size of the enclosing integer in that case. This patch also check the size > parameter which contains the actual size of the field being read. > > The patch was tested by running the testsuite with three different builds of > GCC: > 1) bootstrap of GCC on x86_64-linux-gnu > 2) arm-none-eabi cross compiler (defaulting to little endian) with testsuite > run under qemu emulqting a Cortex M4 > 3) arm-none-eabi cross compiler (defaulting to big endian, thanks to patch > at [1]) > with testsuite run under qemu emulating a Cortex M3. > > [1] https://sourceware.org/ml/binutils/2014-08/msg00014.html > > No regression were observed on any of the tests. The ChangeLog is as follows: > > > 2014-08-11 Thomas Preud'homme <thomas.preudho...@arm.com> > > * gimple-fold.c (fold_ctor_reference): Don't fold in presence of > bitfields, that is when size doesn't match the size of type or the > size of the constructor. > > > diff --git a/gcc/gimple-fold.c b/gcc/gimple-fold.c > index 3dcb576..6270c34 100644 > --- a/gcc/gimple-fold.c > +++ b/gcc/gimple-fold.c > @@ -3099,7 +3099,9 @@ fold_ctor_reference (tree type, tree ctor, unsigned > HOST_WIDE_INT offset, > if (!AGGREGATE_TYPE_P (TREE_TYPE (ctor)) && !offset > /* VIEW_CONVERT_EXPR is defined only for matching sizes. */ > && operand_equal_p (TYPE_SIZE (type), > - TYPE_SIZE (TREE_TYPE (ctor)), 0)) > + TYPE_SIZE (TREE_TYPE (ctor)), 0) > + && !compare_tree_int (TYPE_SIZE (type), size) > + && !compare_tree_int (TYPE_SIZE (TREE_TYPE (ctor)), size)) > { > ret = canonicalize_constructor_val (unshare_expr (ctor), from_decl); > ret = fold_unary (VIEW_CONVERT_EXPR, type, ret); > diff --git a/gcc/testsuite/gcc.c-torture/execute/bitfld-6.c > b/gcc/testsuite/gcc.c-torture/execute/bitfld-6.c > new file mode 100644 > index 0000000..50927dc > --- /dev/null > +++ b/gcc/testsuite/gcc.c-torture/execute/bitfld-6.c > @@ -0,0 +1,23 @@ > +union U > +{ > + const int a; > + unsigned b : 20; > +}; > + > +static union U u = { 0x12345678 }; > + > +/* Constant folding used to fail to account for endianness when folding a > + union. */ > + > +int > +main (void) > +{ > +#ifdef __BYTE_ORDER__ > +#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ > + return u.b - 0x45678; > +#else > + return u.b - 0x12345; > +#endif > +#endif > + return 0; > +} > > Is it ok for trunk? > > Best regards, > > Thomas >
This test case also fails on powerpc64 (BE not LE), sparc64, and m68k, with all current gcc branches (4.10, 4.9, 4.8). On my powerpc64 box the failure started with gcc-4.6; gcc-4.5 back to gcc-3.4.6 seem Ok. Perhaps give this a proper PR and consider backporting? /Mikael