exp_intr.adb (Write_Entity_Name): Moved to outer level
[gcc.git] / gcc / ada / exp_intr.adb
index 163258293142eb53391deaf0fc2f350c63d253fc..aa73839d88741873b0fca68864d8a754bfdf197a 100644 (file)
@@ -6,7 +6,7 @@
 --                                                                          --
 --                                 B o d y                                  --
 --                                                                          --
---          Copyright (C) 1992-2011, Free Software Foundation, Inc.         --
+--          Copyright (C) 1992-2014, Free Software Foundation, Inc.         --
 --                                                                          --
 -- GNAT is free software;  you can  redistribute it  and/or modify it under --
 -- terms of the  GNU General Public License as published  by the Free Soft- --
@@ -27,7 +27,7 @@ with Atree;    use Atree;
 with Checks;   use Checks;
 with Einfo;    use Einfo;
 with Elists;   use Elists;
-with Errout;   use Errout;
+with Expander; use Expander;
 with Exp_Atag; use Exp_Atag;
 with Exp_Ch4;  use Exp_Ch4;
 with Exp_Ch7;  use Exp_Ch7;
@@ -36,7 +36,6 @@ with Exp_Code; use Exp_Code;
 with Exp_Fixd; use Exp_Fixd;
 with Exp_Util; use Exp_Util;
 with Freeze;   use Freeze;
-with Namet;    use Namet;
 with Nmake;    use Nmake;
 with Nlists;   use Nlists;
 with Opt;      use Opt;
@@ -44,6 +43,7 @@ with Restrict; use Restrict;
 with Rident;   use Rident;
 with Rtsfind;  use Rtsfind;
 with Sem;      use Sem;
+with Sem_Aux;  use Sem_Aux;
 with Sem_Eval; use Sem_Eval;
 with Sem_Res;  use Sem_Res;
 with Sem_Type; use Sem_Type;
@@ -108,10 +108,102 @@ package body Exp_Intr is
    procedure Expand_Source_Info (N : Node_Id; Nam : Name_Id);
    --  Rewrite the node by the appropriate string or positive constant.
    --  Nam can be one of the following:
