OSDN Git Service

2012-06-04 Richard Guenther <rguenther@suse.de>
authorrguenth <rguenth@138bc75d-0d04-0410-961f-82ee72b054a4>
Mon, 4 Jun 2012 08:43:23 +0000 (08:43 +0000)
committerrguenth <rguenth@138bc75d-0d04-0410-961f-82ee72b054a4>
Mon, 4 Jun 2012 08:43:23 +0000 (08:43 +0000)
Eric Botcazou  <ebotcazou@adacore.com>

Backport from mainline
2012-04-03  Eric Botcazou  <ebotcazou@adacore.com>

        * expr.c (get_bit_range): Add OFFSET parameter and adjust BITPOS.
        Change type of BITOFFSET to signed.  Make sure the lower bound of
        the computed range is non-negative by adjusting OFFSET and BITPOS.
        (expand_assignment): Adjust call to get_bit_range.

2012-03-27  Eric Botcazou  <ebotcazou@adacore.com>

        * expr.c (get_bit_range): Return the null range if the enclosing record
        is part of a larger bit field.

2012-03-20  Richard Guenther  <rguenther@suse.de>

        * stor-layout.c (finish_bitfield_representative): Fallback
        to conservative maximum size if the padding up to the next
        field cannot be computed as a constant.
        (finish_bitfield_layout): If we cannot compute the distance
        between the start of the bitfield representative and the
        bitfield member start a new representative.
        * expr.c (get_bit_range): The distance between the start of
        the bitfield representative and the bitfield member is zero
        if the field offsets are not constants.

2012-03-16  Richard Guenther  <rguenther@suse.de>

        * stor-layout.c (finish_bitfield_representative): Fall back
        to the conservative maximum size if we cannot compute the
        size of the tail padding.

2012-03-14  Richard Guenther  <rguenther@suse.de>

* tree.h (DECL_BIT_FIELD_REPRESENTATIVE): New define.
* stor-layout.c (start_bitfield_representative): New function.
(finish_bitfield_representative): Likewise.
(finish_bitfield_layout): Likewise.
(finish_record_layout): Call finish_bitfield_layout.
* tree.c (free_lang_data_in_decl): Only free DECL_QUALIFIER
for QUAL_UNION_TYPE fields.
* tree-streamer-in.c (lto_input_ts_field_decl_tree_pointers):
Stream DECL_BIT_FIELD_REPRESENTATIVE.
* tree-streamer-out.c (write_ts_field_decl_tree_pointers): Likewise.

PR middle-end/52080
PR middle-end/52097
PR middle-end/48124
* expr.c (get_bit_range): Unconditionally extract bitrange
from DECL_BIT_FIELD_REPRESENTATIVE.
(expand_assignment): Adjust call to get_bit_range.

* gcc.dg/torture/pr48124-1.c: New testcase.
* gcc.dg/torture/pr48124-2.c: Likewise.
* gcc.dg/torture/pr48124-3.c: Likewise.
* gcc.dg/torture/pr48124-4.c: Likewise.
* gnat.dg/pack16.adb: Likewise.
* gnat.dg/pack16_pkg.ads: Likewise.
* gnat.dg/pack17.adb: Likewise.
* gnat.dg/specs/pack7.ads: Likewise.
* gnat.dg/specs/pack8.ads: Likewise.
* gnat.dg/specs/pack8_pkg.ads: Likewise.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/branches/gcc-4_7-branch@188167 138bc75d-0d04-0410-961f-82ee72b054a4

18 files changed:
gcc/ChangeLog
gcc/expr.c
gcc/stor-layout.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/torture/pr48124-1.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/torture/pr48124-2.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/torture/pr48124-3.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/torture/pr48124-4.c [new file with mode: 0644]
gcc/testsuite/gnat.dg/pack16.adb [new file with mode: 0644]
gcc/testsuite/gnat.dg/pack16_pkg.ads [new file with mode: 0644]
gcc/testsuite/gnat.dg/pack17.adb [new file with mode: 0644]
gcc/testsuite/gnat.dg/specs/pack7.ads [new file with mode: 0644]
gcc/testsuite/gnat.dg/specs/pack8.ads [new file with mode: 0644]
gcc/testsuite/gnat.dg/specs/pack8_pkg.ads [new file with mode: 0644]
gcc/tree-streamer-in.c
gcc/tree-streamer-out.c
gcc/tree.c
gcc/tree.h

