aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEric Botcazou <ebotcazou@adacore.com>2008-11-06 11:28:07 +0000
committerEric Botcazou <ebotcazou@gcc.gnu.org>2008-11-06 11:28:07 +0000
commit8b659f794a1613b10333fa6826c0ed41d802ce8b (patch)
tree63dcedaa432f0032ebe66fee514f25ac1874fba4
parent8a554c70d58393606b9a96dac6a12ae2b8de73e2 (diff)
downloadgcc-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/ChangeLog7
-rw-r--r--gcc/ada/gcc-interface/trans.c23
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;