sem_prag.adb (Get_SPARK_Mode_Id): Handle the case where the pragma may appear without...
authorHristian Kirtchev <kirtchev@adacore.com>
Tue, 10 Sep 2013 14:43:06 +0000 (14:43 +0000)
committerArnaud Charlet <charlet@gcc.gnu.org>
Tue, 10 Sep 2013 14:43:06 +0000 (16:43 +0200)
2013-09-10  Hristian Kirtchev  <kirtchev@adacore.com>

* sem_prag.adb (Get_SPARK_Mode_Id): Handle the
case where the pragma may appear without an argument.
(Analyze_Global_List): Add expanded_name to the list of constructs
that denote a single item.
(Collect_Global_List): Add expanded_name to the list of constructs
that denote a single item.

2013-09-10  Hristian Kirtchev  <kirtchev@adacore.com>

* exp_ch4.adb (Apply_Accessibility_Check): Add local constant
Pool_Id and local variables Fin_Call and Free_Stmt. Finalize
and deallocate a heap-allocated class-wide object after it
has been determined that it violates the accessibility rules.
* rtsfind.ads: Add new RTU_Id for System.Memory. Add new RE_Id
and entry in RE_Unit_Table for RE_Free.

From-SVN: r202451

gcc/ada/ChangeLog
gcc/ada/exp_ch4.adb
gcc/ada/rtsfind.ads
gcc/ada/sem_prag.adb

index 61fd991bef2d8bdb0cc6fba08b753d041d55ec4f..52e373235c77978ab26c4d493567c7da3a9d6dd7 100644 (file)
@@ -1,3 +1,21 @@
+2013-09-10  Hristian Kirtchev  <kirtchev@adacore.com>
+
+       * sem_prag.adb (Get_SPARK_Mode_Id): Handle the
+       case where the pragma may appear without an argument.
+       (Analyze_Global_List): Add expanded_name to the list of constructs
+       that denote a single item.
+       (Collect_Global_List): Add expanded_name to the list of constructs
+       that denote a single item.
+
+2013-09-10  Hristian Kirtchev  <kirtchev@adacore.com>
+
+       * exp_ch4.adb (Apply_Accessibility_Check): Add local constant
+       Pool_Id and local variables Fin_Call and Free_Stmt. Finalize
+       and deallocate a heap-allocated class-wide object after it
+       has been determined that it violates the accessibility rules.
+       * rtsfind.ads: Add new RTU_Id for System.Memory. Add new RE_Id
+       and entry in RE_Unit_Table for RE_Free.
+
 2013-09-01  Eric Botcazou  <ebotcazou@adacore.com>
            Iain Sandoe  <iain@codesourcery.com>
 
index 6fec955113cefc095b05c7f738b10fc0065ff05a..79789b6978d39790c22e12da015a0927d202e674 100644 (file)
@@ -725,20 +725,23 @@ package body Exp_Ch4 is
         (Ref            : Node_Id;
          Built_In_Place : Boolean := False)
       is
-         Cond    : Node_Id;
-         Obj_Ref : Node_Id;
-         Stmts   : List_Id;
+         Pool_Id   : constant Entity_Id := Associated_Storage_Pool (PtrT);
+         Cond      : Node_Id;
+         Fin_Call  : Node_Id;
+         Free_Stmt : Node_Id;
+         Obj_Ref   : Node_Id;
+         Stmts     : List_Id;
 
       begin
          if Ada_Version >= Ada_2005
            and then Is_Class_Wide_Type (DesigT)
+           and then (Tagged_Type_Expansion or else VM_Target /= No_VM)
            and then not Scope_Suppress.Suppress (Accessibility_Check)
            and then
              (Type_Access_Level (Etype (Exp)) > Type_Access_Level (PtrT)
                or else
                  (Is_Class_Wide_Type (Etype (Exp))
                    and then Scope (PtrT) /= Current_Scope))
-           and then (Tagged_Type_Expansion or else VM_Target /= No_VM)
          then
             --  If the allocator was built in place, Ref is already a reference
             --  to the access object initialized to the result of the allocator
@@ -750,7 +753,7 @@ package body Exp_Ch4 is
 
             if Built_In_Place then
                Remove_Side_Effects (Ref);
-               Obj_Ref := New_Copy (Ref);
+               Obj_Ref := New_Copy_Tree (Ref);
             else
                Obj_Ref := New_Reference_To (Ref, Loc);
             end if;
@@ -759,27 +762,68 @@ package body Exp_Ch4 is
 
             Stmts := New_List;
 
-            --  Why don't we free the object ??? discussion and explanation
-            --  needed of why old approach did not work ???
+            --  Deallocate the object if the accessibility check fails. This
+            --  is done only on targets or profiles that support deallocation.
+
+            --    Free (Obj_Ref);
+
+            if RTE_Available (RE_Free) then
+               Free_Stmt := Make_Free_Statement (Loc, New_Copy_Tree (Obj_Ref));
+               Set_Storage_Pool (Free_Stmt, Pool_Id);
+
+               Append_To (Stmts, Free_Stmt);
+
+            --  The target or profile cannot deallocate objects
+
+            else
+               Free_Stmt := Empty;
+            end if;
+
+            --  Finalize the object if applicable. Generate:
 
-            --  Generate:
             --    [Deep_]Finalize (Obj_Ref.all);
 
             if Needs_Finalization (DesigT) then
