expr.c (expand_expr_real_1): Apply the big-endian adjustment for bit-fields to all aggregate types.

* expr.c (expand_expr_real_1) <BIT_FIELD_REF>: Apply the big-endian
	adjustment for bit-fields to all aggregate types.
ada/
	* gcc-interface/gigi.h (make_packable_type): Remove default value.
	(value_factor_p): Tweak prototype.
	* gcc-interface/decl.c (gnat_to_gnu_entity): Add comment.
	(gnat_to_gnu_component_type): Likewise.
	(gnat_to_gnu_field): Likewise.  Fetch the position of the field earlier
	and simplify the condition under which the type is packed.  Declare
 	local variable is_bitfield.  Pass 1 as max_align to make_packable_type
	if it is set to true.
	(copy_and_substitute_in_layout): Pass 0 to make_packable_type.
	* gcc-interface/utils.c (make_packable_array_type): New function.
	(make_packable_type): Use it to rewrite the type of array field.
	(maybe_pad_type): Pass align parameter to make_packable_type.
	(create_field_decl): Minor tweaks.
	(value_factor_p): Assert that FACTOR is a power of 2 and replace the
	modulo computation by a masking operation.

From-SVN: r272810
This commit is contained in:
Eric Botcazou 2019-06-29 07:16:37 +00:00 committed by Eric Botcazou
parent 43e1e8b5b8
commit b1af4cb290
9 changed files with 193 additions and 54 deletions

View File

@ -1,3 +1,8 @@
2019-06-29 Eric Botcazou <ebotcazou@adacore.com>
* expr.c (expand_expr_real_1) <BIT_FIELD_REF>: Apply the big-endian
adjustment for bit-fields to all aggregate types.
2019-06-28 Michael Meissner <meissner@linux.ibm.com> 2019-06-28 Michael Meissner <meissner@linux.ibm.com>
* config/rs6000/predicates.md (pcrel_address): Use * config/rs6000/predicates.md (pcrel_address): Use

View File

@ -1,3 +1,21 @@
2019-06-29 Eric Botcazou <ebotcazou@adacore.com>
* gcc-interface/gigi.h (make_packable_type): Remove default value.
(value_factor_p): Tweak prototype.
* gcc-interface/decl.c (gnat_to_gnu_entity): Add comment.
(gnat_to_gnu_component_type): Likewise.
(gnat_to_gnu_field): Likewise. Fetch the position of the field earlier
and simplify the condition under which the type is packed. Declare
local variable is_bitfield. Pass 1 as max_align to make_packable_type
if it is set to true.
(copy_and_substitute_in_layout): Pass 0 to make_packable_type.
* gcc-interface/utils.c (make_packable_array_type): New function.
(make_packable_type): Use it to rewrite the type of array field.
(maybe_pad_type): Pass align parameter to make_packable_type.
(create_field_decl): Minor tweaks.
(value_factor_p): Assert that FACTOR is a power of 2 and replace the
modulo computation by a masking operation.
2019-06-25 Eric Botcazou <ebotcazou@adacore.com> 2019-06-25 Eric Botcazou <ebotcazou@adacore.com>
* gcc-interface/decl.c (gnat_to_gnu_entity): Remove superfluous test * gcc-interface/decl.c (gnat_to_gnu_entity): Remove superfluous test

View File