-   --    Name_File             - expand string that is the name of source file
-   --    Name_Line             - expand integer line number
-   --    Name_Source_Location  - expand string of form file:line
-   --    Name_Enclosing_Entity - expand string  with name of enclosing entity
+   --    Name_File                  - expand string name of source file
+   --    Name_Line                  - expand integer line number
+   --    Name_Source_Location       - expand string of form file:line
+   --    Name_Enclosing_Entity      - expand string name of enclosing entity
+   --    Name_Compilation_Date      - expand string with compilation date
+   --    Name_Compilation_Time      - expand string with compilation time
+
+   procedure Write_Entity_Name (E : Entity_Id);
+   --  Recursive procedure to construct string for qualified name of enclosing
+   --  program unit. The qualification stops at an enclosing scope has no
+   --  source name (block or loop). If entity is a subprogram instance, skip
+   --  enclosing wrapper package. The name is appended to the current contents
+   --  of Name_Buffer, incrementing Name_Len.
+
+   ---------------------
+   -- Add_Source_Info --
+   ---------------------
+
+   procedure Add_Source_Info (Loc : Source_Ptr; Nam : Name_Id) is
+      Ent : Entity_Id;
+
+      Save_NB : constant String  := Name_Buffer (1 .. Name_Len);
+      Save_NL : constant Natural := Name_Len;
+      --  Save current Name_Buffer contents
+
+   begin
+      Name_Len := 0;
+
+      --  Line
+
+      case Nam is
+
+         when Name_Line =>
+            Add_Nat_To_Name_Buffer (Nat (Get_Logical_Line_Number (Loc)));
+
+         when Name_File =>
+            Get_Decoded_Name_String
+              (Reference_Name (Get_Source_File_Index (Loc)));
+
+         when Name_Source_Location =>
+            Build_Location_String (Loc);
+
+         when Name_Enclosing_Entity =>
+
+            --  Skip enclosing blocks to reach enclosing unit
+
+            Ent := Current_Scope;
+            while Present (Ent) loop
+               exit when Ekind (Ent) /= E_Block
+                 and then Ekind (Ent) /= E_Loop;
+               Ent := Scope (Ent);
+            end loop;
+
+            --  Ent now points to the relevant defining entity
+
+            Write_Entity_Name (Ent);
+
+         when Name_Compilation_Date =>
+            declare
+               subtype S13 is String (1 .. 3);
+               Months : constant array (1 .. 12) of S13 :=
+                          ("Jan", "Feb", "Mar", "Apr", "May", "Jun",
+                           "Jul", "Aug", "Sep", "Oct", "Nov", "Dec");
+
+               M1 : constant Character := Opt.Compilation_Time (6);
+               M2 : constant Character := Opt.Compilation_Time (7);
+
+               MM : constant Natural range 1 .. 12 :=
+                      (Character'Pos (M1) - Character'Pos ('0')) * 10 +
+                 (Character'Pos (M2) - Character'Pos ('0'));
+
+            begin
+               --  Reformat ISO date into MMM DD YYYY (__DATE__) format
+
+               Name_Buffer (1 .. 3)  := Months (MM);
+               Name_Buffer (4)       := ' ';
+               Name_Buffer (5 .. 6)  := Opt.Compilation_Time (9 .. 10);
+               Name_Buffer (7)       := ' ';
+               Name_Buffer (8 .. 11) := Opt.Compilation_Time (1 .. 4);
+               Name_Len := 11;
+            end;
+
+         when Name_Compilation_Time =>
+            Name_Buffer (1 .. 8) := Opt.Compilation_Time (12 .. 19);
+            Name_Len := 8;
+
+         when others =>
+            raise Program_Error;
+      end case;
+
+      --  Prepend original Name_Buffer contents
+
+      Name_Buffer (Save_NL + 1 .. Save_NL + Name_Len) :=
+        Name_Buffer (1 .. Name_Len);
+      Name_Buffer (1 .. Save_NL) := Save_NB;
+   end Add_Source_Info;
 
    ---------------------------------
    -- Expand_Binary_Operator_Call --
@@ -209,6 +301,15 @@ package body Exp_Intr is
       Result_Typ : Entity_Id;
 
    begin
+      --  Remove side effects from tag argument early, before rewriting
+      --  the dispatching constructor call, as Remove_Side_Effects relies
+      --  on Tag_Arg's Parent link properly attached to the tree (once the
+      --  call is rewritten, the Parent is inconsistent as it points to the
+      --  rewritten node, which is not the syntactic parent of the Tag_Arg
+      --  anymore).
+
+      Remove_Side_Effects (Tag_Arg);
+
       --  The subprogram is the third actual in the instantiation, and is
       --  retrieved from the corresponding renaming declaration. However,
       --  freeze nodes may appear before, so we retrieve the declaration
@@ -222,15 +323,10 @@ package body Exp_Intr is
       Act_Constr := Entity (Name (Act_Rename));
       Result_Typ := Class_Wide_Type (Etype (Act_Constr));
 
-      --  Ada 2005 (AI-251): If the result is an interface type, the function
-      --  returns a class-wide interface type (otherwise the resulting object
-      --  would be abstract!)
-
       if Is_Interface (Etype (Act_Constr)) then
-         Set_Etype (Act_Constr, Result_Typ);
 
-         --  If the result type is not parent of Tag_Arg then we need to
-         --  locate the tag of the secondary dispatch table.
+         --  If the result type is not known to be a parent of Tag_Arg then we
+         --  need to locate the tag of the secondary dispatch table.
 
          if not Is_Ancestor (Etype (Result_Typ), Etype (Tag_Arg),
                              Use_Full_View => True)
@@ -242,7 +338,7 @@ package body Exp_Intr is
 
             declare
                Fname : constant Node_Id :=
-                         New_Reference_To (RTE (RE_Secondary_Tag), Loc);
+                         New_Occurrence_Of (RTE (RE_Secondary_Tag), Loc);
 
             begin
                pragma Assert (not Is_Interface (Etype (Tag_Arg)));
