diff options
author | Eric Botcazou <ebotcazou@gcc.gnu.org> | 2020-05-25 10:04:10 +0200 |
---|---|---|
committer | Eric Botcazou <ebotcazou@gcc.gnu.org> | 2020-05-25 10:07:04 +0200 |
commit | 15c55b96a721721e944f8617ae59bdcb273477e6 (patch) | |
tree | 40aa466d1503dd1bba7908b0160e7acd51950a3f /gcc/ada/gcc-interface/decl.c | |
parent | deea3defc9802fcf3f8ea4e45f29dd1ad8fb3cef (diff) | |
download | gcc-15c55b96a721721e944f8617ae59bdcb273477e6.zip gcc-15c55b96a721721e944f8617ae59bdcb273477e6.tar.gz gcc-15c55b96a721721e944f8617ae59bdcb273477e6.tar.bz2 |
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.
Diffstat (limited to 'gcc/ada/gcc-interface/decl.c')
-rw-r--r-- | gcc/ada/gcc-interface/decl.c | 21 |
1 files changed, 18 insertions, 3 deletions
diff --git a/gcc/ada/gcc-interface/decl.c b/gcc/ada/gcc-interface/decl.c index a36b129..ab6e79c 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 |