> I think we indeed can't really in stor-layout, so the only place is very
> likely get_bit_range.
Something like that for example. I think the expmed.c hunk should be applied
to the 4.7 branch as well, because the new code in store_bit_field is quite
dangerous without it.
* expmed.c (store_bit_field): Assert that BITREGION_START is a multiple
of a unit before computing the offset in units.
* expr.c (get_bit_range): Return the null range if the enclosing record
is part of a larger bit field.
--
Eric Botcazou
Index: expr.c
===================================================================
--- expr.c (revision 185767)
+++ expr.c (working copy)
@@ -4462,6 +4462,25 @@ get_bit_range (unsigned HOST_WIDE_INT *b
return;
}
+ /* If we have a DECL_BIT_FIELD_REPRESENTATIVE but the enclosing record is
+ part of a larger bit field, then the representative does not serve any
+ useful purpose. This can occur in Ada. */
+ if (handled_component_p (TREE_OPERAND (exp, 0)))
+ {
+ enum machine_mode rmode;
+ HOST_WIDE_INT rbitsize, rbitpos;
+ tree roffset;
+ int unsignedp;
+ int volatilep = 0;
+ get_inner_reference (TREE_OPERAND (exp, 0), &rbitsize, &rbitpos,
+ &roffset, &rmode, &unsignedp, &volatilep, false);
+ if ((rbitpos % BITS_PER_UNIT) != 0)
+ {
+ *bitstart = *bitend = 0;
+ return;
+ }
+ }
+
/* Compute the adjustment to bitpos from the offset of the field
relative to the representative. DECL_FIELD_OFFSET of field and
repr are the same by construction if they are not constants,
Index: expmed.c
===================================================================
--- expmed.c (revision 185570)
+++ expmed.c (working copy)
@@ -828,8 +828,7 @@ store_bit_field (rtx str_rtx, unsigned H
/* Under the C++0x memory model, we must not touch bits outside the
bit region. Adjust the address to start at the beginning of the
bit region. */
- if (MEM_P (str_rtx)
- && bitregion_start > 0)
+ if (MEM_P (str_rtx) && bitregion_start > 0)
{
enum machine_mode bestmode;
enum machine_mode op_mode;
@@ -839,6 +838,8 @@ store_bit_field (rtx str_rtx, unsigned H
if (op_mode == MAX_MACHINE_MODE)
op_mode = VOIDmode;
+ gcc_assert ((bitregion_start % BITS_PER_UNIT) == 0);
+
offset = bitregion_start / BITS_PER_UNIT;
bitnum -= bitregion_start;
bitregion_end -= bitregion_start;