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