[Ada] Fix internal error on unchecked union with component clauses (2)

The issue arises when the unchecked union contains both a fixed part and
a variant part, and is subject to a full representation clause covering
all the components in all the variants, when the component clauses do not
align the variant boundaries with byte boundaries consistently.

gcc/ada/

	* gcc-interface/decl.cc (components_to_record): Use NULL recursively
	as P_GNU_REP_LIST for the innermost variant level in the unchecked
	union case with a fixed part.
This commit is contained in:
Eric Botcazou 2022-03-02 17:28:14 +01:00 committed by Pierre-Marie de Rodat
parent b64c4968c7
commit db6734819f

View File

@ -7981,6 +7981,7 @@ components_to_record (Node_Id gnat_component_list, Entity_Id gnat_record_type,
tree gnu_union_type; tree gnu_union_type;
tree this_first_free_pos, gnu_variant_list = NULL_TREE; tree this_first_free_pos, gnu_variant_list = NULL_TREE;
bool union_field_needs_strict_alignment = false; bool union_field_needs_strict_alignment = false;
bool innermost_variant_level = true;
auto_vec <vinfo_t, 16> variant_types; auto_vec <vinfo_t, 16> variant_types;
vinfo_t *gnu_variant; vinfo_t *gnu_variant;
unsigned int variants_align = 0; unsigned int variants_align = 0;
@ -8026,6 +8027,19 @@ components_to_record (Node_Id gnat_component_list, Entity_Id gnat_record_type,
} }
} }
/* For an unchecked union with a fixed part, we need to compute whether
we are at the innermost level of the variant part. */
if (unchecked_union && gnu_field_list)
for (variant = First_Non_Pragma (Variants (gnat_variant_part));
Present (variant);
variant = Next_Non_Pragma (variant))
if (Present (Component_List (variant))
&& Present (Variant_Part (Component_List (variant))))
{
innermost_variant_level = false;
break;
}
/* We build the variants in two passes. The bulk of the work is done in /* We build the variants in two passes. The bulk of the work is done in
the first pass, that is to say translating the GNAT nodes, building the first pass, that is to say translating the GNAT nodes, building
the container types and computing the associated properties. However the container types and computing the associated properties. However
@ -8066,11 +8080,12 @@ components_to_record (Node_Id gnat_component_list, Entity_Id gnat_record_type,
/* Add the fields into the record type for the variant but note that /* Add the fields into the record type for the variant but note that
we aren't sure to really use it at this point, see below. In the we aren't sure to really use it at this point, see below. In the
case of an unchecked union, we force the fields with a rep clause case of an unchecked union with a fixed part, we force the fields
present in a nested variant to be moved to the outermost variant, with a rep clause present in the innermost variant to be moved to
so as to flatten the rep-ed layout as much as possible, the reason the outer variant, so as to flatten the rep-ed layout as much as
being that we cannot do any flattening when a subtype statically possible, the reason being that we cannot do any flattening when
selects a variant later on, for example for an aggregate. */ a subtype statically selects a variant later on, for example for
an aggregate. */
has_rep has_rep
= components_to_record (Component_List (variant), gnat_record_type, = components_to_record (Component_List (variant), gnat_record_type,
NULL_TREE, gnu_variant_type, packed, NULL_TREE, gnu_variant_type, packed,
@ -8078,7 +8093,9 @@ components_to_record (Node_Id gnat_component_list, Entity_Id gnat_record_type,
unchecked_union, true, needs_xv_encodings, unchecked_union, true, needs_xv_encodings,
true, this_first_free_pos, true, this_first_free_pos,
(all_rep || this_first_free_pos) (all_rep || this_first_free_pos)
&& !(in_variant && unchecked_union) && !(unchecked_union
&& gnu_field_list
&& innermost_variant_level)
? NULL : &gnu_rep_list); ? NULL : &gnu_rep_list);
/* Translate the qualifier and annotate the GNAT node. */ /* Translate the qualifier and annotate the GNAT node. */