This is a recent regression present on the mainline, 16 and 15 branches.  The 
compiler fails to implement the required sliding when an array aggregate with 
specified bounds is assigned to an unconstrained formal parameter, because the 
Must_Slide predicate considers only the case of an object declaration when the 
object subtype is unconstrained.

Tested on x86-64/Linux, applied on the mainline, 16 and 15 branches.


2026-08-24  Eric Botcazou  <[email protected]>

        PR ada/127026
        * exp_aggr.adb (Must_Slide): Reorder parameters, rename Obj_Type to
        Ob_Typ and add Assign boolean parameter.  Return Assign's value in
        the case where Obj_Typ is unconstrained.
        (Build_Array_Aggr_Code): Adjust call to Must_Slide.
        (In_Place_Assign_OK): Likewise.
        (Expand_Array_Aggregate): Likewise.


2026-08-24  Eric Botcazou  <[email protected]>

        * gnat.dg/array43.adb: New test.

-- 
Eric Botcazou
diff --git a/gcc/ada/exp_aggr.adb b/gcc/ada/exp_aggr.adb
index ba8bf71912b..ab8bfce1607 100644
--- a/gcc/ada/exp_aggr.adb
+++ b/gcc/ada/exp_aggr.adb
@@ -138,19 +138,22 @@ package body Exp_Aggr is
    --  constants that are done in place.
 
    function Must_Slide
-     (Aggr     : Node_Id;
-      Obj_Type : Entity_Id;
-      Typ      : Entity_Id) return Boolean;
+     (Aggr    : Node_Id;
+      Typ     : Entity_Id;
+      Obj_Typ : Entity_Id;
+      Assign  : Boolean) return Boolean;
+   --  Return whether an array aggregate Aggr whose subtype is Typ must slide
+   --  when assigned to an object whose (nominal) subtype is Obj_Typ. Assign
+   --  is True when the context is an assignment statement and False when it
+   --  is an object declaration or an allocator.
+
    --  A static array aggregate in an object declaration can in most cases be
    --  expanded in place. The one exception is when the aggregate is given
    --  with component associations that specify different bounds from those of
    --  the type definition in the object declaration. In this pathological
    --  case the aggregate must slide, and we must introduce an intermediate
-   --  temporary to hold it.
-   --
-   --  The same holds in an assignment to multi-dimensional arrays, when
-   --  components may be given with bounds that differ from those of the
-   --  component type.
+   --  temporary to hold it. The same holds in an assignment, when components
+   --  may be given with bounds that differ from those of the target.
 
    function Number_Of_Choices (N : Node_Id) return Nat;
    --  Returns the number of discrete choices (not including the others choice
@@ -1443,7 +1446,8 @@ package body Exp_Aggr is
                if Nkind (Parent (N)) = N_Assignment_Statement
                  and then Is_Array_Type (Comp_Typ)
                  and then Present (Component_Associations (Expr_Q))
-                 and then Must_Slide (N, Comp_Typ, Etype (Expr_Q))
+                 and then
+                   Must_Slide (N, Etype (Expr_Q), Comp_Typ, Assign => True)
                then
                   Set_Expansion_Delayed (Expr_Q, False);
                   Set_Analyzed (Expr_Q, False);
@@ -4251,7 +4255,8 @@ package body Exp_Aggr is
       --  statically equal to those of the target.
 
       if Is_Array
-        and then Must_Slide (N, Etype (Name (Parent_Node)), Etype (N))
+        and then
+          Must_Slide (N, Etype (N), Etype (Name (Parent_Node)), Assign => True)
       then
          return False;
       end if;
@@ -6276,8 +6281,9 @@ package body Exp_Aggr is
                        or else Needs_Finalization (Typ)
                        or else not Must_Slide
                                      (N,
+                                      Typ,
                                       Designated_Type (Etype (Parent_Node)),
-                                      Typ)))
+                                      Assign => False)))
 
          --  Object declaration (see Convert_Aggr_In_Object_Decl). Sliding
          --  cannot be done in place for the time being.
@@ -6291,9 +6297,10 @@ package body Exp_Aggr is
                                  (Defining_Identifier (Parent_Node))
                        or else not Must_Slide
                                      (N,
+                                      Typ,
                                       Etype
                                         (Defining_Identifier (Parent_Node)),
-                                      Typ)))
+                                      Assign => False)))
 
          --  Safe assignment (see Convert_Aggr_In_Assignment). So far only the
          --  assignments in init procs are taken into account, as well those
@@ -9610,9 +9617,10 @@ package body Exp_Aggr is
    ----------------
 
    function Must_Slide
-     (Aggr     : Node_Id;
-      Obj_Type : Entity_Id;
-      Typ      : Entity_Id) return Boolean
+     (Aggr    : Node_Id;
+      Typ     : Entity_Id;
+      Obj_Typ : Entity_Id;
+      Assign  : Boolean) return Boolean
    is
    begin
       --  No sliding if the type of the object is not established yet, if it is
@@ -9621,13 +9629,13 @@ package body Exp_Aggr is
       --  an Others_Clause it gets its type from the context and no sliding
       --  is involved either.
 
-      if not Is_Array_Type (Obj_Type) then
+      if not Is_Array_Type (Obj_Typ) then
          return False;
 
-      elsif not Is_Constrained (Obj_Type) then
-         return False;
+      elsif not Is_Constrained (Obj_Typ) then
+         return Assign;
 
-      elsif Typ = Obj_Type then
+      elsif Typ = Obj_Typ then
          return False;
 
       elsif Is_Others_Aggregate (Aggr) then
@@ -9637,7 +9645,7 @@ package body Exp_Aggr is
 
       else
          declare
-            Obj_Index  : Node_Id := First_Index (Obj_Type);
+            Obj_Index  : Node_Id := First_Index (Obj_Typ);
             Obj_Bounds : Range_Nodes;
             Typ_Index  : Node_Id := First_Index (Typ);
             Typ_Bounds : Range_Nodes;
-- { dg-do run }

procedure Array43 is

  type Arr is array (Integer range <>) of Integer;

  procedure Fill (B : out Arr; N : Integer) is
  begin
    B := (1 .. N => 7);
  end Fill;

  V : Arr (5 .. 8) := (others => 0);

begin
  Fill (V, V'Length);
  if V /= (V'First .. V'Last => 7) then
    raise Program_Error;
  end if;
end;

Reply via email to