@ -4481,6 +4481,7 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, bool definition)
} }
} }
/* Now check if the type allows atomic access. */
if (Is_Atomic_Or_VFA (gnat_entity)) if (Is_Atomic_Or_VFA (gnat_entity))
check_ok_for_atomic_type (gnu_type, gnat_entity, false); check_ok_for_atomic_type (gnu_type, gnat_entity, false);
@ -5100,6 +5101,7 @@ gnat_to_gnu_component_type (Entity_Id gnat_array, bool definition,
} }
} }
/* Now check if the type of the component allows atomic access. */
if (Has_Atomic_Components (gnat_array) || Is_Atomic_Or_VFA (gnat_type)) if (Has_Atomic_Components (gnat_array) || Is_Atomic_Or_VFA (gnat_type))
check_ok_for_atomic_type (gnu_type, gnat_array, true); check_ok_for_atomic_type (gnu_type, gnat_array, true);
@ -6901,6 +6903,7 @@ gnat_to_gnu_field (Entity_Id gnat_field, tree gnu_record_type, int packed,
boundaries, but that should be guaranteed by the GCC memory model. */ boundaries, but that should be guaranteed by the GCC memory model. */
const bool needs_strict_alignment const bool needs_strict_alignment
= (is_atomic || is_aliased || is_independent || is_strict_alignment); = (is_atomic || is_aliased || is_independent || is_strict_alignment);
bool is_bitfield;
tree gnu_field_type = gnat_to_gnu_type (gnat_field_type); tree gnu_field_type = gnat_to_gnu_type (gnat_field_type);
tree gnu_field_id = get_entity_name (gnat_field); tree gnu_field_id = get_entity_name (gnat_field);
tree gnu_field, gnu_size, gnu_pos; tree gnu_field, gnu_size, gnu_pos;
@ -6915,7 +6918,7 @@ gnat_to_gnu_field (Entity_Id gnat_field, tree gnu_record_type, int packed,
/* If a size is specified, use it. Otherwise, if the record type is packed, /* If a size is specified, use it. Otherwise, if the record type is packed,
use the official RM size. See "Handling of Type'Size Values" in Einfo use the official RM size. See "Handling of Type'Size Values" in Einfo
for further details. */ for further details. */
if (Known_Esize (gnat_field) || Present (gnat_clause)) if (Present (gnat_clause) || Known_Esize (gnat_field))
gnu_size = validate_size (Esize (gnat_field), gnu_field_type, gnat_field, gnu_size = validate_size (Esize (gnat_field), gnu_field_type, gnat_field,
FIELD_DECL, false, true); FIELD_DECL, false, true);
else if (packed == 1) else if (packed == 1)
@ -6927,12 +6930,36 @@ gnat_to_gnu_field (Entity_Id gnat_field, tree gnu_record_type, int packed,
else else
gnu_size = NULL_TREE; gnu_size = NULL_TREE;
/* If we have a specified size that is smaller than that of the field's type, /* Likewise for the position. */
or a position is specified, and the field's type is a record that doesn't if (Present (gnat_clause))
require strict alignment, see if we can get either an integral mode form {
of the type or a smaller form. If we can, show a size was specified for gnu_pos = UI_To_gnu (Component_Bit_Offset (gnat_field), bitsizetype);
the field if there wasn't one already, so we know to make this a bitfield is_bitfield = !value_factor_p (gnu_pos, BITS_PER_UNIT);
and avoid making things wider. }
/* If the record has rep clauses and this is the tag field, make a rep
clause for it as well. */
else if (Has_Specified_Layout (gnat_record_type)
&& Chars (gnat_field) == Name_uTag)
{
gnu_pos = bitsize_zero_node;
gnu_size = TYPE_SIZE (gnu_field_type);
is_bitfield = false;
}
else
{
gnu_pos = NULL_TREE;
is_bitfield = false;
}
/* If the field's type is a fixed-size record that does not require strict
alignment, and the record is packed or we have a position specified for
the field that makes it a bitfield or we have a specified size that is
smaller than that of the field's type, then see if we can get either an
integral mode form of the field's type or a smaller form. If we can,
consider that a size was specified for the field if there wasn't one
already, so we know to make it a bitfield and avoid making things wider.
Changing to an integral mode form is useful when the record is packed as Changing to an integral mode form is useful when the record is packed as
we can then place the field at a non-byte-aligned position and so achieve we can then place the field at a non-byte-aligned position and so achieve
@ -6954,14 +6981,12 @@ gnat_to_gnu_field (Entity_Id gnat_field, tree gnu_record_type, int packed,
&& !TYPE_FAT_POINTER_P (gnu_field_type) && !TYPE_FAT_POINTER_P (gnu_field_type)
&& tree_fits_uhwi_p (TYPE_SIZE (gnu_field_type)) && tree_fits_uhwi_p (TYPE_SIZE (gnu_field_type))
&& (packed == 1 && (packed == 1
|| is_bitfield
|| (gnu_size || (gnu_size
&& (tree_int_cst_lt (gnu_size, TYPE_SIZE (gnu_field_type)) && tree_int_cst_lt (gnu_size, TYPE_SIZE (gnu_field_type)))))
|| (Present (gnat_clause)
&& !(UI_To_Int (Component_Bit_Offset (gnat_field))
% BITS_PER_UNIT == 0
&& value_factor_p (gnu_size, BITS_PER_UNIT)))))))
{ {
tree gnu_packable_type = make_packable_type (gnu_field_type, true); tree gnu_packable_type
= make_packable_type (gnu_field_type, true, is_bitfield ? 1 : 0);
if (gnu_packable_type != gnu_field_type) if (gnu_packable_type != gnu_field_type)
{ {
gnu_field_type = gnu_packable_type; gnu_field_type = gnu_packable_type;
@ -6970,6 +6995,7 @@ gnat_to_gnu_field (Entity_Id gnat_field, tree gnu_record_type, int packed,
} }
} }
/* Now check if the type of the field allows atomic access. */
if (Is_Atomic_Or_VFA (gnat_field)) if (Is_Atomic_Or_VFA (gnat_field))
{ {
const unsigned int align const unsigned int align
@ -6981,12 +7007,11 @@ gnat_to_gnu_field (Entity_Id gnat_field, tree gnu_record_type, int packed,
check_ok_for_atomic_type (gnu_field_type, gnat_field, false); check_ok_for_atomic_type (gnu_field_type, gnat_field, false);
} }
if (Present (gnat_clause)) /* If a position is specified, check that it is valid. */
if (gnu_pos)
{ {
Entity_Id gnat_parent = Parent_Subtype (gnat_record_type); Entity_Id gnat_parent = Parent_Subtype (gnat_record_type);
gnu_pos = UI_To_gnu (Component_Bit_Offset (gnat_field), bitsizetype);
/* Ensure the position does not overlap with the parent subtype, if there /* Ensure the position does not overlap with the parent subtype, if there
is one. This test is omitted if the parent of the tagged type has a is one. This test is omitted if the parent of the tagged type has a
full rep clause since, in this case, component clauses are allowed to full rep clause since, in this case, component clauses are allowed to
@ -7092,19 +7117,8 @@ gnat_to_gnu_field (Entity_Id gnat_field, tree gnu_record_type, int packed,
} }
} }
/* If the record has rep clauses and this is the tag field, make a rep
clause for it as well. */
else if (Has_Specified_Layout (gnat_record_type)
&& Chars (gnat_field) == Name_uTag)
{
gnu_pos = bitsize_zero_node;
gnu_size = TYPE_SIZE (gnu_field_type);
}
else else
{ {
gnu_pos = NULL_TREE;
/* If we are packing the record and the field is BLKmode, round the /* If we are packing the record and the field is BLKmode, round the
size up to a byte boundary. */ size up to a byte boundary. */
if (packed && TYPE_MODE (gnu_field_type) == BLKmode && gnu_size) if (packed && TYPE_MODE (gnu_field_type) == BLKmode && gnu_size)
@ -9681,7 +9695,7 @@ copy_and_substitute_in_layout (Entity_Id gnat_new_type,
if (RECORD_OR_UNION_TYPE_P (gnu_field_type) if (RECORD_OR_UNION_TYPE_P (gnu_field_type)
&& !TYPE_FAT_POINTER_P (gnu_field_type) && !TYPE_FAT_POINTER_P (gnu_field_type)
&& tree_fits_uhwi_p (TYPE_SIZE (gnu_field_type))) && tree_fits_uhwi_p (TYPE_SIZE (gnu_field_type)))
gnu_field_type = make_packable_type (gnu_field_type, true); gnu_field_type = make_packable_type (gnu_field_type, true, 0);
} }
else else

View File

@ -126,7 +126,7 @@ extern tree make_aligning_type (tree type, unsigned int align, tree size,
MAX_ALIGN alignment if the value is non-zero. If so, return the new MAX_ALIGN alignment if the value is non-zero. If so, return the new
type; if not, return the original type. */ type; if not, return the original type. */
extern tree make_packable_type (tree type, bool in_record, extern tree make_packable_type (tree type, bool in_record,
unsigned int max_align = 0); unsigned int max_align);
/* Given a type TYPE, return a new type whose size is appropriate for SIZE. /* Given a type TYPE, return a new type whose size is appropriate for SIZE.
If TYPE is the best type, return it. Otherwise, make a new type. We If TYPE is the best type, return it. Otherwise, make a new type. We
@ -837,7 +837,7 @@ extern unsigned int known_alignment (tree exp);
/* Return true if VALUE is a multiple of FACTOR. FACTOR must be a power /* Return true if VALUE is a multiple of FACTOR. FACTOR must be a power
of 2. */ of 2. */
extern bool value_factor_p (tree value, HOST_WIDE_INT factor); extern bool value_factor_p (tree value, unsigned HOST_WIDE_INT factor);
/* Build an atomic load for the underlying atomic object in SRC. SYNC is /* Build an atomic load for the underlying atomic object in SRC. SYNC is
true if the load requires synchronization. */ true if the load requires synchronization. */

View File

@ -984,10 +984,45 @@ make_aligning_type (tree type, unsigned int align, tree size,
return record_type; return record_type;
} }
/* TYPE is an ARRAY_TYPE that is being used as the type of a field in a packed
record. See if we can rewrite it as a type that has non-BLKmode, which we
can pack tighter in the packed record. If so, return the new type; if not,
return the original type. */
static tree
make_packable_array_type (tree type)
{
const unsigned HOST_WIDE_INT size = tree_to_uhwi (TYPE_SIZE (type));
unsigned HOST_WIDE_INT new_size;
unsigned int new_align;
/* No point in doing anything if the size is either zero or too large for an
integral mode, or if the type already has non-BLKmode. */
if (size == 0 || size > MAX_FIXED_MODE_SIZE || TYPE_MODE (type) != BLKmode)
return type;
/* Punt if the component type is an aggregate type for now. */
if (AGGREGATE_TYPE_P (TREE_TYPE (type)))
return type;
tree new_type = copy_type (type);
new_size = ceil_pow2 (size);
new_align = MIN (new_size, BIGGEST_ALIGNMENT);
SET_TYPE_ALIGN (new_type, new_align);
TYPE_SIZE (new_type) = bitsize_int (new_size);
TYPE_SIZE_UNIT (new_type) = size_int (new_size / BITS_PER_UNIT);
SET_TYPE_MODE (new_type, mode_for_size (new_size, MODE_INT, 1).else_blk ());
return new_type;
}
/* TYPE is a RECORD_TYPE, UNION_TYPE or QUAL_UNION_TYPE that is being used /* TYPE is a RECORD_TYPE, UNION_TYPE or QUAL_UNION_TYPE that is being used
as the field type of a packed record if IN_RECORD is true, or as the as the type of a field in a packed record if IN_RECORD is true, or as
component type of a packed array if IN_RECORD is false. See if we can the component type of a packed array if IN_RECORD is false. See if we
rewrite it either as a type that has non-BLKmode, which we can pack can rewrite it either as a type that has non-BLKmode, which we can pack
tighter in the packed record case, or as a smaller type with at most tighter in the packed record case, or as a smaller type with at most
MAX_ALIGN alignment if the value is non-zero. If so, return the new MAX_ALIGN alignment if the value is non-zero. If so, return the new
type; if not, return the original type. */ type; if not, return the original type. */
@ -995,9 +1030,9 @@ make_aligning_type (tree type, unsigned int align, tree size,
tree tree
make_packable_type (tree type, bool in_record, unsigned int max_align) make_packable_type (tree type, bool in_record, unsigned int max_align)
{ {
unsigned HOST_WIDE_INT size = tree_to_uhwi (TYPE_SIZE (type)); const unsigned HOST_WIDE_INT size = tree_to_uhwi (TYPE_SIZE (type));
const unsigned int align = TYPE_ALIGN (type);
unsigned HOST_WIDE_INT new_size; unsigned HOST_WIDE_INT new_size;
unsigned int align = TYPE_ALIGN (type);
unsigned int new_align; unsigned int new_align;
/* No point in doing anything if the size is zero. */ /* No point in doing anything if the size is zero. */
@ -1058,10 +1093,19 @@ make_packable_type (tree type, bool in_record, unsigned int max_align)
tree new_field_type = TREE_TYPE (field); tree new_field_type = TREE_TYPE (field);
tree new_field, new_field_size; tree new_field, new_field_size;
if (RECORD_OR_UNION_TYPE_P (new_field_type) if (AGGREGATE_TYPE_P (new_field_type)
&& !TYPE_FAT_POINTER_P (new_field_type)
&& tree_fits_uhwi_p (TYPE_SIZE (new_field_type))) && tree_fits_uhwi_p (TYPE_SIZE (new_field_type)))
new_field_type = make_packable_type (new_field_type, true, max_align); {
if (RECORD_OR_UNION_TYPE_P (new_field_type)
&& !TYPE_FAT_POINTER_P (new_field_type))
new_field_type
= make_packable_type (new_field_type, true, max_align);
else if (in_record
&& max_align > 0
&& max_align < BITS_PER_UNIT
&& TREE_CODE (new_field_type) == ARRAY_TYPE)
new_field_type = make_packable_array_type (new_field_type);
}
/* However, for the last field in a not already packed record type /* However, for the last field in a not already packed record type
that is of an aggregate type, we need to use the RM size in the that is of an aggregate type, we need to use the RM size in the
@ -1411,7 +1455,7 @@ maybe_pad_type (tree type, tree size, unsigned int align,
different modes, a VIEW_CONVERT_EXPR will be required for converting different modes, a VIEW_CONVERT_EXPR will be required for converting
between them and it might be hard to overcome afterwards, including between them and it might be hard to overcome afterwards, including
at the RTL level when the stand-alone object is accessed as a whole. */ at the RTL level when the stand-alone object is accessed as a whole. */
if (align != 0 if (align > 0
&& RECORD_OR_UNION_TYPE_P (type) && RECORD_OR_UNION_TYPE_P (type)
&& TYPE_MODE (type) == BLKmode && TYPE_MODE (type) == BLKmode
&& !TYPE_BY_REFERENCE_P (type) && !TYPE_BY_REFERENCE_P (type)
@ -1422,7 +1466,7 @@ maybe_pad_type (tree type, tree size, unsigned int align,
|| (TREE_CODE (size) == INTEGER_CST || (TREE_CODE (size) == INTEGER_CST
&& compare_tree_int (size, MAX_FIXED_MODE_SIZE) <= 0))) && compare_tree_int (size, MAX_FIXED_MODE_SIZE) <= 0)))
{ {
tree packable_type = make_packable_type (type, true); tree packable_type = make_packable_type (type, true, align);
if (TYPE_MODE (packable_type) != BLKmode if (TYPE_MODE (packable_type) != BLKmode
&& align >= TYPE_ALIGN (packable_type)) && align >= TYPE_ALIGN (packable_type))
type = packable_type; type = packable_type;
@ -2790,10 +2834,9 @@ create_field_decl (tree name, tree type, tree record_type, tree size, tree pos,
size = round_up (size, BITS_PER_UNIT); size = round_up (size, BITS_PER_UNIT);
} }
/* If we may, according to ADDRESSABLE, make a bitfield when the size is /* If we may, according to ADDRESSABLE, then make a bitfield when the size
specified for two reasons: first if the size differs from the natural is specified for two reasons: first, when it differs from the natural
size; second, if the alignment is insufficient. There are a number of size; second, when the alignment is insufficient.
ways the latter can be true.
We never make a bitfield if the type of the field has a nonconstant size, We never make a bitfield if the type of the field has a nonconstant size,
because no such entity requiring bitfield operations should reach here. because no such entity requiring bitfield operations should reach here.
@ -2809,17 +2852,17 @@ create_field_decl (tree name, tree type, tree record_type, tree size, tree pos,
&& size && size
&& TREE_CODE (size) == INTEGER_CST && TREE_CODE (size) == INTEGER_CST
&& TREE_CODE (TYPE_SIZE (type)) == INTEGER_CST && TREE_CODE (TYPE_SIZE (type)) == INTEGER_CST
&& (!tree_int_cst_equal (size, TYPE_SIZE (type)) && (packed
|| !tree_int_cst_equal (size, TYPE_SIZE (type))
|| (pos && !value_factor_p (pos, TYPE_ALIGN (type))) || (pos && !value_factor_p (pos, TYPE_ALIGN (type)))
|| packed || (TYPE_ALIGN (record_type)
|| (TYPE_ALIGN (record_type) != 0
&& TYPE_ALIGN (record_type) < TYPE_ALIGN (type)))) && TYPE_ALIGN (record_type) < TYPE_ALIGN (type))))
{ {
DECL_BIT_FIELD (field_decl) = 1; DECL_BIT_FIELD (field_decl) = 1;
DECL_SIZE (field_decl) = size; DECL_SIZE (field_decl) = size;
if (!packed && !pos) if (!packed && !pos)
{ {
if (TYPE_ALIGN (record_type) != 0 if (TYPE_ALIGN (record_type)
&& TYPE_ALIGN (record_type) < TYPE_ALIGN (type)) && TYPE_ALIGN (record_type) < TYPE_ALIGN (type))
SET_DECL_ALIGN (field_decl, TYPE_ALIGN (record_type)); SET_DECL_ALIGN (field_decl, TYPE_ALIGN (record_type));
else else
@ -3001,10 +3044,12 @@ process_attributes (tree *node, struct attrib **attr_list, bool in_place,
a power of 2. */ a power of 2. */
bool bool
value_factor_p (tree value, HOST_WIDE_INT factor) value_factor_p (tree value, unsigned HOST_WIDE_INT factor)
{ {
gcc_checking_assert (pow2p_hwi (factor));
if (tree_fits_uhwi_p (value)) if (tree_fits_uhwi_p (value))
return tree_to_uhwi (value) % factor == 0; return (tree_to_uhwi (value) & (factor - 1)) == 0;
if (TREE_CODE (value) == MULT_EXPR) if (TREE_CODE (value) == MULT_EXPR)
return (value_factor_p (TREE_OPERAND (value, 0), factor) return (value_factor_p (TREE_OPERAND (value, 0), factor)

View File

@ -10893,12 +10893,12 @@ expand_expr_real_1 (tree exp, rtx target, machine_mode tmode,
if (MEM_P (op0) && REG_P (XEXP (op0, 0))) if (MEM_P (op0) && REG_P (XEXP (op0, 0)))
mark_reg_pointer (XEXP (op0, 0), MEM_ALIGN (op0)); mark_reg_pointer (XEXP (op0, 0), MEM_ALIGN (op0));
/* If the result has a record type and the extraction is done in /* If the result has aggregate type and the extraction is done in
an integral mode, then the field may be not aligned on a byte an integral mode, then the field may be not aligned on a byte
boundary; in this case, if it has reverse storage order, it boundary; in this case, if it has reverse storage order, it
needs to be extracted as a scalar field with reverse storage needs to be extracted as a scalar field with reverse storage
order and put back into memory order afterwards. */ order and put back into memory order afterwards. */
if (TREE_CODE (type) == RECORD_TYPE if (AGGREGATE_TYPE_P (type)
&& GET_MODE_CLASS (ext_mode) == MODE_INT) && GET_MODE_CLASS (ext_mode) == MODE_INT)
reversep = TYPE_REVERSE_STORAGE_ORDER (type); reversep = TYPE_REVERSE_STORAGE_ORDER (type);
@ -10908,13 +10908,13 @@ expand_expr_real_1 (tree exp, rtx target, machine_mode tmode,
? NULL_RTX : target), ? NULL_RTX : target),
ext_mode, ext_mode, reversep, alt_rtl); ext_mode, ext_mode, reversep, alt_rtl);
/* If the result has a record type and the mode of OP0 is an /* If the result has aggregate type and the mode of OP0 is an
integral mode then, if BITSIZE is narrower than this mode integral mode then, if BITSIZE is narrower than this mode
and this is for big-endian data, we must put the field and this is for big-endian data, we must put the field
into the high-order bits. And we must also put it back into the high-order bits. And we must also put it back
into memory order if it has been previously reversed. */ into memory order if it has been previously reversed. */
scalar_int_mode op0_mode; scalar_int_mode op0_mode;
if (TREE_CODE (type) == RECORD_TYPE if (AGGREGATE_TYPE_P (type)
&& is_int_mode (GET_MODE (op0), &op0_mode)) && is_int_mode (GET_MODE (op0), &op0_mode))
{ {
HOST_WIDE_INT size = GET_MODE_BITSIZE (op0_mode); HOST_WIDE_INT size = GET_MODE_BITSIZE (op0_mode);

View File

@ -1,3 +1,8 @@
2019-06-29 Eric Botcazou <ebotcazou@adacore.com>
* gnat.dg/array35.adb: New test.
* gnat.dg/array36.adb: Likewise.
2019-06-28 Jan Beulich <jbeulich@suse.com> 2019-06-28 Jan Beulich <jbeulich@suse.com>
* gcc.target/i386/gfni-5.c: New. * gcc.target/i386/gfni-5.c: New.

View File

@ -0,0 +1,24 @@
-- { dg-do run }
procedure Array35 is
subtype Str is String (1 .. 3);
type T is record
B : Boolean;
S : Str;
end record;
for T use record
B at 0 range 0 .. 0;
S at 0 range 1 .. 24;
end record;
X : T := (B => True, S => "123");
begin
X.B := False;
if X.S /= "123" then
raise Program_Error;
end if;
end;

View File

@ -0,0 +1,28 @@
-- { dg-do run }
procedure Array36 is
subtype Str is String (1 .. 3);
type Rec is record
S : Str;
end record;
type T is record
B : Boolean;
R : Rec;
end record;
for T use record
B at 0 range 0 .. 0;
R at 0 range 1 .. 24;
end record;
X : T := (B => True, R => (S => "123"));
begin
X.B := False;
if X.R.S /= "123" then
raise Program_Error;
end if;
end;