]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
Ada: Fix wrong 'Access to aliased constrained array of controlled type
authorEric Botcazou <ebotcazou@adacore.com>
Mon, 7 Apr 2025 08:33:52 +0000 (10:33 +0200)
committerEric Botcazou <ebotcazou@adacore.com>
Mon, 7 Apr 2025 08:35:38 +0000 (10:35 +0200)
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.

gcc/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.

gcc/ada/gcc-interface/utils.cc
gcc/ada/gcc-interface/utils2.cc

index 1448716acc5afaea83dabd58632f94fac9aa068f..9212827aecfef4f8e513e74c1a1bbd85e8fc2c80 100644 (file)
@@ -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))
index 99e592781f5eeadc4ab160f49531cd20027391b8..58418ea7236bfc04a2036286d2ed378cefcb5ca3 100644 (file)
@@ -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;