From: Eric Botcazou <ebotca...@adacore.com>

The problem is that the aligning machinery is not consistently triggered,
depending on whether a constrained view or the nominal unconstrained view
of the element type is used to perform the allocations and deallocations.

gcc/ada/

        * gcc-interface/decl.cc (gnat_to_gnu_entity) <E_Array_Subtype>: Put
        the alignment directly on the type in the constrained case too.
        * gcc-interface/utils.cc (maybe_pad_type): For an array type, take
        the alignment of the element type as the original alignment.

Tested on x86_64-pc-linux-gnu, committed on master.

---
 gcc/ada/gcc-interface/decl.cc  | 12 ++++++++++++
 gcc/ada/gcc-interface/utils.cc | 19 ++++++++++++++++---
 2 files changed, 28 insertions(+), 3 deletions(-)

diff --git a/gcc/ada/gcc-interface/decl.cc b/gcc/ada/gcc-interface/decl.cc
index 9c7f6840e21..c446b146179 100644
--- a/gcc/ada/gcc-interface/decl.cc
+++ b/gcc/ada/gcc-interface/decl.cc
@@ -3010,6 +3010,18 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree 
gnu_expr, bool definition)
                    TREE_TYPE (TYPE_FIELDS (gnu_type)) = gnu_inner;
                }
            }
+
+         /* Otherwise, if an alignment is specified, use it if valid and, if
+            the alignment was requested with an explicit clause, state so.  */
+         else if (Known_Alignment (gnat_entity))
+           {
+             SET_TYPE_ALIGN (gnu_type,
+                             validate_alignment (Alignment (gnat_entity),
+                                                 gnat_entity,
+                                                 TYPE_ALIGN (gnu_type)));
+             if (Present (Alignment_Clause (gnat_entity)))
+               TYPE_USER_ALIGN (gnu_type) = 1;
+           }
        }
       break;
 
diff --git a/gcc/ada/gcc-interface/utils.cc b/gcc/ada/gcc-interface/utils.cc
index 8b2c7f99ef3..e7b5c7783b1 100644
--- a/gcc/ada/gcc-interface/utils.cc
+++ b/gcc/ada/gcc-interface/utils.cc
@@ -1485,7 +1485,14 @@ canonicalize_pad_type (tree type)
    IS_COMPONENT_TYPE is true if this is being done for the component type of
    an array.  DEFINITION is true if this type is being defined.  SET_RM_SIZE
    is true if the RM size of the resulting type is to be set to SIZE too; in
-   this case, the padded type is canonicalized before being returned.  */
+   this case, the padded type is canonicalized before being returned.
+
+   Note that, if TYPE is an array, then we pad it even if it has already got
+   an alignment of ALIGN, provided that it's larger than the alignment of the
+   element type.  This ensures that the size of the type is a multiple of its
+   alignment as required by the GCC type system, and alleviates the oddity of
+   the larger alignment, which is used to implement alignment clauses present
+   on unconstrained array types.  */
 
 tree
 maybe_pad_type (tree type, tree size, unsigned int align,
@@ -1493,7 +1500,10 @@ maybe_pad_type (tree type, tree size, unsigned int align,
                bool definition, bool set_rm_size)
 {
   tree orig_size = TYPE_SIZE (type);
-  unsigned int orig_align = TYPE_ALIGN (type);
+  unsigned int orig_align
+    = TREE_CODE (type) == ARRAY_TYPE
+      ? TYPE_ALIGN (TREE_TYPE (type))
+      : TYPE_ALIGN (type);
   tree record, field;
 
   /* If TYPE is a padded type, see if it agrees with any size and alignment
@@ -1515,7 +1525,10 @@ maybe_pad_type (tree type, tree size, unsigned int align,
 
       type = TREE_TYPE (TYPE_FIELDS (type));
       orig_size = TYPE_SIZE (type);
-      orig_align = TYPE_ALIGN (type);
+      orig_align
+       = TREE_CODE (type) == ARRAY_TYPE
+         ? TYPE_ALIGN (TREE_TYPE (type))
+         : TYPE_ALIGN (type);
     }
 
   /* If the size is either not being changed or is being made smaller (which
-- 
2.42.0

Reply via email to