diff options
author | Eric Botcazou <ebotcazou@adacore.com> | 2014-01-20 10:51:46 +0000 |
---|---|---|
committer | Eric Botcazou <ebotcazou@gcc.gnu.org> | 2014-01-20 10:51:46 +0000 |
commit | 44e9e3ec85bf048bcb73f7a013afbd573466972e (patch) | |
tree | 0abf9652349928c6a4a433eef4046071074ba0cb /gcc/ada/gcc-interface/decl.c | |
parent | 59f5c969a5c5ac08e450ae74c260d57db574a5d0 (diff) | |
download | gcc-44e9e3ec85bf048bcb73f7a013afbd573466972e.zip gcc-44e9e3ec85bf048bcb73f7a013afbd573466972e.tar.gz gcc-44e9e3ec85bf048bcb73f7a013afbd573466972e.tar.bz2 |
decl.c (gnat_to_gnu_entity): Tidy up.
* gcc-interface/decl.c (gnat_to_gnu_entity) <case E_Record_Subtype>:
Tidy up. For a subtype with discriminants and variant part, if a
variant is statically selected and the fields all have a constant
position, put them in order of increasing position. Likewise if
no variant part but representation clause is present.
* gcc-interface/utils.c (make_packable_type): Robustify.
(maybe_pad_type): Use local variable and tidy up condition. If no
alignment is specified, use the original one.
(create_type_stub_decl): Minor tweak.
(convert) <case VECTOR_CST>: Fix typo.
<case CONSTRUCTOR>: Deal with padding types around the same type.
Do not punt on missing fields.
(unchecked_convert): Call finish_record_type to lay out the special
record types made for conversions from/to problematic integer types.
Bump the alignment of CONSTRUCTORs before converting them to a more
aligned type.
From-SVN: r206796
Diffstat (limited to 'gcc/ada/gcc-interface/decl.c')
-rw-r--r-- | gcc/ada/gcc-interface/decl.c | 68 |
1 files changed, 50 insertions, 18 deletions
diff --git a/gcc/ada/gcc-interface/decl.c b/gcc/ada/gcc-interface/decl.c index 9e1ecb0..dd912f3 100644 --- a/gcc/ada/gcc-interface/decl.c +++ b/gcc/ada/gcc-interface/decl.c @@ -6,7 +6,7 @@ * * * C Implementation File * * * - * Copyright (C) 1992-2013, Free Software Foundation, Inc. * + * Copyright (C) 1992-2014, Free Software Foundation, Inc. * * * * GNAT is free software; you can redistribute it and/or modify it under * * terms of the GNU General Public License as published by the Free Soft- * @@ -147,6 +147,7 @@ static bool array_type_has_nonaliased_component (tree, Entity_Id); static bool compile_time_known_address_p (Node_Id); static bool cannot_be_superflat_p (Node_Id); static bool constructor_address_p (tree); +static int compare_field_bitpos (const PTR, const PTR); static bool components_to_record (tree, Node_Id, tree, int, bool, bool, bool, bool, bool, bool, bool, bool, tree, tree *); static Uint annotate_value (tree); @@ -3341,9 +3342,9 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, int definition) { vec<subst_pair> gnu_subst_list = build_subst_list (gnat_entity, gnat_base_type, definition); - tree gnu_unpad_base_type, gnu_rep_part, gnu_variant_part, t; + tree gnu_unpad_base_type, gnu_rep_part, gnu_variant_part; tree gnu_pos_list, gnu_field_list = NULL_TREE; - bool selected_variant = false; + bool selected_variant = false, all_constant_pos = true; Entity_Id gnat_field; vec<variant_desc> gnu_variant_list; @@ -3362,7 +3363,8 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, int definition) else gnu_unpad_base_type = gnu_base_type; - /* Look for a variant part in the base type. */ + /* Look for REP and variant parts in the base type. */ + gnu_rep_part = get_rep_part (gnu_unpad_base_type); gnu_variant_part = get_variant_part (gnu_unpad_base_type); /* If there is a variant part, we must compute whether the @@ -3414,13 +3416,17 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, int definition) selected_variant = false; } + /* Make a list of fields and their position in the base type. */ gnu_pos_list = build_position_list (gnu_unpad_base_type, gnu_variant_list.exists () - && !selected_variant, + && !selected_variant, size_zero_node, bitsize_zero_node, BIGGEST_ALIGNMENT, NULL_TREE); + /* Now go down every component in the subtype and compute its + size and position from those of the component in the base + type and from the constraints of the subtype. */ for (gnat_field = First_Entity (gnat_entity); Present (gnat_field); gnat_field = Next_Entity (gnat_field)) @@ -3428,8 +3434,8 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, int definition) || Ekind (gnat_field) == E_Discriminant) && !(Present (Corresponding_Discriminant (gnat_field)) && Is_Tagged_Type (gnat_base_type)) - && Underlying_Type (Scope (Original_Record_Component - (gnat_field))) + && Underlying_Type + (Scope (Original_Record_Component (gnat_field))) == gnat_base_type) { Name_Id gnat_name = Chars (gnat_field); @@ -3438,7 +3444,7 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, int definition) tree gnu_old_field = gnat_to_gnu_field_decl (gnat_old_field); tree gnu_context = DECL_CONTEXT (gnu_old_field); - tree gnu_field, gnu_field_type, gnu_size; + tree gnu_field, gnu_field_type, gnu_size, gnu_pos; tree gnu_cont_type, gnu_last = NULL_TREE; /* If the type is the same, retrieve the GCC type from the @@ -3489,24 +3495,21 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, int definition) and put the field either in the new type if there is a selected variant or in one of the new variants. */ if (gnu_context == gnu_unpad_base_type - || ((gnu_rep_part = get_rep_part (gnu_unpad_base_type)) + || (gnu_rep_part && gnu_context == TREE_TYPE (gnu_rep_part))) gnu_cont_type = gnu_type; else { variant_desc *v; unsigned int i; + tree rep_part; - t = NULL_TREE; FOR_EACH_VEC_ELT (gnu_variant_list, i, v) if (gnu_context == v->type - || ((gnu_rep_part = get_rep_part (v->type)) - && gnu_context == TREE_TYPE (gnu_rep_part))) - { - t = v->type; - break; - } - if (t) + || ((rep_part = get_rep_part (v->type)) + && gnu_context == TREE_TYPE (rep_part))) + break; + if (v) { if (selected_variant) gnu_cont_type = gnu_type; @@ -3525,6 +3528,7 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, int definition) = create_field_decl_from (gnu_old_field, gnu_field_type, gnu_cont_type, gnu_size, gnu_pos_list, gnu_subst_list); + gnu_pos = DECL_FIELD_OFFSET (gnu_field); /* Put it in one of the new variants directly. */ if (gnu_cont_type != gnu_type) @@ -3557,14 +3561,42 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, int definition) gnu_field_list = gnu_field; if (!gnu_last) gnu_last = gnu_field; + if (TREE_CODE (gnu_pos) != INTEGER_CST) + all_constant_pos = false; } save_gnu_tree (gnat_field, gnu_field, false); } + /* If there is a variant list, a selected variant and the fields + all have a constant position, put them in order of increasing + position to match that of constant CONSTRUCTORs. Likewise if + there is no variant list but a REP part, since the latter has + been flattened in the process. */ + if (((gnu_variant_list.exists () && selected_variant) + || (!gnu_variant_list.exists () && gnu_rep_part)) + && all_constant_pos) + { + const int len = list_length (gnu_field_list); + tree *field_arr = XALLOCAVEC (tree, len), t; + int i; + + for (t = gnu_field_list, i = 0; t; t = DECL_CHAIN (t), i++) + field_arr[i] = t; + + qsort (field_arr, len, sizeof (tree), compare_field_bitpos); + + gnu_field_list = NULL_TREE; + for (i = 0; i < len; i++) + { + DECL_CHAIN (field_arr[i]) = gnu_field_list; + gnu_field_list = field_arr[i]; + } + } + /* If there is a variant list and no selected variant, we need to create the nest of variant parts from the old nest. */ - if (gnu_variant_list.exists () && !selected_variant) + else if (gnu_variant_list.exists () && !selected_variant) { tree new_variant_part = create_variant_part_from (gnu_variant_part, |