Commit 8623afc4 by Eric Botcazou Committed by Eric Botcazou

decl.c (gnat_to_gnu_entity): If the type requires strict alignment, then set the…

decl.c (gnat_to_gnu_entity): If the type requires strict alignment, then set the RM size to the type size.

	* gcc-interface/decl.c (gnat_to_gnu_entity) <E_Record_Type>: If the
	type requires strict alignment, then set the RM size to the type size.
	Rework handling of alignment and sizes of tagged types in ASIS mode.
	(validate_size): Rename local variable and remove special handling for
	strict-alignment types.
	* gcc-interface/utils.c (finish_record_type): Constify local variables
	and use properly typed constants.

From-SVN: r272820
parent 26cf7899
2019-06-29 Eric Botcazou <ebotcazou@adacore.com> 2019-06-29 Eric Botcazou <ebotcazou@adacore.com>
* gcc-interface/decl.c (gnat_to_gnu_entity) <E_Record_Type>: If the
type requires strict alignment, then set the RM size to the type size.
Rework handling of alignment and sizes of tagged types in ASIS mode.
(validate_size): Rename local variable and remove special handling for
strict-alignment types.
* gcc-interface/utils.c (finish_record_type): Constify local variables
and use properly typed constants.
2019-06-29 Eric Botcazou <ebotcazou@adacore.com>
* gcc-interface/decl.c (gnat_to_gnu_field): Rework error messages for * gcc-interface/decl.c (gnat_to_gnu_field): Rework error messages for
fields requiring strict alignment, add explicit test on Storage_Unit fields requiring strict alignment, add explicit test on Storage_Unit
for position and size, and mention type alignment for position. for position and size, and mention type alignment for position.
......
...@@ -3004,9 +3004,9 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, bool definition) ...@@ -3004,9 +3004,9 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, bool definition)
{ {
SET_TYPE_ALIGN (gnu_type, 0); SET_TYPE_ALIGN (gnu_type, 0);
/* If a type needs strict alignment, the minimum size will be the /* If a type needs strict alignment, then its type size will also
type size instead of the RM size (see validate_size). Cap the be the RM size (see below). Cap the alignment if needed, lest
alignment lest it causes this type size to become too large. */ it may cause this type size to become too large. */
if (Strict_Alignment (gnat_entity) && Known_RM_Size (gnat_entity)) if (Strict_Alignment (gnat_entity) && Known_RM_Size (gnat_entity))
{ {
unsigned int max_size = UI_To_Int (RM_Size (gnat_entity)); unsigned int max_size = UI_To_Int (RM_Size (gnat_entity));
...@@ -3283,6 +3283,12 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, bool definition) ...@@ -3283,6 +3283,12 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, bool definition)
compute_record_mode (gnu_type); compute_record_mode (gnu_type);
} }
/* If the type needs strict alignment, then no object of the type
may have a size smaller than the natural size, which means that
the RM size of the type is equal to the type size. */
if (Strict_Alignment (gnat_entity))
SET_TYPE_ADA_SIZE (gnu_type, TYPE_SIZE (gnu_type));
/* If there are entities in the chain corresponding to components /* If there are entities in the chain corresponding to components
that we did not elaborate, ensure we elaborate their types if that we did not elaborate, ensure we elaborate their types if
they are Itypes. */ they are Itypes. */
...@@ -4187,7 +4193,10 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, bool definition) ...@@ -4187,7 +4193,10 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, bool definition)
already defined so we cannot pass true for IN_PLACE here. */ already defined so we cannot pass true for IN_PLACE here. */
process_attributes (&gnu_type, &attr_list, false, gnat_entity); process_attributes (&gnu_type, &attr_list, false, gnat_entity);
/* ??? Don't set the size for a String_Literal since it is either /* See if a size was specified, by means of either an Object_Size or
a regular Size clause, and validate it if so.
??? Don't set the size for a String_Literal since it is either
confirming or we don't handle it properly (if the low bound is confirming or we don't handle it properly (if the low bound is
non-constant). */ non-constant). */
if (!gnu_size && kind != E_String_Literal_Subtype) if (!gnu_size && kind != E_String_Literal_Subtype)
...@@ -4309,49 +4318,44 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, bool definition) ...@@ -4309,49 +4318,44 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, bool definition)
/* If we are just annotating types and the type is tagged, the tag /* If we are just annotating types and the type is tagged, the tag
and the parent components are not generated by the front-end so and the parent components are not generated by the front-end so
alignment and sizes must be adjusted if there is no rep clause. */ alignment and sizes must be adjusted. */
if (type_annotate_only if (type_annotate_only && Is_Tagged_Type (gnat_entity))
&& Is_Tagged_Type (gnat_entity)
&& Unknown_RM_Size (gnat_entity)
&& !VOID_TYPE_P (gnu_type)
&& (!TYPE_FIELDS (gnu_type)
|| integer_zerop (bit_position (TYPE_FIELDS (gnu_type)))))
{ {
tree offset; const bool derived_p = Is_Derived_Type (gnat_entity);
const Entity_Id gnat_parent
if (Is_Derived_Type (gnat_entity)) = derived_p ? Etype (Base_Type (gnat_entity)) : Empty;
{ const unsigned int inherited_align
Entity_Id gnat_parent = Etype (Base_Type (gnat_entity)); = derived_p
offset = UI_To_gnu (Esize (gnat_parent), bitsizetype); ? UI_To_Int (Alignment (gnat_parent)) * BITS_PER_UNIT
Set_Alignment (gnat_entity, Alignment (gnat_parent)); : POINTER_SIZE;
} const unsigned int align
else = MAX (TYPE_ALIGN (gnu_type), inherited_align);
Set_Alignment (gnat_entity, UI_From_Int (align / BITS_PER_UNIT));
/* If there is neither size clause nor representation clause, the
sizes need to be adjusted. */
if (Unknown_RM_Size (gnat_entity)
&& !VOID_TYPE_P (gnu_type)
&& (!TYPE_FIELDS (gnu_type)
|| integer_zerop (bit_position (TYPE_FIELDS (gnu_type)))))
{ {
unsigned int align tree offset
= MAX (TYPE_ALIGN (gnu_type), POINTER_SIZE) / BITS_PER_UNIT; = derived_p
offset = bitsize_int (POINTER_SIZE); ? UI_To_gnu (Esize (gnat_parent), bitsizetype)
Set_Alignment (gnat_entity, UI_From_Int (align)); : bitsize_int (POINTER_SIZE);
if (TYPE_FIELDS (gnu_type))
offset
= round_up (offset, DECL_ALIGN (TYPE_FIELDS (gnu_type)));
gnu_size = size_binop (PLUS_EXPR, gnu_size, offset);
} }
if (TYPE_FIELDS (gnu_type)) gnu_size = round_up (gnu_size, align);
offset
= round_up (offset, DECL_ALIGN (TYPE_FIELDS (gnu_type)));
gnu_size = size_binop (PLUS_EXPR, gnu_size, offset);
gnu_size = round_up (gnu_size, POINTER_SIZE);
Uint uint_size = annotate_value (gnu_size);
Set_RM_Size (gnat_entity, uint_size);
Set_Esize (gnat_entity, uint_size);
}
/* If there is a rep clause, only adjust alignment and Esize. */
else if (type_annotate_only && Is_Tagged_Type (gnat_entity))
{
unsigned int align
= MAX (TYPE_ALIGN (gnu_type), POINTER_SIZE) / BITS_PER_UNIT;
Set_Alignment (gnat_entity, UI_From_Int (align));
gnu_size = round_up (gnu_size, POINTER_SIZE);
Set_Esize (gnat_entity, annotate_value (gnu_size)); Set_Esize (gnat_entity, annotate_value (gnu_size));
/* Tagged types are Strict_Alignment so RM_Size = Esize. */
if (Unknown_RM_Size (gnat_entity))
Set_RM_Size (gnat_entity, Esize (gnat_entity));
} }
/* Otherwise no adjustment is needed. */ /* Otherwise no adjustment is needed. */
...@@ -8732,7 +8736,7 @@ validate_size (Uint uint_size, tree gnu_type, Entity_Id gnat_object, ...@@ -8732,7 +8736,7 @@ validate_size (Uint uint_size, tree gnu_type, Entity_Id gnat_object,
enum tree_code kind, bool component_p, bool zero_ok) enum tree_code kind, bool component_p, bool zero_ok)
{ {
Node_Id gnat_error_node; Node_Id gnat_error_node;
tree type_size, size; tree old_size, size;
/* Return 0 if no size was specified. */ /* Return 0 if no size was specified. */
if (uint_size == No_Uint) if (uint_size == No_Uint)
...@@ -8797,17 +8801,11 @@ validate_size (Uint uint_size, tree gnu_type, Entity_Id gnat_object, ...@@ -8797,17 +8801,11 @@ validate_size (Uint uint_size, tree gnu_type, Entity_Id gnat_object,
&& TYPE_CONTAINS_TEMPLATE_P (gnu_type)) && TYPE_CONTAINS_TEMPLATE_P (gnu_type))
size = size_binop (PLUS_EXPR, DECL_SIZE (TYPE_FIELDS (gnu_type)), size); size = size_binop (PLUS_EXPR, DECL_SIZE (TYPE_FIELDS (gnu_type)), size);
if (kind == VAR_DECL old_size = (kind == VAR_DECL ? TYPE_SIZE (gnu_type) : rm_size (gnu_type));
/* If a type needs strict alignment, a component of this type in
a packed record cannot be packed and thus uses the type size. */
|| (kind == TYPE_DECL && Strict_Alignment (gnat_object)))
type_size = TYPE_SIZE (gnu_type);
else
type_size = rm_size (gnu_type);
/* Modify the size of a discriminated type to be the maximum size. */ /* If the old size is self-referential, get the maximum size. */
if (type_size && CONTAINS_PLACEHOLDER_P (type_size)) if (CONTAINS_PLACEHOLDER_P (old_size))
type_size = max_size (type_size, true); old_size = max_size (old_size, true);
/* If this is an access type or a fat pointer, the minimum size is that given /* If this is an access type or a fat pointer, the minimum size is that given
by the smallest integral mode that's valid for pointers. */ by the smallest integral mode that's valid for pointers. */
...@@ -8816,23 +8814,23 @@ validate_size (Uint uint_size, tree gnu_type, Entity_Id gnat_object, ...@@ -8816,23 +8814,23 @@ validate_size (Uint uint_size, tree gnu_type, Entity_Id gnat_object,
scalar_int_mode p_mode = NARROWEST_INT_MODE; scalar_int_mode p_mode = NARROWEST_INT_MODE;
while (!targetm.valid_pointer_mode (p_mode)) while (!targetm.valid_pointer_mode (p_mode))
p_mode = GET_MODE_WIDER_MODE (p_mode).require (); p_mode = GET_MODE_WIDER_MODE (p_mode).require ();
type_size = bitsize_int (GET_MODE_BITSIZE (p_mode)); old_size = bitsize_int (GET_MODE_BITSIZE (p_mode));
} }
/* Issue an error either if the default size of the object isn't a constant /* Issue an error either if the default size of the object isn't a constant
or if the new size is smaller than it. */ or if the new size is smaller than it. */
if (TREE_CODE (type_size) != INTEGER_CST if (TREE_CODE (old_size) != INTEGER_CST
|| TREE_OVERFLOW (type_size) || TREE_OVERFLOW (old_size)
|| tree_int_cst_lt (size, type_size)) || tree_int_cst_lt (size, old_size))
{ {
if (component_p) if (component_p)
post_error_ne_tree post_error_ne_tree
("component size for& too small{, minimum allowed is ^}", ("component size for& too small{, minimum allowed is ^}",
gnat_error_node, gnat_object, type_size); gnat_error_node, gnat_object, old_size);
else else
post_error_ne_tree post_error_ne_tree
("size for& too small{, minimum allowed is ^}", ("size for& too small{, minimum allowed is ^}",
gnat_error_node, gnat_object, type_size); gnat_error_node, gnat_object, old_size);
return NULL_TREE; return NULL_TREE;
} }
......
...@@ -1859,13 +1859,18 @@ void ...@@ -1859,13 +1859,18 @@ void
finish_record_type (tree record_type, tree field_list, int rep_level, finish_record_type (tree record_type, tree field_list, int rep_level,
bool debug_info_p) bool debug_info_p)
{ {
enum tree_code code = TREE_CODE (record_type); const enum tree_code orig_code = TREE_CODE (record_type);
const bool had_size = TYPE_SIZE (record_type) != NULL_TREE;
const bool had_size_unit = TYPE_SIZE_UNIT (record_type) != NULL_TREE;
const bool had_align = TYPE_ALIGN (record_type) > 0;
/* For all-repped records with a size specified, lay the QUAL_UNION_TYPE
out just like a UNION_TYPE, since the size will be fixed. */
const enum tree_code code
= (orig_code == QUAL_UNION_TYPE && rep_level > 0 && had_size
? UNION_TYPE : orig_code);
tree name = TYPE_IDENTIFIER (record_type); tree name = TYPE_IDENTIFIER (record_type);
tree ada_size = bitsize_zero_node; tree ada_size = bitsize_zero_node;
tree size = bitsize_zero_node; tree size = bitsize_zero_node;
bool had_size = TYPE_SIZE (record_type) != 0;
bool had_size_unit = TYPE_SIZE_UNIT (record_type) != 0;
bool had_align = TYPE_ALIGN (record_type) != 0;
tree field; tree field;
TYPE_FIELDS (record_type) = field_list; TYPE_FIELDS (record_type) = field_list;
...@@ -1878,26 +1883,21 @@ finish_record_type (tree record_type, tree field_list, int rep_level, ...@@ -1878,26 +1883,21 @@ finish_record_type (tree record_type, tree field_list, int rep_level,
that just means some initializations; otherwise, layout the record. */ that just means some initializations; otherwise, layout the record. */
if (rep_level > 0) if (rep_level > 0)
{ {
SET_TYPE_ALIGN (record_type, MAX (BITS_PER_UNIT, if (TYPE_ALIGN (record_type) < BITS_PER_UNIT)
TYPE_ALIGN (record_type))); SET_TYPE_ALIGN (record_type, BITS_PER_UNIT);
if (!had_size_unit)
TYPE_SIZE_UNIT (record_type) = size_zero_node;
if (!had_size) if (!had_size)
TYPE_SIZE (record_type) = bitsize_zero_node; TYPE_SIZE (record_type) = bitsize_zero_node;
/* For all-repped records with a size specified, lay the QUAL_UNION_TYPE if (!had_size_unit)
out just like a UNION_TYPE, since the size will be fixed. */ TYPE_SIZE_UNIT (record_type) = size_zero_node;
else if (code == QUAL_UNION_TYPE)
code = UNION_TYPE;
} }
else else
{ {
/* Ensure there isn't a size already set. There can be in an error /* Ensure there isn't a size already set. There can be in an error
case where there is a rep clause but all fields have errors and case where there is a rep clause but all fields have errors and
no longer have a position. */ no longer have a position. */
TYPE_SIZE (record_type) = 0; TYPE_SIZE (record_type) = NULL_TREE;
/* Ensure we use the traditional GCC layout for bitfields when we need /* Ensure we use the traditional GCC layout for bitfields when we need
to pack the record type or have a representation clause. The other to pack the record type or have a representation clause. The other
......
2019-06-29 Eric Botcazou <ebotcazou@adacore.com> 2019-06-29 Eric Botcazou <ebotcazou@adacore.com>
* gnat.dg/specs/size_clause3.ads: Adjust error message.
2019-06-29 Eric Botcazou <ebotcazou@adacore.com>
* gnat.dg/specs/atomic2.ads: Adjust error message. * gnat.dg/specs/atomic2.ads: Adjust error message.
* gnat.dg/specs/clause_on_volatile.ads: Likewise. * gnat.dg/specs/clause_on_volatile.ads: Likewise.
* gnat.dg/specs/size_clause3.ads: Likewise. * gnat.dg/specs/size_clause3.ads: Likewise.
......
...@@ -14,7 +14,7 @@ package Size_Clause3 is ...@@ -14,7 +14,7 @@ package Size_Clause3 is
rr : R1; -- size must be 40 rr : R1; -- size must be 40
end record; end record;
for S1 use record for S1 use record
rr at 0 range 0 .. 39; -- { dg-error "size for .rr. with aliased or tagged" } rr at 0 range 0 .. 39; -- { dg-error "size for .rr. too small" }
end record; end record;
-- The record is explicitly given alignment 1 so its real type is 40. -- The record is explicitly given alignment 1 so its real type is 40.
...@@ -44,7 +44,7 @@ package Size_Clause3 is ...@@ -44,7 +44,7 @@ package Size_Clause3 is
rr : R3; -- size must be 40 rr : R3; -- size must be 40
end record; end record;
for S3 use record for S3 use record
rr at 0 range 0 .. 39; -- { dg-error "size for .rr. with aliased or tagged" } rr at 0 range 0 .. 39; -- { dg-error "size for .rr. too small" }
end record; end record;
end Size_Clause3; end Size_Clause3;
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment