diff mbox series

[COMMITTED,03/30] ada: Allow making empty aggregates positional

Message ID 20240801151738.400796-3-poulhies@adacore.com
State New
Headers show
Series [COMMITTED,01/30] ada: Remove obsolete workaround | expand

Commit Message

Marc Poulhiès Aug. 1, 2024, 3:17 p.m. UTC
From: Ronan Desplanques <desplanques@adacore.com>

This patch makes Exp_Aggr.Convert_To_Positional accepts appropriate
empty aggregates. The end goal is to remove violations of the
No_Elaboration_Code restriction in some cases of library-level array
objects.

gcc/ada/

	* exp_aggr.adb (Flatten): Do not reject empty aggregates. Adjust
	criterion for emitting warning about ineffective others clause.
	* sem_aggr.adb (Array_Aggr_Subtype): Fix typo. Add handling of
	aggregates that were converted to positional form.
	(Resolve_Aggregate): Tweak criterion for transforming into a
	string literal.
	(Resolve_Array_Aggregate): Tweak criterion for reusing existing
	bounds of aggregate.
	(Retrieve_Aggregate_Bounds): New procedure.
	* sem_util.adb (Has_Static_Empty_Array_Bounds): New function.
	* sem_util.ads (Has_Static_Empty_Array_Bounds): Likewise.

Tested on x86_64-pc-linux-gnu, committed on master.

---
 gcc/ada/exp_aggr.adb |  6 +++--
 gcc/ada/sem_aggr.adb | 53 ++++++++++++++++++++++++++++++--------------
 gcc/ada/sem_util.adb | 14 ++++++++++++
 gcc/ada/sem_util.ads |  3 +++
 4 files changed, 57 insertions(+), 19 deletions(-)
diff mbox series

Patch

diff --git a/gcc/ada/exp_aggr.adb b/gcc/ada/exp_aggr.adb
index df228713a28..419a98c681a 100644
--- a/gcc/ada/exp_aggr.adb
+++ b/gcc/ada/exp_aggr.adb
@@ -4657,8 +4657,7 @@  package body Exp_Aggr is
          --  present we can proceed since the bounds can be obtained from the
          --  aggregate.
 
-         if Hiv < Lov
-           or else (not Compile_Time_Known_Value (Blo) and then Others_Present)
+         if not Compile_Time_Known_Value (Blo) and then Others_Present
          then
             return False;
          end if;
@@ -4801,6 +4800,9 @@  package body Exp_Aggr is
 
                      if Rep_Count = 0
                        and then Warn_On_Redundant_Constructs
+                       -- We don't emit warnings on null arrays initialized
+                       -- with an aggregate of the form "(others => ...)".
+                       and then Vals'Length > 0
                      then
                         Error_Msg_N ("there are no others?r?", Elmt);
                      end if;
diff --git a/gcc/ada/sem_aggr.adb b/gcc/ada/sem_aggr.adb
index bc53ea904a3..bddfbecf46d 100644
--- a/gcc/ada/sem_aggr.adb
+++ b/gcc/ada/sem_aggr.adb
@@ -468,6 +468,12 @@  package body Sem_Aggr is
       --  corresponding to the same dimension are static and found to differ,
       --  then emit a warning, and mark N as raising Constraint_Error.
 
+      procedure Retrieve_Aggregate_Bounds (This_Range : Node_Id);
+      --  In some cases, an appropriate list of aggregate bounds has been
+      --  created during resolution. Populate Aggr_Range with that list, and
+      --  remove the elements from the list so they can be added to another
+      --  list later.
+
       -------------------------
       -- Collect_Aggr_Bounds --
       -------------------------
@@ -631,6 +637,24 @@  package body Sem_Aggr is
          end if;
       end Collect_Aggr_Bounds;
 
+      -------------------------------
+      -- Retrieve_Aggregate_Bounds --
+      -------------------------------
+
+      procedure Retrieve_Aggregate_Bounds (This_Range : Node_Id) is
+         R : Node_Id := This_Range;
+      begin
+         for J in 1 .. Aggr_Dimension loop
+            Aggr_Range (J) := R;
+            Next_Index (R);
+
+            --  Remove bounds from the list, so they can be reattached as
+            --  the First_Index/Next_Index again.
+
+            Remove (Aggr_Range (J));
+         end loop;
+      end Retrieve_Aggregate_Bounds;
+
       --  Array_Aggr_Subtype variables
 
       Itype : Entity_Id;
