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
+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
/* 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
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. */
}
}
+/* 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
/* 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;
+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
--- /dev/null
+/* { 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;
+}
--- /dev/null
+/* { 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;
+}
--- /dev/null
+/* { 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;
+}
--- /dev/null
+/* { 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;
+}
--- /dev/null
+-- { 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;
--- /dev/null
+package Pack16_Pkg is
+
+ N : Natural := 16;
+
+end Pack16_Pkg;
--- /dev/null
+-- { 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;
--- /dev/null
+-- { 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;
--- /dev/null
+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;
--- /dev/null
+package Pack8_Pkg is
+
+ N : Natural := 1;
+
+end Pack8_Pkg;
{
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);
}
{
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);
}
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)
#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)