aboutsummaryrefslogtreecommitdiff
path: root/gcc/ada/gcc-interface
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/ada/gcc-interface')
-rw-r--r--gcc/ada/gcc-interface/utils.cc17
-rw-r--r--gcc/ada/gcc-interface/utils2.cc11
2 files changed, 22 insertions, 6 deletions
diff --git a/gcc/ada/gcc-interface/utils.cc b/gcc/ada/gcc-interface/utils.cc
index 1448716..9212827 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 99e5927..58418ea 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;