@@ -251,13 +347,13 @@ package body Exp_Intr is
                  Make_Object_Declaration (Loc,
                    Defining_Identifier => Make_Temporary (Loc, 'V'),
                    Object_Definition   =>
-                     New_Reference_To (RTE (RE_Tag), Loc),
+                     New_Occurrence_Of (RTE (RE_Tag), Loc),
                    Expression          =>
                      Make_Function_Call (Loc,
-                       Name => Fname,
+                       Name                   => Fname,
                        Parameter_Associations => New_List (
                          Relocate_Node (Tag_Arg),
-                         New_Reference_To
+                         New_Occurrence_Of
                            (Node (First_Elmt (Access_Disp_Table
                                                (Etype (Etype (Act_Constr))))),
                             Loc))));
@@ -282,7 +378,6 @@ package body Exp_Intr is
          Set_Controlling_Argument (Cnstr_Call,
            New_Occurrence_Of (Defining_Identifier (Iface_Tag), Loc));
       else
-         Remove_Side_Effects (Tag_Arg);
          Set_Controlling_Argument (Cnstr_Call,
            Relocate_Node (Tag_Arg));
       end if;
@@ -313,14 +408,14 @@ package body Exp_Intr is
 
       elsif not Is_Interface (Result_Typ) then
          declare
-            Obj_Tag_Node : Node_Id := Duplicate_Subexpr (Tag_Arg);
+            Obj_Tag_Node : Node_Id := New_Copy_Tree (Tag_Arg);
             CW_Test_Node : Node_Id;
 
          begin
             Build_CW_Membership (Loc,
               Obj_Tag_Node => Obj_Tag_Node,
               Typ_Tag_Node =>
-                New_Reference_To (
+                New_Occurrence_Of (
                    Node (First_Elmt (Access_Disp_Table (
                                        Root_Type (Result_Typ)))), Loc),
               Related_Nod => N,
@@ -347,10 +442,10 @@ package body Exp_Intr is
                     Name => New_Occurrence_Of (RTE (RE_IW_Membership), Loc),
                     Parameter_Associations => New_List (
                       Make_Attribute_Reference (Loc,
-                        Prefix         => Duplicate_Subexpr (Tag_Arg),
+                        Prefix         => New_Copy_Tree (Tag_Arg),
                         Attribute_Name => Name_Address),
 
-                      New_Reference_To (
+                      New_Occurrence_Of (
                         Node (First_Elmt (Access_Disp_Table (
                                             Root_Type (Result_Typ)))), Loc)))),
              Then_Statements =>
@@ -417,7 +512,7 @@ package body Exp_Intr is
                   New_Occurrence_Of (Choice_Parameter (P), Loc))));
             exit;
 
-         --  Keep climbing!
+         --  Keep climbing
 
          else
             P := Parent (P);
