aboutsummaryrefslogtreecommitdiff
path: root/gcc/ada/decl.c
diff options
context:
space:
mode:
authorEric Botcazou <ebotcazou@adacore.com>2008-06-12 13:19:06 +0000
committerEric Botcazou <ebotcazou@gcc.gnu.org>2008-06-12 13:19:06 +0000
commit1dd4a3e6378a4f20d7c6ce9ef588e65cbe0e38e7 (patch)
tree2db270491bd07d4352f95eee6ffa4b3a27eca273 /gcc/ada/decl.c
parentfcd2a5d4d6600edbd2937830c60b5e5696ab1593 (diff)
downloadgcc-1dd4a3e6378a4f20d7c6ce9ef588e65cbe0e38e7.zip
gcc-1dd4a3e6378a4f20d7c6ce9ef588e65cbe0e38e7.tar.gz
gcc-1dd4a3e6378a4f20d7c6ce9ef588e65cbe0e38e7.tar.bz2
decl.c (gnat_to_gnu_entity): In the case of a constrained subtype of a discriminated type...
* decl.c (gnat_to_gnu_entity) <E_Record_Subtype>: In the case of a constrained subtype of a discriminated type, discard the fields that are beyond its limits according to its size. From-SVN: r136707
Diffstat (limited to 'gcc/ada/decl.c')
-rw-r--r--gcc/ada/decl.c98
1 files changed, 54 insertions, 44 deletions
diff --git a/gcc/ada/decl.c b/gcc/ada/decl.c
index b8bcb4b..dbd7970 100644
--- a/gcc/ada/decl.c
+++ b/gcc/ada/decl.c
@@ -2922,9 +2922,42 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, int definition)
gnu_type = make_node (RECORD_TYPE);
TYPE_NAME (gnu_type) = gnu_entity_id;
- TYPE_ALIGN (gnu_type) = TYPE_ALIGN (gnu_base_type);
TYPE_VOLATILE (gnu_type) = Treat_As_Volatile (gnat_entity);
+ /* Set the size, alignment and alias set of the new type to
+ match that of the old one, doing required substitutions.
+ We do it this early because we need the size of the new
+ type below to discard old fields if necessary. */
+ TYPE_SIZE (gnu_type) = TYPE_SIZE (gnu_base_type);
+ TYPE_SIZE_UNIT (gnu_type) = TYPE_SIZE_UNIT (gnu_base_type);
+ SET_TYPE_ADA_SIZE (gnu_type, TYPE_ADA_SIZE (gnu_base_type));
+ TYPE_ALIGN (gnu_type) = TYPE_ALIGN (gnu_base_type);
+ copy_alias_set (gnu_type, gnu_base_type);
+
+ if (CONTAINS_PLACEHOLDER_P (TYPE_SIZE (gnu_type)))
+ for (gnu_temp = gnu_subst_list;
+ gnu_temp; gnu_temp = TREE_CHAIN (gnu_temp))
+ TYPE_SIZE (gnu_type)
+ = substitute_in_expr (TYPE_SIZE (gnu_type),
+ TREE_PURPOSE (gnu_temp),
+ TREE_VALUE (gnu_temp));
+
+ if (CONTAINS_PLACEHOLDER_P (TYPE_SIZE_UNIT (gnu_type)))
+ for (gnu_temp = gnu_subst_list;
+ gnu_temp; gnu_temp = TREE_CHAIN (gnu_temp))
+ TYPE_SIZE_UNIT (gnu_type)
+ = substitute_in_expr (TYPE_SIZE_UNIT (gnu_type),
+ TREE_PURPOSE (gnu_temp),
+ TREE_VALUE (gnu_temp));
+
+ if (CONTAINS_PLACEHOLDER_P (TYPE_ADA_SIZE (gnu_type)))
+ for (gnu_temp = gnu_subst_list;
+ gnu_temp; gnu_temp = TREE_CHAIN (gnu_temp))
+ SET_TYPE_ADA_SIZE
+ (gnu_type, substitute_in_expr (TYPE_ADA_SIZE (gnu_type),
+ TREE_PURPOSE (gnu_temp),
+ TREE_VALUE (gnu_temp)));
+
for (gnat_field = First_Entity (gnat_entity);
Present (gnat_field); gnat_field = Next_Entity (gnat_field))
if ((Ekind (gnat_field) == E_Component
@@ -2946,7 +2979,7 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, int definition)
tree gnu_field_type
= gnat_to_gnu_type (Etype (gnat_field));
tree gnu_size = TYPE_SIZE (gnu_field_type);
- tree gnu_new_pos = 0;
+ tree gnu_new_pos = NULL_TREE;
unsigned int offset_align
= tree_low_cst (TREE_PURPOSE (TREE_VALUE (gnu_offset)),
1);
@@ -2992,11 +3025,23 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, int definition)
TREE_PURPOSE (gnu_temp),
TREE_VALUE (gnu_temp));
- /* If the size is now a constant, we can set it as the
- size of the field when we make it. Otherwise, we need
- to deal with it specially. */
+ /* If the position is now a constant, we can set it as the
+ position of the field when we make it. Otherwise, we need
+ to deal with it specially below. */
if (TREE_CONSTANT (gnu_pos))
- gnu_new_pos = bit_from_pos (gnu_pos, gnu_bitpos);
+ {
+ gnu_new_pos = bit_from_pos (gnu_pos, gnu_bitpos);
+
+ /* Discard old fields that are outside the new type.
+ This avoids confusing code scanning it to decide
+ how to pass it to functions on some platforms. */
+ if (TREE_CODE (gnu_new_pos) == INTEGER_CST
+ && TREE_CODE (TYPE_SIZE (gnu_type)) == INTEGER_CST
+ && !integer_zerop (gnu_size)
+ && !tree_int_cst_lt (gnu_new_pos,
+ TYPE_SIZE (gnu_type)))
+ continue;
+ }
gnu_field
= create_field_decl
@@ -3044,49 +3089,14 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, int definition)
gnat_to_gnu_entity (Etype (gnat_field), NULL_TREE, 0);
/* Do not finalize it since we're going to modify it below. */
- finish_record_type (gnu_type, nreverse (gnu_field_list),
- 2, true);
-
- /* Now set the size, alignment and alias set of the new type to
- match that of the old one, doing any substitutions, as
- above. */
- TYPE_ALIGN (gnu_type) = TYPE_ALIGN (gnu_base_type);
- TYPE_SIZE (gnu_type) = TYPE_SIZE (gnu_base_type);
- TYPE_SIZE_UNIT (gnu_type) = TYPE_SIZE_UNIT (gnu_base_type);
- SET_TYPE_ADA_SIZE (gnu_type, TYPE_ADA_SIZE (gnu_base_type));
- copy_alias_set (gnu_type, gnu_base_type);
-
- if (CONTAINS_PLACEHOLDER_P (TYPE_SIZE (gnu_type)))
- for (gnu_temp = gnu_subst_list;
- gnu_temp; gnu_temp = TREE_CHAIN (gnu_temp))
- TYPE_SIZE (gnu_type)
- = substitute_in_expr (TYPE_SIZE (gnu_type),
- TREE_PURPOSE (gnu_temp),
- TREE_VALUE (gnu_temp));
-
- if (CONTAINS_PLACEHOLDER_P (TYPE_SIZE_UNIT (gnu_type)))
- for (gnu_temp = gnu_subst_list;
- gnu_temp; gnu_temp = TREE_CHAIN (gnu_temp))
- TYPE_SIZE_UNIT (gnu_type)
- = substitute_in_expr (TYPE_SIZE_UNIT (gnu_type),
- TREE_PURPOSE (gnu_temp),
- TREE_VALUE (gnu_temp));
-
- if (CONTAINS_PLACEHOLDER_P (TYPE_ADA_SIZE (gnu_type)))
- for (gnu_temp = gnu_subst_list;
- gnu_temp; gnu_temp = TREE_CHAIN (gnu_temp))
- SET_TYPE_ADA_SIZE
- (gnu_type, substitute_in_expr (TYPE_ADA_SIZE (gnu_type),
- TREE_PURPOSE (gnu_temp),
- TREE_VALUE (gnu_temp)));
+ gnu_field_list = nreverse (gnu_field_list);
+ finish_record_type (gnu_type, gnu_field_list, 2, true);
- /* Reapply variable_size since we have changed the sizes. */
+ /* Finalize size and mode. */
TYPE_SIZE (gnu_type) = variable_size (TYPE_SIZE (gnu_type));
TYPE_SIZE_UNIT (gnu_type)
= variable_size (TYPE_SIZE_UNIT (gnu_type));
- /* Recompute the mode of this record type now that we know its
- actual size. */
compute_record_mode (gnu_type);
/* Fill in locations of fields. */