Fix incorrect handling of Component_Size

The compiler can mishandle a Component_Size clause on an array type
specifying a size multiple of the storage unit, when this size is
not a multiple of the alignment of the component type.

gcc/ada/ChangeLog
	* gcc-interface/decl.c (gnat_to_gnu_component_type): Cap alignment
	of the component type according to the component size.

gcc/testsuite/ChangeLog
	* gnat.dg/array40.adb: New test.
	* gnat.dg/array40_pkg.ads: New helper.
This commit is contained in:
Eric Botcazou 2020-05-25 10:04:10 +02:00
parent deea3defc9
commit 15c55b96a7
5 changed files with 62 additions and 3 deletions

View File

@ -1,3 +1,8 @@
2020-05-25 Eric Botcazou <ebotcazou@adacore.com>
* gcc-interface/decl.c (gnat_to_gnu_component_type): Cap the alignment
of the component type according to the component size.
2020-05-25 Eric Botcazou <ebotcazou@adacore.com>
* gcc-interface/decl.c (gnat_to_gnu_entity) <E_Array_Type>: Add a
@ -11,6 +16,7 @@
fat pointer types and tidy up accordingly.
* gcc-interface/utils.c (build_unc_object_type): Do not set the
context on the template type.
(gnat_pushdecl): Mark the canonical fat pointer types as artificial.
2020-05-25 Eric Botcazou <ebotcazou@adacore.com>

View File

@ -5153,7 +5153,7 @@ gnat_to_gnu_component_type (Entity_Id gnat_array, bool definition,
unsigned int max_align;
/* If an alignment is specified, use it as a cap on the component type
so that it can be honored for the whole type. But ignore it for the
so that it can be honored for the whole type, but ignore it for the
original type of packed array types. */
if (No (Packed_Array_Impl_Type (gnat_array))
&& Known_Alignment (gnat_array))
@ -5200,6 +5200,7 @@ gnat_to_gnu_component_type (Entity_Id gnat_array, bool definition,
if (gnu_comp_size && !is_bit_packed)
{
tree orig_type = gnu_type;
unsigned int gnu_comp_align;
gnu_type = make_type_from_size (gnu_type, gnu_comp_size, false);
if (max_align > 0 && TYPE_ALIGN (gnu_type) > max_align)
@ -5207,8 +5208,22 @@ gnat_to_gnu_component_type (Entity_Id gnat_array, bool definition,
else
orig_type = gnu_type;
gnu_type = maybe_pad_type (gnu_type, gnu_comp_size, 0, gnat_array,
true, definition, true);
/* We need to make sure that the size is a multiple of the alignment.
But we do not misalign the component type because of the alignment
of the array type here; this either must have been done earlier in
the packed case or should be rejected in the non-packed case. */
if (TREE_CODE (gnu_comp_size) == INTEGER_CST)
{
const unsigned HOST_WIDE_INT int_size = tree_to_uhwi (gnu_comp_size);
gnu_comp_align = int_size & -int_size;
if (gnu_comp_align > TYPE_ALIGN (gnu_type))
gnu_comp_align = 0;
}
else
gnu_comp_align = 0;
gnu_type = maybe_pad_type (gnu_type, gnu_comp_size, gnu_comp_align,
gnat_array, true, definition, true);
/* If a padding record was made, declare it now since it will never be
declared otherwise. This is necessary to ensure that its subtrees

View File

@ -1,3 +1,8 @@
2020-05-25 Eric Botcazou <ebotcazou@adacore.com>
* gnat.dg/array40.adb: New test.
* gnat.dg/array40_pkg.ads: New helper.
2020-05-25 Eric Botcazou <ebotcazou@adacore.com>
* gnat.dg/array39.adb: New test.

View File

@ -0,0 +1,21 @@
-- { dg-do run }
-- { dg-options "-gnatws" }
with System.Storage_Elements;
with Array40_Pkg; use Array40_Pkg;
procedure Array40 is
use System;
use System.Storage_Elements;
begin
if A(1)'Size /= 40 then
raise Program_Error;
end if;
if (A(2)'Address - A(1)'Address) * System.Storage_Unit /= 40 then
raise Program_Error;
end if;
end;

View File

@ -0,0 +1,12 @@
package Array40_Pkg is
type Rec is record
I : Integer;
end record;
type Arr is array (1 .. 4) of Rec;
for Arr'Component_Size use 40;
A : Arr;
end Array40_Pkg;