diff options
author | Eric Botcazou <ebotcazou@adacore.com> | 2008-11-06 11:28:07 +0000 |
---|---|---|
committer | Eric Botcazou <ebotcazou@gcc.gnu.org> | 2008-11-06 11:28:07 +0000 |
commit | 8b659f794a1613b10333fa6826c0ed41d802ce8b (patch) | |
tree | 63dcedaa432f0032ebe66fee514f25ac1874fba4 | |
parent | 8a554c70d58393606b9a96dac6a12ae2b8de73e2 (diff) | |
download | gcc-8b659f794a1613b10333fa6826c0ed41d802ce8b.zip gcc-8b659f794a1613b10333fa6826c0ed41d802ce8b.tar.gz gcc-8b659f794a1613b10333fa6826c0ed41d802ce8b.tar.bz2 |
re PR ada/19419 (Overlapping memcpy with array slices)
PR ada/19419
* gcc-interface/trans.c (gnat_to_gnu) <N_Assignment_Statement>:
Generate a call to memmove for an assignment between overlapping
array slices.
From-SVN: r141637
-rw-r--r-- | gcc/ada/ChangeLog | 7 | ||||
-rw-r--r-- | gcc/ada/gcc-interface/trans.c | 23 |
2 files changed, 29 insertions, 1 deletions
diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index ba94a5e..6730093 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,10 @@ +2008-11-06 Eric Botcazou <ebotcazou@adacore.com> + + PR ada/19419 + * gcc-interface/trans.c (gnat_to_gnu) <N_Assignment_Statement>: + Generate a call to memmove for an assignment between overlapping + array slices. + 2008-11-02 Andreas Krebbel <Andreas.Krebbel@de.ibm.com> PR target/37977 diff --git a/gcc/ada/gcc-interface/trans.c b/gcc/ada/gcc-interface/trans.c index 6ade568..9f050bd 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; |