]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
ada: fix: drop renamings along with dropped subp
authorMarc Poulhiès <poulhies@adacore.com>
Fri, 5 Dec 2025 10:24:56 +0000 (11:24 +0100)
committerMarc Poulhiès <dkm@gcc.gnu.org>
Tue, 26 May 2026 08:38:19 +0000 (10:38 +0200)
During unnesting, the compiler may drop some subp if reachability
analysis decides it's never used. This change adds tracking for subp
renamings, making sure renamings are also dropped with the subp.

When traversing the tree, when looking at a subp renaming declaration, it's
possible that the Subps entry (accessed through Subps_Index) for the renamed
subp has not yet been created. In this case, the renaming is recorded in a
"pending" list, and moved later when the Subps entry is created.

gcc/ada/ChangeLog:

* exp_unst.adb (Maybe_Subp_Index): New non throwing version of
Subp_Index.
(Nullify_Renamings, Move_Pending_Renamings): New.
(Register_Subprogram): Record subp renamings. Call
Nullify_Renamings when a subp is dropped.
(with Elist): Moved to...
* exp_unst.ads (with Elist): ... here.
(Subp_Entry): Add Renamings component.
(Pending_Renamings): New list.

gcc/ada/exp_unst.adb
gcc/ada/exp_unst.ads

index 601318e10d5986fe77b02b6a14569681fcda5ad4..84db16ef3b8885b8fb292136157c639fa7524d7a 100644 (file)
@@ -27,7 +27,6 @@ with Atree;          use Atree;
 with Debug;          use Debug;
 with Einfo.Entities; use Einfo.Entities;
 with Einfo.Utils;    use Einfo.Utils;
-with Elists;         use Elists;
 with Lib;            use Lib;
 with Namet;          use Namet;
 with Nlists;         use Nlists;
@@ -55,6 +54,13 @@ package body Exp_Unst is
    -- Local Subprograms --
    -----------------------
 
+   function Maybe_Subp_Index (Sub : Entity_Id) return SI_Type;
+   --  Returns the subps index value if it has been set, 0 if not
+
+   procedure Nullify_Renamings (Renamings : Elist_Id);
+   --  Iterates over all renamings in the Renamings list and replace them with
+   --  null statements.
+
    procedure Unnest_Subprogram
      (Subp : Entity_Id; Subp_Body : Node_Id; For_Inline : Boolean := False);
    --  Subp is a library-level subprogram which has nested subprograms, and
@@ -264,8 +270,14 @@ package body Exp_Unst is
    ----------------
 
    function Subp_Index (Sub : Entity_Id) return SI_Type is
-      E : Entity_Id := Sub;
+      Ret : constant SI_Type := Maybe_Subp_Index (Sub);
+   begin
+      pragma Assert (Ret /= 0);
+      return Ret;
+   end Subp_Index;
 
+   function Maybe_Subp_Index (Sub : Entity_Id) return SI_Type is
+      E : Entity_Id := Sub;
    begin
       pragma Assert (Is_Subprogram (E));
 
@@ -283,9 +295,54 @@ package body Exp_Unst is
          end if;
       end if;
 
-      pragma Assert (Subps_Index (E) /= Uint_0);
-      return SI_Type (UI_To_Int (Subps_Index (E)));
-   end Subp_Index;
+      if not Field_Is_Initial_Zero (E, F_Subps_Index) then
+         return SI_Type (UI_To_Int (Subps_Index (E)));
+      else
+         --  Field has not been set, don't try to access it yet
+         return 0;
+      end if;
+   end Maybe_Subp_Index;
+
+   procedure Nullify_Renamings (Renamings : Elist_Id) is
+      Iterator : Elmt_Id := First_Elmt (Renamings);
+      Nod : Node_Id;
+      F_Nod : Node_Id;
+   begin
+      if Debug_Flag_Dot_3 and then Present (Iterator) then
+         Nod := Node (Iterator);
+         Write_Str ("Dropping renamings for ");
+         Write_Name (Chars (Entity (Name (Nod))));
+         Write_Eol;
+      end if;
+
+      while Present (Iterator) loop
+         Nod := Node (Iterator);
+
+         if Debug_Flag_Dot_3 then
+            Write_Str (" -  ");
+            Write_Name (Chars (Defining_Unit_Name (Specification (Nod))));
+            Write_Eol;
+         end if;
+
+         --  Remove the freeze node if there is one
+
+         F_Nod := Freeze_Node (Defining_Unit_Name
+           (Specification (Nod)));
+         if Present (F_Nod) then
+            Rewrite (F_Nod,
+                     Make_Null_Statement (Sloc (Nod)));
+         end if;
+
+         Rewrite (Nod,
+                  Make_Null_Statement (Sloc (Nod)));
+
+         Next_Elmt (Iterator);
+      end loop;
+
+      while Present (First_Elmt (Renamings)) loop
+         Remove_Last_Elmt (Renamings);
+      end loop;
+   end Nullify_Renamings;
 
    -----------------------
    -- Unnest_Subprogram --
@@ -482,6 +539,11 @@ package body Exp_Unst is
             --  is an access type, check whether the designated type
             --  has dynamic bounds.
 
