> 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;

Reply via email to