aboutsummaryrefslogtreecommitdiff
path: root/gcc/ada/gcc-interface
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/ada/gcc-interface')
-rw-r--r--gcc/ada/gcc-interface/ada-tree.h25
-rw-r--r--gcc/ada/gcc-interface/decl.c150
-rw-r--r--gcc/ada/gcc-interface/gigi.h15
-rw-r--r--gcc/ada/gcc-interface/trans.c16
-rw-r--r--gcc/ada/gcc-interface/utils.c15
5 files changed, 130 insertions, 91 deletions
diff --git a/gcc/ada/gcc-interface/ada-tree.h b/gcc/ada/gcc-interface/ada-tree.h
index a3d38b1b22e..852e2a5138b 100644
--- a/gcc/ada/gcc-interface/ada-tree.h
+++ b/gcc/ada/gcc-interface/ada-tree.h
@@ -6,7 +6,7 @@
* *
* C Header File *
* *
- * Copyright (C) 1992-2016, Free Software Foundation, Inc. *
+ * Copyright (C) 1992-2018, 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- *
@@ -83,6 +83,12 @@ do { \
((TREE_CODE (NODE) == INTEGER_TYPE || TREE_CODE (NODE) == ARRAY_TYPE) \
&& TYPE_PACKED_ARRAY_TYPE_P (NODE))
+/* For FUNCTION_TYPEs, nonzero if the function returns by direct reference,
+ i.e. the callee returns a pointer to a memory location it has allocated
+ and the caller only needs to dereference the pointer. */
+#define TYPE_RETURN_BY_DIRECT_REF_P(NODE) \
+ TYPE_LANG_FLAG_0 (FUNCTION_TYPE_CHECK (NODE))
+
/* For INTEGER_TYPE, nonzero if this is a modular type with a modulus that
is not equal to two to the power of its mode's size. */
#define TYPE_MODULAR_P(NODE) TYPE_LANG_FLAG_1 (INTEGER_TYPE_CHECK (NODE))
@@ -152,12 +158,6 @@ do { \
#define TYPE_CONVENTION_FORTRAN_P(NODE) \
TYPE_LANG_FLAG_4 (ARRAY_TYPE_CHECK (NODE))
-/* For FUNCTION_TYPEs, nonzero if the function returns by direct reference,
- i.e. the callee returns a pointer to a memory location it has allocated
- and the caller only needs to dereference the pointer. */
-#define TYPE_RETURN_BY_DIRECT_REF_P(NODE) \
- TYPE_LANG_FLAG_4 (FUNCTION_TYPE_CHECK (NODE))
-
/* For RECORD_TYPE, UNION_TYPE and ENUMERAL_TYPE, nonzero if this is a dummy
type, made to correspond to a private or incomplete type. */
#define TYPE_DUMMY_P(NODE) \
@@ -186,6 +186,9 @@ do { \
/* True for a dummy type if TYPE appears in a profile. */
#define TYPE_DUMMY_IN_PROFILE_P(NODE) TYPE_LANG_FLAG_6 (NODE)
+/* True if objects of this type are guaranteed to be properly aligned. */
+#define TYPE_ALIGN_OK(NODE) TYPE_LANG_FLAG_7 (NODE)
+
/* True for types that implement a packed array and for original packed array
types. */
#define TYPE_IMPL_PACKED_ARRAY_P(NODE) \
@@ -199,9 +202,6 @@ do { \
alignment value the type ought to have. */
#define TYPE_MAX_ALIGN(NODE) (TYPE_PRECISION (RECORD_OR_UNION_CHECK (NODE)))
-/* True if objects of tagged types are guaranteed to be properly aligned. */
-#define TYPE_ALIGN_OK(NODE) TYPE_LANG_FLAG_7 (NODE)
-
/* For an UNCONSTRAINED_ARRAY_TYPE, this is the record containing both the
template and the object.
@@ -232,6 +232,11 @@ do { \
refer to the routine gnat_to_gnu_entity. */
#define TYPE_CI_CO_LIST(NODE) TYPE_LANG_SLOT_1 (FUNCTION_TYPE_CHECK (NODE))
+/* For an ARRAY_TYPE with variable size, this is the padding type built for
+ the array type when it is itself the component type of another array. */
+#define TYPE_PADDING_FOR_COMPONENT(NODE) \
+ TYPE_LANG_SLOT_1 (ARRAY_TYPE_CHECK (NODE))
+
/* For a VECTOR_TYPE, this is the representative array type. */
#define TYPE_REPRESENTATIVE_ARRAY(NODE) \
TYPE_LANG_SLOT_1 (VECTOR_TYPE_CHECK (NODE))
diff --git a/gcc/ada/gcc-interface/decl.c b/gcc/ada/gcc-interface/decl.c
index e226f256b47..d2316afc8f1 100644
--- a/gcc/ada/gcc-interface/decl.c
+++ b/gcc/ada/gcc-interface/decl.c
@@ -206,7 +206,6 @@ static tree gnat_to_gnu_component_type (Entity_Id, bool, bool);
static tree gnat_to_gnu_subprog_type (Entity_Id, bool, bool, tree *);
static tree gnat_to_gnu_field (Entity_Id, tree, int, bool, bool);
static tree gnu_ext_name_for_subprog (Entity_Id, tree);
-static tree change_qualified_type (tree, int);
static void set_nonaliased_component_on_array_type (tree);
static void set_reverse_storage_order_on_array_type (tree);
static bool same_discriminant_p (Entity_Id, Entity_Id);
@@ -592,17 +591,22 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, bool definition)
/* If we have a constant that we are not defining, get the expression it
was defined to represent. This is necessary to avoid generating dumb
elaboration code in simple cases, but we may throw it away later if it
- is not a constant. But do not retrieve it if it is an allocator since
- the designated type might still be dummy at this point. */
+ is not a constant. But do not do it for dispatch tables because they
+ are only referenced indirectly and we need to have a consistent view
+ of the exported and of the imported declarations of the tables from
+ external units for them to be properly merged in LTO mode. Moreover
+ simply do not retrieve the expression it if it is an allocator since
+ the designated type might still be dummy at this point. Note that we
+ invoke gnat_to_gnu_external and not gnat_to_gnu because the expression
+ may contain N_Expression_With_Actions nodes and thus declarations of
+ objects from other units that we need to discard. */
if (!definition
&& !No_Initialization (Declaration_Node (gnat_entity))
- && Present (Expression (Declaration_Node (gnat_entity)))
- && Nkind (Expression (Declaration_Node (gnat_entity)))
- != N_Allocator)
- /* The expression may contain N_Expression_With_Actions nodes and
- thus object declarations from other units. Discard them. */
- gnu_expr
- = gnat_to_gnu_external (Expression (Declaration_Node (gnat_entity)));
+ && !Is_Dispatch_Table_Entity (gnat_entity)
+ && Present (gnat_temp = Expression (Declaration_Node (gnat_entity)))
+ && Nkind (gnat_temp) != N_Allocator
+ && (!type_annotate_only || Compile_Time_Known_Value (gnat_temp)))
+ gnu_expr = gnat_to_gnu_external (gnat_temp);
/* ... fall through ... */
@@ -2063,11 +2067,16 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, bool definition)
{
gnu_fat_type = TYPE_MAIN_VARIANT (TYPE_POINTER_TO (gnu_type));
TYPE_NAME (gnu_fat_type) = NULL_TREE;
- /* Save the contents of the dummy type for update_pointer_to. */
- TYPE_POINTER_TO (gnu_type) = copy_type (gnu_fat_type);
gnu_ptr_template =
- TREE_TYPE (TREE_CHAIN (TYPE_FIELDS (gnu_fat_type)));
+ TREE_TYPE (DECL_CHAIN (TYPE_FIELDS (gnu_fat_type)));
gnu_template_type = TREE_TYPE (gnu_ptr_template);
+
+ /* Save the contents of the dummy type for update_pointer_to. */
+ TYPE_POINTER_TO (gnu_type) = copy_type (gnu_fat_type);
+ TYPE_FIELDS (TYPE_POINTER_TO (gnu_type))
+ = copy_node (TYPE_FIELDS (gnu_fat_type));
+ DECL_CHAIN (TYPE_FIELDS (TYPE_POINTER_TO (gnu_type)))
+ = copy_node (DECL_CHAIN (TYPE_FIELDS (gnu_fat_type)));
}
else
{
@@ -2088,29 +2097,39 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, bool definition)
/* Build the fat pointer type. Use a "void *" object instead of
a pointer to the array type since we don't have the array type
- yet (it will reference the fat pointer via the bounds). */
- tem
- = create_field_decl (get_identifier ("P_ARRAY"), ptr_type_node,
- gnu_fat_type, NULL_TREE, NULL_TREE, 0, 0);
- DECL_CHAIN (tem)
- = create_field_decl (get_identifier ("P_BOUNDS"), gnu_ptr_template,
- gnu_fat_type, NULL_TREE, NULL_TREE, 0, 0);
-
+ yet (it will reference the fat pointer via the bounds). Note
+ that we reuse the existing fields of a dummy type because for:
+
+ type Arr is array (Positive range <>) of Element_Type;
+ type Array_Ref is access Arr;
+ Var : Array_Ref := Null;
+
+ in a declarative part, Arr will be frozen only after Var, which
+ means that the fields used in the CONSTRUCTOR built for Null are
+ those of the dummy type, which in turn means that COMPONENT_REFs
+ of Var may be built with these fields. Now if COMPONENT_REFs of
+ 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))
{
- /* We are going to lay it out again so reset the alias set. */
- alias_set_type alias_set = TYPE_ALIAS_SET (gnu_fat_type);
- TYPE_ALIAS_SET (gnu_fat_type) = -1;
- finish_fat_pointer_type (gnu_fat_type, tem);
- TYPE_ALIAS_SET (gnu_fat_type) = alias_set;
+ tem = TYPE_FIELDS (gnu_fat_type);
+ TREE_TYPE (tem) = ptr_type_node;
+ TREE_TYPE (DECL_CHAIN (tem)) = gnu_ptr_template;
+ TYPE_DECL_SUPPRESS_DEBUG (TYPE_STUB_DECL (gnu_fat_type)) = 0;
for (t = gnu_fat_type; t; t = TYPE_NEXT_VARIANT (t))
- {
- TYPE_FIELDS (t) = tem;
- SET_TYPE_UNCONSTRAINED_ARRAY (t, gnu_type);
- }
+ SET_TYPE_UNCONSTRAINED_ARRAY (t, gnu_type);
}
else
{
+ tem
+ = create_field_decl (get_identifier ("P_ARRAY"),
+ ptr_type_node, gnu_fat_type,
+ NULL_TREE, NULL_TREE, 0, 0);
+ DECL_CHAIN (tem)
+ = create_field_decl (get_identifier ("P_BOUNDS"),
+ gnu_ptr_template, gnu_fat_type,
+ NULL_TREE, NULL_TREE, 0, 0);
finish_fat_pointer_type (gnu_fat_type, tem);
SET_TYPE_UNCONSTRAINED_ARRAY (gnu_fat_type, gnu_type);
}
@@ -3389,20 +3408,6 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, bool definition)
break;
}
- /* If this is a record subtype associated with a dispatch table,
- strip the suffix. This is necessary to make sure 2 different
- subtypes associated with the imported and exported views of a
- dispatch table are properly merged in LTO mode. */
- if (Is_Dispatch_Table_Entity (gnat_entity))
- {
- char *p;
- Get_Encoded_Name (gnat_entity);
- p = strchr (Name_Buffer, '_');
- gcc_assert (p);
- strcpy (p+2, "dtS");
- gnu_entity_name = get_identifier (Name_Buffer);
- }
-
/* When the subtype has discriminants and these discriminants affect
the initial shape it has inherited, factor them in. But for an
Unchecked_Union (it must be an Itype), just return the type.
@@ -4681,7 +4686,7 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, bool definition)
/* If this is not an unconstrained array type, set some flags. */
if (TREE_CODE (gnu_type) != UNCONSTRAINED_ARRAY_TYPE)
{
- /* Tell the middle-end that objects of tagged types are guaranteed to
+ /* 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. */
@@ -5272,17 +5277,6 @@ gnat_to_gnu_component_type (Entity_Id gnat_array, bool definition,
Is_Bit_Packed_Array (gnat_array) ? TYPE_DECL : VAR_DECL,
true, Has_Component_Size_Clause (gnat_array));
- /* If the array has aliased components and the component size can be zero,
- force at least unit size to ensure that the components have distinct
- addresses. */
- if (!gnu_comp_size
- && Has_Aliased_Components (gnat_array)
- && (integer_zerop (TYPE_SIZE (gnu_type))
- || (TREE_CODE (gnu_type) == ARRAY_TYPE
- && !TREE_CONSTANT (TYPE_SIZE (gnu_type)))))
- gnu_comp_size
- = size_binop (MAX_EXPR, TYPE_SIZE (gnu_type), bitsize_unit_node);
-
/* If the component type is a RECORD_TYPE that has a self-referential size,
then use the maximum size for the component size. */
if (!gnu_comp_size
@@ -5290,6 +5284,13 @@ gnat_to_gnu_component_type (Entity_Id gnat_array, bool definition,
&& CONTAINS_PLACEHOLDER_P (TYPE_SIZE (gnu_type)))
gnu_comp_size = max_size (TYPE_SIZE (gnu_type), true);
+ /* If the array has aliased components and the component size is zero, force
+ the unit size to ensure that the components have distinct addresses. */
+ if (!gnu_comp_size
+ && Has_Aliased_Components (gnat_array)
+ && integer_zerop (TYPE_SIZE (gnu_type)))
+ gnu_comp_size = bitsize_unit_node;
+
/* Honor the component size. This is not needed for bit-packed arrays. */
if (gnu_comp_size && !Is_Bit_Packed_Array (gnat_array))
{
@@ -5312,6 +5313,30 @@ gnat_to_gnu_component_type (Entity_Id gnat_array, bool definition,
gnat_array);
}
+ /* This is a very special case where the array has aliased components and the
+ component size might be zero at run time. As explained above, we force at
+ least the unit size but we don't want to build a distinct padding type for
+ each invocation (they are not canonicalized if they have variable size) so
+ we cache this special padding type as TYPE_PADDING_FOR_COMPONENT. */
+ else if (Has_Aliased_Components (gnat_array)
+ && TREE_CODE (gnu_type) == ARRAY_TYPE
+ && !TREE_CONSTANT (TYPE_SIZE (gnu_type)))
+ {
+ if (TYPE_PADDING_FOR_COMPONENT (gnu_type))
+ gnu_type = TYPE_PADDING_FOR_COMPONENT (gnu_type);
+ else
+ {
+ gnu_comp_size
+ = size_binop (MAX_EXPR, TYPE_SIZE (gnu_type), bitsize_unit_node);
+ TYPE_PADDING_FOR_COMPONENT (gnu_type)
+ = maybe_pad_type (gnu_type, gnu_comp_size, 0, gnat_array,
+ true, false, definition, true);
+ gnu_type = TYPE_PADDING_FOR_COMPONENT (gnu_type);
+ create_type_decl (TYPE_NAME (gnu_type), gnu_type, true, debug_info_p,
+ gnat_array);
+ }
+ }
+
/* If the component type is a padded type made for a non-bit-packed array
of scalars with reverse storage order, we need to propagate the reverse
storage order to the padding type since it is the innermost enclosing
@@ -6276,19 +6301,6 @@ gnu_ext_name_for_subprog (Entity_Id gnat_subprog, tree gnu_entity_name)
return gnu_ext_name;
}
-/* Like build_qualified_type, but TYPE_QUALS is added to the existing
- qualifiers on TYPE. */
-
-static tree
-change_qualified_type (tree type, int type_quals)
-{
- /* Qualifiers must be put on the associated array type. */
- if (TREE_CODE (type) == UNCONSTRAINED_ARRAY_TYPE)
- return type;
-
- return build_qualified_type (type, TYPE_QUALS (type) | type_quals);
-}
-
/* Set TYPE_NONALIASED_COMPONENT on an array type built by means of
build_nonshared_array_type. */
diff --git a/gcc/ada/gcc-interface/gigi.h b/gcc/ada/gcc-interface/gigi.h
index 1d87b5be44e..2b33c13302c 100644
--- a/gcc/ada/gcc-interface/gigi.h
+++ b/gcc/ada/gcc-interface/gigi.h
@@ -1074,7 +1074,7 @@ maybe_vector_array (tree exp)
static inline unsigned HOST_WIDE_INT
ceil_pow2 (unsigned HOST_WIDE_INT x)
{
- return (unsigned HOST_WIDE_INT) 1 << (floor_log2 (x - 1) + 1);
+ return (unsigned HOST_WIDE_INT) 1 << ceil_log2 (x);
}
/* Return true if EXP, a CALL_EXPR, is an atomic load. */
@@ -1171,3 +1171,16 @@ maybe_debug_type (tree type)
return type;
}
+
+/* Like build_qualified_type, but TYPE_QUALS is added to the existing
+ qualifiers on TYPE. */
+
+static inline tree
+change_qualified_type (tree type, int type_quals)
+{
+ /* Qualifiers must be put on the associated array type. */
+ if (TREE_CODE (type) == UNCONSTRAINED_ARRAY_TYPE)
+ return type;
+
+ return build_qualified_type (type, TYPE_QUALS (type) | type_quals);
+}
diff --git a/gcc/ada/gcc-interface/trans.c b/gcc/ada/gcc-interface/trans.c
index eaad084959c..47c8a286220 100644
--- a/gcc/ada/gcc-interface/trans.c
+++ b/gcc/ada/gcc-interface/trans.c
@@ -4326,12 +4326,15 @@ Call_to_gnu (Node_Id gnat_node, tree *gnu_result_type_p, tree gnu_target,
because we need to preserve the return value before copying back the
parameters.
- 2. There is no target and the call is made for neither an object nor a
+ 2. There is no target and the call is made for neither an object, nor a
renaming declaration, nor a return statement, nor an allocator, and
the return type has variable size because in this case the gimplifier
- cannot create the temporary, or more generally is simply an aggregate
- type, because the gimplifier would then create the temporary in the
- outermost scope instead of locally.
+ cannot create the temporary, or more generally is an aggregate type,
+ because the gimplifier would create the temporary in the outermost
+ scope instead of locally. But there is an exception for an allocator
+ of an unconstrained record type with default discriminant because we
+ allocate the actual size in this case, unlike the other 3 cases, so
+ we need a temporary to fetch the discriminant and we create it here.
3. There is a target and it is a slice or an array with fixed size,
and the return type has variable size, because the gimplifier
@@ -4350,8 +4353,9 @@ Call_to_gnu (Node_Id gnat_node, tree *gnu_result_type_p, tree gnu_target,
&& Nkind (Parent (gnat_node)) != N_Object_Declaration
&& Nkind (Parent (gnat_node)) != N_Object_Renaming_Declaration
&& Nkind (Parent (gnat_node)) != N_Simple_Return_Statement
- && !(Nkind (Parent (gnat_node)) == N_Qualified_Expression
- && Nkind (Parent (Parent (gnat_node))) == N_Allocator)
+ && (!(Nkind (Parent (gnat_node)) == N_Qualified_Expression
+ && Nkind (Parent (Parent (gnat_node))) == N_Allocator)
+ || type_is_padding_self_referential (gnu_result_type))
&& AGGREGATE_TYPE_P (gnu_result_type)
&& !TYPE_IS_FAT_POINTER_P (gnu_result_type))
|| (gnu_target
diff --git a/gcc/ada/gcc-interface/utils.c b/gcc/ada/gcc-interface/utils.c
index f362946e63a..cb2c4d22a41 100644
--- a/gcc/ada/gcc-interface/utils.c
+++ b/gcc/ada/gcc-interface/utils.c
@@ -3255,8 +3255,11 @@ finish_subprog_decl (tree decl, tree asm_name, tree type)
DECL_BY_REFERENCE (result_decl) = TREE_ADDRESSABLE (type);
DECL_RESULT (decl) = result_decl;
+ /* Propagate the "const" property. */
TREE_READONLY (decl) = TYPE_READONLY (type);
- TREE_SIDE_EFFECTS (decl) = TREE_THIS_VOLATILE (decl) = TYPE_VOLATILE (type);
+
+ /* Propagate the "noreturn" property. */
+ TREE_THIS_VOLATILE (decl) = TYPE_VOLATILE (type);
if (asm_name)
{
@@ -4543,9 +4546,12 @@ convert (tree type, tree expr)
etype)))
return build1 (VIEW_CONVERT_EXPR, type, expr);
- /* If we are converting between tagged types, try to upcast properly. */
+ /* If we are converting between tagged types, try to upcast properly.
+ But don't do it if we are just annotating types since tagged types
+ aren't fully laid out in this mode. */
else if (ecode == RECORD_TYPE && code == RECORD_TYPE
- && TYPE_ALIGN_OK (etype) && TYPE_ALIGN_OK (type))
+ && TYPE_ALIGN_OK (etype) && TYPE_ALIGN_OK (type)
+ && !type_annotate_only)
{
tree child_etype = etype;
do {
@@ -6113,8 +6119,7 @@ handle_noreturn_attribute (tree *node, tree name, tree ARG_UNUSED (args),
&& TREE_CODE (TREE_TYPE (type)) == FUNCTION_TYPE)
TREE_TYPE (*node)
= build_pointer_type
- (build_type_variant (TREE_TYPE (type),
- TYPE_READONLY (TREE_TYPE (type)), 1));
+ (change_qualified_type (TREE_TYPE (type), TYPE_QUAL_VOLATILE));
else
{
warning (OPT_Wattributes, "%qs attribute ignored",