http://gcc.gnu.org/bugzilla/show_bug.cgi?id=48124
--- Comment #10 from Richard Guenther <rguenth at gcc dot gnu.org> 2012-02-01 12:48:56 UTC --- (In reply to comment #9) > Simpler patch I am going to test. Let's hope the wreckage adjust_address > does to the to_rtx MEM (apart from setting its mode) is harmless. > > Index: expr.c > =================================================================== > --- expr.c (revision 183791) > +++ expr.c (working copy) > @@ -4705,6 +4705,21 @@ expand_assignment (tree to, tree from, b > to_rtx = adjust_address (to_rtx, mode1, 0); > else if (GET_MODE (to_rtx) == VOIDmode) > to_rtx = adjust_address (to_rtx, BLKmode, 0); > + /* If the alignment of tem is larger than its size and we > + are performing a bitfield access limit the mode we use > + for the access to make sure we do not access the decl > + beyond its end. See PR48124. */ > + else if (GET_MODE (to_rtx) == BLKmode > + && mode1 == VOIDmode > + && DECL_P (tem) > + && TREE_CODE (DECL_SIZE (tem)) == INTEGER_CST > + && TREE_INT_CST_LOW (DECL_SIZE (tem)) % DECL_ALIGN (tem)) > + { > + mode1 = mode_for_size (TREE_INT_CST_LOW (DECL_SIZE (tem)) > + % DECL_ALIGN (tem), > + MODE_INT, 0); > + to_rtx = adjust_address (to_rtx, mode1, 0); > + } > } > > if (offset != 0) Or rather Index: gcc/expr.c =================================================================== --- gcc/expr.c (revision 183791) +++ gcc/expr.c (working copy) @@ -4705,6 +4705,22 @@ expand_assignment (tree to, tree from, b to_rtx = adjust_address (to_rtx, mode1, 0); else if (GET_MODE (to_rtx) == VOIDmode) to_rtx = adjust_address (to_rtx, BLKmode, 0); + /* If the alignment of tem is larger than its size and we + are performing a bitfield access limit the mode we use + for the access to make sure we do not access the decl + beyond its end. See PR48124. */ + else if (GET_MODE (to_rtx) == BLKmode + && mode1 == VOIDmode + && DECL_P (tem) + && TREE_CODE (DECL_SIZE (tem)) == INTEGER_CST + && (TREE_INT_CST_LOW (DECL_SIZE (tem)) + & (DECL_ALIGN (tem) - 1)) != 0) + { + unsigned HOST_WIDE_INT mis; + mis = TREE_INT_CST_LOW (DECL_SIZE (tem)) & (DECL_ALIGN (tem) - 1); + mode1 = mode_for_size (mis & -mis, MODE_INT, 0); + to_rtx = adjust_address (to_rtx, mode1, 0); + } } if (offset != 0)