aboutsummaryrefslogtreecommitdiff
path: root/gcc/ada/gcc-interface/decl.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/ada/gcc-interface/decl.c')
-rw-r--r--gcc/ada/gcc-interface/decl.c97
1 files changed, 74 insertions, 23 deletions
diff --git a/gcc/ada/gcc-interface/decl.c b/gcc/ada/gcc-interface/decl.c
index 5ea1b16..aea191c 100644
--- a/gcc/ada/gcc-interface/decl.c
+++ b/gcc/ada/gcc-interface/decl.c
@@ -2197,14 +2197,16 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, bool definition)
}
else
{
+ /* We make the fields addressable for the sake of compatibility
+ with languages for which the regular fields are addressable. */
tem
= create_field_decl (get_identifier ("P_ARRAY"),
ptr_type_node, gnu_fat_type,
- NULL_TREE, NULL_TREE, 0, 0);
+ NULL_TREE, NULL_TREE, 0, 1);
DECL_CHAIN (tem)
= create_field_decl (get_identifier ("P_BOUNDS"),
gnu_ptr_template, gnu_fat_type,
- NULL_TREE, NULL_TREE, 0, 0);
+ NULL_TREE, NULL_TREE, 0, 1);
finish_fat_pointer_type (gnu_fat_type, tem);
SET_TYPE_UNCONSTRAINED_ARRAY (gnu_fat_type, gnu_type);
}
@@ -2327,7 +2329,6 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, bool definition)
finish_record_type (gnu_template_type, gnu_template_fields, 0,
debug_info_p);
TYPE_CONTEXT (gnu_template_type) = current_function_decl;
- TYPE_READONLY (gnu_template_type) = 1;
/* If Component_Size is not already specified, annotate it with the
size of the component. */
@@ -3054,15 +3055,24 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, bool definition)
|| type_annotate_only);
}
- /* Make a node for the record. If we are not defining the record,
- suppress expanding incomplete types. */
+ /* Make a node for the record type. */
gnu_type = make_node (tree_code_for_record_type (gnat_entity));
TYPE_NAME (gnu_type) = gnu_entity_name;
TYPE_PACKED (gnu_type) = (packed != 0) || has_align || has_rep;
TYPE_REVERSE_STORAGE_ORDER (gnu_type)
= Reverse_Storage_Order (gnat_entity);
+
+ /* If the record type has discriminants, pointers to it may also point
+ to constrained subtypes of it, so mark it as may_alias for LTO. */
+ if (has_discr)
+ prepend_one_attribute
+ (&attr_list, ATTR_MACHINE_ATTRIBUTE,
+ get_identifier ("may_alias"), NULL_TREE,
+ gnat_entity);
+
process_attributes (&gnu_type, &attr_list, true, gnat_entity);
+ /* If we are not defining it, suppress expanding incomplete types. */
if (!definition)
{
defer_incomplete_level++;
@@ -8320,12 +8330,12 @@ components_to_record (Node_Id gnat_component_list, Entity_Id gnat_record_type,
if (p_gnu_rep_list && gnu_rep_list)
*p_gnu_rep_list = chainon (*p_gnu_rep_list, gnu_rep_list);
- /* Deal with the annoying case of an extension of a record with variable size
- and partial rep clause, for which the _Parent field is forced at offset 0
- and has variable size, which we do not support below. Note that we cannot
- do it if the field has fixed size because we rely on the presence of the
- REP part built below to trigger the reordering of the fields in a derived
- record type when all the fields have a fixed position. */
+ /* Deal with the case of an extension of a record type with variable size and
+ partial rep clause, for which the _Parent field is forced at offset 0 and
+ has variable size. Note that we cannot do it if the field has fixed size
+ because we rely on the presence of the REP part built below to trigger the
+ reordering of the fields in a derived record type when all the fields have
+ a fixed position. */
else if (gnu_rep_list
&& !DECL_CHAIN (gnu_rep_list)
&& TREE_CODE (DECL_SIZE (gnu_rep_list)) != INTEGER_CST
@@ -8343,33 +8353,52 @@ components_to_record (Node_Id gnat_component_list, Entity_Id gnat_record_type,
record, before the others, if we also have fields without rep clause. */
else if (gnu_rep_list)
{
- tree gnu_rep_type, gnu_rep_part;
- int i, len = list_length (gnu_rep_list);
- tree *gnu_arr = XALLOCAVEC (tree, len);
+ tree gnu_parent, gnu_rep_type;
/* If all the fields have a rep clause, we can do a flat layout. */
layout_with_rep = !gnu_field_list
&& (!gnu_variant_part || variants_have_rep);
+
+ /* Same as above but the extension itself has a rep clause, in which case
+ we need to set aside the _Parent field to lay out the REP part. */
+ if (TREE_CODE (DECL_SIZE (gnu_rep_list)) != INTEGER_CST
+ && !layout_with_rep
+ && !variants_have_rep
+ && first_free_pos
+ && integer_zerop (first_free_pos)
+ && integer_zerop (bit_position (gnu_rep_list)))
+ {
+ gnu_parent = gnu_rep_list;
+ gnu_rep_list = DECL_CHAIN (gnu_rep_list);
+ }
+ else
+ gnu_parent = NULL_TREE;
+
gnu_rep_type
= layout_with_rep ? gnu_record_type : make_node (RECORD_TYPE);
- for (gnu_field = gnu_rep_list, i = 0;
- gnu_field;
- gnu_field = DECL_CHAIN (gnu_field), i++)
- gnu_arr[i] = gnu_field;
+ /* Sort the fields in order of increasing bit position. */
+ const int len = list_length (gnu_rep_list);
+ tree *gnu_arr = XALLOCAVEC (tree, len);
+
+ gnu_field = gnu_rep_list;
+ for (int i = 0; i < len; i++)
+ {
+ gnu_arr[i] = gnu_field;
+ gnu_field = DECL_CHAIN (gnu_field);
+ }
qsort (gnu_arr, len, sizeof (tree), compare_field_bitpos);
- /* Put the fields in the list in order of increasing position, which
- means we start from the end. */
gnu_rep_list = NULL_TREE;
- for (i = len - 1; i >= 0; i--)
+ for (int i = len - 1; i >= 0; i--)
{
DECL_CHAIN (gnu_arr[i]) = gnu_rep_list;
gnu_rep_list = gnu_arr[i];
DECL_CONTEXT (gnu_arr[i]) = gnu_rep_type;
}
+ /* Do the layout of the REP part, if any. */
if (layout_with_rep)
gnu_field_list = gnu_rep_list;
else
@@ -8378,14 +8407,36 @@ components_to_record (Node_Id gnat_component_list, Entity_Id gnat_record_type,
= create_concat_name (gnat_record_type, "REP");
TYPE_REVERSE_STORAGE_ORDER (gnu_rep_type)
= TYPE_REVERSE_STORAGE_ORDER (gnu_record_type);
- finish_record_type (gnu_rep_type, gnu_rep_list, 1, debug_info);
+ finish_record_type (gnu_rep_type, gnu_rep_list, 1, false);
/* If FIRST_FREE_POS is nonzero, we need to ensure that the fields
without rep clause are laid out starting from this position.
Therefore, we force it as a minimal size on the REP part. */
- gnu_rep_part
+ tree gnu_rep_part
= create_rep_part (gnu_rep_type, gnu_record_type, first_free_pos);
+ /* If this is an extension, put back the _Parent field as the first
+ field of the REP part at offset 0 and update its layout. */
+ if (gnu_parent)
+ {
+ const unsigned int align = DECL_ALIGN (gnu_parent);
+ DECL_CHAIN (gnu_parent) = TYPE_FIELDS (gnu_rep_type);
+ TYPE_FIELDS (gnu_rep_type) = gnu_parent;
+ DECL_CONTEXT (gnu_parent) = gnu_rep_type;
+ if (align > TYPE_ALIGN (gnu_rep_type))
+ {
+ SET_TYPE_ALIGN (gnu_rep_type, align);
+ TYPE_SIZE (gnu_rep_type)
+ = round_up (TYPE_SIZE (gnu_rep_type), align);
+ TYPE_SIZE_UNIT (gnu_rep_type)
+ = round_up (TYPE_SIZE_UNIT (gnu_rep_type), align);
+ SET_DECL_ALIGN (gnu_rep_part, align);
+ }
+ }
+
+ if (debug_info)
+ rest_of_record_type_compilation (gnu_rep_type);
+
/* Chain the REP part at the beginning of the field list. */
DECL_CHAIN (gnu_rep_part) = gnu_field_list;
gnu_field_list = gnu_rep_part;