index 8c5c036..b4dc872 100644 (file)
@@ -1,3 +1,57 @@
+2012-06-04  Richard Guenther  <rguenther@suse.de>
+       Eric Botcazou  <ebotcazou@adacore.com>
+
+       Backport from mainline
+       2012-04-03  Eric Botcazou  <ebotcazou@adacore.com>
+
+        * expr.c (get_bit_range): Add OFFSET parameter and adjust BITPOS.
+        Change type of BITOFFSET to signed.  Make sure the lower bound of
+        the computed range is non-negative by adjusting OFFSET and BITPOS.
+        (expand_assignment): Adjust call to get_bit_range.
+
+       2012-03-27  Eric Botcazou  <ebotcazou@adacore.com>
+
+        * expr.c (get_bit_range): Return the null range if the enclosing record
+        is part of a larger bit field.
+
+       2012-03-20  Richard Guenther  <rguenther@suse.de>
+
+        * stor-layout.c (finish_bitfield_representative): Fallback
+        to conservative maximum size if the padding up to the next
+        field cannot be computed as a constant.
+        (finish_bitfield_layout): If we cannot compute the distance
+        between the start of the bitfield representative and the
+        bitfield member start a new representative.
+        * expr.c (get_bit_range): The distance between the start of
+        the bitfield representative and the bitfield member is zero
+        if the field offsets are not constants.
+
+       2012-03-16  Richard Guenther  <rguenther@suse.de>
+
+        * stor-layout.c (finish_bitfield_representative): Fall back
+        to the conservative maximum size if we cannot compute the
+        size of the tail padding.
+
+       2012-03-14  Richard Guenther  <rguenther@suse.de>
+
+       * tree.h (DECL_BIT_FIELD_REPRESENTATIVE): New define.
+       * stor-layout.c (start_bitfield_representative): New function.
+       (finish_bitfield_representative): Likewise.
+       (finish_bitfield_layout): Likewise.
+       (finish_record_layout): Call finish_bitfield_layout.
+       * tree.c (free_lang_data_in_decl): Only free DECL_QUALIFIER
+       for QUAL_UNION_TYPE fields.
+       * tree-streamer-in.c (lto_input_ts_field_decl_tree_pointers):
+       Stream DECL_BIT_FIELD_REPRESENTATIVE.
+       * tree-streamer-out.c (write_ts_field_decl_tree_pointers): Likewise.
+
+       PR middle-end/52080
+       PR middle-end/52097
+       PR middle-end/48124
+       * expr.c (get_bit_range): Unconditionally extract bitrange
+       from DECL_BIT_FIELD_REPRESENTATIVE.
+       (expand_assignment): Adjust call to get_bit_range.
+
 2012-06-01  Eric Botcazou  <ebotcazou@adacore.com>
 
        PR middle-end/53501
