For technical reasons, the recently reimplemented finalization machinery for 
controlled types requires arrays of controlled types to be allocated with 
their bounds, including in the case where their nominal subtype is 
constrained.  However, in this case, the type of 'Access for the arrays is 
pointer-to-constrained-array and, therefore, its value must designate the 
array itself and not the bounds.

Tested on x86-64/Linux, applied on the mainline (branches are not affected).


2025-04-07  Eric Botcazou  <ebotca...@adacore.com>

ada/
        * gcc-interface/utils.cc (convert) <POINTER_TYPE>: Use fold_convert
        to convert between thin pointers.  If the source is a thin pointer
        with zero offset from the base and the target is a pointer to its
        array, displace the pointer after converting it.
        * gcc-interface/utils2.cc (build_unary_op) <ATTR_ADDR_EXPR>: Use
        fold_convert to convert the address before displacing it.

-- 
Eric Botcazou
diff --git a/gcc/ada/gcc-interface/utils.cc b/gcc/ada/gcc-interface/utils.cc
index 1448716acc5..9212827aecf 100644
--- a/gcc/ada/gcc-interface/utils.cc
+++ b/gcc/ada/gcc-interface/utils.cc
@@ -5259,7 +5259,7 @@ convert (tree type, tree expr)
 	      : size_zero_node;
 	  tree byte_diff = size_diffop (type_pos, etype_pos);
 
-	  expr = build1 (NOP_EXPR, type, expr);
+	  expr = fold_convert (type, expr);
 	  if (integer_zerop (byte_diff))
 	    return expr;
 
@@ -5267,6 +5267,21 @@ convert (tree type, tree expr)
 				  fold_convert (sizetype, byte_diff));
 	}
 
+      /* If converting from a thin pointer with zero offset from the base to
+	 a pointer to the array, add the offset of the array field.  */
+      if (TYPE_IS_THIN_POINTER_P (etype)
+	  && !TYPE_UNCONSTRAINED_ARRAY (TREE_TYPE (etype)))
+	{
+	  tree arr_field = DECL_CHAIN (TYPE_FIELDS (TREE_TYPE (etype)));
+
+	  if (TREE_TYPE (type) == TREE_TYPE (arr_field))
+	    {
+	      expr = fold_convert (type, expr);
+	      return build_binary_op (POINTER_PLUS_EXPR, type, expr,
+				      byte_position (arr_field));
+	    }
+	}
+
       /* If converting fat pointer to normal or thin pointer, get the pointer
 	 to the array and then convert it.  */
       if (TYPE_IS_FAT_POINTER_P (etype))
diff --git a/gcc/ada/gcc-interface/utils2.cc b/gcc/ada/gcc-interface/utils2.cc
index 99e592781f5..58418ea7236 100644
--- a/gcc/ada/gcc-interface/utils2.cc
+++ b/gcc/ada/gcc-interface/utils2.cc
@@ -1628,11 +1628,12 @@ build_unary_op (enum tree_code op_code, tree result_type, tree operand)
 		= size_binop (PLUS_EXPR, offset,
 			      size_int (bits_to_bytes_round_down (bitpos)));
 
-	      /* Take the address of INNER, convert it to a pointer to our type
-		 and add the offset.  */
-	      inner = build_unary_op (ADDR_EXPR,
-				      build_pointer_type (TREE_TYPE (operand)),
-				      inner);
+	      /* Take the address of INNER, formally convert it to a pointer
+		 to the operand type, and finally add the offset.  */
+	      inner = build_unary_op (ADDR_EXPR, NULL_TREE, inner);
+	      inner
+		= fold_convert (build_pointer_type (TREE_TYPE (operand)),
+				inner);
 	      result = build_binary_op (POINTER_PLUS_EXPR, TREE_TYPE (inner),
 					inner, offset);
 	      break;

Reply via email to