+            procedure Move_Pending_Renamings (Subp : Entity_Id;
+                                              Renamings : in out Elist_Id);
+            --  Move all pending renamings that are renaming Subp to its own
+            --  Renamings list.
+
             procedure Note_Uplevel_Ref
               (E      : Entity_Id;
                N      : Node_Id;
@@ -759,17 +821,41 @@ package body Exp_Unst is
                Urefs.Append ((N, Full_E, Caller, Callee));
             end Note_Uplevel_Ref;
 
+            procedure Move_Pending_Renamings (Subp : Entity_Id;
+                                              Renamings : in out Elist_Id) is
+               Iterator : Elmt_Id := First_Elmt (Pending_Renamings);
+               Nod : Node_Id;
+            begin
+               while Present (Iterator) loop
+                  Nod := Node (Iterator);
+
+                  if Entity (Name (Nod)) = Subp then
+                     Append_New_Elmt (Nod, Renamings);
+                  end if;
+                  Next_Elmt (Iterator);
+               end loop;
+
+               Iterator := First_Elmt (Renamings);
+               while Present (Iterator) loop
+                  Remove (Pending_Renamings, Node (Iterator));
+                  Next_Elmt (Iterator);
+               end loop;
+            end Move_Pending_Renamings;
+
             -------------------------
             -- Register_Subprogram --
             -------------------------
 
             procedure Register_Subprogram (E : Entity_Id; Bod : Node_Id) is
                L : constant Nat := Get_Level (Subp, E);
-
+               Renamings : Elist_Id := New_Elmt_List;
             begin
-               --  Subprograms declared in tasks and protected types cannot be
-               --  eliminated because calls to them may be in other units, so
-               --  they must be treated as reachable.
+               Move_Pending_Renamings (E, Renamings);
+
+               --  Subprograms declared in tasks and protected types or whose
+               --  address is taken (through attribute Address or Access)
+               --  cannot be eliminated because calls to them may be in other
+               --  units, so they must be treated as reachable.
 
                Subps.Append
                  ((Ent           => E,
@@ -786,7 +872,8 @@ package body Exp_Unst is
                    ARECnT        => Empty,
                    ARECnPT       => Empty,
                    ARECnP        => Empty,
-                   ARECnU        => Empty));
+                   ARECnU        => Empty,
+                   Renamings     => Renamings));
 
                Set_Subps_Index (E, UI_From_Int (Subps.Last));
 
@@ -1222,6 +1309,54 @@ package body Exp_Unst is
                      return Skip;
                   end if;
 
+               when N_Subprogram_Renaming_Declaration =>
+                  --  Record the subprogram renaming. If the reachability
+                  --  analysis decides to drop the procedure, we also need to
+                  --  drop all the associated renamings.
+
+                  if Nkind (Name (N)) in N_Has_Entity then
+                     declare
+                        E : constant Entity_Id := Entity (Name (N));
+                        SE : Subp_Entry;
+                     begin
+                        --  Do not record renamings for something not a
+                        --  subprogram. e.g.
+                        --    function t return boolean renames true;
+
+                        if Is_Subprogram (E) then
+                           if Maybe_Subp_Index (E) /= 0
+                             and then Enclosing_Subprogram (E) /= Empty
+                           then
+                              SE := Subps.Table (Subp_Index (E));
+                              Append_Elmt (N, SE.Renamings);
+
+                              if Debug_Flag_Dot_3 then
+                                 Write_Str ("Record renaming ");
+                                 Write_Name (Chars (Entity (Name (N))));
+                                 Write_Str (" for subp ");
+                                 Write_Name (Chars (SE.Ent));
+                                 Write_Str (" at ");
+                                 Write_Location (Sloc (E));
+                                 Write_Eol;
+                              end if;
+                           else
+                              Append_Elmt (N, Pending_Renamings);
+
+                              if Debug_Flag_Dot_3 then
+                                 Write_Str ("Record pending renaming ");
+                                 Write_Name (Chars (
+                                   Defining_Unit_Name (Specification (N))));
+                                 Write_Str (" for subp ");
+                                 Write_Name (Chars (E));
+                                 Write_Str (" at ");
+                                 Write_Location (Sloc (E));
+                                 Write_Eol;
+                              end if;
+                           end if;
+                        end if;
+                     end;
+                  end if;
+
                --  Otherwise record an uplevel reference in a local identifier
 
                when others =>
@@ -1531,6 +1666,8 @@ package body Exp_Unst is
                   if Present (STJ.Bod) then
                      Spec := Corresponding_Spec (STJ.Bod);
 
+                     Nullify_Renamings (STJ.Renamings);
+
                      if Present (Spec) then
                         Decl := Parent (Declaration_Node (Spec));
                         Rewrite (Decl, Make_Null_Statement (Sloc (Decl)));
index b710ff5ecd416b85621fa56aa8ba9ab718a1a350..0fcad7f103c6f2d27212ab3909a1aaca5a71d676 100644 (file)
@@ -27,6 +27,7 @@
 
 with Table;
 with Types; use Types;
+with Elists;         use Elists;
 
 package Exp_Unst is
 
@@ -696,8 +697,19 @@ package Exp_Unst is
       --  activation record that references the ARECnF pointer (which points
       --  the activation record one level higher, thus forming the chain).
 
+      Renamings : Elist_Id;
+      --  This list contains all renamings of this subprogram. It is used when
+      --  the subprogram is dropped because it's unreachable: all renamings
+      --  must also be dropped.
+
    end record;
 
+   Pending_Renamings : Elist_Id := New_Elmt_List;
+   --  This is a list of subprogram renamings that are waiting for their
+   --  corresponding Subp_Entry to be created. Once the Subp_Entry is
+   --  available, the compiler moves the renaming entry from this list to
+   --  the Subp_Entry.Renamings list.
+
    package Subps is new Table.Table (
      Table_Component_Type => Subp_Entry,
      Table_Index_Type     => SI_Type,