index e2957d2..963bb7d 100644 (file)
@@ -4439,113 +4439,88 @@ optimize_bitfield_assignment_op (unsigned HOST_WIDE_INT bitsize,
 /* In the C++ memory model, consecutive bit fields in a structure are
    considered one memory location.
 
-   Given a COMPONENT_REF, this function returns the bit range of
-   consecutive bits in which this COMPONENT_REF belongs in.  The
-   values are returned in *BITSTART and *BITEND.  If either the C++
-   memory model is not activated, or this memory access is not thread
-   visible, 0 is returned in *BITSTART and *BITEND.
-
-   EXP is the COMPONENT_REF.
-   INNERDECL is the actual object being referenced.
-   BITPOS is the position in bits where the bit starts within the structure.
-   BITSIZE is size in bits of the field being referenced in EXP.
-
-   For example, while storing into FOO.A here...
-
-      struct {
-        BIT 0:
-          unsigned int a : 4;
-         unsigned int b : 1;
-       BIT 8:
-         unsigned char c;
-         unsigned int d : 6;
-      } foo;
-
-   ...we are not allowed to store past <b>, so for the layout above, a
-   range of 0..7 (because no one cares if we store into the
-   padding).  */
+   Given a COMPONENT_REF EXP at position (BITPOS, OFFSET), this function
+   returns the bit range of consecutive bits in which this COMPONENT_REF
+   belongs.  The values are returned in *BITSTART and *BITEND.  *BITPOS
+   and *OFFSET may be adjusted in the process.
+
+   If the access does not need to be restricted, 0 is returned in both
+   *BITSTART and *BITEND.  */
 
 static void
 get_bit_range (unsigned HOST_WIDE_INT *bitstart,
               unsigned HOST_WIDE_INT *bitend,
-              tree exp, tree innerdecl,
-              HOST_WIDE_INT bitpos, HOST_WIDE_INT bitsize)
+              tree exp,
+              HOST_WIDE_INT *bitpos,
+              tree *offset)
 {
-  tree field, record_type, fld;
-  bool found_field = false;
-  bool prev_field_is_bitfield;
+  HOST_WIDE_INT bitoffset;
+  tree field, repr;
 
   gcc_assert (TREE_CODE (exp) == COMPONENT_REF);
 
-  /* If other threads can't see this value, no need to restrict stores.  */
-  if (ALLOW_STORE_DATA_RACES
-      || ((TREE_CODE (innerdecl) == MEM_REF
-          || TREE_CODE (innerdecl) == TARGET_MEM_REF)
-         && !ptr_deref_may_alias_global_p (TREE_OPERAND (innerdecl, 0)))
-      || (DECL_P (innerdecl)
-         && ((TREE_CODE (innerdecl) == VAR_DECL
-              && DECL_THREAD_LOCAL_P (innerdecl))
-             || !TREE_STATIC (innerdecl))))
+  field = TREE_OPERAND (exp, 1);
+  repr = DECL_BIT_FIELD_REPRESENTATIVE (field);
+  /* If we do not have a DECL_BIT_FIELD_REPRESENTATIVE there is no
+     need to limit the range we can access.  */
+  if (!repr)
     {
       *bitstart = *bitend = 0;
       return;
     }
 
-  /* Bit field we're storing into.  */
-  field = TREE_OPERAND (exp, 1);
-  record_type = DECL_FIELD_CONTEXT (field);
-
-  /* Count the contiguous bitfields for the memory location that
-     contains FIELD.  */
-  *bitstart = 0;
-  prev_field_is_bitfield = true;
-  for (fld = TYPE_FIELDS (record_type); fld; fld = DECL_CHAIN (fld))
+  /* 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)))
     {
-      tree t, offset;
-      enum machine_mode mode;
-      int unsignedp, volatilep;
-
-      if (TREE_CODE (fld) != FIELD_DECL)
-       continue;
-
-      t = build3 (COMPONENT_REF, TREE_TYPE (exp),
-                 unshare_expr (TREE_OPERAND (exp, 0)),
-                 fld, NULL_TREE);
-      get_inner_reference (t, &bitsize, &bitpos, &offset,
-                          &mode, &unsignedp, &volatilep, true);
-
-      if (field == fld)
-       found_field = true;
-
-      if (DECL_BIT_FIELD_TYPE (fld) && bitsize > 0)
-       {
-         if (prev_field_is_bitfield == false)
-           {
-             *bitstart = bitpos;
-             prev_field_is_bitfield = true;
-           }
-       }
-      else
+      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)
        {
-         prev_field_is_bitfield = false;
-         if (found_field)
-           break;
+         *bitstart = *bitend = 0;
+         return;
        }
     }
-  gcc_assert (found_field);
 
-  if (fld)
-    {
-      /* We found the end of the bit field sequence.  Include the
-        padding up to the next field and be done.  */
-      *bitend = bitpos - 1;
-    }
+  /* 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,
+     see finish_bitfield_layout.  */
+  if (host_integerp (DECL_FIELD_OFFSET (field), 1)
+      && host_integerp (DECL_FIELD_OFFSET (repr), 1))
+    bitoffset = (tree_low_cst (DECL_FIELD_OFFSET (field), 1)
+                - tree_low_cst (DECL_FIELD_OFFSET (repr), 1)) * BITS_PER_UNIT;
   else
+    bitoffset = 0;
+  bitoffset += (tree_low_cst (DECL_FIELD_BIT_OFFSET (field), 1)
+               - tree_low_cst (DECL_FIELD_BIT_OFFSET (repr), 1));
+
+  /* If the adjustment is larger than bitpos, we would have a negative bit
+     position for the lower bound and this may wreak havoc later.  This can
+     occur only if we have a non-null offset, so adjust offset and bitpos
+     to make the lower bound non-negative.  */
+  if (bitoffset > *bitpos)
     {
-      /* If this is the last element in the structure, include the padding
-        at the end of structure.  */
-      *bitend = TREE_INT_CST_LOW (TYPE_SIZE (record_type)) - 1;
+      HOST_WIDE_INT adjust = bitoffset - *bitpos;
+
+      gcc_assert ((adjust % BITS_PER_UNIT) == 0);
+      gcc_assert (*offset != NULL_TREE);
+
+      *bitpos += adjust;
+      *offset
+       = size_binop (MINUS_EXPR, *offset, size_int (adjust / BITS_PER_UNIT));
+      *bitstart = 0;
     }