@@ -655,25 +679,17 @@  package body Sem_Aggr is
 
       Set_Parent (Index_Constraints, N);
 
+      if Is_Rewrite_Substitution (N)
+        and then Present (Component_Associations (Original_Node (N)))
+      then
+         Retrieve_Aggregate_Bounds (First_Index (Etype (Original_Node (N))));
+
       --  When resolving a null aggregate we created a list of aggregate bounds
       --  for the consecutive dimensions. The bounds for the first dimension
       --  are attached as the Aggregate_Bounds of the aggregate node.
 
-      if Is_Null_Aggregate (N) then
-         declare
-            This_Range : Node_Id := Aggregate_Bounds (N);
-         begin
-            for J in 1 .. Aggr_Dimension loop
-               Aggr_Range (J) := This_Range;
-               Next_Index (This_Range);
-
-               --  Remove bounds from the list, so they can be reattached as
-               --  the First_Index/Next_Index again by the code that also
-               --  handles non-null aggregates.
-
-               Remove (Aggr_Range (J));
-            end loop;
-         end;
+      elsif Is_Null_Aggregate (N) then
+         Retrieve_Aggregate_Bounds (Aggregate_Bounds (N));
       else
          Collect_Aggr_Bounds (N, 1);
       end if;
@@ -1378,6 +1394,7 @@  package body Sem_Aggr is
            and then Is_OK_Static_Subtype (Component_Type (Typ))
            and then Base_Type (Etype (First_Index (Typ))) =
                       Base_Type (Standard_Integer)
+           and then not Has_Static_Empty_Array_Bounds (Typ)
          then
             declare
                Expr : Node_Id;
@@ -3595,10 +3612,12 @@  package body Sem_Aggr is
       --  If the aggregate already has bounds attached to it, it means this is
       --  a positional aggregate created as an optimization by
       --  Exp_Aggr.Convert_To_Positional, so we don't want to change those
-      --  bounds.
+      --  bounds, unless they depend on discriminants. If they do, we have to
+      --  perform analysis in the current context.
 
       if Present (Aggregate_Bounds (N))
-        and then not Others_Allowed
+        and then No (Others_N)
+        and then not Depends_On_Discriminant (Aggregate_Bounds (N))
         and then not Comes_From_Source (N)
       then
          Aggr_Low  := Low_Bound  (Aggregate_Bounds (N));
diff --git a/gcc/ada/sem_util.adb b/gcc/ada/sem_util.adb
index 9d4fd74b98f..19941ae3060 100644
--- a/gcc/ada/sem_util.adb
+++ b/gcc/ada/sem_util.adb
@@ -13250,6 +13250,20 @@  package body Sem_Util is
       return All_Static;
    end Has_Static_Array_Bounds;
 
+   -----------------------------------
+   -- Has_Static_Empty_Array_Bounds --
+   -----------------------------------
+
+   function Has_Static_Empty_Array_Bounds (Typ : Node_Id) return Boolean is
+      All_Static : Boolean;
+      Has_Empty  : Boolean;
+
+   begin
+      Examine_Array_Bounds (Typ, All_Static, Has_Empty);
+
+      return Has_Empty;
+   end Has_Static_Empty_Array_Bounds;
+
    ---------------------------------------
    -- Has_Static_Non_Empty_Array_Bounds --
    ---------------------------------------
diff --git a/gcc/ada/sem_util.ads b/gcc/ada/sem_util.ads
index 21e90dcf53b..eccbd4351d0 100644
--- a/gcc/ada/sem_util.ads
+++ b/gcc/ada/sem_util.ads
@@ -1531,6 +1531,9 @@  package Sem_Util is
    function Has_Static_Array_Bounds (Typ : Node_Id) return Boolean;
    --  Return whether an array type has static bounds
 
+   function Has_Static_Empty_Array_Bounds (Typ : Node_Id) return Boolean;
+   --  Return whether array type Typ has static empty bounds
+
    function Has_Static_Non_Empty_Array_Bounds (Typ : Node_Id) return Boolean;
    --  Determine whether array type Typ has static non-empty bounds