]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
ada: Fix missing finalization in library-unit instance spec
authorEric Botcazou <ebotcazou@adacore.com>
Wed, 8 Feb 2023 21:16:23 +0000 (22:16 +0100)
committerMarc Poulhiès <poulhies@adacore.com>
Mon, 22 May 2023 08:44:10 +0000 (10:44 +0200)
This fixes the missing finalization of objects declared in the spec of
package instances that are library units (and only them, i.e. not all
library-level package instances) when the instances have a package body.

The finalization is done when there is no package body, and supporting
this case precisely broke the other case because of a thinko or a typo.

This also requires a small adjustment to the routine writing ALI files.

gcc/ada/

* exp_ch7.adb (Build_Finalizer): Reverse the test comparing the
instantiation and declaration nodes of a package instance, and
therefore bail out only when they are equal.  Adjust comments.
(Expand_N_Package_Declaration): Do not clear the Finalizer field.
* lib-writ.adb: Add with and use clauses for Sem_Util.
(Write_Unit_Information): Look at unit nodes to find finalizers.
* sem_ch12.adb (Analyze_Package_Instantiation): Beef up the comment
about the rewriting of the instantiation node into a declaration.

gcc/ada/exp_ch7.adb
gcc/ada/lib-writ.adb
gcc/ada/sem_ch12.adb

index 7ea39f7ba16e6be7ea4c1a8ac3ff2905d3c08ade..a02e28e4b3458a7fb5fce02d726d22315027118e 100644 (file)
@@ -3534,15 +3534,21 @@ package body Exp_Ch7 is
         and then
           (not Is_Library_Level_Entity (Spec_Id)
 
-            --  Nested packages are library level entities, but do not need to
+            --  Nested packages are library-level entities, but do not need to
             --  be processed separately.
 
             or else Scope_Depth (Spec_Id) /= Uint_1
+
+            --  Do not build two finalizers for an instance without body that
+            --  is a library unit (see Analyze_Package_Instantiation).
+
             or else (Is_Generic_Instance (Spec_Id)
-                      and then Package_Instantiation (Spec_Id) /= N))
+                      and then Package_Instantiation (Spec_Id) = N))
 
-         --  Still need to process package body instantiations which may
-         --  contain objects requiring finalization.
+         --  Still need to process library-level package body instances, whose
+         --  instantiation was deferred and thus could not be seen during the
+         --  processing of the enclosing scope, and which may contain objects
+         --  requiring finalization.
 
         and then not
           (For_Package_Body
@@ -5376,7 +5382,9 @@ package body Exp_Ch7 is
             Defer_Abort => False,
             Fin_Id      => Fin_Id);
 
-         Set_Finalizer (Id, Fin_Id);
+         if Present (Fin_Id) then
+            Set_Finalizer (Id, Fin_Id);
+         end if;
       end if;
 
       --  If this is a library-level package and unnesting is enabled,
index deecfc067c503df8eed5175ba002e4039b8795cf..23b6266bb415550bcc28d278f3d3dddd04576995 100644 (file)
@@ -50,6 +50,7 @@ with Rident;         use Rident;
 with Stand;          use Stand;
 with Scn;            use Scn;
 with Sem_Eval;       use Sem_Eval;
+with Sem_Util;       use Sem_Util;
 with Sinfo;          use Sinfo;
 with Sinfo.Nodes;    use Sinfo.Nodes;
 with Sinfo.Utils;    use Sinfo.Utils;
@@ -524,10 +525,20 @@ package body Lib.Writ is
          Write_Info_Str (" O");
          Write_Info_Char (OA_Setting (Unit_Num));
 
-         if Ekind (Uent) in E_Package | E_Package_Body
-           and then Present (Finalizer (Uent))
-         then
-            Write_Info_Str (" PF");
+         --  For a package instance with a body that is a library unit, the two
+         --  compilation units share Cunit_Entity so we cannot rely on Uent.
+
+         if Ukind in N_Package_Declaration | N_Package_Body then
+            declare
+               E : constant Entity_Id := Defining_Entity (Unit (Unode));
+
+            begin
+               if Ekind (E) in E_Package | E_Package_Body
+                 and then Present (Finalizer (E))
+               then
+                  Write_Info_Str (" PF");
+               end if;
+            end;
          end if;
 
          if Is_Preelaborated (Uent) then
index 181392c2132b9894fd156509bf5eeb53afd789f4..c31d0c62faaf8fd6c592ca6d728f36e884991323 100644 (file)
@@ -5007,10 +5007,12 @@ package body Sem_Ch12 is
          Set_First_Private_Entity (Defining_Unit_Name (Unit_Renaming),
            First_Private_Entity (Act_Decl_Id));
 
-         --  If the instantiation will receive a body, the unit will be
-         --  transformed into a package body, and receive its own elaboration
-         --  entity. Otherwise, the nature of the unit is now a package
-         --  declaration.
+         --  If the instantiation needs a body, the unit will be turned into
+         --  a package body and receive its own elaboration entity. Otherwise,
+         --  the nature of the unit is now a package declaration.
+
+         --  Note that the below rewriting means that Act_Decl, which has been
+         --  analyzed and expanded, will be re-expanded as the rewritten N.
 
          if Nkind (Parent (N)) = N_Compilation_Unit
            and then not Needs_Body