+  else
+    *bitstart = *bitpos - bitoffset;
+
+  *bitend = *bitstart + tree_low_cst (DECL_SIZE (repr), 1) - 1;
 }
 
 /* Returns true if the MEM_REF REF refers to an object that does not
@@ -4675,8 +4650,7 @@ expand_assignment (tree to, tree from, bool nontemporal)
 
       if (TREE_CODE (to) == COMPONENT_REF
          && DECL_BIT_FIELD_TYPE (TREE_OPERAND (to, 1)))
-       get_bit_range (&bitregion_start, &bitregion_end,
-                      to, tem, bitpos, bitsize);
+       get_bit_range (&bitregion_start, &bitregion_end, to, &bitpos, &offset);
 
       /* If we are going to use store_bit_field and extract_bit_field,
         make sure to_rtx will be safe for multiple use.  */
index a1ac000..2600aab 100644 (file)
@@ -1722,6 +1722,221 @@ finalize_type_size (tree type)
     }
 }
 
+/* Return a new underlying object for a bitfield started with FIELD.  */
+
+static tree
+start_bitfield_representative (tree field)
+{
+  tree repr = make_node (FIELD_DECL);
+  DECL_FIELD_OFFSET (repr) = DECL_FIELD_OFFSET (field);
+  /* Force the representative to begin at a BITS_PER_UNIT aligned
+     boundary - C++ may use tail-padding of a base object to
+     continue packing bits so the bitfield region does not start
+     at bit zero (see g++.dg/abi/bitfield5.C for example).
+     Unallocated bits may happen for other reasons as well,
+     for example Ada which allows explicit bit-granular structure layout.  */
+  DECL_FIELD_BIT_OFFSET (repr)
+    = size_binop (BIT_AND_EXPR,
+                 DECL_FIELD_BIT_OFFSET (field),
+                 bitsize_int (~(BITS_PER_UNIT - 1)));
+  SET_DECL_OFFSET_ALIGN (repr, DECL_OFFSET_ALIGN (field));
+  DECL_SIZE (repr) = DECL_SIZE (field);
+  DECL_SIZE_UNIT (repr) = DECL_SIZE_UNIT (field);
+  DECL_PACKED (repr) = DECL_PACKED (field);
+  DECL_CONTEXT (repr) = DECL_CONTEXT (field);
+  return repr;
+}
+
+/* Finish up a bitfield group that was started by creating the underlying
+   object REPR with the last field in the bitfield group FIELD.  */
+
+static void
+finish_bitfield_representative (tree repr, tree field)
+{
+  unsigned HOST_WIDE_INT bitsize, maxbitsize;
+  enum machine_mode mode;
+  tree nextf, size;
+
+  size = size_diffop (DECL_FIELD_OFFSET (field),
+                     DECL_FIELD_OFFSET (repr));
+  gcc_assert (host_integerp (size, 1));
+  bitsize = (tree_low_cst (size, 1) * BITS_PER_UNIT
+            + tree_low_cst (DECL_FIELD_BIT_OFFSET (field), 1)
+            - tree_low_cst (DECL_FIELD_BIT_OFFSET (repr), 1)
+            + tree_low_cst (DECL_SIZE (field), 1));
+
+  /* Round up bitsize to multiples of BITS_PER_UNIT.  */
+  bitsize = (bitsize + BITS_PER_UNIT - 1) & ~(BITS_PER_UNIT - 1);
+
+  /* Now nothing tells us how to pad out bitsize ...  */
+  nextf = DECL_CHAIN (field);
+  while (nextf && TREE_CODE (nextf) != FIELD_DECL)
+    nextf = DECL_CHAIN (nextf);
+  if (nextf)
+    {
+      tree maxsize;
+      /* If there was an error, the field may be not laid out
+         correctly.  Don't bother to do anything.  */
+      if (TREE_TYPE (nextf) == error_mark_node)
+       return;
+      maxsize = size_diffop (DECL_FIELD_OFFSET (nextf),
+                            DECL_FIELD_OFFSET (repr));
+      if (host_integerp (maxsize, 1))
+       {
+         maxbitsize = (tree_low_cst (maxsize, 1) * BITS_PER_UNIT
+                       + tree_low_cst (DECL_FIELD_BIT_OFFSET (nextf), 1)
+                       - tree_low_cst (DECL_FIELD_BIT_OFFSET (repr), 1));
+         /* If the group ends within a bitfield nextf does not need to be
+            aligned to BITS_PER_UNIT.  Thus round up.  */
+         maxbitsize = (maxbitsize + BITS_PER_UNIT - 1) & ~(BITS_PER_UNIT - 1);
+       }
+      else
+       maxbitsize = bitsize;
+    }
+  else
+    {
+      /* ???  If you consider that tail-padding of this struct might be
+         re-used when deriving from it we cannot really do the following
+        and thus need to set maxsize to bitsize?  Also we cannot
+        generally rely on maxsize to fold to an integer constant, so
+        use bitsize as fallback for this case.  */
+      tree maxsize = size_diffop (TYPE_SIZE_UNIT (DECL_CONTEXT (field)),
+                                 DECL_FIELD_OFFSET (repr));
+      if (host_integerp (maxsize, 1))
+       maxbitsize = (tree_low_cst (maxsize, 1) * BITS_PER_UNIT
+                     - tree_low_cst (DECL_FIELD_BIT_OFFSET (repr), 1));
+      else
+       maxbitsize = bitsize;
+    }
+
+  /* Only if we don't artificially break up the representative in
+     the middle of a large bitfield with different possibly
+     overlapping representatives.  And all representatives start
+     at byte offset.  */
+  gcc_assert (maxbitsize % BITS_PER_UNIT == 0);
+
+  /* Find the smallest nice mode to use.  */
+  for (mode = GET_CLASS_NARROWEST_MODE (MODE_INT); mode != VOIDmode;
+       mode = GET_MODE_WIDER_MODE (mode))
+    if (GET_MODE_BITSIZE (mode) >= bitsize)
+      break;
+  if (mode != VOIDmode
+      && (GET_MODE_BITSIZE (mode) > maxbitsize
+         || GET_MODE_BITSIZE (mode) > MAX_FIXED_MODE_SIZE))
+    mode = VOIDmode;
+
+  if (mode == VOIDmode)
+    {
+      /* We really want a BLKmode representative only as a last resort,
+         considering the member b in
+          struct { int a : 7; int b : 17; int c; } __attribute__((packed));
+        Otherwise we simply want to split the representative up
+        allowing for overlaps within the bitfield region as required for
+          struct { int a : 7; int b : 7;
+                   int c : 10; int d; } __attribute__((packed));
+        [0, 15] HImode for a and b, [8, 23] HImode for c.  */
+      DECL_SIZE (repr) = bitsize_int (bitsize);
+      DECL_SIZE_UNIT (repr) = size_int (bitsize / BITS_PER_UNIT);
+      DECL_MODE (repr) = BLKmode;
+      TREE_TYPE (repr) = build_array_type_nelts (unsigned_char_type_node,
+                                                bitsize / BITS_PER_UNIT);
+    }
+  else
+    {
+      unsigned HOST_WIDE_INT modesize = GET_MODE_BITSIZE (mode);
+      DECL_SIZE (repr) = bitsize_int (modesize);
+      DECL_SIZE_UNIT (repr) = size_int (modesize / BITS_PER_UNIT);
+      DECL_MODE (repr) = mode;
+      TREE_TYPE (repr) = lang_hooks.types.type_for_mode (mode, 1);
+    }
+
+  /* Remember whether the bitfield group is at the end of the
+     structure or not.  */
+  DECL_CHAIN (repr) = nextf;
+}
+
+/* Compute and set FIELD_DECLs for the underlying objects we should
+   use for bitfield access for the structure laid out with RLI.  */
+
+static void
+finish_bitfield_layout (record_layout_info rli)
+{
+  tree field, prev;
+  tree repr = NULL_TREE;
+
+  /* Unions would be special, for the ease of type-punning optimizations
+     we could use the underlying type as hint for the representative
+     if the bitfield would fit and the representative would not exceed
+     the union in size.  */
+  if (TREE_CODE (rli->t) != RECORD_TYPE)
+    return;
+
+  for (prev = NULL_TREE, field = TYPE_FIELDS (rli->t);
+       field; field = DECL_CHAIN (field))
+    {
+      if (TREE_CODE (field) != FIELD_DECL)
+       continue;
+
+      /* In the C++ memory model, consecutive bit fields in a structure are
+        considered one memory location and updating a memory location
+        may not store into adjacent memory locations.  */
+      if (!repr
+         && DECL_BIT_FIELD_TYPE (field))
+       {
+         /* Start new representative.  */
+         repr = start_bitfield_representative (field);
+       }
+      else if (repr
+              && ! DECL_BIT_FIELD_TYPE (field))
+       {
+         /* Finish off new representative.  */
+         finish_bitfield_representative (repr, prev);
+         repr = NULL_TREE;
+       }
+      else if (DECL_BIT_FIELD_TYPE (field))
+       {
+         gcc_assert (repr != NULL_TREE);
+
+         /* Zero-size bitfields finish off a representative and
+            do not have a representative themselves.  This is
+            required by the C++ memory model.  */
+         if (integer_zerop (DECL_SIZE (field)))
+           {
+             finish_bitfield_representative (repr, prev);
+             repr = NULL_TREE;
+           }
+
+         /* We assume that either DECL_FIELD_OFFSET of the representative
+            and each bitfield member is a constant or they are equal.
+            This is because we need to be able to compute the bit-offset
+            of each field relative to the representative in get_bit_range
+            during RTL expansion.
+            If these constraints are not met, simply force a new
+            representative to be generated.  That will at most
+            generate worse code but still maintain correctness with
+            respect to the C++ memory model.  */
+         else if (!((host_integerp (DECL_FIELD_OFFSET (repr), 1)
+                     && host_integerp (DECL_FIELD_OFFSET (field), 1))
+                    || operand_equal_p (DECL_FIELD_OFFSET (repr),
+                                        DECL_FIELD_OFFSET (field), 0)))
+           {
+             finish_bitfield_representative (repr, prev);
+             repr = start_bitfield_representative (field);
+           }
+       }
+      else
+       continue;
+
+      if (repr)
+       DECL_BIT_FIELD_REPRESENTATIVE (field) = repr;
+
+      prev = field;
+    }
+
+  if (repr)
+    finish_bitfield_representative (repr, prev);
+}
+
 /* Do all of the work required to layout the type indicated by RLI,
    once the fields have been laid out.  This function will call `free'
    for RLI, unless FREE_P is false.  Passing a value other than false
@@ -1742,6 +1957,9 @@ finish_record_layout (record_layout_info rli, int free_p)
   /* Perform any last tweaks to the TYPE_SIZE, etc.  */
   finalize_type_size (rli->t);
 
