[COMMITTED] ada: Fix issue with indefinite vector of overaligned unconstrained array

Message ID 20231121100100.1965337-1-poulhies@adacore.com
State Committed
Commit 4d011701c074cac9bab7edfcf07c1868f0472177
Headers
Series [COMMITTED] ada: Fix issue with indefinite vector of overaligned unconstrained array |

Checks

Context Check Description
linaro-tcwg-bot/tcwg_gcc_build--master-arm warning Patch is already merged
linaro-tcwg-bot/tcwg_gcc_build--master-aarch64 warning Patch is already merged

Commit Message

Marc Poulhiès Nov. 21, 2023, 10:01 a.m. UTC
  From: Eric Botcazou <ebotcazou@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(-)
  

Patch

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