From: Eric Botcazou Date: Thu, 6 Nov 2008 11:28:07 +0000 (+0000) Subject: re PR ada/19419 (Overlapping memcpy with array slices) X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=8b659f794a1613b10333fa6826c0ed41d802ce8b;p=gcc.git re PR ada/19419 (Overlapping memcpy with array slices) PR ada/19419 * gcc-interface/trans.c (gnat_to_gnu) : Generate a call to memmove for an assignment between overlapping array slices. From-SVN: r141637 --- diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index ba94a5e9a7f..67300939fe0 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,10 @@ +2008-11-06 Eric Botcazou + + PR ada/19419 + * gcc-interface/trans.c (gnat_to_gnu) : + Generate a call to memmove for an assignment between overlapping + array slices. + 2008-11-02 Andreas Krebbel PR target/37977 diff --git a/gcc/ada/gcc-interface/trans.c b/gcc/ada/gcc-interface/trans.c index 6ade56869d9..9f050bdc5d1 100644 --- a/gcc/ada/gcc-interface/trans.c +++ b/gcc/ada/gcc-interface/trans.c @@ -4159,12 +4159,33 @@ gnat_to_gnu (Node_Id gnat_node) gnu_rhs = maybe_unconstrained_array (gnat_to_gnu (Expression (gnat_node))); - /* If range check is needed, emit code to generate it */ + /* If range check is needed, emit code to generate it. */ if (Do_Range_Check (Expression (gnat_node))) gnu_rhs = emit_range_check (gnu_rhs, Etype (Name (gnat_node))); gnu_result = build_binary_op (MODIFY_EXPR, NULL_TREE, gnu_lhs, gnu_rhs); + + /* If the type being assigned is an array type and the two sides + are not completely disjoint, play safe and use memmove. */ + if (TREE_CODE (gnu_result) == MODIFY_EXPR + && Is_Array_Type (Etype (Name (gnat_node))) + && !(Forwards_OK (gnat_node) && Backwards_OK (gnat_node))) + { + tree to, from, size, to_ptr, from_ptr, t; + + to = TREE_OPERAND (gnu_result, 0); + from = TREE_OPERAND (gnu_result, 1); + + size = TYPE_SIZE_UNIT (TREE_TYPE (from)); + size = SUBSTITUTE_PLACEHOLDER_IN_EXPR (size, from); + + to_ptr = build_fold_addr_expr (to); + from_ptr = build_fold_addr_expr (from); + + t = implicit_built_in_decls[BUILT_IN_MEMMOVE]; + gnu_result = build_call_expr (t, 3, to_ptr, from_ptr, size); + } } break;