From db6734819f777dbbf9eea464baa7fc60a953dc8a Mon Sep 17 00:00:00 2001 From: Eric Botcazou Date: Wed, 2 Mar 2022 17:28:14 +0100 Subject: [PATCH] [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. --- gcc/ada/gcc-interface/decl.cc | 29 +++++++++++++++++++++++------ 1 file changed, 23 insertions(+), 6 deletions(-) diff --git a/gcc/ada/gcc-interface/decl.cc b/gcc/ada/gcc-interface/decl.cc index aa8736c7a86..af6475e7307 100644 --- a/gcc/ada/gcc-interface/decl.cc +++ b/gcc/ada/gcc-interface/decl.cc @@ -7981,6 +7981,7 @@ components_to_record (Node_Id gnat_component_list, Entity_Id gnat_record_type, tree gnu_union_type; tree this_first_free_pos, gnu_variant_list = NULL_TREE; bool union_field_needs_strict_alignment = false; + bool innermost_variant_level = true; auto_vec variant_types; vinfo_t *gnu_variant; 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 the first pass, that is to say translating the GNAT nodes, building 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 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 - present in a nested variant to be moved to the outermost variant, - so as to flatten the rep-ed layout as much as possible, the reason - being that we cannot do any flattening when a subtype statically - selects a variant later on, for example for an aggregate. */ + case of an unchecked union with a fixed part, we force the fields + with a rep clause present in the innermost variant to be moved to + the outer variant, so as to flatten the rep-ed layout as much as + possible, the reason being that we cannot do any flattening when + a subtype statically selects a variant later on, for example for + an aggregate. */ has_rep = components_to_record (Component_List (variant), gnat_record_type, 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, true, 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); /* Translate the qualifier and annotate the GNAT node. */