[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Bug#650764: gnat-4.4: FTBFS: sinput.adb:776:19: deallocation from empty storage pool



I have traced this to the following diff hunk in the sources of GNAT:

--- a/gcc/ada/sem_intr.adb 4.4
+++ b/gcc/ada/sem_intr.adb 4.6
@@ -134,12 +159,23 @@ package body Sem_Intr is
       --  Check for the case of freeing a non-null object which will raise
       --  Constraint_Error. Issue warning here, do the expansion in Exp_Intr.
 
-      elsif Cnam = Name_Free
+      elsif Cnam = Name_Unchecked_Deallocation
         and then Can_Never_Be_Null (Etype (Arg1))
       then
          Error_Msg_N
            ("freeing `NOT NULL` object will raise Constraint_Error?", N);
 
+      --  For unchecked deallocation, error to deallocate from empty pool.
+      --  Note: this test used to be in Exp_Intr as a warning, but AI 157
+      --  issues a binding interpretation that this should be an error, and
+      --  consequently it needs to be done in the semantic analysis so that
+      --  the error is issued even in semantics only mode.
+
+      elsif Cnam = Name_Unchecked_Deallocation
+        and then No_Pool_Assigned (Rtyp)
+      then
+         Error_Msg_N ("deallocation from empty storage pool!", N);
+
       --  For now, no other special checks are required
 
       else

This explains why gnat-4.6 issues an (unsuppressible) error instead of a
(suppressed) warning when compiling the following piece of source of
gnat-4.4 (line 776 is of course the call to Free_Ptr):

            declare
               S : Source_File_Record renames Source_File.Table (J);

               procedure Free_Ptr is new Unchecked_Deallocation
                 (Big_Source_Buffer, Source_Buffer_Ptr);

               pragma Warnings (Off);
               --  This unchecked conversion is aliasing safe, since it is not
               --  used to create improperly aliased pointer values.

               function To_Source_Buffer_Ptr is new
                 Unchecked_Conversion (Address, Source_Buffer_Ptr);

               pragma Warnings (On);

               Tmp1 : Source_Buffer_Ptr;

            begin
               if S.Instantiation /= No_Location then
                  null;

               else
                  --  Free the buffer, we use Free here, because we used malloc
                  --  or realloc directly to allocate the tables. That is
                  --  because we were playing the big array trick. We need to
                  --  suppress the warning for freeing from an empty pool!

                  --  We have to recreate a proper pointer to the actual array
                  --  from the zero origin pointer stored in the source table.

                  Tmp1 :=
                    To_Source_Buffer_Ptr
                      (S.Source_Text (S.Source_First)'Address);
                  pragma Warnings (Off);
                  Free_Ptr (Tmp1);
                  pragma Warnings (On);

                  if S.Lines_Table /= null then
                     Memory.Free (To_Address (S.Lines_Table));
                     S.Lines_Table := null;
                  end if;

                  if S.Logical_Lines_Table /= null then
                     Memory.Free (To_Address (S.Logical_Lines_Table));
                     S.Logical_Lines_Table := null;
                  end if;
               end if;
            end;


This does not however explain why gnat-4.6 compiles gnat-4.6
successfully, given that sinput.adb has changed very little in that
area:

--- a/gcc/ada/sinput.adb 4.4
+++ b/gcc/ada/sinput.adb 4.6
@@ -763,8 +811,7 @@ package body Sinput is
                else
                   --  Free the buffer, we use Free here, because we used malloc
                   --  or realloc directly to allocate the tables. That is
-                  --  because we were playing the big array trick. We need to
-                  --  suppress the warning for freeing from an empty pool!
+                  --  because we were playing the big array trick.
 
                   --  We have to recreate a proper pointer to the actual array
                   --  from the zero origin pointer stored in the source table.
@@ -772,9 +819,7 @@ package body Sinput is
                   Tmp1 :=
                     To_Source_Buffer_Ptr
                       (S.Source_Text (S.Source_First)'Address);
-                  pragma Warnings (Off);
                   Free_Ptr (Tmp1);
-                  pragma Warnings (On);
 
                   if S.Lines_Table /= null then
                      Memory.Free (To_Address (S.Lines_Table));




The mystery disappears when we read the corresponding ChangeLog entry:

2010-10-07  Robert Dewar  <dewar@adacore.com>

	* par-ch6.adb: Fix error in handling of parametrized expressions.
	* par-ch4.adb (P_Name): Allow qualified expression as name in Ada 2012
	mode.
	(P_Simple_Expression): Better message for qualified expression prefix
	* s-crc32.adb: Minor reformatting.
	* exp_intr.adb (Expand_Unc_Deallocation): Remove test for empty
	storage pool (this test is moved to Sem_Intr).
	* sem_intr.adb (Check_Intrinsic_Call): Add check for deallocation from
	empty storage pool, moved here from Exp_Intr and made into error.
	(Check_Intrinsic_Call): Remove assumption in generating not-null free
	warning that the name of the instantiation is Free.
	* sinput.adb (Tree_Read): Document use of illegal free call allowed in
	GNAT mode.
	* types.ads: Remove storage size clauses from big types (since we may
	need to do deallocations, which are now illegal for empty pools).


So I think that backporting the entire commit (affecting exp_intr.adb,
sem_intr.adb, sinput.adb and most importantly types.ads) to gnat-4.4
should resolve this bug.

-- 
Ludovic Brenta.



Reply to: