re PR ada/19419 (Overlapping memcpy with array slices)
authorEric Botcazou <ebotcazou@adacore.com>
Thu, 6 Nov 2008 11:28:07 +0000 (11:28 +0000)
committerEric Botcazou <ebotcazou@gcc.gnu.org>
Thu, 6 Nov 2008 11:28:07 +0000 (11:28 +0000)
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

gcc/ada/ChangeLog
gcc/ada/gcc-interface/trans.c

index ba94a5e9a7f2d3426dc7593bcfe64b93ee2504b9..67300939fe0af3c6e2d97aea406c0521bcc2ebc3 100644 (file)
@@ -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
index 6ade56869d9f58d49782200185677f579183a314..9f050bdc5d1ae59d593b3f8d5a6b4228bc32113d 100644 (file)
@@ -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;