This changes the logic of Is_Non_Local_Array to return true for anything that
is not a component or a slice of a local entity, for example a dereference, so
as to generate a call to memmove instead of memcpy in more cases, e.g.:

package P is

  type String_Access is access all String;

  type Rec1 is record
    A : String_Access;
  end record;

  procedure Proc (R : Rec1; S : String);

end P;
package body P is

  procedure Proc (R : Rec1; S : String) is
  begin
    R.A (1 .. S'Length) := S;
  end;

end P;

This will also fix PR ada/64057.

Tested on x86_64-pc-linux-gnu, committed on trunk

2016-10-12  Eric Botcazou  <ebotca...@adacore.com>

        PR ada/64057.
        * exp_ch5.adb (Is_Non_Local_Array): Return true for every array
        that is not a component or slice of an entity in the current
        scope.

Index: exp_ch5.adb
===================================================================
--- exp_ch5.adb (revision 241024)
+++ exp_ch5.adb (working copy)
@@ -278,9 +278,9 @@
 
       function Is_Non_Local_Array (Exp : Node_Id) return Boolean;
       --  Determine if Exp is a reference to an array variable which is other
-      --  than an object defined in the current scope, or a slice of such
-      --  an object. Such objects can be aliased to parameters (unlike local
-      --  array references).
+      --  than an object defined in the current scope, or a component or a
+      --  slice of such an object. Such objects can be aliased to parameters
+      --  (unlike local array references).
 
       -----------------------
       -- Apply_Dereference --
@@ -327,10 +327,14 @@
 
       function Is_Non_Local_Array (Exp : Node_Id) return Boolean is
       begin
-         return (Is_Entity_Name (Exp)
-                   and then Scope (Entity (Exp)) /= Current_Scope)
-            or else (Nkind (Exp) = N_Slice
-                       and then Is_Non_Local_Array (Prefix (Exp)));
+         case Nkind (Exp) is
+            when N_Indexed_Component | N_Selected_Component | N_Slice =>
+               return Is_Non_Local_Array (Prefix (Exp));
+            when others =>
+               return
+                 not (Is_Entity_Name (Exp) and then
+                                        Scope (Entity (Exp)) = Current_Scope);
+         end case;
       end Is_Non_Local_Array;
 
       --  Determine if Lhs, Rhs are formal arrays or nonlocal arrays

Reply via email to