aboutsummaryrefslogtreecommitdiff
path: root/gcc/ada/gcc-interface/decl.cc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/ada/gcc-interface/decl.cc')
-rw-r--r--gcc/ada/gcc-interface/decl.cc727
1 files changed, 528 insertions, 199 deletions
diff --git a/gcc/ada/gcc-interface/decl.cc b/gcc/ada/gcc-interface/decl.cc
index 1854c58..fdbbb7c 100644
--- a/gcc/ada/gcc-interface/decl.cc
+++ b/gcc/ada/gcc-interface/decl.cc
@@ -201,6 +201,7 @@ static tree gnat_to_gnu_component_type (Entity_Id, bool, bool);
static tree gnat_to_gnu_subprog_type (Entity_Id, bool, bool, tree *);
static int adjust_packed (tree, tree, int);
static tree gnat_to_gnu_field (Entity_Id, tree, int, bool, bool);
+static tree get_extended_unconstrained_array (Entity_Id, tree);
static enum inline_status_t inline_status_for_subprog (Entity_Id);
static Entity_Id Gigi_Cloned_Subtype (Entity_Id);
static tree gnu_ext_name_for_subprog (Entity_Id, tree);
@@ -279,6 +280,13 @@ is_artificial (Entity_Id gnat_entity)
initial value (in GCC tree form). This is optional for a variable. For
a renamed entity, GNU_EXPR gives the object being renamed.
+ If GNAT_ENTITY is an array type and GNU_EXPR is NULL_TREE, a GCC tree for a
+ regular fat pointer will be generated. However, if GNU_EXPR is not
+ NULL_TREE, it's an existing GCC tree for the fat pointer, and a GCC tree for
+ the extended pointer will be created instead. The caller must clear the
+ association between GNAT_ENTITY and GNU_EXPR before calling
+ gnat_to_gnu_entity with a non-NULL GNU_EXPR and restore it after the call.
+
DEFINITION is true if this call is intended for a definition. This is used
for separate compilation where it is necessary to know whether an external
declaration or a definition must be created if the GCC equivalent was not
@@ -441,7 +449,8 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, bool definition)
must be specified unless it was specified by the programmer. Exceptions
are for access-to-protected-subprogram types and all access subtypes, as
another GNAT type is used to lay out the GCC type for them, as well as
- access-to-subprogram types if front-end unnesting is enabled. */
+ access-to-subprogram types if front-end unnesting is enabled, and also
+ extended access types. */
gcc_assert (!is_type
|| Known_Esize (gnat_entity)
|| Has_Size_Clause (gnat_entity)
@@ -454,6 +463,7 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, bool definition)
|| kind == E_Anonymous_Access_Subprogram_Type)
&& Unnest_Subprogram_Mode)
|| kind == E_Access_Subtype
+ || Is_Extended_Access_Type (gnat_entity)
|| type_annotate_only)));
/* The RM size must be specified for all discrete and fixed-point types. */
@@ -638,7 +648,9 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, bool definition)
/* Build a CONST_DECL for debugging purposes exclusively. */
gnu_decl
= create_var_decl (gnu_entity_name, gnu_ext_name, gnu_type,
- gnu_expr, true, Is_Public (gnat_entity),
+ gnu_expr, true,
+ Is_Public (gnat_entity),
+ Is_Link_Once (gnat_entity),
false, false, false, artificial_p,
debug_info_p, NULL, gnat_entity);
}
@@ -1186,6 +1198,7 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, bool definition)
create_var_decl (gnu_entity_name, NULL_TREE,
TREE_TYPE (gnu_expr), gnu_expr,
const_flag, Is_Public (gnat_entity),
+ Is_Link_Once (gnat_entity),
imported_p, static_flag, volatile_flag,
artificial_p, debug_info_p, attr_list,
gnat_entity, false);
@@ -1228,6 +1241,24 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, bool definition)
gnu_expr = gnat_build_constructor (gnu_type, v);
}
+ /* If we are allocating the anonymous object of a small aggregate on
+ the stack, zero-initialize it so that the entire object is assigned
+ and the subsequent assignments need not preserve unknown bits, but
+ do it only when optimization is enabled for the sake of consistency
+ with the gimplifier which does the same for CONSTRUCTORs. */
+ else if (definition
+ && !imported_p
+ && !static_flag
+ && !gnu_expr
+ && TREE_CODE (gnu_type) == RECORD_TYPE
+ && TREE_CODE (gnu_object_size) == INTEGER_CST
+ && compare_tree_int (gnu_object_size, MAX_FIXED_MODE_SIZE) <= 0
+ && Present (Related_Expression (gnat_entity))
+ && Nkind (Original_Node (Related_Expression (gnat_entity)))
+ == N_Aggregate
+ && optimize)
+ gnu_expr = build_constructor (gnu_type, NULL);
+
/* Convert the expression to the type of the object if need be. */
if (gnu_expr && initial_value_needs_conversion (gnu_type, gnu_expr))
gnu_expr = convert (gnu_type, gnu_expr);
@@ -1236,7 +1267,9 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, bool definition)
initialize it to NULL, unless the object is declared imported as
per RM B.1(24). */
if (definition
- && (POINTER_TYPE_P (gnu_type) || TYPE_IS_FAT_POINTER_P (gnu_type))
+ && (POINTER_TYPE_P (gnu_type)
+ || TYPE_IS_FAT_POINTER_P (gnu_type)
+ || TYPE_IS_EXTENDED_POINTER_P (gnu_type))
&& !gnu_expr
&& !Is_Imported (gnat_entity))
gnu_expr = null_pointer_node;
@@ -1370,16 +1403,15 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, bool definition)
}
}
- /* If we are at top level and this object is of variable size,
- make the actual type a hidden pointer to the real type and
- make the initializer be a memory allocation and initialization.
- Likewise for objects we aren't defining (presumed to be
- external references from other packages), but there we do
- not set up an initialization.
-
- If the object's size overflows, make an allocator too, so that
- Storage_Error gets raised. Note that we will never free
- such memory, so we presume it never will get allocated. */
+ /* If we are at top level and this object is of variable size, make
+ the actual type a reference to the real type and the initializer
+ be a memory allocation and initialization. Likewise for an object
+ that we aren't defining or is imported (presumed to be an external
+ reference from another package), but in this case we do not set up
+ an initialization. Likewise if the object's size is constant but
+ too large. In either case, this will also cause Storage_Error to
+ be raised if the size ends up overflowing. Note that we will never
+ free such memory, but it will be allocated only at top level. */
if (!allocatable_size_p (TYPE_SIZE_UNIT (gnu_type),
global_bindings_p ()
|| !definition
@@ -1393,6 +1425,29 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, bool definition)
|| !definition
|| static_flag)))
{
+ /* Give a warning if the size is constant. */
+ if ((TREE_CODE (TYPE_SIZE_UNIT (gnu_type)) == INTEGER_CST
+ || (gnu_size && TREE_CODE (gnu_size) == INTEGER_CST))
+ && definition)
+ {
+ if (imported_p)
+ {
+ post_error
+ ("??too large object cannot be imported directly",
+ gnat_entity);
+ post_error ("\\??indirect import will be used instead",
+ gnat_entity);
+ }
+ else if (global_bindings_p () || static_flag)
+ {
+ post_error
+ ("??too large object cannot be allocated statically",
+ gnat_entity);
+ post_error ("\\??dynamic allocation will be used instead",
+ gnat_entity);
+ }
+ }
+
if (volatile_flag && !TYPE_VOLATILE (gnu_type))
gnu_type = change_qualified_type (gnu_type, TYPE_QUAL_VOLATILE);
gnu_type = build_reference_type (gnu_type);
@@ -1435,21 +1490,10 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, bool definition)
}
/* Give a warning if the size is constant but too large. */
- if (TREE_CODE (TYPE_SIZE_UNIT (gnu_alloc_type)) == INTEGER_CST)
- {
- if (valid_constant_size_p (TYPE_SIZE_UNIT (gnu_alloc_type)))
- {
- post_error
- ("??too large object cannot be allocated statically",
- gnat_entity);
- post_error ("\\??dynamic allocation will be used instead",
- gnat_entity);
- }
-
- else
- post_error ("??Storage_Error will be raised at run time!",
- gnat_entity);
- }
+ if (TREE_CODE (TYPE_SIZE_UNIT (gnu_alloc_type)) == INTEGER_CST
+ && !valid_constant_size_p (TYPE_SIZE_UNIT (gnu_alloc_type)))
+ post_error ("??Storage_Error will be raised at run time!",
+ gnat_entity);
gnu_expr
= build_allocator (gnu_alloc_type, gnu_expr, gnu_type,
@@ -1477,7 +1521,7 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, bool definition)
tree gnu_new_var
= create_var_decl (create_concat_name (gnat_entity, "ALIGN"),
NULL_TREE, gnu_new_type, NULL_TREE,
- false, false, false, false, false,
+ false, false, false, false, false, false,
true, debug_info_p && definition, NULL,
gnat_entity);
@@ -1539,8 +1583,9 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, bool definition)
= create_var_decl (concat_name (gnu_entity_name, "UNC"),
NULL_TREE, gnu_type, gnu_expr,
const_flag, Is_Public (gnat_entity),
- imported_p || !definition, static_flag,
- volatile_flag, true,
+ Is_Link_Once (gnat_entity),
+ imported_p || !definition,
+ static_flag, volatile_flag, true,
debug_info_p && definition,
NULL, gnat_entity);
gnu_expr = build_unary_op (ADDR_EXPR, NULL_TREE, gnu_unc_var);
@@ -1586,8 +1631,9 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, bool definition)
gnu_decl
= create_var_decl (gnu_entity_name, gnu_ext_name, gnu_type,
gnu_expr, const_flag, Is_Public (gnat_entity),
- imported_p || !definition, static_flag,
- volatile_flag, artificial_p,
+ Is_Link_Once (gnat_entity),
+ imported_p || !definition,
+ static_flag, volatile_flag, artificial_p,
debug_info_p && definition, attr_list,
gnat_entity);
DECL_BY_REF_P (gnu_decl) = used_by_ref;
@@ -1634,6 +1680,7 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, bool definition)
tree gnu_corr_var
= create_var_decl (gnu_entity_name, gnu_ext_name, gnu_type,
gnu_expr, true, Is_Public (gnat_entity),
+ Is_Link_Once (gnat_entity),
!definition, static_flag, volatile_flag,
artificial_p, debug_info_p && definition,
attr_list, gnat_entity, false);
@@ -1739,7 +1786,7 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, bool definition)
tree gnu_literal
= create_var_decl (get_entity_name (gnat_literal), NULL_TREE,
gnu_type, gnu_value, true, false, false,
- false, false, artificial_p, false,
+ false, false, false, artificial_p, false,
NULL, gnat_literal);
save_gnu_tree (gnat_literal, gnu_literal, false);
gnu_list
@@ -2136,21 +2183,28 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, bool definition)
have are pointers to that type. In addition to the type node itself,
4 other types associated with it are built in the process:
- 1. the array type (suffix XUA) containing the actual data,
+ 1. the array type (suffix XUA for fat pointer, XUAEA for extended
+ access) containing the actual data,
- 2. the template type (suffix XUB) containing the bounds,
+ 2. the template type (suffix XUB for fat pointer, XUBEA for extended
+ access) containing the bounds,
3. the fat pointer type (suffix XUP) representing a pointer or a
reference to the unconstrained array type:
XUP = struct { XUA *, XUB * }
- 4. the object record type (suffix XUT) containing bounds and data:
- XUT = struct { XUB, XUA }
+ or the extended access type (suffix XUPEA) representing a pointer
+ or a reference to the unconstrained array type:
+ XUPEA = struct { XUAEA *, XUBEA }
+
+ 4. the object record type (suffix XUT for fat pointer, XUTEA for
+ extended access) containing bounds and data:
+ XUT[EA] = struct { XUB[EA], XUA[EA] }
The bounds of the array type XUA (de)reference the XUB * field of a
PLACEHOLDER_EXPR for the fat pointer type XUP, so the array type XUA
is to be interpreted in the context of the fat pointer type XUB for
- debug info purposes. */
+ debug info purposes. Likewise for the extended access case. */
case E_Array_Type:
{
@@ -2158,14 +2212,13 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, bool definition)
const Entity_Id PAT = Packed_Array_Impl_Type (gnat_entity);
const bool convention_fortran_p
= (Convention (gnat_entity) == Convention_Fortran);
+ const bool extended_access_p = gnu_expr != NULL_TREE;
const int ndim = Number_Dimensions (gnat_entity);
tree gnu_fat_type, gnu_template_type, gnu_ptr_template;
- tree gnu_template_reference, gnu_template_fields;
+ tree gnu_template_reference;
tree *gnu_index_types = XALLOCAVEC (tree, ndim);
- tree *gnu_temp_fields = XALLOCAVEC (tree, ndim);
tree gnu_max_size = size_one_node;
tree comp_type, fld, tem, obj;
- Entity_Id gnat_index;
alias_set_type ptr_set = -1;
int index;
@@ -2185,7 +2238,7 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, bool definition)
better debugging information in DWARF by leveraging the support for
incomplete declarations of "tagged" types in the DWARF back-end. */
gnu_type = get_dummy_type (gnat_entity);
- if (gnu_type && TYPE_POINTER_TO (gnu_type))
+ if (gnu_type && TYPE_POINTER_TO (gnu_type) && !extended_access_p)
{
gnu_fat_type = TYPE_MAIN_VARIANT (TYPE_POINTER_TO (gnu_type));
TYPE_NAME (gnu_fat_type) = NULL_TREE;
@@ -2200,10 +2253,42 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, bool definition)
DECL_CHAIN (TYPE_FIELDS (TYPE_POINTER_TO (gnu_type)))
= copy_node (DECL_CHAIN (TYPE_FIELDS (gnu_fat_type)));
}
+
+ /* We complete an existing dummy for extended access, but we haven't
+ created a specific tree yet for the array type. The extended access
+ type is stored directly in the original unconstrained array type,
+ where we will store the new array type later. */
+ else if (gnu_type
+ && TYPE_DUMMY_EXT_POINTER_TO (gnu_type)
+ && extended_access_p)
+ {
+ gnu_ptr_template = NULL_TREE;
+ tree gnu_ext_acc_type = TYPE_DUMMY_EXT_POINTER_TO (gnu_type);
+ gnu_fat_type = TYPE_MAIN_VARIANT (gnu_ext_acc_type);
+ TYPE_NAME (gnu_fat_type) = NULL_TREE;
+
+ /* The dummy types has a XUBEA that was only used to get the size of
+ the extended pointer. We now drop this type and use the XUB type
+ from the regular fat pointer instead. */
+ gnu_template_type
+ = TREE_TYPE (TREE_TYPE (DECL_CHAIN (TYPE_FIELDS (TREE_TYPE (gnu_expr)))));
+
+ DECL_CHAIN (TYPE_FIELDS (gnu_fat_type))
+ = create_field_decl (get_identifier ("BOUNDS"),
+ gnu_template_type, gnu_fat_type,
+ NULL_TREE, NULL_TREE, 0, 1);
+ }
+
else
{
gnu_fat_type = make_node (RECORD_TYPE);
- gnu_template_type = make_node (RECORD_TYPE);
+
+ if (extended_access_p)
+ gnu_template_type
+ = TREE_TYPE (TREE_TYPE (DECL_CHAIN (TYPE_FIELDS (TREE_TYPE (gnu_expr)))));
+ else
+ gnu_template_type = make_node (RECORD_TYPE);
+
gnu_ptr_template = build_pointer_type (gnu_template_type);
}
@@ -2235,7 +2320,7 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, bool definition)
Var are also built later with the fields of the final type, the
aliasing machinery may consider that the accesses are distinct
if the FIELD_DECLs are distinct as objects. */
- if (COMPLETE_TYPE_P (gnu_fat_type))
+ if (COMPLETE_TYPE_P (gnu_fat_type) && !extended_access_p)
{
fld = TYPE_FIELDS (gnu_fat_type);
if (TYPE_ALIAS_SET_KNOWN_P (TYPE_CANONICAL (TREE_TYPE (fld))))
@@ -2246,6 +2331,39 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, bool definition)
for (tree t = gnu_fat_type; t; t = TYPE_NEXT_VARIANT (t))
SET_TYPE_UNCONSTRAINED_ARRAY (t, gnu_type);
}
+
+ else if (COMPLETE_TYPE_P (gnu_fat_type) && extended_access_p)
+ {
+ fld = TYPE_FIELDS (gnu_fat_type);
+ if (TYPE_ALIAS_SET_KNOWN_P (TYPE_CANONICAL (TREE_TYPE (fld))))
+ ptr_set = TYPE_ALIAS_SET (TYPE_CANONICAL (TREE_TYPE (fld)));
+ TREE_TYPE (fld) = ptr_type_node;
+ /* For extended access, we leave the BOUNDS field alone. */
+ TYPE_DECL_SUPPRESS_DEBUG (TYPE_STUB_DECL (gnu_fat_type)) = 0;
+ for (tree t = gnu_fat_type; t; t = TYPE_NEXT_VARIANT (t))
+ SET_TYPE_UNCONSTRAINED_ARRAY (t, gnu_type);
+ }
+
+ else if (extended_access_p)
+ {
+ /* We make the fields addressable for the sake of compatibility
+ with languages for which the regular fields are addressable. */
+ fld
+ = create_field_decl (get_identifier ("P_ARRAY"),
+ ptr_type_node, gnu_fat_type,
+ NULL_TREE, NULL_TREE, 0, 1);
+ /* At this step, gnu_template_type is an empty RECORD to be
+ be populated later. */
+ DECL_CHAIN (fld)
+ = create_field_decl (get_identifier ("BOUNDS"),
+ gnu_template_type, gnu_fat_type,
+ NULL_TREE, NULL_TREE, 0, 1);
+ /* Too early to finish the record, but set the fields so that
+ they are available through the type. */
+ TYPE_FIELDS (gnu_fat_type) = fld;
+ SET_TYPE_UNCONSTRAINED_ARRAY (gnu_fat_type, gnu_type);
+ }
+
else
{
/* We make the fields addressable for the sake of compatibility
@@ -2273,135 +2391,56 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, bool definition)
: gnat_entity;
tree xup_name
= gnat_encodings == DWARF_GNAT_ENCODINGS_ALL
- ? create_concat_name (gnat_name, "XUP")
+ ? create_concat_name (gnat_name,
+ extended_access_p ? "XUPEA" : "XUP")
: gnu_entity_name;
create_type_decl (xup_name, gnu_fat_type, true, debug_info_p,
gnat_entity, false);
/* Build a reference to the template from a PLACEHOLDER_EXPR that
- is the fat pointer. This will be used to access the individual
- fields once we build them. */
- tem = build3 (COMPONENT_REF, gnu_ptr_template,
- build0 (PLACEHOLDER_EXPR, gnu_fat_type),
- DECL_CHAIN (fld), NULL_TREE);
- gnu_template_reference
- = build_unary_op (INDIRECT_REF, gnu_template_type, tem);
- TREE_READONLY (gnu_template_reference) = 1;
- TREE_THIS_NOTRAP (gnu_template_reference) = 1;
-
- /* Now create the GCC type for each index and add the fields for that
- index to the template. */
- for (index = (convention_fortran_p ? ndim - 1 : 0),
- gnat_index = First_Index (gnat_entity);
- IN_RANGE (index, 0, ndim - 1);
- index += (convention_fortran_p ? - 1 : 1),
- gnat_index = Next_Index (gnat_index))
+ is the extended/fat pointer. This will be used to access the
+ individual fields once we build them. */
+ if (extended_access_p)
{
- const Entity_Id gnat_index_type = Etype (gnat_index);
- const bool is_flb
- = Is_Fixed_Lower_Bound_Index_Subtype (gnat_index_type);
- tree gnu_index_type = get_unpadded_type (gnat_index_type);
- tree gnu_orig_min = TYPE_MIN_VALUE (gnu_index_type);
- tree gnu_orig_max = TYPE_MAX_VALUE (gnu_index_type);
- tree gnu_index_base_type = get_base_type (gnu_index_type);
- tree gnu_lb_field, gnu_hb_field;
- tree gnu_min, gnu_max, gnu_high;
- char field_name[16];
-
- /* Update the maximum size of the array in elements. */
- if (gnu_max_size)
- gnu_max_size
- = update_n_elem (gnu_max_size, gnu_orig_min, gnu_orig_max);
-
- /* Now build the self-referential bounds of the index type. */
- gnu_index_type = maybe_character_type (gnu_index_type);
- gnu_index_base_type = maybe_character_type (gnu_index_base_type);
-
- /* Make the FIELD_DECLs for the low and high bounds of this
- type and then make extractions of these fields from the
- template. */
- sprintf (field_name, "LB%d", index);
- gnu_lb_field = create_field_decl (get_identifier (field_name),
- gnu_index_type,
- gnu_template_type, NULL_TREE,
- NULL_TREE, 0, 0);
- /* Mark the field specifically for INSTANTIATE_LOAD_IN_EXPR. */
- DECL_DISCRIMINANT_NUMBER (gnu_lb_field) = integer_minus_one_node;
- Sloc_to_locus (Sloc (gnat_entity),
- &DECL_SOURCE_LOCATION (gnu_lb_field));
-
- field_name[0] = 'U';
- gnu_hb_field = create_field_decl (get_identifier (field_name),
- gnu_index_type,
- gnu_template_type, NULL_TREE,
- NULL_TREE, 0, 0);
- /* Mark the field specifically for INSTANTIATE_LOAD_IN_EXPR. */
- DECL_DISCRIMINANT_NUMBER (gnu_hb_field) = integer_minus_one_node;
- Sloc_to_locus (Sloc (gnat_entity),
- &DECL_SOURCE_LOCATION (gnu_hb_field));
-
- gnu_temp_fields[index] = chainon (gnu_lb_field, gnu_hb_field);
-
- /* We can't use build_component_ref here since the template type
- isn't complete yet. */
- if (!is_flb)
- {
- gnu_orig_min = build3 (COMPONENT_REF, TREE_TYPE (gnu_lb_field),
- gnu_template_reference, gnu_lb_field,
- NULL_TREE);
- TREE_READONLY (gnu_orig_min) = 1;
- }
-
- gnu_orig_max = build3 (COMPONENT_REF, TREE_TYPE (gnu_hb_field),
- gnu_template_reference, gnu_hb_field,
- NULL_TREE);
- TREE_READONLY (gnu_orig_max) = 1;
-
- gnu_min = convert (sizetype, gnu_orig_min);
- gnu_max = convert (sizetype, gnu_orig_max);
+ /* Extended pointers reference the template directly through the
+ BOUNDS field, which is the second field. */
+ gnu_template_reference
+ = build3 (COMPONENT_REF, gnu_template_type,
+ build0 (PLACEHOLDER_EXPR, gnu_fat_type),
+ DECL_CHAIN (fld), NULL_TREE);
+ TREE_READONLY (gnu_template_reference) = 1;
+ }
+ else
+ {
+ /* Fat pointers reference the template indirectly through the
+ P_BOUNDS field, which is the second field. */
+ tem = build3 (COMPONENT_REF, gnu_ptr_template,
+ build0 (PLACEHOLDER_EXPR, gnu_fat_type),
+ DECL_CHAIN (fld), NULL_TREE);
+ gnu_template_reference
+ = build_unary_op (INDIRECT_REF, gnu_template_type, tem);
+ TREE_READONLY (gnu_template_reference) = 1;
+ TREE_THIS_NOTRAP (gnu_template_reference) = 1;
+ }
- /* Compute the size of this dimension. See the E_Array_Subtype
- case below for the rationale. */
- if (is_flb
- && Nkind (gnat_index) == N_Subtype_Indication
- && flb_cannot_be_superflat (gnat_index))
- gnu_high = gnu_max;
+ if (!extended_access_p)
+ {
+ /* Build the template type. */
+ TYPE_NAME (gnu_template_type)
+ = create_concat_name (gnat_entity, "XUB");
+ }
- else
- gnu_high
- = build3 (COND_EXPR, sizetype,
- build2 (GE_EXPR, boolean_type_node,
- gnu_orig_max, gnu_orig_min),
- gnu_max,
- TREE_CODE (gnu_min) == INTEGER_CST
- ? int_const_binop (MINUS_EXPR, gnu_min, size_one_node)
- : size_binop (MINUS_EXPR, gnu_min, size_one_node));
-
- /* Make a range type with the new range in the Ada base type.
- Then make an index type with the size range in sizetype. */
- gnu_index_types[index]
- = create_index_type (gnu_min, gnu_high,
- create_range_type (gnu_index_base_type,
- gnu_orig_min,
- gnu_orig_max),
- gnat_entity);
+ build_template_type (gnat_entity, gnu_template_type,
+ gnu_template_reference, gnu_index_types,
+ gnu_max_size, debug_info_p);
- TYPE_NAME (gnu_index_types[index])
- = create_concat_name (gnat_entity, field_name);
- }
+ if (!extended_access_p)
+ TYPE_CONTEXT (gnu_template_type) = gnu_fat_type;
- /* Install all the fields into the template. */
- TYPE_NAME (gnu_template_type)
- = create_concat_name (gnat_entity, "XUB");
- TYPE_NAMELESS (gnu_template_type)
- = gnat_encodings != DWARF_GNAT_ENCODINGS_ALL;
- gnu_template_fields = NULL_TREE;
- for (index = 0; index < ndim; index++)
- gnu_template_fields
- = chainon (gnu_template_fields, gnu_temp_fields[index]);
- finish_record_type (gnu_template_type, gnu_template_fields, 0,
- debug_info_p);
- TYPE_CONTEXT (gnu_template_type) = gnu_fat_type;
+ /* Now that the template type has been created, the record type for
+ extended access can be finished. */
+ if (extended_access_p)
+ finish_extended_pointer_type (gnu_fat_type, fld);
/* If Component_Size is not already specified, annotate it with the
size of the component. */
@@ -2481,9 +2520,11 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, bool definition)
TYPE_ARRAY_MAX_SIZE (tem) = gnu_max_size;
/* See the above description for the rationale. */
+ tree xua_name
+ = create_concat_name (gnat_entity,
+ extended_access_p ? "XUAEA" : "XUA");
tree gnu_tmp_decl
- = create_type_decl (create_concat_name (gnat_entity, "XUA"), tem,
- true, debug_info_p, gnat_entity);
+ = create_type_decl (xua_name, tem, true, debug_info_p, gnat_entity);
TYPE_CONTEXT (tem) = gnu_fat_type;
TYPE_CONTEXT (TYPE_POINTER_TO (tem)) = gnu_fat_type;
@@ -2495,7 +2536,8 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, bool definition)
If the GNAT encodings are used, give it a name. */
tree xut_name
= (gnat_encodings == DWARF_GNAT_ENCODINGS_ALL)
- ? create_concat_name (gnat_name, "XUT")
+ ? create_concat_name (gnat_name,
+ extended_access_p ? "XUTEA" : "XUT")
: gnu_entity_name;
obj = build_unc_object_type (gnu_template_type, tem, xut_name,
artificial_p, debug_info_p);
@@ -2513,7 +2555,7 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, bool definition)
/* If this is a packed type implemented specially, then process the
implementation type so it is elaborated in the proper scope. */
- if (Present (PAT))
+ if (Present (PAT) && !extended_access_p)
{
/* Save the XUA type as our equivalent temporarily for the call
to gnat_to_gnu_type on the OAT below. */
@@ -3651,6 +3693,14 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, bool definition)
TYPE_PACKED (gnu_type) = TYPE_PACKED (gnu_base_type);
TYPE_REVERSE_STORAGE_ORDER (gnu_type)
= Reverse_Storage_Order (gnat_entity);
+
+ /* Do the same for subtypes as for the base type, since pointers
+ to them may symmetrically also point to the latter. */
+ 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);
/* Set the size, alignment and alias set of the type to match
@@ -3705,7 +3755,7 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, bool definition)
= create_var_decl (create_concat_name (gnat_entity,
"XVZ"),
NULL_TREE, sizetype, gnu_size_unit,
- true, false, false, false, false,
+ true, false, false, false, false, false,
true, true, NULL, gnat_entity, false);
}
@@ -3914,7 +3964,9 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, bool definition)
}
/* Access-to-unconstrained-array types need a special treatment. */
- if (Is_Array_Type (gnat_desig_rep) && !Is_Constrained (gnat_desig_rep))
+ if (Is_Array_Type (gnat_desig_rep)
+ && !Is_Constrained (gnat_desig_rep)
+ && !Is_Extended_Access_Type (gnat_entity))
{
/* If the processing above got something that has a pointer, then
we are done. This could have happened either because the type
@@ -3925,6 +3977,26 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, bool definition)
gnu_type = TYPE_POINTER_TO (gnu_desig_type);
}
+ else if (Is_Array_Type (gnat_desig_rep)
+ && !Is_Constrained (gnat_desig_rep)
+ && Is_Extended_Access_Type (gnat_entity))
+ {
+ if (TYPE_IS_DUMMY_P (gnu_desig_type))
+ gnu_type
+ = build_dummy_unc_pointer_types_ext (gnat_desig_rep,
+ gnu_desig_type);
+ else
+ {
+ tree gnu_extended_type
+ = get_extended_unconstrained_array (gnat_desig_rep,
+ gnu_desig_type);
+
+ /* We should not get a dummy type. */
+ gnu_type = TYPE_POINTER_TO (gnu_extended_type);
+ gcc_assert (gnu_type);
+ }
+ }
+
/* If we haven't done it yet, build the pointer type the usual way. */
else if (!gnu_type)
{
@@ -4229,8 +4301,9 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, bool definition)
gnu_decl
= create_var_decl (gnu_entity_name, gnu_ext_name, gnu_type,
gnu_address, false, Is_Public (gnat_entity),
- extern_flag, false, false, artificial_p,
- debug_info_p, NULL, gnat_entity);
+ Is_Link_Once (gnat_entity), extern_flag,
+ false, false, artificial_p, debug_info_p,
+ NULL, gnat_entity);
DECL_BY_REF_P (gnu_decl) = 1;
}
@@ -4259,6 +4332,7 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, bool definition)
= create_subprog_decl (gnu_entity_name, gnu_ext_name,
gnu_type, gnu_param_list, inline_status,
Is_Public (gnat_entity) || imported_p,
+ Is_Link_Once (gnat_entity),
extern_flag, artificial_p, debug_info_p,
definition && imported_p, attr_list,
gnat_entity);
@@ -4476,7 +4550,7 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, bool definition)
if (Known_Esize (gnat_entity))
gnu_size
= validate_size (Esize (gnat_entity), gnu_type, gnat_entity,
- VAR_DECL, false, false, size_s, type_s);
+ VAR_DECL, false, false, NULL, NULL);
/* ??? The test on Has_Size_Clause must be removed when "unknown" is
no longer represented as Uint_0 (i.e. Use_New_Unknown_Rep). */
@@ -4523,7 +4597,8 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, bool definition)
if (gnu_size)
size = gnu_size;
else if (RECORD_OR_UNION_TYPE_P (gnu_type)
- && !TYPE_FAT_POINTER_P (gnu_type))
+ && !TYPE_FAT_POINTER_P (gnu_type)
+ && !TYPE_EXTENDED_POINTER_P (gnu_type))
size = rm_size (gnu_type);
else
size = TYPE_SIZE (gnu_type);
@@ -4795,14 +4870,6 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, bool definition)
{
bool align_clause;
- /* Record the property that objects of tagged types are guaranteed to
- be properly aligned. This is necessary because conversions to the
- class-wide type are translated into conversions to the root type,
- which can be less aligned than some of its derived types. */
- if (Is_Tagged_Type (gnat_entity)
- || Is_Class_Wide_Equivalent_Type (gnat_entity))
- TYPE_ALIGN_OK (gnu_type) = 1;
-
/* Record whether the type is passed by reference. */
if (is_by_ref && !VOID_TYPE_P (gnu_type))
TYPE_BY_REFERENCE_P (gnu_type) = 1;
@@ -5108,6 +5175,22 @@ get_unpadded_type (Entity_Id gnat_entity)
return type;
}
+/* Similar, but GNAT_ENTITY is assumed to refer to a GNAT type. Return
+ the extended version of the GCC type corresponding to that entity. */
+
+tree
+get_unpadded_extended_type (Entity_Id gnat_entity)
+{
+ tree type = gnat_to_gnu_type (gnat_entity);
+
+ tree extended_type = get_extended_unconstrained_array (gnat_entity, type);
+
+ if (TYPE_IS_PADDING_P (extended_type))
+ extended_type = TREE_TYPE (TYPE_FIELDS (extended_type));
+
+ return extended_type;
+}
+
/* Return whether the E_Subprogram_Type/E_Function/E_Procedure GNAT_ENTITY is
a C++ imported method or equivalent.
@@ -5123,7 +5206,7 @@ is_cplusplus_method (Entity_Id gnat_entity)
it is declared without the 'this' parameter in the sources and, although
the front-end will create a version with the 'this' parameter for code
generation purposes, we want to return true for both versions. */
- if (Is_Constructor (gnat_entity))
+ if (Is_CPP_Constructor (gnat_entity))
return true;
/* Check that the subprogram has C++ convention. */
@@ -5215,6 +5298,47 @@ is_cplusplus_method (Entity_Id gnat_entity)
return false;
}
+/* Get the UNCONSTRAINED_ARRAY_TYPE tree used for extended access handling,
+ for the unconstrained array type GNAT_ENTITY.
+
+ GNU_TYPE is the UNCONSTRAINED_ARRAY_TYPE tree used for the regular
+ fat/thin pointers. */
+
+static tree
+get_extended_unconstrained_array (Entity_Id gnat_entity, tree gnu_type)
+{
+ gcc_assert (Is_Array_Type (gnat_entity)
+ && TREE_CODE (gnu_type) == UNCONSTRAINED_ARRAY_TYPE);
+
+
+ if (Ekind (gnat_entity) == E_Array_Subtype)
+ return get_extended_unconstrained_array (Etype (gnat_entity), gnu_type);
+
+ tree gnu_extended_type = TYPE_EXTENDED_UNCONSTRAINED_ARRAY (gnu_type);
+
+ /* Building the extended type is achieved by translating the array type
+ a second time using a special processing. */
+ if (!gnu_extended_type)
+ {
+ /* To have gnat_to_gnu_entity trigger the special processing for extended
+ access types, we pass GNU_TYPE as second parameter, we backup the
+ existing association for GNAT_ENTITY and clear it before the call. */
+ tree gnu_decl = get_gnu_tree (gnat_entity);
+ save_gnu_tree (gnat_entity, NULL_TREE, false);
+
+ gnu_extended_type
+ = TREE_TYPE (gnat_to_gnu_entity (gnat_entity, gnu_type, false));
+ gcc_assert (gnu_extended_type);
+ SET_TYPE_EXTENDED_UNCONSTRAINED_ARRAY (gnu_type, gnu_extended_type);
+
+ /* And finally, we restore the original association for GNAT_ENTITY. */
+ save_gnu_tree (gnat_entity, NULL_TREE, false);
+ save_gnu_tree (gnat_entity, gnu_decl, false);
+ }
+
+ return gnu_extended_type;
+}
+
/* Return the inlining status of the GNAT subprogram SUBPROG. */
static enum inline_status_t
@@ -5243,7 +5367,7 @@ inline_status_for_subprog (Entity_Id subprog)
&& Is_Record_Type (Etype (First_Formal (subprog)))
&& (gnu_type = gnat_to_gnu_type (Etype (First_Formal (subprog))))
&& !TYPE_IS_BY_REFERENCE_P (gnu_type)
- && tree_fits_uhwi_p (TYPE_SIZE (gnu_type))
+ && TREE_CODE (TYPE_SIZE (gnu_type)) == INTEGER_CST
&& compare_tree_int (TYPE_SIZE (gnu_type), MAX_FIXED_MODE_SIZE) <= 0)
return is_prescribed;
@@ -5418,7 +5542,7 @@ gnat_to_gnu_component_type (Entity_Id gnat_array, bool definition,
const bool is_bit_packed = Is_Bit_Packed_Array (gnat_array);
tree gnu_type = gnat_to_gnu_type (gnat_type);
tree gnu_comp_size;
- bool has_packed_components;
+ bool has_packed_component;
unsigned int max_align;
/* If an alignment is specified, use it as a cap on the component type
@@ -5437,18 +5561,25 @@ gnat_to_gnu_component_type (Entity_Id gnat_array, bool definition,
&& !Strict_Alignment (gnat_type)
&& RECORD_OR_UNION_TYPE_P (gnu_type)
&& !TYPE_FAT_POINTER_P (gnu_type)
+ && !TYPE_EXTENDED_POINTER_P (gnu_type)
&& tree_fits_uhwi_p (TYPE_SIZE (gnu_type)))
{
- gnu_type = make_packable_type (gnu_type, false, max_align);
- has_packed_components = true;
+ tree gnu_packable_type = make_packable_type (gnu_type, false, max_align);
+ if (gnu_packable_type != gnu_type)
+ {
+ gnu_type = gnu_packable_type;
+ has_packed_component = true;
+ }
+ else
+ has_packed_component = false;
}
else
- has_packed_components = is_bit_packed;
+ has_packed_component = is_bit_packed;
/* Get and validate any specified Component_Size. */
gnu_comp_size
= validate_size (Component_Size (gnat_array), gnu_type, gnat_array,
- has_packed_components ? TYPE_DECL : VAR_DECL, true,
+ has_packed_component ? TYPE_DECL : VAR_DECL, true,
Has_Component_Size_Clause (gnat_array), NULL, NULL);
/* If the component type is a RECORD_TYPE that has a self-referential size,
@@ -5705,7 +5836,7 @@ gnat_to_gnu_param (Entity_Id gnat_param, tree gnu_param_type, bool first,
= make_type_from_size (gnu_param_type, size_int (POINTER_SIZE), 0);
/* Use a pointer type for the "this" pointer of C++ constructors. */
- else if (Chars (gnat_param) == Name_uInit && Is_Constructor (gnat_subprog))
+ else if (Chars (gnat_param) == Name_uInit && Is_CPP_Constructor (gnat_subprog))
{
gcc_assert (mech == By_Reference);
gnu_param_type = build_pointer_type (gnu_param_type);
@@ -5990,7 +6121,8 @@ gnat_to_gnu_profile_type (Entity_Id gnat_type)
return gnu_type;
}
-/* Return true if TYPE contains only integral data, recursively if need be. */
+/* Return true if TYPE contains only integral data, recursively if need be.
+ (integral data is to be understood as not floating-point data here). */
static bool
type_contains_only_integral_data (tree type)
@@ -6010,7 +6142,7 @@ type_contains_only_integral_data (tree type)
return type_contains_only_integral_data (TREE_TYPE (type));
default:
- return INTEGRAL_TYPE_P (type);
+ return INTEGRAL_TYPE_P (type) || POINTER_TYPE_P (type);
}
gcc_unreachable ();
@@ -6388,6 +6520,33 @@ gnat_to_gnu_subprog_type (Entity_Id gnat_subprog, bool definition,
since structures are incomplete for the back-end. */
else if (Convention (gnat_subprog) != Convention_Stubbed)
{
+ /* If we have two entries that may be returned in integer registers,
+ the larger has power-of-2 size and the smaller is integer, then
+ extend the smaller to this power-of-2 size to get a return type
+ with power-of-2 size and no holes, again to speed up accesses. */
+ if (list_length (gnu_cico_field_list) == 2
+ && gnu_cico_only_integral_type)
+ {
+ tree typ1 = TREE_TYPE (gnu_cico_field_list);
+ tree typ2 = TREE_TYPE (DECL_CHAIN (gnu_cico_field_list));
+ if (TREE_CODE (typ1) == INTEGER_TYPE
+ && integer_pow2p (TYPE_SIZE (typ2))
+ && compare_tree_int (TYPE_SIZE (typ2),
+ MAX_FIXED_MODE_SIZE) <= 0
+ && tree_int_cst_lt (TYPE_SIZE (typ1), TYPE_SIZE (typ2)))
+ TREE_TYPE (gnu_cico_field_list)
+ = gnat_type_for_size (TREE_INT_CST_LOW (TYPE_SIZE (typ2)),
+ TYPE_UNSIGNED (typ1));
+ else if (TREE_CODE (typ2) == INTEGER_TYPE
+ && integer_pow2p (TYPE_SIZE (typ1))
+ && compare_tree_int (TYPE_SIZE (typ1),
+ MAX_FIXED_MODE_SIZE) <= 0
+ && tree_int_cst_lt (TYPE_SIZE (typ2), TYPE_SIZE (typ1)))
+ TREE_TYPE (DECL_CHAIN (gnu_cico_field_list))
+ = gnat_type_for_size (TREE_INT_CST_LOW (TYPE_SIZE (typ1)),
+ TYPE_UNSIGNED (typ2));
+ }
+
finish_record_type (gnu_cico_return_type,
nreverse (gnu_cico_field_list),
0, false);
@@ -6452,7 +6611,7 @@ gnat_to_gnu_subprog_type (Entity_Id gnat_subprog, bool definition,
/* Turn imported C++ constructors into their callable form as done in the
front-end, i.e. add the "this" pointer and void the return type. */
if (method_p
- && Is_Constructor (gnat_subprog)
+ && Is_CPP_Constructor (gnat_subprog)
&& !VOID_TYPE_P (gnu_return_type))
{
tree gnu_param_type
@@ -7094,6 +7253,155 @@ elaborate_entity (Entity_Id gnat_entity)
}
}
+/* Build the template type GNU_TEMPLATE_TYPE for the array type GNAT_ENTITY.
+ GNU_TEMPLATE_REFERENCE is an expression to access the template value from
+ the pointer type. If GNU_INDEX_TYPES is not null, it's an array where the
+ index types whose bounds are the values of the template are to be stored.
+ If GNU_MAX_SIZE is not NULL_TREE, it's a tree where the maximum size of
+ the array type is computed. DEBUG_INFO_P is true if debug info needs to
+ be output for this type. */
+
+void
+build_template_type (Entity_Id gnat_entity, tree gnu_template_type,
+ tree gnu_template_reference,
+ tree *gnu_index_types, tree &gnu_max_size,
+ bool debug_info_p)
+{
+ const bool convention_fortran_p
+ = (Convention (gnat_entity) == Convention_Fortran);
+ const int ndim = Number_Dimensions (gnat_entity);
+ tree *gnu_temp_fields = XALLOCAVEC (tree, ndim);
+ Entity_Id gnat_index;
+ int index;
+
+ tree template_fields = TYPE_FIELDS (gnu_template_type);
+ const bool template_exists_p = template_fields != NULL_TREE;
+
+ /* Now create the GCC type for each index and add the fields for that
+ index to the template. */
+ for (index = (convention_fortran_p ? ndim - 1 : 0),
+ gnat_index = First_Index (gnat_entity);
+ IN_RANGE (index, 0, ndim - 1);
+ index += (convention_fortran_p ? - 1 : 1),
+ gnat_index = Next_Index (gnat_index))
+ {
+ const Entity_Id gnat_index_type = Etype (gnat_index);
+ const bool is_flb = Is_Fixed_Lower_Bound_Index_Subtype (gnat_index_type);
+ tree gnu_index_type = get_unpadded_type (gnat_index_type);
+ tree gnu_orig_min = TYPE_MIN_VALUE (gnu_index_type);
+ tree gnu_orig_max = TYPE_MAX_VALUE (gnu_index_type);
+ tree gnu_index_base_type = get_base_type (gnu_index_type);
+ tree gnu_lb_field, gnu_hb_field;
+ tree gnu_min, gnu_max, gnu_high;
+ char field_name[16];
+
+ /* Update the maximum size of the array in elements. */
+ if (gnu_max_size)
+ gnu_max_size
+ = update_n_elem (gnu_max_size, gnu_orig_min, gnu_orig_max);
+
+ /* Now build the self-referential bounds of the index type. */
+ gnu_index_type = maybe_character_type (gnu_index_type);
+ gnu_index_base_type = maybe_character_type (gnu_index_base_type);
+
+ if (template_fields != NULL_TREE)
+ {
+ gnu_lb_field = template_fields;
+ template_fields = DECL_CHAIN (template_fields);
+ gnu_hb_field = template_fields;
+ template_fields = DECL_CHAIN (template_fields);
+ }
+ else
+ {
+ /* Make the FIELD_DECLs for the low and high bounds of this
+ type and then make extractions of these fields from the
+ template. */
+ sprintf (field_name, "LB%d", index);
+ gnu_lb_field = create_field_decl (get_identifier (field_name),
+ gnu_index_type,
+ gnu_template_type, NULL_TREE,
+ NULL_TREE, 0, 0);
+ /* Mark the field specifically for INSTANTIATE_LOAD_IN_EXPR. */
+ DECL_DISCRIMINANT_NUMBER (gnu_lb_field) = integer_minus_one_node;
+ Sloc_to_locus (Sloc (gnat_entity), &DECL_SOURCE_LOCATION (gnu_lb_field));
+
+ field_name[0] = 'U';
+ gnu_hb_field = create_field_decl (get_identifier (field_name),
+ gnu_index_type,
+ gnu_template_type, NULL_TREE,
+ NULL_TREE, 0, 0);
+ /* Mark the field specifically for INSTANTIATE_LOAD_IN_EXPR. */
+ DECL_DISCRIMINANT_NUMBER (gnu_hb_field) = integer_minus_one_node;
+ Sloc_to_locus (Sloc (gnat_entity), &DECL_SOURCE_LOCATION (gnu_hb_field));
+
+ gnu_temp_fields[index] = chainon (gnu_lb_field, gnu_hb_field);
+ }
+
+ if (gnu_index_types)
+ {
+ /* We can't use build_component_ref here since the template type
+ isn't complete yet. */
+ if (!is_flb)
+ {
+ gnu_orig_min
+ = build3 (COMPONENT_REF, TREE_TYPE (gnu_lb_field),
+ gnu_template_reference, gnu_lb_field,
+ NULL_TREE);
+ TREE_READONLY (gnu_orig_min) = 1;
+ }
+
+ gnu_orig_max = build3 (COMPONENT_REF, TREE_TYPE (gnu_hb_field),
+ gnu_template_reference, gnu_hb_field,
+ NULL_TREE);
+ TREE_READONLY (gnu_orig_max) = 1;
+
+ gnu_min = convert (sizetype, gnu_orig_min);
+ gnu_max = convert (sizetype, gnu_orig_max);
+
+ /* Compute the size of this dimension. See the E_Array_Subtype
+ case of gnat_to_gnu_entity for the rationale. */
+ if (is_flb
+ && Nkind (gnat_index) == N_Subtype_Indication
+ && flb_cannot_be_superflat (gnat_index))
+ gnu_high = gnu_max;
+
+ else
+ gnu_high
+ = build3 (COND_EXPR, sizetype,
+ build2 (GE_EXPR, boolean_type_node,
+ gnu_orig_max, gnu_orig_min),
+ gnu_max,
+ TREE_CODE (gnu_min) == INTEGER_CST
+ ? int_const_binop (MINUS_EXPR, gnu_min, size_one_node)
+ : size_binop (MINUS_EXPR, gnu_min, size_one_node));
+
+ /* Make a range type with the new range in the Ada base type.
+ Then make an index type with the size range in sizetype. */
+ gnu_index_types[index]
+ = create_index_type (gnu_min, gnu_high,
+ create_range_type (gnu_index_base_type,
+ gnu_orig_min,
+ gnu_orig_max),
+ gnat_entity);
+
+ TYPE_NAME (gnu_index_types[index])
+ = create_concat_name (gnat_entity, field_name);
+ }
+ }
+
+ if (!template_exists_p)
+ {
+ TYPE_NAMELESS (gnu_template_type)
+ = gnat_encodings != DWARF_GNAT_ENCODINGS_ALL;
+
+ tree gnu_template_fields = NULL_TREE;
+ for (index = 0; index < ndim; index++)
+ gnu_template_fields
+ = chainon (gnu_template_fields, gnu_temp_fields[index]);
+ finish_record_type (gnu_template_type, gnu_template_fields, 0, debug_info_p);
+ }
+}
+
/* Prepend to ATTR_LIST an entry for an attribute with provided TYPE,
NAME, ARGS and ERROR_POINT. */
@@ -7261,8 +7569,7 @@ static tree
elaborate_expression_1 (tree gnu_expr, Entity_Id gnat_entity, const char *s,
bool definition, bool need_for_debug)
{
- const bool expr_public_p = Is_Public (gnat_entity);
- const bool expr_global_p = expr_public_p || global_bindings_p ();
+ const bool expr_global_p = Is_Public (gnat_entity) || global_bindings_p ();
bool expr_variable_p, use_variable;
/* If GNU_EXPR contains a placeholder, just return it. We rely on the fact
@@ -7312,7 +7619,7 @@ elaborate_expression_1 (tree gnu_expr, Entity_Id gnat_entity, const char *s,
if (need_for_debug
&& gnat_encodings != DWARF_GNAT_ENCODINGS_ALL
&& (TREE_CONSTANT (gnu_expr)
- || (!expr_public_p
+ || (!Is_Public (gnat_entity)
&& DECL_P (gnu_expr)
&& !DECL_IGNORED_P (gnu_expr))))
need_for_debug = false;
@@ -7331,7 +7638,8 @@ elaborate_expression_1 (tree gnu_expr, Entity_Id gnat_entity, const char *s,
tree gnu_decl
= create_var_decl (create_concat_name (gnat_entity, s), NULL_TREE,
TREE_TYPE (gnu_expr), gnu_expr, true,
- expr_public_p, !definition && expr_global_p,
+ Is_Public (gnat_entity), Is_Link_Once (gnat_entity),
+ !definition && expr_global_p,
expr_global_p, false, true,
Needs_Debug_Info (gnat_entity),
NULL, gnat_entity, false);
@@ -7715,6 +8023,7 @@ gnat_to_gnu_field (Entity_Id gnat_field, tree gnu_record_type, int packed,
if (!needs_strict_alignment
&& RECORD_OR_UNION_TYPE_P (gnu_field_type)
&& !TYPE_FAT_POINTER_P (gnu_field_type)
+ && !TYPE_EXTENDED_POINTER_P (gnu_field_type)
&& tree_fits_uhwi_p (TYPE_SIZE (gnu_field_type))
&& (packed == 1
|| is_bitfield
@@ -7912,6 +8221,7 @@ gnat_to_gnu_field (Entity_Id gnat_field, tree gnu_record_type, int packed,
if (!needs_strict_alignment
&& RECORD_OR_UNION_TYPE_P (gnu_field_type)
&& !TYPE_FAT_POINTER_P (gnu_field_type)
+ && !TYPE_EXTENDED_POINTER_P (gnu_field_type)
&& TYPE_MODE (gnu_field_type) == BLKmode
&& is_bitfield)
gnu_field_type = make_packable_type (gnu_field_type, true, 1);
@@ -9638,7 +9948,9 @@ validate_size (Uint uint_size, tree gnu_type, Entity_Id gnat_object,
/* If this is an access type or a fat pointer, the minimum size is that given
by the default pointer mode. */
- if (TREE_CODE (gnu_type) == POINTER_TYPE || TYPE_IS_FAT_POINTER_P (gnu_type))
+ if (TREE_CODE (gnu_type) == POINTER_TYPE
+ || TYPE_IS_FAT_POINTER_P (gnu_type)
+ || TYPE_IS_EXTENDED_POINTER_P (gnu_type))
old_size = bitsize_int (GET_MODE_BITSIZE (ptr_mode));
/* Issue an error either if the default size of the object isn't a constant
@@ -9664,6 +9976,20 @@ validate_size (Uint uint_size, tree gnu_type, Entity_Id gnat_object,
return NULL_TREE;
}
+ /* The size of stand-alone objects is always a multiple of the alignment,
+ but that's already enforced for elementary types by the front-end. */
+ if (kind == VAR_DECL
+ && !component_p
+ && RECORD_OR_UNION_TYPE_P (gnu_type)
+ && !TYPE_FAT_POINTER_P (gnu_type)
+ && !integer_zerop (size_binop (TRUNC_MOD_EXPR, size,
+ bitsize_int (TYPE_ALIGN (gnu_type)))))
+ {
+ post_error_ne_num ("size for& must be multiple of alignment ^",
+ gnat_error_node, gnat_object, TYPE_ALIGN (gnu_type));
+ return NULL_TREE;
+ }
+
return size;
}
@@ -9740,7 +10066,8 @@ set_rm_size (Uint uint_size, tree gnu_type, Entity_Id gnat_entity)
/* ...or the Ada size for record and union types. */
else if (RECORD_OR_UNION_TYPE_P (gnu_type)
- && !TYPE_FAT_POINTER_P (gnu_type))
+ && !TYPE_FAT_POINTER_P (gnu_type)
+ && !TYPE_EXTENDED_POINTER_P (gnu_type))
SET_TYPE_ADA_SIZE (gnu_type, size);
}
@@ -10544,6 +10871,7 @@ copy_and_substitute_in_layout (Entity_Id gnat_new_type,
gnu_size = DECL_SIZE (gnu_old_field);
if (RECORD_OR_UNION_TYPE_P (gnu_field_type)
&& !TYPE_FAT_POINTER_P (gnu_field_type)
+ && !TYPE_EXTENDED_POINTER_P (gnu_field_type)
&& tree_fits_uhwi_p (TYPE_SIZE (gnu_field_type)))
gnu_field_type = make_packable_type (gnu_field_type, true, 0);
}
@@ -10916,6 +11244,7 @@ rm_size (tree gnu_type)
/* For record or union types, we store the size explicitly. */
if (RECORD_OR_UNION_TYPE_P (gnu_type)
&& !TYPE_FAT_POINTER_P (gnu_type)
+ && !TYPE_EXTENDED_POINTER_P (gnu_type)
&& TYPE_ADA_SIZE (gnu_type))
return TYPE_ADA_SIZE (gnu_type);