+  /* Compute bitfield representatives.  */
+  finish_bitfield_layout (rli);
+
   /* Propagate TYPE_PACKED to variants.  With C++ templates,
      handle_packed_attribute is too early to do this.  */
   for (variant = TYPE_NEXT_VARIANT (rli->t); variant;
index 89511d1..7da9492 100644 (file)
@@ -1,3 +1,21 @@
+2012-06-04  Richard Guenther  <rguenther@suse.de>
+       Eric Botcazou  <ebotcazou@adacore.com>
+
+       Backport from mainline
+       PR middle-end/52080
+       PR middle-end/52097
+       PR middle-end/48124
+       * gcc.dg/torture/pr48124-1.c: New testcase.
+       * gcc.dg/torture/pr48124-2.c: Likewise.
+       * gcc.dg/torture/pr48124-3.c: Likewise.
+       * gcc.dg/torture/pr48124-4.c: Likewise.
+       * gnat.dg/pack16.adb: Likewise.
+       * gnat.dg/pack16_pkg.ads: Likewise.
+       * gnat.dg/pack17.adb: Likewise.
+       * gnat.dg/specs/pack7.ads: Likewise.
+       * gnat.dg/specs/pack8.ads: Likewise.
+       * gnat.dg/specs/pack8_pkg.ads: Likewise.
+
 2012-06-01  Jason Merrill  <jason@redhat.com>
 
        PR c++/52973
diff --git a/gcc/testsuite/gcc.dg/torture/pr48124-1.c b/gcc/testsuite/gcc.dg/torture/pr48124-1.c
new file mode 100644 (file)
index 0000000..a0c73bf
--- /dev/null
@@ -0,0 +1,34 @@
+/* { dg-do run } */
+/* { dg-options "-fno-toplevel-reorder" } */
+/* { dg-require-effective-target int32plus } */
+
+extern void abort (void);
+
+struct S
+{
+  signed a : 26;
+  signed b : 16;
+  signed c : 10;
+  volatile signed d : 14;
+};
+
+static struct S e = { 0, 0, 0, 1 };
+static int f = 1;
+
+void __attribute__((noinline))
+foo (void)
+{
+  e.d = 0;
+  f = 2;
+}
+
+int
+main ()
+{
+  if (e.a || e.b || e.c || e.d != 1 || f != 1)
+    abort ();
+  foo ();
+  if (e.a || e.b || e.c || e.d || f != 2)
+    abort ();
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/torture/pr48124-2.c b/gcc/testsuite/gcc.dg/torture/pr48124-2.c
new file mode 100644 (file)
index 0000000..485d8d4
--- /dev/null
@@ -0,0 +1,27 @@
+/* { dg-do run } */
+
+extern void abort (void);
+
+static volatile struct S0 {
+    short f3[9];
+    unsigned f8 : 15;
+} s = {1};
+static unsigned short sh = 0x1234;
+
+struct S0 a, b;
+int vi = 0;
+
+void func_4()
+{
+  s.f8 |= 1;
+  sh = 15;
+  if (vi) a = b;
+}
+
+int main()
+{
+  func_4();
+  if (sh != 15)
+    abort ();
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/torture/pr48124-3.c b/gcc/testsuite/gcc.dg/torture/pr48124-3.c
new file mode 100644 (file)
index 0000000..386d88b
--- /dev/null
@@ -0,0 +1,32 @@
+/* { dg-do run } */
+
+extern void abort (void);
+struct S1
+{
+  int f0;
+  int:1;
+  int f3;
+  int:1;
+  int:0;
+  int f6:1;
+};
+int g_13 = 1;
+volatile struct S1 g_118 = {
+    1
+};
+
+void __attribute__((noinline))
+func_46 ()
+{
+  for (g_13 = 0; g_13 >= 0; g_13 -= 1)
+    g_118.f6 = 0;
+}
+
+int
+main ()
+{
+  func_46 ();
+  if (g_13 != -1)
+    abort ();
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/torture/pr48124-4.c b/gcc/testsuite/gcc.dg/torture/pr48124-4.c
new file mode 100644 (file)
index 0000000..fe9f97e
--- /dev/null
@@ -0,0 +1,29 @@
+/* { dg-do run } */
+/* { dg-require-effective-target int32plus } */
+
+extern void abort (void);
+struct S1 {
+    unsigned f0, f1;
+    unsigned short f2, f3;
+    unsigned f4 : 16;
+    unsigned f5, f6;
+    volatile unsigned f7 : 28;
+};
+static struct S1 g_76;
+static struct S1 g_245 = {0,0,0,0,0,0,0,1};
+static signed char g_323 = 0x80;
+static void func_1(void)
+{
+  g_245.f7 &= 1;
+  for (g_323 = 0; g_323 <= -1; g_323 -= 2) {
+      g_76 = g_76;
+      g_76.f4 ^= 11;
+  }
+}
+int main()
+{
+  func_1();
+  if (g_323 != 0 || g_245.f7 != 1)
+    abort ();
+  return 0;
+}
diff --git a/gcc/testsuite/gnat.dg/pack16.adb b/gcc/testsuite/gnat.dg/pack16.adb
new file mode 100644 (file)
index 0000000..eb8e2f9
--- /dev/null
@@ -0,0 +1,26 @@
+-- { dg-do compile }
+-- { dg-options "-gnatws" }
+
+with Pack16_Pkg; use Pack16_Pkg;
+
+procedure Pack16 is
+
+   type Sample_Table_T is array (1 .. N) of Integer;
+
+   type Clock_T is record
+      N_Ticks  : Integer := 0;
+   end record;
+
+   type Sampling_Descriptor_T is record
+      Values : Sample_Table_T;
+      Valid  : Boolean;
+      Tstamp : Clock_T;
+   end record;
+
+   pragma Pack (Sampling_Descriptor_T);
+
+   Sampling_Data : Sampling_Descriptor_T;
+
+begin
+   null;
+end;
diff --git a/gcc/testsuite/gnat.dg/pack16_pkg.ads b/gcc/testsuite/gnat.dg/pack16_pkg.ads
new file mode 100644 (file)
index 0000000..92884f3
--- /dev/null
@@ -0,0 +1,5 @@
+package Pack16_Pkg is
+
+   N : Natural := 16;
+
+end Pack16_Pkg;
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;
diff --git a/gcc/testsuite/gnat.dg/specs/pack7.ads b/gcc/testsuite/gnat.dg/specs/pack7.ads
new file mode 100644 (file)
index 0000000..8a1250a
--- /dev/null
@@ -0,0 +1,13 @@
+-- { dg-do compile }
+
+package Pack7 is
+
+   type R (D : Natural) is record
+      S : String (1 .. D);
+      N : Natural;
+      B : Boolean;
+   end record;
+   for R'Alignment use 4;
+   pragma Pack (R);
+
+end Pack7;
diff --git a/gcc/testsuite/gnat.dg/specs/pack8.ads b/gcc/testsuite/gnat.dg/specs/pack8.ads
new file mode 100644 (file)
index 0000000..db839cb
--- /dev/null
@@ -0,0 +1,19 @@
+with Pack8_Pkg;
+
+package Pack8 is
+
+   subtype Index_Type is Integer range 1 .. Pack8_Pkg.N;
+
+   subtype Str is String( Index_Type);
+
+   subtype Str2 is String (1 .. 11);
+
+   type Rec is record
+      S1 : Str;
+      S2 : Str;
+      B  : Boolean;
+      S3 : Str2;
+   end record;
+   pragma Pack (Rec);
+
+end Pack8;
diff --git a/gcc/testsuite/gnat.dg/specs/pack8_pkg.ads b/gcc/testsuite/gnat.dg/specs/pack8_pkg.ads
new file mode 100644 (file)
index 0000000..f35e629
--- /dev/null
@@ -0,0 +1,5 @@
+package Pack8_Pkg is
+
+   N : Natural := 1;
+
+end Pack8_Pkg;
index cc6fae7..cb940aa 100644 (file)
@@ -640,7 +640,7 @@ lto_input_ts_field_decl_tree_pointers (struct lto_input_block *ib,
 {
   DECL_FIELD_OFFSET (expr) = stream_read_tree (ib, data_in);
   DECL_BIT_FIELD_TYPE (expr) = stream_read_tree (ib, data_in);
-  /* Do not stream DECL_QUALIFIER, it is useless after gimplification.  */
+  DECL_BIT_FIELD_REPRESENTATIVE (expr) = stream_read_tree (ib, data_in);
   DECL_FIELD_BIT_OFFSET (expr) = stream_read_tree (ib, data_in);
   DECL_FCONTEXT (expr) = stream_read_tree (ib, data_in);
 }
index 21689df..c792fc2 100644 (file)
@@ -552,7 +552,7 @@ write_ts_field_decl_tree_pointers (struct output_block *ob, tree expr,
 {
   stream_write_tree (ob, DECL_FIELD_OFFSET (expr), ref_p);
   stream_write_tree (ob, DECL_BIT_FIELD_TYPE (expr), ref_p);
-  /* Do not stream DECL_QUALIFIER, it is useless after gimplification.  */
+  stream_write_tree (ob, DECL_BIT_FIELD_REPRESENTATIVE (expr), ref_p);
   stream_write_tree (ob, DECL_FIELD_BIT_OFFSET (expr), ref_p);
   stream_write_tree (ob, DECL_FCONTEXT (expr), ref_p);
 }
index 9d154d1..9278d1b 100644 (file)
@@ -4598,7 +4598,8 @@ free_lang_data_in_decl (tree decl)
   if (TREE_CODE (decl) == FIELD_DECL)
     {
       free_lang_data_in_one_sizepos (&DECL_FIELD_OFFSET (decl));
-      DECL_QUALIFIER (decl) = NULL_TREE;
+      if (TREE_CODE (DECL_CONTEXT (decl)) == QUAL_UNION_TYPE)
+       DECL_QUALIFIER (decl) = NULL_TREE;
     }
 
  if (TREE_CODE (decl) == FUNCTION_DECL)
index 140f23e..7162dab 100644 (file)
@@ -3021,6 +3021,11 @@ struct GTY(()) tree_decl_with_rtl {
 #define DECL_BIT_FIELD_TYPE(NODE) \
   (FIELD_DECL_CHECK (NODE)->field_decl.bit_field_type)
 
+/* In a FIELD_DECL of a RECORD_TYPE, this is a pointer to the storage
+   representative FIELD_DECL.  */
+#define DECL_BIT_FIELD_REPRESENTATIVE(NODE) \
+  (FIELD_DECL_CHECK (NODE)->field_decl.qualifier)
+
 /* For a FIELD_DECL in a QUAL_UNION_TYPE, records the expression, which
    if nonzero, indicates that the field occupies the type.  */
 #define DECL_QUALIFIER(NODE) (FIELD_DECL_CHECK (NODE)->field_decl.qualifier)