-               Append_To (Stmts,
+               Fin_Call :=
                  Make_Final_Call (
                    Obj_Ref =>
                      Make_Explicit_Dereference (Loc, New_Copy (Obj_Ref)),
-                   Typ     => DesigT));
+                   Typ     => DesigT);
+
+               --  When the target or profile supports deallocation, wrap the
+               --  finalization call in a block to ensure proper deallocation
+               --  even if finalization fails. Generate:
+
+               --    begin
+               --       <Fin_Call>
+               --    exception
+               --       when others =>
+               --          <Free_Stmt>
+               --          raise;
+               --    end;
+
+               if Present (Free_Stmt) then
+                  Fin_Call :=
+                    Make_Block_Statement (Loc,
+                      Handled_Statement_Sequence =>
+                        Make_Handled_Sequence_Of_Statements (Loc,
+                          Statements => New_List (Fin_Call),
+
+                        Exception_Handlers => New_List (
+                          Make_Exception_Handler (Loc,
+                            Exception_Choices => New_List (
+                              Make_Others_Choice (Loc)),
+
+                            Statements        => New_List (
+                              New_Copy_Tree (Free_Stmt),
+                              Make_Raise_Statement (Loc))))));
+               end if;
+
+               Prepend_To (Stmts, Fin_Call);
             end if;
 
             --  Signal the accessibility failure through a Program_Error
 
-            --  Since we may have a storage leak, I would be inclined to
-            --  define a new PE_ code that warns of this possibility where
-            --  the message would be Accessibility_Check_Failed (causing
-            --  storage leak) ???
-
             Append_To (Stmts,
               Make_Raise_Program_Error (Loc,
                 Condition => New_Reference_To (Standard_True, Loc),
index f218cdc7a2bdad2ddbd59a5ef53c1e39cbefc1e6..511f83348fcafd27bd4a2bbbc3aff135163258a1 100644 (file)
@@ -278,6 +278,7 @@ package Rtsfind is
       System_Machine_Code,
       System_Mantissa,
       System_Memcop,
+      System_Memory,
       System_Multiprocessors,
       System_Pack_03,
       System_Pack_05,
@@ -940,7 +941,9 @@ package Rtsfind is
      RE_Asm_Input_Operand,               -- System.Machine_Code
      RE_Asm_Output_Operand,              -- System.Machine_Code
 
-     RE_Mantissa_Value,                  -- System_Mantissa
+     RE_Mantissa_Value,                  -- System.Mantissa
+
+     RE_Free,                            -- System.Memory
 
      RE_CPU_Range,                       -- System.Multiprocessors
 
@@ -2197,6 +2200,8 @@ package Rtsfind is
 
      RE_Mantissa_Value                   => System_Mantissa,
 
+     RE_Free                             => System_Memory,
+
      RE_CPU_Range                        => System_Multiprocessors,
 
      RE_Bits_03                          => System_Pack_03,
index 4fe6c57a5bd0ada4f907ba6fe8c352bad2c89024..5e532b7e50ef5a03c16bfb35ae7fcc0e7da47883 100644 (file)
@@ -1576,7 +1576,10 @@ package body Sem_Prag is
       begin
          --  Single global item declaration
 
-         if Nkind_In (List, N_Identifier, N_Selected_Component) then
+         if Nkind_In (List, N_Expanded_Name,
+                            N_Identifier,
+                            N_Selected_Component)
+         then
             Analyze_Global_Item (List, Global_Mode);
 
          --  Simple global list or moded global list declaration
@@ -16338,7 +16341,7 @@ package body Sem_Prag is
          -- SPARK_Mode --
          ----------------
 
-         --  pragma SPARK_Mode (On | Off | Auto);
+         --  pragma SPARK_Mode [(On | Off | Auto)];
 
          when Pragma_SPARK_Mode => SPARK_Mod : declare
             procedure Chain_Pragma (Context : Entity_Id; Prag : Node_Id);
@@ -18369,7 +18372,10 @@ package body Sem_Prag is
       begin
          --  Single global item declaration
 
-         if Nkind_In (List, N_Identifier, N_Selected_Component) then
+         if Nkind_In (List, N_Expanded_Name,
+                            N_Identifier,
+                            N_Selected_Component)
+         then
             Collect_Global_Item (List, Mode);
 
          --  Simple global list or moded global list declaration
@@ -18596,16 +18602,24 @@ package body Sem_Prag is
    -----------------------
 
    function Get_SPARK_Mode_Id (N : Node_Id) return SPARK_Mode_Id is
+      Args : List_Id;
       Mode : Node_Id;
 
    begin
-      pragma Assert
-        (Nkind (N) = N_Pragma
-          and then Present (Pragma_Argument_Associations (N)));
+      pragma Assert (Nkind (N) = N_Pragma);
+      Args := Pragma_Argument_Associations (N);
+
+      --  Extract the mode from the argument list
 
-      Mode := First (Pragma_Argument_Associations (N));
+      if Present (Args) then
+         Mode := First (Pragma_Argument_Associations (N));
+         return Get_SPARK_Mode_Id (Chars (Get_Pragma_Arg (Mode)));
 
-      return Get_SPARK_Mode_Id (Chars (Get_Pragma_Arg (Mode)));
+      --  When SPARK_Mode appears without an argument, the default is ON
+
+      else
+         return SPARK_On;
+      end if;
    end Get_SPARK_Mode_Id;
 
    ----------------