expmed.c (store_bit_field): Assert that BITREGION_START is a multiple of a unit befor...
authorEric Botcazou <ebotcazou@adacore.com>
Tue, 27 Mar 2012 10:35:55 +0000 (10:35 +0000)
committerEric Botcazou <ebotcazou@gcc.gnu.org>
Tue, 27 Mar 2012 10:35:55 +0000 (10:35 +0000)
* 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.

From-SVN: r185857

gcc/ChangeLog
gcc/expmed.c
gcc/expr.c
gcc/testsuite/ChangeLog
gcc/testsuite/gnat.dg/pack17.adb [new file with mode: 0644]

index 8321a8e27506a5441357793f2972c3a65d46dc7c..bf370df44ec866b2e87f9801f6689e966074e69b 100644 (file)
@@ -1,3 +1,10 @@
+2012-03-27  Eric Botcazou  <ebotcazou@adacore.com>
+
+       * 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.
+
 2012-03-27  Tristan Gingold  <gingold@adacore.com>
 
        * config/ia64/vms.h (CASE_VECTOR_MODE): Define.
index 5134b738b05ce8d76b6818999ad34e89cb5f9717..54e51dca02dd28a98a0f1f6a26b60997d4f43f78 100644 (file)
@@ -828,8 +828,7 @@ store_bit_field (rtx str_rtx, unsigned HOST_WIDE_INT bitsize,
   /* 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 HOST_WIDE_INT bitsize,
       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;
index c63343ec68235406e2f1f4265f28bfcea997c80f..56ec3fa8e2aee3243b6a162f9682869f53fdbc78 100644 (file)
@@ -4458,6 +4458,25 @@ get_bit_range (unsigned HOST_WIDE_INT *bitstart,
       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 e10e53dc51f8e5d8b5c6e0c1f9b6d37186ec7261..63de5d4e7ba22ff2cd70466ff5ff2e9d82783210 100644 (file)
@@ -1,3 +1,7 @@
+2012-03-27  Eric Botcazou  <ebotcazou@adacore.com>
+
+       * gnat.dg/pack17.adb: New test.
+
 2012-03-27  Ramana Radhakrishnan  <ramana.radhakrishnan@linaro.org>
 
        * gcc.target/arm/thumb-ifcvt.c: Only run for -mthumb.
diff --git a/gcc/testsuite/gnat.dg/pack17.adb b/gcc/testsuite/gnat.dg/pack17.adb
new file mode 100644 (file)
index 0000000..2333ba7
--- /dev/null
@@ -0,0 +1,38 @@
+-- { dg-do run }
+
+procedure Pack17 is
+
+   type Bitmap_T is array (Natural range <>) of Boolean;
+   pragma Pack (Bitmap_T);
+
+   type Uint8 is range 0 .. 2 ** 8 - 1;
+   for Uint8'Size use 8;
+
+   type Record_With_QImode_Variants (D : Boolean) is record
+      C_Filler : Bitmap_T (1..7);
+      C_Map : Bitmap_T (1..3);
+      case D is
+         when False =>
+            F_Bit : Boolean;
+            F_Filler : Bitmap_T (1..7);
+         when True =>
+            T_Int : Uint8;
+      end case;
+   end record;
+   pragma Pack (Record_With_QImode_Variants);
+
+   procedure Fill (R : out Record_With_QImode_Variants) is
+   begin
+      R.C_Filler := (True, False, True, False, True, False, True);
+      R.C_Map := (True, False, True);
+      R.T_Int := 17;
+   end;
+
+   RT : Record_With_QImode_Variants (D => True);
+
+begin
+   Fill (RT);
+   if RT.T_Int /= 17 then
+     raise Program_Error;
+   end if;
+end;