From: Eric Botcazou Date: Mon, 25 May 2020 08:04:10 +0000 (+0200) Subject: Fix incorrect handling of Component_Size X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=15c55b96a721721e944f8617ae59bdcb273477e6;p=gcc.git 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. --- diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index a900f53efe0..e4892ee5229 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,8 @@ +2020-05-25 Eric Botcazou + + * 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 * gcc-interface/decl.c (gnat_to_gnu_entity) : 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 diff --git a/gcc/ada/gcc-interface/decl.c b/gcc/ada/gcc-interface/decl.c index a36b1298bed..ab6e79ce3c1 100644 --- a/gcc/ada/gcc-interface/decl.c +++ b/gcc/ada/gcc-interface/decl.c @@ -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 diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 3bbe2e3d2b3..6e839c1262e 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2020-05-25 Eric Botcazou + + * gnat.dg/array40.adb: New test. + * gnat.dg/array40_pkg.ads: New helper. + 2020-05-25 Eric Botcazou * gnat.dg/array39.adb: New test. diff --git a/gcc/testsuite/gnat.dg/array40.adb b/gcc/testsuite/gnat.dg/array40.adb new file mode 100644 index 00000000000..227288d368f --- /dev/null +++ b/gcc/testsuite/gnat.dg/array40.adb @@ -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; diff --git a/gcc/testsuite/gnat.dg/array40_pkg.ads b/gcc/testsuite/gnat.dg/array40_pkg.ads new file mode 100644 index 00000000000..a3cec8b43f4 --- /dev/null +++ b/gcc/testsuite/gnat.dg/array40_pkg.ads @@ -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;