@@ -450,7 +545,7 @@ package body Exp_Intr is
             New_Occurrence_Of (Standard_Character, Loc)),
 
         Make_Pragma (Loc,
-          Chars => Name_Import,
+          Chars                        => Name_Import,
           Pragma_Argument_Associations => New_List (
             Make_Pragma_Argument_Association (Loc,
               Expression => Make_Identifier (Loc, Name_Ada)),
@@ -514,11 +609,9 @@ package body Exp_Intr is
       elsif Nam = Name_Generic_Dispatching_Constructor then
          Expand_Dispatching_Constructor_Call (N);
 
-      elsif Nam = Name_Import_Address
-              or else
-            Nam = Name_Import_Largest_Value
-              or else
-            Nam = Name_Import_Value
+      elsif Nam_In (Nam, Name_Import_Address,
+                         Name_Import_Largest_Value,
+                         Name_Import_Value)
       then
          Expand_Import_Call (N);
 
@@ -552,10 +645,12 @@ package body Exp_Intr is
       elsif Nam = Name_To_Pointer then
          Expand_To_Pointer (N);
 
-      elsif Nam = Name_File
-        or else Nam = Name_Line
-        or else Nam = Name_Source_Location
-        or else Nam = Name_Enclosing_Entity
+      elsif Nam_In (Nam, Name_File,
+                         Name_Line,
+                         Name_Source_Location,
+                         Name_Enclosing_Entity,
+                         Name_Compilation_Date,
+                         Name_Compilation_Time)
       then
          Expand_Source_Info (N, Nam);
 
@@ -564,16 +659,15 @@ package body Exp_Intr is
          --  conventions and this has already been checked.
 
       elsif Present (Alias (E)) then
-         Expand_Intrinsic_Call (N,  Alias (E));
+         Expand_Intrinsic_Call (N, Alias (E));
 
       elsif Nkind (N) in N_Binary_Op then
          Expand_Binary_Operator_Call (N);
 
-         --  The only other case is where an external name was specified,
-         --  since this is the only way that an otherwise unrecognized
-         --  name could escape the checking in Sem_Prag. Nothing needs
-         --  to be done in such a case, since we pass such a call to the
-         --  back end unchanged.
+         --  The only other case is where an external name was specified, since
+         --  this is the only way that an otherwise unrecognized name could
+         --  escape the checking in Sem_Prag. Nothing needs to be done in such
+         --  a case, since we pass such a call to the back end unchanged.
 
       else
          null;
@@ -603,7 +697,7 @@ package body Exp_Intr is
       --    end if;
 
       Rewrite (N,
-        Make_Conditional_Expression (Loc,
+        Make_If_Expression (Loc,
           Expressions => New_List (
             Make_Op_Lt (Loc,
               Left_Opnd  => Duplicate_Subexpr (Opnd),
@@ -611,7 +705,7 @@ package body Exp_Intr is
 
             New_Occurrence_Of (Standard_True, Loc),
 
-            Make_Conditional_Expression (Loc,
+            Make_If_Expression (Loc,
              Expressions => New_List (
                Make_Op_Gt (Loc,
                  Left_Opnd  => Duplicate_Subexpr_No_Checks (Opnd),
@@ -643,27 +737,27 @@ package body Exp_Intr is
 
    --  As a result, whenever a shift is used in the source program, it will
    --  remain as a call until converted by this routine to the operator node
-   --  form which Gigi is expecting to see.
+   --  form which the back end is expecting to see.
 
    --  Note: it is possible for the expander to generate shift operator nodes
    --  directly, which will be analyzed in the normal manner by calling Analyze
    --  and Resolve. Such shift operator nodes will not be seen by Expand_Shift.
 
    procedure Expand_Shift (N : Node_Id; E : Entity_Id; K : Node_Kind) is
-      Loc   : constant Source_Ptr := Sloc (N);
-      Typ   : constant Entity_Id  := Etype (N);
+      Entyp : constant Entity_Id  := Etype (E);
       Left  : constant Node_Id    := First_Actual (N);
+      Loc   : constant Source_Ptr := Sloc (N);
       Right : constant Node_Id    := Next_Actual (Left);
       Ltyp  : constant Node_Id    := Etype (Left);
       Rtyp  : constant Node_Id    := Etype (Right);
+      Typ   : constant Entity_Id  := Etype (N);
       Snode : Node_Id;
 
    begin
       Snode := New_Node (K, Loc);
-      Set_Left_Opnd  (Snode, Relocate_Node (Left));
       Set_Right_Opnd (Snode, Relocate_Node (Right));
       Set_Chars      (Snode, Chars (E));
-      Set_Etype      (Snode, Base_Type (Typ));
+      Set_Etype      (Snode, Base_Type (Entyp));
       Set_Entity     (Snode, E);
 
       if Compile_Time_Known_Value (Type_High_Bound (Rtyp))
@@ -672,76 +766,46 @@ package body Exp_Intr is
          Set_Shift_Count_OK (Snode, True);
       end if;
 
-      --  Do the rewrite. Note that we don't call Analyze and Resolve on
-      --  this node, because it already got analyzed and resolved when
-      --  it was a function call!
+      if Typ = Entyp then
 
-      Rewrite (N, Snode);
-      Set_Analyzed (N);
-   end Expand_Shift;
-
-   ------------------------
-   -- Expand_Source_Info --
-   ------------------------
-
-   procedure Expand_Source_Info (N : Node_Id; Nam : Name_Id) is
-      Loc : constant Source_Ptr := Sloc (N);
-      Ent : Entity_Id;
+         --  Note that we don't call Analyze and Resolve on this node, because
+         --  it already got analyzed and resolved when it was a function call.
 
-      procedure Write_Entity_Name (E : Entity_Id);
-      --  Recursive procedure to construct string for qualified name of
-      --  enclosing program unit. The qualification stops at an enclosing
-      --  scope has no source name (block or loop). If entity is a subprogram
-      --  instance, skip enclosing wrapper package.
+         Set_Left_Opnd (Snode, Relocate_Node (Left));
+         Rewrite (N, Snode);
+         Set_Analyzed (N);
 
-      -----------------------
-      -- Write_Entity_Name --
-      -----------------------
-
-      procedure Write_Entity_Name (E : Entity_Id) is
-         SDef : Source_Ptr;
-         TDef : constant Source_Buffer_Ptr :=
-                  Source_Text (Get_Source_File_Index (Sloc (E)));
-
-      begin
-         --  Nothing to do if at outer level
-
-         if Scope (E) = Standard_Standard then
-            null;
-
-         --  If scope comes from source, write its name
-
-         elsif Comes_From_Source (Scope (E)) then
-            Write_Entity_Name (Scope (E));
-            Add_Char_To_Name_Buffer ('.');
-
-         --  If in wrapper package skip past it
+         --  However, we do call the expander, so that the expansion for
+         --  rotates and shift_right_arithmetic happens if Modify_Tree_For_C
+         --  is set.
 
-         elsif Is_Wrapper_Package (Scope (E)) then
-            Write_Entity_Name (Scope (Scope (E)));
-            Add_Char_To_Name_Buffer ('.');
+         if Expander_Active then
+            Expand (N);
+         end if;
 
-         --  Otherwise nothing to output (happens in unnamed block statements)
+      else
+         --  If the context type is not the type of the operator, it is an
+         --  inherited operator for a derived type. Wrap the node in a
+         --  conversion so that it is type-consistent for possible further
+         --  expansion (e.g. within a lock-free protected type).
 
-         else
-            null;
-         end if;
+         Set_Left_Opnd (Snode,
+           Unchecked_Convert_To (Base_Type (Entyp), Relocate_Node (Left)));
+         Rewrite (N, Unchecked_Convert_To (Typ, Snode));
 
-         --  Loop to output the name
+         --  Analyze and resolve result formed by conversion to target type
 
-         --  is this right wrt wide char encodings ??? (no!)
+         Analyze_And_Resolve (N, Typ);
+      end if;
+   end Expand_Shift;
 
-         SDef := Sloc (E);
-         while TDef (SDef) in '0' .. '9'
-           or else TDef (SDef) >= 'A'
-           or else TDef (SDef) = ASCII.ESC
-         loop
-            Add_Char_To_Name_Buffer (TDef (SDef));
-            SDef := SDef + 1;
-         end loop;
-      end Write_Entity_Name;
+   ------------------------
+   -- Expand_Source_Info --
+   ------------------------
 
-   --  Start of processing for Expand_Source_Info
+   procedure Expand_Source_Info (N : Node_Id; Nam : Name_Id) is
+      Loc : constant Source_Ptr := Sloc (N);
+      Ent : Entity_Id;
 
    begin
       --  Integer cases
@@ -780,6 +844,35 @@ package body Exp_Intr is
 
                Write_Entity_Name (Ent);
 
+            when Name_Compilation_Date =>
+               declare
+                  subtype S13 is String (1 .. 3);
+                  Months : constant array (1 .. 12) of S13 :=
+                    ("Jan", "Feb", "Mar", "Apr", "May", "Jun",
+                     "Jul", "Aug", "Sep", "Oct", "Nov", "Dec");
+
+                  M1 : constant Character := Opt.Compilation_Time (6);
+                  M2 : constant Character := Opt.Compilation_Time (7);
+
+                  MM : constant Natural range 1 .. 12 :=
+                    (Character'Pos (M1) - Character'Pos ('0')) * 10 +
+                    (Character'Pos (M2) - Character'Pos ('0'));
+
+               begin
+                  --  Reformat ISO date into MMM DD YYYY (__DATE__) format
+
+                  Name_Buffer (1 .. 3)  := Months (MM);
+                  Name_Buffer (4)       := ' ';
+                  Name_Buffer (5 .. 6)  := Opt.Compilation_Time (9 .. 10);
+                  Name_Buffer (7)       := ' ';
+                  Name_Buffer (8 .. 11) := Opt.Compilation_Time (1 .. 4);
+                  Name_Len := 11;
+               end;
+
+            when Name_Compilation_Time =>
+               Name_Buffer (1 .. 8) := Opt.Compilation_Time (12 .. 19);
+               Name_Len := 8;
+
             when others =>
                raise Program_Error;
          end case;
@@ -888,6 +981,7 @@ package body Exp_Intr is
       Finalizer_Data  : Finalization_Exception_Data;
 
       Blk        : Node_Id := Empty;
+      Blk_Id     : Entity_Id;
       Deref      : Node_Id;
       Final_Code : List_Id;
       Free_Arg   : Node_Id;
@@ -900,6 +994,10 @@ package body Exp_Intr is
       --  that we analyze some generated statements before properly attaching
       --  them to the tree, and that can disturb current value settings.
 
+      Dummy : Entity_Id;
+      --  This variable captures an unused dummy internal entity, see the
+      --  comment associated with its use.
+
    begin
       --  Nothing to do if we know the argument is null
 
@@ -964,19 +1062,15 @@ package body Exp_Intr is
            Make_Block_Statement (Loc,
              Handled_Statement_Sequence =>
                Make_Handled_Sequence_Of_Statements (Loc,
-                 Statements => New_List (
-                   Make_Final_Call (
-                     Obj_Ref => Deref,
-                     Typ     => Desig_T)),
+                 Statements         => New_List (
+                   Make_Final_Call (Obj_Ref => Deref, Typ => Desig_T)),
                  Exception_Handlers => New_List (
                    Build_Exception_Handler (Finalizer_Data)))));
 
          --  For .NET/JVM, detach the object from the containing finalization
          --  collection before finalizing it.
 
-         if VM_Target /= No_VM
-           and then Is_Controlled (Desig_T)
-         then
+         if VM_Target /= No_VM and then Is_Controlled (Desig_T) then
             Prepend_To (Final_Code,
               Make_Detach_Call (New_Copy_Tree (Arg)));
          end if;
@@ -985,8 +1079,7 @@ package body Exp_Intr is
          --  protected by an abort defer/undefer pair.
 
          if Abort_Allowed then
-            Prepend_To (Final_Code,
-              Build_Runtime_Call (Loc, RE_Abort_Defer));
+            Prepend_To (Final_Code, Build_Runtime_Call (Loc, RE_Abort_Defer));
 
             Blk :=
               Make_Block_Statement (Loc, Handled_Statement_Sequence =>
@@ -994,9 +1087,15 @@ package body Exp_Intr is
                   Statements  => Final_Code,
                   At_End_Proc =>
                     New_Occurrence_Of (RTE (RE_Abort_Undefer_Direct), Loc)));
+            Add_Block_Identifier (Blk, Blk_Id);
 
             Append (Blk, Stmts);
+
          else
+            --  Generate a dummy entity to ensure that the internal symbols are
+            --  in sync when a unit is compiled with and without aborts.
+
+            Dummy := New_Internal_Entity (E_Block, Current_Scope, Loc, 'B');
             Append_List_To (Stmts, Final_Code);
          end if;
       end if;
@@ -1004,40 +1103,12 @@ package body Exp_Intr is
       --  For a task type, call Free_Task before freeing the ATCB
 
       if Is_Task_Type (Desig_T) then
-         declare
-            Stat : Node_Id := Prev (N);
-            Nam1 : Node_Id;
-            Nam2 : Node_Id;
 
-         begin
-            --  An Abort followed by a Free will not do what the user
-            --  expects, because the abort is not immediate. This is
-            --  worth a friendly warning.
-
-            while Present (Stat)
-              and then not Comes_From_Source (Original_Node (Stat))
-            loop
-               Prev (Stat);
-            end loop;
-
-            if Present (Stat)
-              and then Nkind (Original_Node (Stat)) = N_Abort_Statement
-            then
-               Stat := Original_Node (Stat);
-               Nam1 := First (Names (Stat));
-               Nam2 := Original_Node (First (Parameter_Associations (N)));
-
-               if Nkind (Nam1) = N_Explicit_Dereference
-                 and then Is_Entity_Name (Prefix (Nam1))
-                 and then Is_Entity_Name (Nam2)
-                 and then Entity (Prefix (Nam1)) = Entity (Nam2)
-               then
-                  Error_Msg_N ("abort may take time to complete?", N);
-                  Error_Msg_N ("\deallocation might have no effect?", N);
-                  Error_Msg_N ("\safer to wait for termination.?", N);
-               end if;
-            end if;
-         end;
+         --  We used to detect the case of Abort followed by a Free here,
+         --  because the Free wouldn't actually free if it happens before
+         --  the aborted task actually terminates. The warning was removed,
+         --  because Free now works properly (the task will be freed once
+         --  it terminates).
 
          Append_To
            (Stmts, Cleanup_Task (N, Duplicate_Subexpr_No_Checks (Arg)));
@@ -1069,9 +1140,11 @@ package body Exp_Intr is
          end if;
       end if;
 
-      --  Normal processing for non-controlled types
+      --  Normal processing for non-controlled types. The argument to free is
+      --  a renaming rather than a constant to ensure that the original context
+      --  is always set to null after the deallocation takes place.
 
-      Free_Arg := Duplicate_Subexpr_No_Checks (Arg);
+      Free_Arg  := Duplicate_Subexpr_No_Checks (Arg, Renaming_Req => True);
       Free_Node := Make_Free_Statement (Loc, Empty);
       Append_To (Stmts, Free_Node);
       Set_Storage_Pool (Free_Node, Pool);
@@ -1089,6 +1162,33 @@ package body Exp_Intr is
          if Is_RTE (Pool, RE_SS_Pool) then
             null;
 
+         --  If the pool object is of a simple storage pool type, then attempt
+         --  to locate the type's Deallocate procedure, if any, and set the
+         --  free operation's procedure to call. If the type doesn't have a
+         --  Deallocate (which is allowed), then the actual will simply be set
+         --  to null.
+
+         elsif Present (Get_Rep_Pragma
+                          (Etype (Pool), Name_Simple_Storage_Pool_Type))
+         then
+            declare
+               Pool_Type  : constant Entity_Id := Base_Type (Etype (Pool));
+               Dealloc_Op : Entity_Id;
+            begin
+               Dealloc_Op := Get_Name_Entity_Id (Name_Deallocate);
+               while Present (Dealloc_Op) loop
+                  if Scope (Dealloc_Op) = Scope (Pool_Type)
+                    and then Present (First_Formal (Dealloc_Op))
+                    and then Etype (First_Formal (Dealloc_Op)) = Pool_Type
+                  then
+                     Set_Procedure_To_Call (Free_Node, Dealloc_Op);
+                     exit;
+                  else
+                     Dealloc_Op := Homonym (Dealloc_Op);
+                  end if;
+               end loop;
+            end;
+
          --  Case of a class-wide pool type: make a dispatching call to
          --  Deallocate through the class-wide Deallocate_Any.
 
@@ -1105,9 +1205,9 @@ package body Exp_Intr is
 
       if Present (Procedure_To_Call (Free_Node)) then
 
-         --  For all cases of a Deallocate call, the back-end needs to be
-         --  able to compute the size of the object being freed. This may
-         --  require some adjustments for objects of dynamic size.
+         --  For all cases of a Deallocate call, the back-end needs to be able
+         --  to compute the size of the object being freed. This may require
+         --  some adjustments for objects of dynamic size.
          --
          --  If the type is class wide, we generate an implicit type with the
          --  right dynamic size, so that the deallocate call gets the right
@@ -1117,8 +1217,8 @@ package body Exp_Intr is
          if Is_Class_Wide_Type (Desig_T)
            or else
             (Is_Array_Type (Desig_T)
-               and then not Is_Constrained (Desig_T)
-               and then Is_Packed (Desig_T))
+              and then not Is_Constrained (Desig_T)
+              and then Is_Packed (Desig_T))
          then
             declare
                Deref    : constant Node_Id :=
@@ -1128,6 +1228,10 @@ package body Exp_Intr is
                D_Type   : Entity_Id;
 
             begin
+               --  Perform minor decoration as it is needed by the side effect
+               --  removal mechanism.
+
+               Set_Etype  (Deref, Desig_T);
                Set_Parent (Deref, Free_Node);
                D_Subtyp := Make_Subtype_From_Expr (Deref, Desig_T);
 
@@ -1168,7 +1272,7 @@ package body Exp_Intr is
          Set_Expression (Free_Node,
            Unchecked_Convert_To (Typ,
              Make_Function_Call (Loc,
-               Name => New_Reference_To (RTE (RE_Base_Address), Loc),
+               Name => New_Occurrence_Of (RTE (RE_Base_Address), Loc),
                Parameter_Associations => New_List (
                  Unchecked_Convert_To (RTE (RE_Address), Free_Arg)))));
 
@@ -1179,8 +1283,8 @@ package body Exp_Intr is
          Set_Expression (Free_Node, Free_Arg);
       end if;
 
-      --  Only remaining step is to set result to null, or generate a
-      --  raise of constraint error if the target object is "not null".
+      --  Only remaining step is to set result to null, or generate a raise of
+      --  Constraint_Error if the target object is "not null".
 
       if Can_Never_Be_Null (Etype (Arg)) then
          Append_To (Stmts,
@@ -1267,7 +1371,7 @@ package body Exp_Intr is
       Obj := Make_Explicit_Dereference (Loc, Relocate_Node (Arg));
 
       Rewrite (N,
-        Make_Conditional_Expression (Loc,
+        Make_If_Expression (Loc,
           Expressions => New_List (
             Make_Op_Eq (Loc,
               Left_Opnd => New_Copy_Tree (Arg),
@@ -1292,4 +1396,70 @@ package body Exp_Intr is
       Analyze (N);
    end Expand_To_Pointer;
 
+   -----------------------
+   -- Write_Entity_Name --
+   -----------------------
+
+   procedure Write_Entity_Name (E : Entity_Id) is
+      SDef : Source_Ptr;
+      TDef : constant Source_Buffer_Ptr :=
+               Source_Text (Get_Source_File_Index (Sloc (E)));
+
+   begin
+      --  Nothing to do if at outer level
+
+      if Scope (E) = Standard_Standard then
+         null;
+
+         --  If scope comes from source, write its name
+
+      elsif Comes_From_Source (Scope (E)) then
+         Write_Entity_Name (Scope (E));
+         Add_Char_To_Name_Buffer ('.');
+
+         --  If in wrapper package skip past it
+
+      elsif Is_Wrapper_Package (Scope (E)) then
+         Write_Entity_Name (Scope (Scope (E)));
+         Add_Char_To_Name_Buffer ('.');
+
+         --  Otherwise nothing to output (happens in unnamed block statements)
+
+      else
+         null;
+      end if;
+
+      --  Output the name
+
+      SDef := Sloc (E);
+
+      --  Check for operator name in quotes
+
+      if TDef (SDef) = '"' then
+         Add_Char_To_Name_Buffer ('"');
+
+         --  Loop to output characters of operator name and terminating quote
+
+         loop
+            SDef := SDef + 1;
+            Add_Char_To_Name_Buffer (TDef (SDef));
+            exit when TDef (SDef) = '"';
+         end loop;
+
+      --  Normal case of identifier
+
+      else
+         --  Loop to output the name
+
+         --  This is not right wrt wide char encodings ??? ()
+
+         while TDef (SDef) in '0' .. '9'
+           or else TDef (SDef) >= 'A'
+           or else TDef (SDef) = ASCII.ESC
+         loop
+            Add_Char_To_Name_Buffer (TDef (SDef));
+            SDef := SDef + 1;
+         end loop;
+      end if;
+   end Write_Entity_Name;
 end Exp_Intr;