home *** CD-ROM | disk | FTP | other *** search
/ Geek Gadgets 1 / ADE-1.bin / ade-dist / gnat-2.06-src.tgz / tar.out / fsf / gnat / ada / exp_ch7.adb < prev    next >
Text File  |  1996-09-28  |  67KB  |  1,925 lines

  1. -----------------------------------------------------------------------------
  2. --                                                                          --
  3. --                         GNAT COMPILER COMPONENTS                         --
  4. --                                                                          --
  5. --                              E X P _ C H 7                               --
  6. --                                                                          --
  7. --                                 B o d y                                  --
  8. --                                                                          --
  9. --                            $Revision: 1.96 $                             --
  10. --                                                                          --
  11. --       Copyright (c) 1992,1993,1994,1995 NYU, All Rights Reserved         --
  12. --                                                                          --
  13. -- GNAT is free software;  you can  redistribute it  and/or modify it under --
  14. -- terms of the  GNU General Public License as published  by the Free Soft- --
  15. -- ware  Foundation;  either version 2,  or (at your option) any later ver- --
  16. -- sion.  GNAT is distributed in the hope that it will be useful, but WITH- --
  17. -- OUT ANY WARRANTY;  without even the  implied warranty of MERCHANTABILITY --
  18. -- or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License --
  19. -- for  more details.  You should have  received  a copy of the GNU General --
  20. -- Public License  distributed with GNAT;  see file COPYING.  If not, write --
  21. -- to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. --
  22. --                                                                          --
  23. ------------------------------------------------------------------------------
  24.  
  25. --  This package contains virtually all expansion mechanisms related to
  26. --    - controlled types
  27. --    - transient scopes
  28.  
  29. with Atree;    use Atree;
  30. with Debug;    use Debug;
  31. with Einfo;    use Einfo;
  32. with Expander; use Expander;
  33. with Exp_Ch9;  use Exp_Ch9;
  34. with Exp_TSS;  use Exp_TSS;
  35. with Exp_Util; use Exp_Util;
  36. with Nlists;   use Nlists;
  37. with Nmake;    use Nmake;
  38. with Output;   use Output;
  39. with Rtsfind;  use Rtsfind;
  40. with Sinfo;    use Sinfo;
  41. with Sem;      use Sem;
  42. with Sem_Ch3;  use Sem_Ch3;
  43. with Sem_Ch8;  use Sem_Ch8;
  44. with Sem_Res;  use Sem_Res;
  45. with Sem_Util; use Sem_Util;
  46. with Snames;   use Snames;
  47. with Stand;    use Stand;
  48. with Tbuild;   use Tbuild;
  49. with Uintp;    use Uintp;
  50.  
  51. package body Exp_Ch7 is
  52.  
  53.    ---------------------------
  54.    -- Expand_N_Package_Body --
  55.    ---------------------------
  56.  
  57.    --  Add call to Activate_Tasks if body is an activator (actual
  58.    --  processing is in chapter 9).
  59.  
  60.    procedure Expand_N_Package_Body (N : Node_Id) is
  61.    begin
  62.       if Ekind (Corresponding_Spec (N)) = E_Package then
  63.          New_Scope (Corresponding_Spec (N));
  64.          Build_Task_Activation_Call (N);
  65.          Pop_Scope;
  66.       end if;
  67.    end Expand_N_Package_Body;
  68.  
  69.    ----------------------------------
  70.    -- Expand_N_Package_Declaration --
  71.    ----------------------------------
  72.  
  73.    --  Add call to Activate_Tasks if there are tasks declared and the
  74.    --  package has no body. Note that in Ada83,  this may result in
  75.    --  premature activation of some tasks, given that we cannot tell
  76.    --  whether a body will eventually appear.
  77.  
  78.    procedure Expand_N_Package_Declaration (N : Node_Id) is
  79.    begin
  80.       if Nkind (Parent (N)) = N_Compilation_Unit
  81.         and then not Body_Required (Parent (N))
  82.         and then Present (Activation_Chain_Entity (N))
  83.       then
  84.          New_Scope (Defining_Unit_Simple_Name (Specification (N)));
  85.          Build_Task_Activation_Call (N);
  86.          Pop_Scope;
  87.       end if;
  88.    end Expand_N_Package_Declaration;
  89.  
  90.  
  91.    --------------------------------------------------
  92.    -- Transient Blocks and Finalization Management --
  93.    --------------------------------------------------
  94.  
  95.    function Find_Node_To_Be_Wrapped (N : Node_Id) return Node_Id;
  96.    --  N is a node wich may generate a transient scope.  Loop over the
  97.    --  parent pointers of N until it find the appropriate node to
  98.    --  wrap. It it returns Empty, it means that no transient scope is
  99.    --  needed in this context.
  100.  
  101.    function Make_Clean
  102.      (Clean     : Entity_Id;
  103.       Mark      : Entity_Id;
  104.       Flist     : Entity_Id;
  105.       Is_Task   : Boolean;
  106.       Is_Master : Boolean)
  107.       return      Node_Id;
  108.    --  Expand a the clean-up procedure for controlled and/or transient
  109.    --  block, and/or task master or task body. Clean is the entity for
  110.    --  such a procedure. Mark is the entity for the secondary stack
  111.    --  mark, if empty only controlled block clean-up will be
  112.    --  performed. Flist is the entity for the local final list, if empty
  113.    --  only transient scope clean-up will be performed. The flags
  114.    --  Is_Task and Is_Master control the calls to the corresponding
  115.    --  finalization actions for a task body or for an entity that is a
  116.    --  task master.
  117.  
  118.    procedure Set_Scope_Is_Transient (V : Boolean := True);
  119.    --  Set the flag Is_Transient of the current scope
  120.  
  121.    procedure Set_Node_To_Be_Wrapped (N : Node_Id);
  122.    --  Set the field Node_To_Be_Wrapped of the current scope
  123.  
  124.    procedure Insert_Actions_In_Scope_Before (N : Node_Id);
  125.    --  Insert the actions kept in the scope stack after N, which must
  126.    --  be a member of a list.
  127.  
  128.    function Make_Transient_Block
  129.      (Loc         : Source_Ptr;
  130.       Instruction : Node_Id)
  131.       return        Node_Id;
  132.    --  Create a transient block whose name is Scope, which is also a
  133.    --  controlled block if Flist is not empty and whose only instruction
  134.    --  is Instruction.
  135.  
  136.  
  137.    type Final_Primitives is (Initialize_Case, Adjust_Case, Finalize_Case);
  138.    --  This enumeration type is defined in order to ease sharing code for
  139.    --  building finalization procedures for composite types.
  140.  
  141.    Name_Of      : constant array (Final_Primitives) of Name_Id :=
  142.                     (Initialize_Case => Name_Initialize,
  143.                      Adjust_Case     => Name_Adjust,
  144.                      Finalize_Case   => Name_Finalize);
  145.  
  146.    Deep_Name_Of : constant array (Final_Primitives) of Name_Id :=
  147.                     (Initialize_Case => Name_uDeep_Initialize,
  148.                      Adjust_Case     => Name_uDeep_Adjust,
  149.                      Finalize_Case   => Name_uDeep_Finalize);
  150.  
  151.    procedure Build_Record_Deep_Procs (Typ : Entity_Id);
  152.    --  Build the deep Initialize/Adjust/Finalize for a record Typ that
  153.    --  Has_Controlled components and store them using the TSS mechanism.
  154.  
  155.    procedure Build_Array_Deep_Procs (Typ : Entity_Id);
  156.    --  Build the deep Initialize/Adjust/Finalize for a record Typ that
  157.    --  Has_Controlled components and store them using the TSS mechanism.
  158.  
  159.    function Make_Deep_Proc
  160.      (Prim  : Final_Primitives;
  161.       Typ   : Entity_Id;
  162.       Stmts : List_Id)
  163.       return  Node_Id;
  164.    --  This function generates the tree for Deep_Initialize, Deep_Adjust
  165.    --  or Deep_Finalize procedures according to the first parameter,
  166.    --  these procedures operate on the type Typ.  The Stmts parameter
  167.    --  gives the body of the procedure.
  168.  
  169.    function Make_Deep_Array_Body
  170.      (Prim : Final_Primitives;
  171.       Typ  : Entity_Id)
  172.       return List_Id;
  173.    --  This function generates the list of statements for implementing
  174.    --  Deep_Initialize, Deep_Adjust or Deep_Finalize procedures
  175.    --  according to the first parameter, these procedures operate on the
  176.    --  array type Typ.
  177.  
  178.    function Make_Deep_Record_Body
  179.      (Prim : Final_Primitives;
  180.       Typ  : Entity_Id)
  181.       return List_Id;
  182.    --  This function generates the list of statements for implementing
  183.    --  Deep_Initialize, Deep_Adjust or Deep_Finalize procedures
  184.    --  according to the first parameter, these procedures operate on the
  185.    --  record type Typ.
  186.  
  187.    -----------------------------
  188.    -- Finalization Management --
  189.    -----------------------------
  190.  
  191.    --  This part describe how Initialization/Adjusment/Finalization
  192.    --  procedures are generated and called. 2 cases must be considered, type
  193.    --  that are Controlled (Is_Controlled) and composite types that contain
  194.    --  controlled components (Has_Controlled). In the first case the
  195.    --  procedures to call are the user-defined primitive operations
  196.    --  Initialize/Adjust/Finalize. In the second case, GNAT generates
  197.    --  Deep_Initialize, Deep_Adjust and Deep_Finalize that are in charge of
  198.    --  calling the former procedures on the controlled components.
  199.  
  200.    --  For 'HAS_Controlled' records a hidden 'controller' component is
  201.    --  inserted. This controller component contains its own finalization
  202.    --  list on which every controlled components are attached creating an
  203.    --  indirection on the upper-level Finalization list. This technique
  204.    --  facilitates the management of objects whose number of controlled
  205.    --  components change during execution. This controller component is
  206.    --  itself controlled and is attached to the upper-level finalization
  207.    --  chain. Its adjust primitive is in charge of calling adjust on the
  208.    --  components and adusting the finalization pointer to match their new
  209.    --  location (see a-finali.adb)
  210.  
  211.    --  It is not possible to use a similar technique for 'HAS_Controlled'
  212.    --  Arrays. So deep procedures are generated that call
  213.    --  initialize/adjust/finalize + attachment or detachment on the
  214.    --  finalization list for all component.
  215.  
  216.    --  Initizalize calls: they are generated for declarations or dynamic
  217.    --  allocations of Controlled objects with no initial value. They are
  218.    --  always followed by an attachment to the current Finalization
  219.    --  Chain. For the dynamic allocation case this the chain attached to
  220.    --  the scope of the access type definition otherwise, this is the chain
  221.    --  of the current scope.
  222.  
  223.    --  Adjust Calls: They are generated on 2 occasions: (1) for
  224.    --  declarations or dynamic allocations of Controlled objects with an
  225.    --  initial value. (2) after an assignment. In the first case they are
  226.    --  followed by an attachment to the final chain, in the second case
  227.    --  they are not.
  228.  
  229.    --  Finalization Calls: They are generated on (1) scope exit, (2)
  230.    --  assignments, (3) unchecked deallocations. In case (3) they have to
  231.    --  be detached from the final chain, in case (2) the must not and in
  232.    --  case (1) this is not important since we are exiting the scope
  233.    --  anyway.
  234.  
  235.    --  Here is a simple example of the expansion of a controlled block :
  236.  
  237.    --    declare
  238.    --       X : Controlled ;
  239.    --       Y : Controlled := Init;
  240.    --
  241.    --       type R is record
  242.    --          C : Controlled;
  243.    --       end record;
  244.    --       W : R;
  245.    --       Z : R := (C => X);
  246.    --    begin
  247.    --       X := Y;
  248.    --       W := Z;
  249.    --    end;
  250.    --
  251.    --  is expanded into
  252.    --
  253.    --    declare
  254.    --       _L : System.FI.Finalizable_Ptr;
  255.  
  256.    --       procedure _Clean is
  257.    --       begin
  258.    --          Abort_Defer;
  259.    --          System.FI.Finalize_List (_L);
  260.    --          Abort_Undefer;
  261.    --       end _Clean;
  262.  
  263.    --       X : Controlled;
  264.    --       Initialize (X);
  265.    --       Attach_To_Final_List (_L, Finalizable (X));
  266.    --       Y : Controlled := Init;
  267.    --       Adjust (Y);
  268.    --       Attach_To_Final_List (_L, Finalizable (Y));
  269.    --
  270.    --       type R is record
  271.    --         _C : Record_Controller;
  272.    --          C : Controlled;
  273.    --       end record;
  274.    --       W : R;
  275.    --       Deep_Initialize (W, _L, True);
  276.    --       Z : R := (C => X);
  277.    --       Deep_Adjust (Z, _L, True);
  278.  
  279.    --    begin
  280.    --       Finalize (X);
  281.    --       X := Y;
  282.    --       Adjust (X);
  283.  
  284.    --       Deep_Finalize (W, _L, False);
  285.    --       W := Z;
  286.    --       Deep_Adjust (W, _L, False);
  287.    --    at end
  288.    --       _Clean;
  289.    --    end;
  290.  
  291.    ------------------------------------
  292.    -- In_Finalization_Implementation --
  293.    ------------------------------------
  294.  
  295.    --  It would seem simpler to test Scope (RTE (RE_Root_Controlled)) but
  296.    --  the purpose of this function is to avoid a circular call to RTSfind
  297.    --  which would been acheive by such a test.
  298.  
  299.    function In_Finalization_Implementation (E : Entity_Id) return Boolean is
  300.       S : constant Entity_Id := Scope (E);
  301.  
  302.    begin
  303.       return Chars (Scope (S))     = Name_System
  304.         and then Chars (S)         = Name_Finalization_Implementation
  305.         and then Scope (Scope (S)) = Standard_Standard;
  306.    end  In_Finalization_Implementation;
  307.  
  308.    ---------------------
  309.    -- Controlled_Type --
  310.    ---------------------
  311.  
  312.    function  Controlled_Type (T : Entity_Id) return Boolean is
  313.    begin
  314.       --  Class-wide types are considered controlled because they may contain
  315.       --  an extension that has controlled components
  316.  
  317.       return (Is_Class_Wide_Type (T)
  318.                 and then not In_Finalization_Implementation (T))
  319.         or else Is_Controlled (T)
  320.         or else Has_Controlled (T)
  321.         or else (Is_Concurrent_Type (T)
  322.           and then Controlled_Type (Corresponding_Record_Type (T)));
  323.    end Controlled_Type;
  324.  
  325.    --------------------------
  326.    -- Controller_Component --
  327.    --------------------------
  328.  
  329.    function Controller_Component (Typ : Entity_Id) return Entity_Id is
  330.       T    : Entity_Id := Typ;
  331.       Comp : Entity_Id;
  332.  
  333.    begin
  334.       if Is_Class_Wide_Type (T) then
  335.          T := Root_Type (T);
  336.       end if;
  337.  
  338.       if Is_Private_Type (T) then
  339.          T := Underlying_Type (T);
  340.       end if;
  341.  
  342.       Comp := First_Entity (T);
  343.       while Present (Comp) loop
  344.          if Chars (Comp) = Name_uController then
  345.             return Comp;
  346.          end if;
  347.  
  348.          Comp := Next_Entity (Comp);
  349.       end loop;
  350.  
  351.       --  If we fall through the loop, there is no controller component
  352.  
  353.       return Empty;
  354.    end Controller_Component;
  355.  
  356.    -----------------------------
  357.    -- Build_Controlling_Procs --
  358.    -----------------------------
  359.  
  360.    procedure Build_Controlling_Procs (Typ : Entity_Id) is
  361.    begin
  362.       if Is_Array_Type (Typ) then
  363.          Build_Array_Deep_Procs (Typ);
  364.  
  365.       elsif Is_Record_Type (Typ) then
  366.          Build_Record_Deep_Procs (Typ);
  367.  
  368.       else
  369.          pragma Assert (False);
  370.          null;
  371.       end if;
  372.    end Build_Controlling_Procs;
  373.  
  374.    --------------------
  375.    -- Make_Init_Call --
  376.    --------------------
  377.  
  378.    function Make_Init_Call
  379.      (Ref         : Node_Id;
  380.       Typ         : Entity_Id;
  381.       Flist_Ref   : Node_Id)
  382.       return        List_Id
  383.    is
  384.       Loc      : constant Source_Ptr := Sloc (Ref);
  385.       Res      : constant List_Id := New_List;
  386.       Proc     : Entity_Id;
  387.       Utyp     : Entity_Id;
  388.       Cref     : Node_Id;
  389.  
  390.    begin
  391.       if Is_Concurrent_Type (Typ) then
  392.          Utyp := Corresponding_Record_Type (Typ);
  393.          Cref := Convert_Concurrent (Ref, Typ);
  394.  
  395.       elsif Is_Private_Type (Typ)
  396.         and then Present (Full_View (Typ))
  397.         and then Is_Concurrent_Type (Full_View (Typ))
  398.       then
  399.          Utyp := Corresponding_Record_Type (Full_View (Typ));
  400.          Cref := Convert_Concurrent (Ref, Full_View (Typ));
  401.       else
  402.          Utyp := Typ;
  403.          Cref := Ref;
  404.       end if;
  405.  
  406.       Utyp := Underlying_Type (Base_Type (Utyp));
  407.       Set_Assignment_OK (Cref);
  408.  
  409.       --  Generate:
  410.       --    Deep_Initialize (Ref, Flist_Ref);
  411.  
  412.       if Has_Controlled (Utyp) then
  413.          Proc := TSS (Utyp, Deep_Name_Of (Initialize_Case));
  414.  
  415.          Append_To (Res,
  416.            Make_Procedure_Call_Statement (Loc,
  417.              Name => New_Reference_To (Proc, Loc),
  418.              Parameter_Associations => New_List (
  419.                Node1 => Flist_Ref,
  420.                Node2 => Cref,
  421.                Node3 => New_Reference_To (Standard_True, Loc))));
  422.  
  423.       --  Generate:
  424.       --    Initialize (Ref);
  425.       --    Attach_To_Final_List (Ref, Flist_Ref);
  426.  
  427.       else -- Is_Controlled (Utyp)
  428.  
  429.          Proc := Find_Prim_Op (Utyp, Name_Of (Initialize_Case));
  430.          Append_To (Res,
  431.            Make_Procedure_Call_Statement (Loc,
  432.              Name => New_Reference_To (Proc, Loc),
  433.              Parameter_Associations => New_List (Cref)));
  434.  
  435.          Append_To (Res, Make_Attach_Call (New_Copy_Tree (Cref), Flist_Ref));
  436.       end if;
  437.       return Res;
  438.    end Make_Init_Call;
  439.  
  440.    -----------------------
  441.    -- Make_Adjust_Call --
  442.    -----------------------
  443.  
  444.    function Make_Adjust_Call
  445.      (Ref         : Node_Id;
  446.       Typ         : Entity_Id;
  447.       Flist_Ref   : Node_Id;
  448.       With_Attach : Node_Id)
  449.       return        List_Id
  450.    is
  451.       Loc  : constant Source_Ptr := Sloc (Ref);
  452.       Res  : constant List_Id    := New_List;
  453.       Utyp : Entity_Id;
  454.       Proc : Entity_Id;
  455.  
  456.    begin
  457.       if Is_Class_Wide_Type (Typ) then
  458.          Utyp := Underlying_Type (Base_Type (Root_Type (Typ)));
  459.       else
  460.          Utyp := Underlying_Type (Base_Type (Typ));
  461.       end if;
  462.  
  463.       Set_Assignment_OK (Ref);
  464.  
  465.       --  Generate:
  466.       --    Deep_Adjust (Flist_Ref, Ref, With_Attach);
  467.  
  468.       if Has_Controlled (Utyp) or else Is_Class_Wide_Type (Typ) then
  469.  
  470.          if Is_Tagged_Type (Utyp) then
  471.             Proc := Find_Prim_Op (Utyp, Deep_Name_Of (Adjust_Case));
  472.  
  473.          else
  474.             Proc := TSS (Utyp, Deep_Name_Of (Adjust_Case));
  475.          end if;
  476.  
  477.          Append_To (Res,
  478.            Make_Procedure_Call_Statement (Loc,
  479.              Name => New_Reference_To (Proc, Loc),
  480.              Parameter_Associations =>
  481.                New_List (Flist_Ref, Ref, With_Attach)));
  482.  
  483.       --  Generate:
  484.       --    Adjust (Ref);
  485.       --    if With_Attach then
  486.       --       Attach_To_Final_List (Ref, Flist_Ref);
  487.       --    end if;
  488.  
  489.       else -- Is_Controlled (Utyp)
  490.  
  491.          Proc := Find_Prim_Op (Utyp, Name_Of (Adjust_Case));
  492.          Append_To (Res,
  493.            Make_Procedure_Call_Statement (Loc,
  494.              Name => New_Reference_To (Proc, Loc),
  495.              Parameter_Associations => New_List (Ref)));
  496.  
  497.          if Chars (With_Attach) = Chars (Standard_True) then
  498.             Append_To (Res,
  499.               Make_Attach_Call (New_Copy_Tree (Ref), Flist_Ref));
  500.  
  501.          elsif Chars (With_Attach) /= Chars (Standard_False) then
  502.             Append_To (Res,
  503.               Make_If_Statement (Loc,
  504.                 Condition => With_Attach,
  505.                 Then_Statements => New_List (
  506.                   Make_Attach_Call (New_Copy_Tree (Ref), Flist_Ref))));
  507.          end if;
  508.       end if;
  509.       return Res;
  510.    end Make_Adjust_Call;
  511.  
  512.    ----------------------
  513.    -- Make_Final_Call --
  514.    ----------------------
  515.  
  516.    function Make_Final_Call
  517.      (Ref         : Node_Id;
  518.       Typ         : Entity_Id;
  519.       Flist_Ref   : Node_Id;
  520.       With_Detach : Node_Id)
  521.       return        List_Id
  522.    is
  523.       Loc        : constant Source_Ptr := Sloc (Ref);
  524.       Res        : constant List_Id    := New_List;
  525.       Cref       : Node_Id;
  526.       Proc       : Entity_Id;
  527.       Utyp       : Entity_Id;
  528.       True_Case  : Node_Id;
  529.       False_Case : Node_Id;
  530.  
  531.    begin
  532.       if Is_Class_Wide_Type (Typ) then
  533.          Utyp := Underlying_Type (Base_Type (Root_Type (Typ)));
  534.          Cref := Ref;
  535.  
  536.       elsif Is_Concurrent_Type (Typ) then
  537.          Utyp := Underlying_Type (Base_Type (Corresponding_Record_Type (Typ)));
  538.          Cref := Convert_Concurrent (Ref, Typ);
  539.  
  540.       else
  541.          Utyp := Underlying_Type (Base_Type (Typ));
  542.          Cref := Ref;
  543.       end if;
  544.  
  545.       Set_Assignment_OK (Ref);
  546.  
  547.       --  Generate:
  548.       --    Deep_Finalize (Flist_Ref, Ref, With_Detach);
  549.  
  550.       if Has_Controlled (Utyp) or else Is_Class_Wide_Type (Typ) then
  551.  
  552.          if Is_Tagged_Type (Utyp) then
  553.             Proc := Find_Prim_Op (Utyp, Deep_Name_Of (Finalize_Case));
  554.          else
  555.             Proc := TSS (Utyp, Deep_Name_Of (Finalize_Case));
  556.          end if;
  557.  
  558.          Append_To (Res,
  559.            Make_Procedure_Call_Statement (Loc,
  560.              Name => New_Reference_To (Proc, Loc),
  561.              Parameter_Associations =>
  562.                New_List (Flist_Ref, Cref, With_Detach)));
  563.  
  564.       --  Generate:
  565.       --    if With_Detach then
  566.       --       Finalize_One (Flist_Ref, Ref);
  567.       --    else
  568.       --       Finalize (Ref);
  569.       --    end if;
  570.  
  571.       else
  572.          True_Case :=
  573.             Make_Procedure_Call_Statement (Loc,
  574.               Name => New_Reference_To (RTE (RE_Finalize_One), Loc),
  575.               Parameter_Associations => New_List (
  576.                 Node1 => Flist_Ref,
  577.                 Node2 =>
  578.                   Make_Unchecked_Type_Conversion (Loc,
  579.                     Subtype_Mark =>
  580.                       New_Reference_To (RTE (RE_Finalizable), Loc),
  581.                     Expression => Ref)));
  582.  
  583.          False_Case :=
  584.             Make_Procedure_Call_Statement (Loc,
  585.               Name => New_Reference_To (
  586.                 Find_Prim_Op (Utyp, Name_Of (Finalize_Case)), Loc),
  587.               Parameter_Associations => New_List (Ref));
  588.  
  589.          if Chars (With_Detach) = Chars (Standard_True) then
  590.             Append_To (Res, True_Case);
  591.          elsif Chars (With_Detach) = Chars (Standard_False) then
  592.             Append_To (Res, False_Case);
  593.          else
  594.             Append_To (Res,
  595.               Make_If_Statement (Loc,
  596.                 Condition => With_Detach,
  597.                 Then_Statements => New_List (True_Case),
  598.                 Else_Statements => New_List (False_Case)));
  599.          end if;
  600.       end if;
  601.  
  602.       return Res;
  603.    end Make_Final_Call;
  604.  
  605.    -------------------------------
  606.    -- Expand_Ctrl_Function_Call --
  607.    -------------------------------
  608.  
  609.    --  Transform F(x) into:
  610.  
  611.    --    [_V : Finalizable_Ptr;
  612.    --     _V := Finalizable_Ptr (F (x)'Ref);
  613.    --     Attach_To_Final_List ("Final_List_Of_Current_Scope", _V.all);
  614.  
  615.    --   Type_Of_F!(_V.all)]
  616.  
  617.    procedure Expand_Ctrl_Function_Call (N : Node_Id) is
  618.       Loc   : constant Source_Ptr := Sloc (N);
  619.       Act   : constant List_Id    := New_List;
  620.       Rtype : constant Entity_Id  := Etype (N);
  621.       Utype : constant Entity_Id  := Underlying_Type (Rtype);
  622.       V     : Multi_Use.Exp_Id;
  623.       Ref   : Node_Id;
  624.  
  625.    begin
  626.       Multi_Use.New_Exp_Id (N, Act, V);
  627.       Ref := Multi_Use.New_Ref (V);
  628.  
  629.       if not Is_Record_Type (Utype) then
  630.          return;
  631.       end if;
  632.  
  633.       if Has_Controlled (Rtype) then
  634.          if Rtype /= Utype then
  635.             Ref :=
  636.               Make_Unchecked_Type_Conversion (Loc,
  637.                 Subtype_Mark => New_Reference_To (Utype, Loc),
  638.                 Expression   => Ref);
  639.          end if;
  640.  
  641.          Ref :=
  642.            Make_Selected_Component (Loc,
  643.              Prefix        => Ref,
  644.              Selector_Name => Make_Identifier (Loc, Name_uController));
  645.       end if;
  646.  
  647.       if Has_Controlled (Rtype) or else Is_Controlled (Rtype) then
  648.          Append_To (Act,
  649.            Make_Attach_Call (Ref, Find_Final_List (Current_Scope)));
  650.  
  651.       else
  652.          --  This is a class-wide type (potentially controlled)
  653.          --  We cannot attach him since it may not have a Final pointer
  654.          --  ??? for now do nothing. The proper fix is to pass the final
  655.          --  chain to the called function as an implicit parameter
  656.  
  657.          null;
  658.       end if;
  659.  
  660.       Rewrite_Substitute_Tree (N,
  661.         Make_Expression_Actions (Loc,
  662.           Actions    => Act,
  663.           Expression => Multi_Use.New_Ref (V)));
  664.  
  665.       Analyze (N);
  666.       Resolve (N, Rtype);
  667.    end Expand_Ctrl_Function_Call;
  668.  
  669.    ---------------------
  670.    -- Make_Deep_Proc  --
  671.    ---------------------
  672.  
  673.    --  Generate:
  674.    --    procedure DEEP_<prim>
  675.    --      (L : IN OUT Finalisable_Ptr;
  676.    --       V : IN OUT <typ>;
  677.    --       B : IN Boolean) is
  678.    --    begin
  679.    --       <stmts>;
  680.    --    exception                   --  Finalize and Adjust Cases only
  681.    --       raise Program_Error;     --  idem
  682.    --    end DEEP_<prim>;
  683.  
  684.    function Make_Deep_Proc
  685.      (Prim  : Final_Primitives;
  686.       Typ   : Entity_Id;
  687.       Stmts : List_Id)
  688.       return Entity_Id
  689.    is
  690.       Loc       : constant Source_Ptr := Sloc (Typ);
  691.       Formals   : List_Id;
  692.       Proc_Name : Entity_Id;
  693.       Handler   : List_Id := No_List;
  694.       Subp_Body : Node_Id;
  695.  
  696.    begin
  697.       Formals := New_List (
  698.         Make_Parameter_Specification (Loc,
  699.           Defining_Identifier => Make_Defining_Identifier (Loc, Name_L),
  700.           In_Present          => True,
  701.           Out_Present         => True,
  702.           Parameter_Type      =>
  703.             New_Reference_To (RTE (RE_Finalizable_Ptr), Loc)),
  704.  
  705.         Make_Parameter_Specification (Loc,
  706.           Defining_Identifier => Make_Defining_Identifier (Loc, Name_V),
  707.           In_Present          => True,
  708.           Out_Present         => True,
  709.           Parameter_Type      => New_Reference_To (Typ, Loc)),
  710.  
  711.         Make_Parameter_Specification (Loc,
  712.           Defining_Identifier => Make_Defining_Identifier (Loc, Name_B),
  713.           Parameter_Type      => New_Reference_To (Standard_Boolean, Loc)));
  714.  
  715.       if Prim = Finalize_Case or else Prim = Adjust_Case then
  716.          Handler := New_List (
  717.            Make_Exception_Handler (Loc,
  718.              Exception_Choices => New_List (Make_Others_Choice (Loc)),
  719.              Statements        => New_List (
  720.                Make_Raise_Statement (Loc,
  721.                  New_Reference_To (Standard_Program_Error, Loc)))));
  722.       end if;
  723.  
  724.       Proc_Name := Make_Defining_Identifier (Loc, Deep_Name_Of (Prim));
  725.  
  726.       Subp_Body :=
  727.         Make_Subprogram_Body (Loc,
  728.           Specification =>
  729.             Make_Procedure_Specification (Loc,
  730.               Defining_Unit_Name       => Proc_Name,
  731.               Parameter_Specifications => Formals),
  732.  
  733.           Declarations =>  Empty_List,
  734.           Handled_Statement_Sequence =>
  735.             Make_Handled_Sequence_Of_Statements (Loc,
  736.               Statements         => Stmts,
  737.               Exception_Handlers => Handler));
  738.  
  739.       return Proc_Name;
  740.    end Make_Deep_Proc;
  741.  
  742.    --------------------------
  743.    -- Make_Deep_Array_Body --
  744.    --------------------------
  745.  
  746.    --  Array components are initialized and adjusted in the normal order
  747.    --  and finalized in the reverse order. Exceptions are handled and
  748.    --  Program_Error is re-raise in the Adjust and Finalize case
  749.    --  (RM 7.6.1(12)). Generate the following code :
  750.    --
  751.    --  procedure Deep_<P>   --  with <P> being Initialize or Adjust or Finalize
  752.    --   (L : in out Finalizable_Ptr;
  753.    --    V : in out Typ)
  754.    --  is
  755.    --  begin
  756.    --     for J1 in             Typ'First (1) .. Typ'Last (1) loop
  757.    --               ^ reverse ^  --  in the finalization case
  758.    --        ...
  759.    --           for J2 in Typ'First (n) .. Typ'Last (n) loop
  760.    --                 Make_<P>_Call (Typ, V (J1, .. , Jn), L, V);
  761.    --           end loop;
  762.    --        ...
  763.    --     end loop;
  764.    --  exception                                --  not in the
  765.    --     when others => raise Program_Error;   --     Initialize case
  766.    --  end Deep_<P>;
  767.  
  768.    function Make_Deep_Array_Body
  769.      (Prim : Final_Primitives;
  770.       Typ  : Entity_Id)
  771.       return List_Id
  772.    is
  773.       Loc : constant Source_Ptr := Sloc (Typ);
  774.  
  775.       Index_List : constant List_Id := New_List;
  776.       --  Stores the list of references to the indexes (one per dimension)
  777.  
  778.       function One_Component return List_Id;
  779.       --  Create one statement to initialize/adjust/finalize one array
  780.       --  component, designated by a full set of indices.
  781.  
  782.       function One_Dimension (N : Int) return List_Id;
  783.       --  Create loop to deal with one dimension of the array. The single
  784.       --  statement in the body of the loop initializes the inner dimensions if
  785.       --  any, or else a single component.
  786.  
  787.       -------------------
  788.       -- One_Component --
  789.       -------------------
  790.  
  791.       function One_Component return List_Id is
  792.          Comp_Typ : constant Entity_Id := Component_Type (Typ);
  793.          Comp_Ref : constant Node_Id :=
  794.                       Make_Indexed_Component (Loc,
  795.                         Prefix      => Make_Identifier (Loc, Name_V),
  796.                         Expressions => Index_List);
  797.  
  798.          L_Ref : constant Node_Id := Make_Identifier (Loc, Name_L);
  799.          B_Ref : constant Node_Id := Make_Identifier (Loc, Name_B);
  800.  
  801.       begin
  802.          case Prim is
  803.             when Initialize_Case =>
  804.                return Make_Init_Call (Comp_Ref, Comp_Typ, L_Ref);
  805.  
  806.             when Adjust_Case =>
  807.                return Make_Adjust_Call (Comp_Ref, Comp_Typ, L_Ref, B_Ref);
  808.  
  809.             when Finalize_Case =>
  810.                return
  811.                  Make_Final_Call (Comp_Ref, Comp_Typ, L_Ref, B_Ref);
  812.          end case;
  813.       end One_Component;
  814.  
  815.       -------------------
  816.       -- One_Dimension --
  817.       -------------------
  818.  
  819.       function One_Dimension (N : Int) return List_Id is
  820.          Index : Entity_Id;
  821.  
  822.       begin
  823.          if N > Number_Dimensions (Typ) then
  824.             return One_Component;
  825.  
  826.          else
  827.             Index :=
  828.               Make_Defining_Identifier (Loc, New_External_Name ('J', N));
  829.  
  830.             Append_To (Index_List, New_Reference_To (Index, Loc));
  831.  
  832.             return New_List (
  833.               Make_Loop_Statement (Loc,
  834.                 Identifier => Empty,
  835.                 Iteration_Scheme =>
  836.                   Make_Iteration_Scheme (Loc,
  837.                     Loop_Parameter_Specification =>
  838.                       Make_Loop_Parameter_Specification (Loc,
  839.                         Defining_Identifier => Index,
  840.                         Discrete_Subtype_Definition =>
  841.                           Make_Attribute_Reference (Loc,
  842.                             Prefix => Make_Identifier (Loc, Name_V),
  843.                             Attribute_Name  => Name_Range,
  844.                             Expressions => New_List (
  845.                               Make_Integer_Literal (Loc, UI_From_Int (N)))),
  846.                         Reverse_Present => Prim = Finalize_Case)),
  847.                 Statements => One_Dimension (N + 1)));
  848.          end if;
  849.       end One_Dimension;
  850.  
  851.    --  Start of processing for Make_Deep_Array_Body
  852.  
  853.    begin
  854.       return One_Dimension (1);
  855.    end Make_Deep_Array_Body;
  856.  
  857.    ---------------------------
  858.    -- Make_Deep_Record_Body --
  859.    ---------------------------
  860.  
  861.    --  The Deep procedures call the appropriate Controlling proc on the
  862.    --  the controller component. In the init case, it also attach the
  863.    --  controller to the current finalization list.
  864.  
  865.    function Make_Deep_Record_Body
  866.      (Prim : Final_Primitives;
  867.       Typ  : Entity_Id)
  868.       return List_Id
  869.    is
  870.       Loc            : constant Source_Ptr := Sloc (Typ);
  871.       Controller_Typ : Entity_Id;
  872.       Obj_Ref        : constant Node_Id := Make_Identifier (Loc, Name_V);
  873.       Controller_Ref : constant Node_Id :=
  874.                          Make_Selected_Component (Loc,
  875.                            Prefix        => Obj_Ref,
  876.                            Selector_Name =>
  877.                              Make_Identifier (Loc, Name_uController));
  878.  
  879.       L_Ref : constant Node_Id := Make_Identifier (Loc, Name_L);
  880.       B_Ref : constant Node_Id := Make_Identifier (Loc, Name_B);
  881.  
  882.    begin
  883.       if Is_Limited_Type (Typ) then
  884.          Controller_Typ := RTE (RE_Limited_Record_Controller);
  885.       else
  886.          Controller_Typ := RTE (RE_Record_Controller);
  887.       end if;
  888.  
  889.       case Prim is
  890.          when Initialize_Case =>
  891.             declare
  892.                Res  : constant List_Id := New_List;
  893.  
  894.             begin
  895.                Append_List_To (Res,
  896.                  Make_Init_Call (Controller_Ref, Controller_Typ, L_Ref));
  897.  
  898.                --  When the type is also a controlled type by itself,
  899.                --  Initialize it and attach it at the end of the internal
  900.                --  finalization chain
  901.  
  902.                if Is_Controlled (Typ) then
  903.                   Append_To (Res,
  904.                     Make_Procedure_Call_Statement (Loc,
  905.                       Name => New_Reference_To (
  906.                         Find_Prim_Op (Typ, Name_Of (Prim)), Loc),
  907.  
  908.                       Parameter_Associations =>
  909.                         New_List (New_Copy_Tree (Obj_Ref))));
  910.  
  911.                   Append_To (Res,
  912.                     Make_Attach_Call (New_Copy_Tree (Obj_Ref),
  913.                       Make_Selected_Component (Loc,
  914.                         Prefix        => New_Copy_Tree (Controller_Ref),
  915.                         Selector_Name => Make_Identifier (Loc, Name_F))));
  916.                end if;
  917.  
  918.                return Res;
  919.             end;
  920.  
  921.          when Adjust_Case =>
  922.             return
  923.               Make_Adjust_Call (Controller_Ref, Controller_Typ, L_Ref, B_Ref);
  924.  
  925.          when Finalize_Case =>
  926.             return
  927.               Make_Final_Call (Controller_Ref, Controller_Typ, L_Ref, B_Ref);
  928.       end case;
  929.    end Make_Deep_Record_Body;
  930.  
  931.    ----------------------------
  932.    -- Build_Array_Deep_Procs --
  933.    ----------------------------
  934.  
  935.    procedure Build_Array_Deep_Procs (Typ : Entity_Id) is
  936.    begin
  937.       Set_TSS (Typ,
  938.         Make_Deep_Proc (
  939.           Prim  => Initialize_Case,
  940.           Typ   => Typ,
  941.           Stmts => Make_Deep_Array_Body (Initialize_Case, Typ)));
  942.  
  943.       if not Is_Limited_Type (Typ) then
  944.          Set_TSS (Typ,
  945.            Make_Deep_Proc (
  946.              Prim  => Adjust_Case,
  947.              Typ   => Typ,
  948.              Stmts => Make_Deep_Array_Body (Adjust_Case, Typ)));
  949.       end if;
  950.  
  951.       Set_TSS (Typ,
  952.         Make_Deep_Proc (
  953.           Prim  => Finalize_Case,
  954.           Typ   => Typ,
  955.           Stmts => Make_Deep_Array_Body (Finalize_Case, Typ)));
  956.    end Build_Array_Deep_Procs;
  957.  
  958.    -----------------------------
  959.    -- Build_Record_Deep_Procs --
  960.    -----------------------------
  961.  
  962.    procedure Build_Record_Deep_Procs (Typ : Entity_Id) is
  963.    begin
  964.       Set_TSS (Typ,
  965.         Make_Deep_Proc (
  966.           Prim  => Initialize_Case,
  967.           Typ   => Typ,
  968.           Stmts => Make_Deep_Record_Body (Initialize_Case, Typ)));
  969.  
  970.       if not Is_Limited_Type (Typ) then
  971.          Set_TSS (Typ,
  972.            Make_Deep_Proc (
  973.              Prim  => Adjust_Case,
  974.              Typ   => Typ,
  975.              Stmts => Make_Deep_Record_Body (Adjust_Case, Typ)));
  976.       end if;
  977.  
  978.       Set_TSS (Typ,
  979.         Make_Deep_Proc (
  980.           Prim  => Finalize_Case,
  981.           Typ   => Typ,
  982.           Stmts => Make_Deep_Record_Body (Finalize_Case, Typ)));
  983.    end Build_Record_Deep_Procs;
  984.  
  985.    ----------------------
  986.    -- Make_Attach_Call --
  987.    ----------------------
  988.  
  989.    --  Generate:
  990.    --    System.FI.Attach_To_Final_List (Flist, Ref)
  991.  
  992.    function Make_Attach_Call (Obj_Ref, Flist_Ref : Node_Id) return Node_Id is
  993.       Loc : constant Source_Ptr := Sloc (Obj_Ref);
  994.  
  995.    begin
  996.       return
  997.         Make_Procedure_Call_Statement (Loc,
  998.           Name => New_Reference_To (RTE (RE_Attach_To_Final_List), Loc),
  999.           Parameter_Associations => New_List (
  1000.             Flist_Ref,
  1001.             Make_Unchecked_Type_Conversion (Loc,
  1002.               Subtype_Mark => New_Reference_To (RTE (RE_Finalizable), Loc),
  1003.               Expression => Obj_Ref)));
  1004.    end Make_Attach_Call;
  1005.  
  1006.    ----------------------
  1007.    -- Make_Detach_Call --
  1008.    ----------------------
  1009.  
  1010.    --  Generate:
  1011.    --    System.FI.Detach_From_Final_List (Flist, Ref)
  1012.  
  1013.    function Make_Detach_Call (Obj_Ref, Flist_Ref : Node_Id) return Node_Id is
  1014.       Loc : constant Source_Ptr := Sloc (Obj_Ref);
  1015.  
  1016.    begin
  1017.       return
  1018.         Make_Procedure_Call_Statement (Loc,
  1019.           Name => New_Reference_To (RTE (RE_Detach_From_Final_List), Loc),
  1020.           Parameter_Associations => New_List (
  1021.             Flist_Ref,
  1022.             Make_Unchecked_Type_Conversion (Loc,
  1023.               Subtype_Mark => New_Reference_To (RTE (RE_Finalizable), Loc),
  1024.               Expression => Obj_Ref)));
  1025.    end Make_Detach_Call;
  1026.  
  1027.    ----------------------
  1028.    --  Find_Final_List --
  1029.    ----------------------
  1030.  
  1031.    function Find_Final_List
  1032.      (E    : Entity_Id;
  1033.       Ref  : Node_Id := Empty)
  1034.       return Node_Id
  1035.    is
  1036.       Loc : constant Source_Ptr := Sloc (Ref);
  1037.       S   : Entity_Id;
  1038.       Id  : Entity_Id;
  1039.       R   : Node_Id;
  1040.  
  1041.    begin
  1042.       --  Case of an internal component. The Final list is the record
  1043.       --  controller of the enclosing record
  1044.  
  1045.       if Present (Ref) then
  1046.          R := Ref;
  1047.          loop
  1048.             case Nkind (R) is
  1049.                when N_Unchecked_Type_Conversion |
  1050.                     N_Type_Conversion      => R := Expression (R);
  1051.  
  1052.                when N_Indexed_Component |
  1053.                     N_Explicit_Dereference => R := Prefix (R);
  1054.  
  1055.                when  N_Selected_Component  => R := Prefix (R); exit;
  1056.  
  1057.                when  N_Identifier          => exit;
  1058.  
  1059.                when others                 => pragma Assert (False); null;
  1060.             end case;
  1061.          end loop;
  1062.  
  1063.          return
  1064.            Make_Selected_Component (Loc,
  1065.              Prefix =>
  1066.                Make_Selected_Component (Loc,
  1067.                  Prefix        => R,
  1068.                  Selector_Name => Make_Identifier (Loc, Name_uController)),
  1069.              Selector_Name => Make_Identifier (Loc, Name_F));
  1070.  
  1071.  
  1072.       --  Case of a dynamically allocated object. The final list is the
  1073.       --  corresponding list controller (The next entity in the scope of
  1074.       --  the access type with the right type)
  1075.  
  1076.       elsif Is_Access_Type (E) then
  1077.          return
  1078.            Make_Selected_Component (Loc,
  1079.              Prefix        =>
  1080.                New_Reference_To (Associated_Final_Chain (Base_Type (E)), Loc),
  1081.              Selector_Name => Make_Identifier (Loc, Name_F));
  1082.  
  1083.       else
  1084.          S := Enclosing_Dynamic_Scope (E);
  1085.          if S = Standard_Standard then
  1086.             return New_Reference_To (RTE (RE_Global_Final_List), Sloc (E));
  1087.          else
  1088.             if No (Finalization_Chain_Entity (S)) then
  1089.  
  1090.                Id := Make_Defining_Identifier (Sloc (S),
  1091.                        New_Internal_Name ('F'));
  1092.                Set_Finalization_Chain_Entity (S, Id);
  1093.  
  1094.                --  Set momentarily some semantics attributes to allow normal
  1095.                --  analysis of expansions containing references to this chain.
  1096.                --  Will be fully decorated during the expansion of the scope
  1097.                --  itself
  1098.  
  1099.                Set_Ekind (Id, E_Variable);
  1100.                Set_Etype (Id, RTE (RE_Finalizable_Ptr));
  1101.             end if;
  1102.  
  1103.             return New_Reference_To (Finalization_Chain_Entity (S), Sloc (E));
  1104.          end if;
  1105.       end if;
  1106.    end Find_Final_List;
  1107.  
  1108.    --------------------------------
  1109.    -- Transient Scope Management --
  1110.    --------------------------------
  1111.  
  1112.    --  A transient scope is created when temporary objects are created by the
  1113.    --  compiler. These temporary objects are allocated on the secondary stack
  1114.    --  and the transient scope is responsible for finalizing the object when
  1115.    --  appropriate and reclaiming the memory at the right time. The temporary
  1116.    --  objects are generally the objects allocated to store the result of a
  1117.    --  function returning an unconstrained or a tagged value.  Expressions
  1118.    --  needing to be wrapped in a transient scope (functions calls returning
  1119.    --  unconstrained or tagged values) may appear in 3 different contexts which
  1120.    --  lead to 3 different kinds of transient scope expansion:
  1121.  
  1122.    --   1. In a simple statement (procedure call, assignment, ...). In
  1123.    --      this case the instruction is wrapped into a transient block.
  1124.    --      (See Wrap_Transient_Statement for details)
  1125.  
  1126.    --   2. In an expression of a control structure (test in a IF statement,
  1127.    --      expression in a CASE statement, ...). In this case this expression
  1128.    --      is wrapped into an Expression_Action containing a transient block.
  1129.    --      (See Wrap_Transient_Expression for details)
  1130.  
  1131.    --   3. In a expression of an object_declaration. No wrapping is possible
  1132.    --      here, so the finalization actions, if any are done right after the
  1133.    --      declaration and the secondary stack deallocation is done in the
  1134.    --      proper enclosing scope (see Wrap_Transient_Declaration for details)
  1135.  
  1136.    --  Note about function returning tagged types: It has been decided to
  1137.    --  always allocate their result in the secondary stack while it is not
  1138.    --  absolutely mandatory when the tagged type is constrained because the
  1139.    --  caller knows the size of the returned object and thus could allocate the
  1140.    --  result in the primary stack. But, allocating them always in the
  1141.    --  secondary stack simplifies many implementation hassles:
  1142.  
  1143.    --    - If it is dispatching function call, the computation of the size of
  1144.    --      the result is possible but complex from the outside.
  1145.  
  1146.    --    - If the returned type is controlled, the assignment of the returned
  1147.    --      value to the anonymous object involves an Adjust, and we have no
  1148.    --      easy way to access the anonymous object created by the back-end
  1149.  
  1150.    --    - If the returned type is class-wide, this is an unconstrained type
  1151.    --      anyway
  1152.  
  1153.    --  Furthermore, the little loss in efficiency which is the result of this
  1154.    --  decision is not such a big deal because function returning tagged types
  1155.    --  are not very much used in real life as opposed to functions returning
  1156.    --  access to a tagged type
  1157.  
  1158.    ------------------------------
  1159.    -- Requires_Transient_Scope --
  1160.    ------------------------------
  1161.  
  1162.    --  A transient scope is required when temporaries are allocated in the
  1163.    --  primary or secondary stack, or when finalization actions must be
  1164.    --  generated before the next instruction
  1165.  
  1166.    function Requires_Transient_Scope (T : Entity_Id) return Boolean is
  1167.       Typ : Entity_Id := Underlying_Type (T);
  1168.  
  1169.    begin
  1170.       if No (Typ) then
  1171.  
  1172.          --  This is a private type which is not completed yet. This can only
  1173.          --  happen in a default expression (of a formal parameter or of a
  1174.          --  record component). Do not expand transient scope in this case
  1175.  
  1176.          return False;
  1177.  
  1178.       --  The back-end has trouble to allocate variable-size temporaries so
  1179.       --  we generate them in the front-end and need a transient scope to
  1180.       --  reclaim them properly
  1181.  
  1182.       elsif not Size_Known_At_Compile_Time (Typ) then
  1183.          return True;
  1184.  
  1185.       --  functions returning tagged types may dispatch on result so their
  1186.       --  returned value is allocated on the secondary stack. Controlled
  1187.       --  type temporaries need finalization.
  1188.  
  1189.       elsif Is_Tagged_Type (Typ) or else Has_Controlled (Typ) then
  1190.          return True;
  1191.  
  1192.       --  Unconstrained types are returned on the secondary stack
  1193.  
  1194.       elsif Is_Array_Type (Typ) then
  1195.          return not Is_Constrained (Typ);
  1196.       end if;
  1197.  
  1198.       return False;
  1199.    end Requires_Transient_Scope;
  1200.  
  1201.    -------------------------------
  1202.    -- Establish_Transient_Scope --
  1203.    -------------------------------
  1204.  
  1205.    --  This procedure is called each time a transient block has to be inserted
  1206.    --  that is to say for each call to a function with unconstrained ot tagged
  1207.    --  result. It creates a new scope on the stack scope in order to enclose
  1208.    --  all transient variables generated
  1209.  
  1210.    procedure Establish_Transient_Scope (N : Node_Id) is
  1211.       Loc       : constant Source_Ptr := Sloc (N);
  1212.       Wrap_Node : Node_Id;
  1213.  
  1214.    begin
  1215.       --  Only create a new transient scope if the current one is not
  1216.  
  1217.       if not Scope_Is_Transient then
  1218.          Wrap_Node := Find_Node_To_Be_Wrapped (N);
  1219.  
  1220.          --  Case of no wrap node, false alert, no transient scope needed
  1221.  
  1222.          if No (Wrap_Node) then
  1223.             null;
  1224.  
  1225.          --  Transient scope is required
  1226.  
  1227.          else
  1228.             New_Scope (New_Internal_Entity (E_Block, Current_Scope, Loc, 'B'));
  1229.             Set_Scope_Is_Transient;
  1230.             Set_Uses_Sec_Stack (Current_Scope);
  1231.             Set_Node_To_Be_Wrapped (Wrap_Node);
  1232.  
  1233.             if Debug_Flag_W then
  1234.                Write_Str ("    <Transient>");
  1235.                Write_Eol;
  1236.             end if;
  1237.          end if;
  1238.       end if;
  1239.    end Establish_Transient_Scope;
  1240.  
  1241.    ------------------------
  1242.    -- Node_To_Be_Wrapped --
  1243.    ------------------------
  1244.  
  1245.    function Node_To_Be_Wrapped return Node_Id is
  1246.    begin
  1247.       return Scope_Stack.Table (Scope_Stack.Last).Node_To_Be_Wrapped;
  1248.    end Node_To_Be_Wrapped;
  1249.  
  1250.    ------------------------
  1251.    -- Scope_Is_Transient --
  1252.    ------------------------
  1253.  
  1254.    function Scope_Is_Transient  return Boolean is
  1255.    begin
  1256.       return Scope_Stack.Table (Scope_Stack.Last).Is_Transient;
  1257.    end Scope_Is_Transient;
  1258.  
  1259.    ----------------------------
  1260.    -- Expand_Cleanup_Actions --
  1261.    ----------------------------
  1262.  
  1263.    procedure Expand_Cleanup_Actions (N : Node_Id) is
  1264.       Loc        : constant Source_Ptr := Sloc (N);
  1265.       S          : constant Entity_Id  := Current_Scope;
  1266.       Flist      : constant Entity_Id  := Finalization_Chain_Entity (S);
  1267.       Is_Task    : constant Boolean := (Nkind (N) = N_Task_Body);
  1268.       Is_Master  : constant Boolean :=
  1269.                      Nkind (N) /= N_Entry_Body
  1270.                        and then Is_Task_Master (N);
  1271.  
  1272.       Clean      : Entity_Id;
  1273.       Mark       : Entity_Id := Empty;
  1274.       New_Decls  : List_Id := New_List;
  1275.       Blok       : Node_Id;
  1276.       Wrapped    : Boolean := False;
  1277.  
  1278.    begin
  1279.  
  1280.       --  There are cleanup actions only if the secondary stack needs
  1281.       --  releasing or some finalizations are needed or in the context of
  1282.       --  tasking
  1283.  
  1284.       if not Uses_Sec_Stack  (Current_Scope)
  1285.         and then No (Flist)
  1286.         and then not Is_Master
  1287.         and then not Is_Task
  1288.       then
  1289.          return;
  1290.       end if;
  1291.  
  1292.       if No (Declarations (N)) then
  1293.          Set_Declarations (N, New_List);
  1294.       end if;
  1295.  
  1296.       Build_Task_Activation_Call (N);
  1297.  
  1298.       if Is_Master then
  1299.          Establish_Task_Master (N);
  1300.       end if;
  1301.  
  1302.       --  If secondary stack is in use, expand:
  1303.       --    _Mxx : constant Mark_Id := SS_Mark;
  1304.  
  1305.       if Uses_Sec_Stack (Current_Scope) then
  1306.          Mark := Make_Defining_Identifier (Loc, New_Internal_Name ('M'));
  1307.          Append_To (New_Decls,
  1308.            Make_Object_Declaration (Loc,
  1309.              Defining_Identifier => Mark,
  1310.              Object_Definition   => New_Reference_To (RTE (RE_Mark_Id), Loc),
  1311.              Expression =>
  1312.                Make_Function_Call (Loc,
  1313.                  Name => New_Reference_To (RTE (RE_SS_Mark), Loc))));
  1314.  
  1315.          Set_Uses_Sec_Stack (Current_Scope, False);
  1316.       end if;
  1317.  
  1318.       --  If finalization list is present then expand:
  1319.       --   Local_Final_List : System.FI.Finalizable_Ptr;
  1320.  
  1321.       if Present (Flist) then
  1322.          Append_To (New_Decls,
  1323.            Make_Object_Declaration (Loc,
  1324.              Defining_Identifier => Flist,
  1325.              Object_Definition   =>
  1326.                New_Reference_To (RTE (RE_Finalizable_Ptr), Loc)));
  1327.       end if;
  1328.  
  1329.       --  Clean-up procedure definition
  1330.  
  1331.       Clean := Make_Defining_Identifier (Loc, Name_uClean);
  1332.       Append_To (New_Decls,
  1333.         Make_Clean (Clean, Mark, Flist, Is_Task, Is_Master));
  1334.  
  1335.       --  If exception handlers are present, wrap the Sequence of
  1336.       --  statements in a block because it is not possible to get
  1337.       --  exception handlers and an AT END call in the same scope.
  1338.  
  1339.       if Present (Exception_Handlers (Handled_Statement_Sequence (N))) then
  1340.  
  1341.          Blok :=
  1342.            Make_Block_Statement (Loc,
  1343.              Handled_Statement_Sequence => Handled_Statement_Sequence (N));
  1344.  
  1345.          Set_Handled_Statement_Sequence (N,
  1346.            Make_Handled_Sequence_Of_Statements (Loc, New_List (Blok)));
  1347.  
  1348.          Wrapped := True;
  1349.       end if;
  1350.  
  1351.       --  Now we move the declarations into the Sequence of statements
  1352.       --  in order to get them protected by the AT END call. It may seem
  1353.       --  wierd to put declarations in the sequence of statement but in
  1354.       --  fact nothing forbids that at the tree level. We also set the
  1355.       --  First_Real_Statement field so that we remember where the real
  1356.       --  statements (i.e. original statements) begin. Note that if we
  1357.       --  wrapped the statements, the first real statement is inside the
  1358.       --  inner block.
  1359.  
  1360.       if not Wrapped then
  1361.          Set_First_Real_Statement (Handled_Statement_Sequence (N),
  1362.            First (Statements (Handled_Statement_Sequence (N))));
  1363.  
  1364.       else
  1365.          Set_First_Real_Statement (Handled_Statement_Sequence (N), Blok);
  1366.       end if;
  1367.  
  1368.       Append_List_To (Declarations (N),
  1369.         Statements (Handled_Statement_Sequence (N)));
  1370.       Set_Statements (Handled_Statement_Sequence (N), Declarations (N));
  1371.  
  1372.       --  ??? The actual mechanism of executing AT_END calls uses the
  1373.       --  setjmp/longjmp mechanism that destroys some of the data that
  1374.       --  could be uses by finalization actions. The proper fix is to
  1375.       --  execute all enclosing AT_END calls before longjumping to the next
  1376.       --  handler. This requires a new mechanism that is not in place
  1377.       --  yet. Meanwhile, a temporary kludge consists of generating a
  1378.       --  protection buffer that can be 'safely' garbled by the AT_END
  1379.       --  call. A very empirical test shows that a 64 byte buffer seems
  1380.       --  sufficient on all tested targets
  1381.  
  1382.       Protection_Buffer_Kludge : declare
  1383.          First_Node : constant Node_Id   := First (Declarations (N));
  1384.          Size_Obj   : constant Entity_Id :=
  1385.                         Make_Defining_Identifier (Loc,
  1386.                           Chars => New_Internal_Name ('S'));
  1387.          Buff_Obj   : constant Entity_Id :=
  1388.                         Make_Defining_Identifier (Loc,
  1389.                           Chars => New_Internal_Name ('B'));
  1390.  
  1391.       begin
  1392.          --  Generates:
  1393.          --    Vxx : Integer := 64;
  1394.          --    Sxx : String (1 .. Vxx);
  1395.  
  1396.          Insert_List_Before_And_Analyze (First_Node, New_List (
  1397.            Make_Object_Declaration (Loc,
  1398.              Defining_Identifier => Size_Obj,
  1399.              Object_Definition   => New_Reference_To (Standard_Integer, Loc),
  1400.              Expression => Make_Integer_Literal (Loc, Intval => Uint_64)),
  1401.  
  1402.            Make_Object_Declaration (Loc,
  1403.              Defining_Identifier => Buff_Obj,
  1404.              Object_Definition   =>
  1405.                Make_Subtype_Indication (Loc,
  1406.                  Subtype_Mark => New_Reference_To (Standard_String, Loc),
  1407.                  Constraint   =>
  1408.                    Make_Index_Or_Discriminant_Constraint (Loc,
  1409.                      Constraints => New_List (
  1410.                        Make_Range (Loc,
  1411.                          Low_Bound  => Make_Integer_Literal (Loc, Uint_1),
  1412.                          High_Bound => New_Reference_To (Size_Obj, Loc))))))));
  1413.  
  1414.       end Protection_Buffer_Kludge;
  1415.  
  1416.       --  The declarations of the _Clean procedure and finalization chain
  1417.       --  replace the old declarations that have been moved inward
  1418.  
  1419.       Set_Declarations (N, New_Decls);
  1420.       Analyze_Declarations (New_Decls);
  1421.  
  1422.       --  The AT END call is attached to the sequence of statements
  1423.  
  1424.       Set_Identifier (Handled_Statement_Sequence (N),
  1425.         New_Occurrence_Of (Clean, Loc));
  1426.    end Expand_Cleanup_Actions;
  1427.  
  1428.    --------------------------------
  1429.    -- Wrap_Transient_Declaration --
  1430.    --------------------------------
  1431.  
  1432.    --  If a transient scope has been established during the processing of the
  1433.    --  Expression of an Object_Declaration, it is not possible to wrap the
  1434.    --  declaration into a transient block as usual case, otherwise the object
  1435.    --  would be itself declared in the wrong scope. Therefore, all entities (if
  1436.    --  any) defined in the transient block are moved to the proper enclosing
  1437.    --  scope, furthermore, if they are controlled variables they are finalized
  1438.    --  right after the declaration. The finalization list of the transient
  1439.    --  scope is defined as a renaming of the enclosing one so during their
  1440.    --  initialization they will be attached to the proper finalization
  1441.    --  list. For instance, the following declaration :
  1442.    --  list. For instance, the following declaration :
  1443.  
  1444.    --        X : Typ := F (G (A), G (B));
  1445.  
  1446.    --  (where G(A) and G(B) return controlled values, expanded as _v1 and _v2)
  1447.    --  is expanded into :
  1448.  
  1449.    --    _local_final_list_1 : Finalizable_Ptr;
  1450.    --    X : Typ := [ complex Expression-Action ];
  1451.    --    Finalize_One(_v1);
  1452.    --    Finalize_One (_v2);
  1453.  
  1454.    procedure Wrap_Transient_Declaration (N : Node_Id) is
  1455.       S           : Entity_Id;
  1456.       Ent         : Entity_Id;
  1457.       Node        : Node_Id;
  1458.       Loc         : constant Source_Ptr := Sloc (N);
  1459.       Enclosing_S : Entity_Id;
  1460.       Uses_SS     : Boolean;
  1461.  
  1462.    begin
  1463.       S := Current_Scope;
  1464.       Enclosing_S := Scope (S);
  1465.  
  1466.       --  Renaming declaration to point to the right finalization chain
  1467.  
  1468.       if Present (Finalization_Chain_Entity (S)) then
  1469.          Node :=
  1470.            Make_Object_Renaming_Declaration (Loc,
  1471.              Defining_Identifier => Finalization_Chain_Entity (S),
  1472.              Subtype_Mark => New_Reference_To (RTE (RE_Finalizable_Ptr), Loc),
  1473.              Name => Find_Final_List (Enclosing_S));
  1474.  
  1475.          --  Put the declaration at the beginning of the declaration part
  1476.          --  to make sur it will be before all other actions that have been
  1477.          --  inserted before N
  1478.  
  1479.          Insert_Before (First (List_Containing (N)), Node);
  1480.          Analyze (Node);
  1481.       end if;
  1482.  
  1483.       --  Insert Actions kept in the Scope stack
  1484.  
  1485.       Insert_Actions_In_Scope_Before (N);
  1486.  
  1487.       Ent := First_Entity (S);
  1488.       while Present (Ent) loop
  1489.  
  1490.          --  Generate the Finalization calls
  1491.  
  1492.          if (Ekind (Ent) = E_Variable or else Ekind (Ent) = E_Constant)
  1493.            and then Is_Access_Type (Etype (Ent))
  1494.            and then Controlled_Type (Designated_Type (Etype (Ent)))
  1495.          then
  1496.             Insert_List_After (N,
  1497.               Make_Final_Call (
  1498.                 Ref         =>
  1499.                   Make_Explicit_Dereference (Loc, New_Reference_To (Ent, Loc)),
  1500.                 Typ         => Designated_Type (Etype (Ent)),
  1501.                 Flist_Ref   => Find_Final_List (Enclosing_S),
  1502.                 With_Detach => New_Reference_To (Standard_True, Loc)));
  1503.          end if;
  1504.  
  1505.          Ent := Next_Entity (Ent);
  1506.       end loop;
  1507.  
  1508.       --  Expand the node before leaving the transient scope
  1509.  
  1510.       Set_Scope_Is_Transient (False);
  1511.       Expand (N);
  1512.  
  1513.       --  If the declaration is consuming some secondary stack, mark the
  1514.       --  Enclosing scope appropriately
  1515.  
  1516.       Uses_SS := Uses_Sec_Stack (Current_Scope);
  1517.       Pop_Scope;
  1518.  
  1519.       --  Put the local entities back in the enclosing scope, and set the
  1520.       --  Is_Public flag appropriately.
  1521.  
  1522.       Transfer_Entities (S, Enclosing_S);
  1523.  
  1524.       if Uses_SS then
  1525.          Set_Uses_Sec_Stack (Current_Scope);
  1526.       end if;
  1527.    end Wrap_Transient_Declaration;
  1528.  
  1529.    -------------------------------
  1530.    -- Wrap_Transient_Expression --
  1531.    -------------------------------
  1532.  
  1533.    --  Transform <Expression> into
  1534.  
  1535.    --  (lines marked with <CTRL> are expanded only in presence of Controlled
  1536.    --   objects needing finalization)
  1537.  
  1538.    --    [_E : Etyp;
  1539.    --     declare
  1540.    --        _M : constant Mark_Id := SS_Mark;
  1541.    --        Local_Final_List : System.FI.Finalizable_Ptr;    <CTRL>
  1542.  
  1543.    --        procedure _Clean is
  1544.    --        begin
  1545.    --           Abort_Defer;
  1546.    --           System.FI.Finalize_List (Local_Final_List);   <CTRL>
  1547.    --           SS_Release (M);
  1548.    --           Abort_Undefer;
  1549.    --        end _Clean;
  1550.  
  1551.    --     begin
  1552.    --        _E := <Expression>;
  1553.    --     at end
  1554.    --        _Clean;
  1555.    --     end;
  1556.  
  1557.    --    _E]
  1558.  
  1559.    procedure Wrap_Transient_Expression (N : Node_Id) is
  1560.       Loc     : constant Source_Ptr := Sloc (N);
  1561.       E       : constant Entity_Id :=
  1562.                   Make_Defining_Identifier (Loc, New_Internal_Name ('E'));
  1563.       Etyp    : constant Entity_Id := Etype (N);
  1564.       New_Exp : constant Node_Id := Relocate_Node (N);
  1565.  
  1566.    begin
  1567.       Replace_Substitute_Tree (N,
  1568.         Make_Expression_Actions (Loc,
  1569.           Actions => New_List (
  1570.  
  1571.             Make_Object_Declaration (Loc,
  1572.               Defining_Identifier => E,
  1573.               Object_Definition   => New_Reference_To (Etyp, Loc)),
  1574.  
  1575.             Make_Transient_Block (Loc,
  1576.               Instruction =>
  1577.                 Make_Assignment_Statement (Loc,
  1578.                   Name       => New_Reference_To (E, Loc),
  1579.                   Expression => New_Exp))),
  1580.  
  1581.           Expression =>  New_Reference_To (E, Loc)));
  1582.  
  1583.       --  Expand the node before leaving the transient scope
  1584.  
  1585.       Set_Scope_Is_Transient (False);
  1586.       Expand (New_Exp);
  1587.  
  1588.       Pop_Scope;
  1589.       Analyze (N);
  1590.       Resolve (N, Etyp);
  1591.    end Wrap_Transient_Expression;
  1592.  
  1593.    ------------------------------
  1594.    -- Wrap_Transient_Statement --
  1595.    ------------------------------
  1596.  
  1597.    --  Transform <Instruction> into
  1598.  
  1599.    --  (lines marked with <CTRL> are expanded only in presence of Controlled
  1600.    --   objects needing finalization)
  1601.  
  1602.    --    declare
  1603.    --       _M : Mark_Id := SS_Mark;
  1604.    --       Local_Final_List : System.FI.Finalizable_Ptr ;    <CTRL>
  1605.  
  1606.    --       procedure _Clean is
  1607.    --       begin
  1608.    --          Abort_Defer;
  1609.    --          System.FI.Finalize_List (Local_Final_List);    <CTRL>
  1610.    --          SS_Release (_M);
  1611.    --          Abort_Undefer;
  1612.    --       end _Clean;
  1613.  
  1614.    --    begin
  1615.    --       <Instruction>;
  1616.    --    at end
  1617.    --       _Clean;
  1618.    --    end;
  1619.  
  1620.    procedure Wrap_Transient_Statement (N : Node_Id) is
  1621.       Loc           : constant Source_Ptr := Sloc (N);
  1622.       Block         : Node_Id;
  1623.       New_Statement : constant Node_Id := Relocate_Node (N);
  1624.  
  1625.    begin
  1626.       Block := Make_Transient_Block (Loc, New_Statement);
  1627.       Replace_Substitute_Tree (N, Block);
  1628.  
  1629.       --  Expand the node before leaving the transient scope
  1630.  
  1631.       Set_Scope_Is_Transient (False);
  1632.       Expand (New_Statement);
  1633.  
  1634.       --  When the transient scope was established, we pushed the entry for
  1635.       --  the transient scope onto the scope stack, so that the scope was
  1636.       --  active for the installation of finalizable entities etc. Now we
  1637.       --  must remove this entry, since we have constructed a proper block.
  1638.  
  1639.       Pop_Scope;
  1640.  
  1641.       --  With the scope stack back to normal, we can call analyze on the
  1642.       --  resulting block. At this point, the transient scope is being
  1643.       --  treated like a perfectly normal scope, so there is nothing
  1644.       --  special about it.
  1645.  
  1646.       --  Note: Wrap_Transient_Statement is called with the node already
  1647.       --  analyzed (i.e. Analyzed (N) is True). This is important, since
  1648.       --  otherwise we would get a recursive processing of the node when
  1649.       --  we do this Analyze call.
  1650.  
  1651.       Analyze (N);
  1652.    end Wrap_Transient_Statement;
  1653.  
  1654.    ----------------------------
  1655.    -- Set_Scope_Is_Transient --
  1656.    ----------------------------
  1657.  
  1658.    procedure Set_Scope_Is_Transient (V : Boolean := True) is
  1659.    begin
  1660.       Scope_Stack.Table (Scope_Stack.Last).Is_Transient := V;
  1661.    end Set_Scope_Is_Transient;
  1662.  
  1663.    ----------------------------
  1664.    -- Set_Node_To_Be_Wrapped --
  1665.    ----------------------------
  1666.  
  1667.    procedure Set_Node_To_Be_Wrapped (N : Node_Id) is
  1668.    begin
  1669.       Scope_Stack.Table (Scope_Stack.Last).Node_To_Be_Wrapped := N;
  1670.    end Set_Node_To_Be_Wrapped;
  1671.  
  1672.    ----------------------------
  1673.    -- Store_Actions_In_Scope --
  1674.    ----------------------------
  1675.  
  1676.    procedure Store_Actions_In_Scope (L : List_Id) is
  1677.       SE    : Scope_Stack_Entry renames Scope_Stack.Table (Scope_Stack.Last);
  1678.       Acts  : constant List_Id := SE.Actions_To_Be_Wrapped;
  1679.  
  1680.    begin
  1681.       if Present (SE.Actions_To_Be_Wrapped) then
  1682.          Insert_List_After_And_Analyze (Last (SE.Actions_To_Be_Wrapped), L);
  1683.  
  1684.       else
  1685.          SE.Actions_To_Be_Wrapped := L;
  1686.          Set_Parent (L, SE.Node_To_Be_Wrapped);
  1687.          Analyze_List (L);
  1688.       end if;
  1689.    end Store_Actions_In_Scope;
  1690.  
  1691.    ------------------------------------
  1692.    -- Insert_Actions_In_Scope_Before --
  1693.    ------------------------------------
  1694.  
  1695.    procedure Insert_Actions_In_Scope_Before (N : Node_Id) is
  1696.       SE : Scope_Stack_Entry renames Scope_Stack.Table (Scope_Stack.Last);
  1697.  
  1698.    begin
  1699.  
  1700.       if Present (SE.Actions_To_Be_Wrapped) then
  1701.          Insert_List_Before (N, SE.Actions_To_Be_Wrapped);
  1702.          SE.Actions_To_Be_Wrapped := No_List;
  1703.       end if;
  1704.    end Insert_Actions_In_Scope_Before;
  1705.  
  1706.    -----------------------------
  1707.    -- Find_Node_To_Be_Wrapped --
  1708.    -----------------------------
  1709.  
  1710.    function Find_Node_To_Be_Wrapped (N : Node_Id) return Node_Id is
  1711.       P          : Node_Id;
  1712.       The_Parent : Node_Id;
  1713.  
  1714.    begin
  1715.       The_Parent := N;
  1716.       loop
  1717.          P := The_Parent;
  1718.          pragma Assert (P /= Empty);
  1719.          The_Parent := Parent (P);
  1720.  
  1721.          case Nkind (The_Parent) is
  1722.  
  1723.             --  Simple statements are ideal nodes to be wrapped
  1724.  
  1725.             when N_Assignment_Statement     |
  1726.                  N_Procedure_Call_Statement |
  1727.                  N_Entry_Call_Statement     =>
  1728.                return The_Parent;
  1729.  
  1730.             --  Object declarations are also a boundary for the transient scope
  1731.             --  even if they are not really wrapped
  1732.             --  (see Wrap_Transient_Declaration)
  1733.  
  1734.             when N_Object_Declaration          |
  1735.                  N_Object_Renaming_Declaration |
  1736.                  N_Subtype_Declaration         =>
  1737.                return The_Parent;
  1738.  
  1739.             --  The expression itself is to be wrapped if its parent is a
  1740.             --  compound statement or any other statement where the expression
  1741.             --  is known to be scalar
  1742.  
  1743.             when N_Accept_Alternative               |
  1744.                  N_Attribute_Definition_Clause      |
  1745.                  N_Case_Statement                   |
  1746.                  N_Code_Statement                   |
  1747.                  N_Delay_Alternative                |
  1748.                  N_Delay_Until_Statement            |
  1749.                  N_Delay_Relative_Statement         |
  1750.                  N_Discriminant_Association         |
  1751.                  N_Elsif_Part                       |
  1752.                  N_Entry_Body_Formal_Part           |
  1753.                  N_Exit_Statement                   |
  1754.                  N_If_Statement                     |
  1755.                  N_Iteration_Scheme                 |
  1756.                  N_Terminate_Alternative            =>
  1757.                return P;
  1758.  
  1759.             --  ??? No scheme yet for "for I in Expression'Range loop"
  1760.             --  ??? the current scheme for Expression wrapping doesn't apply
  1761.             --  ??? because a RANGE is NOT an expression. Tricky problem...
  1762.             --  ??? while this problem is no solved we have a potential for
  1763.             --  ??? leak and unfinalized intermediate objects here.
  1764.  
  1765.             when N_Loop_Parameter_Specification =>
  1766.                return Empty;
  1767.  
  1768.             --  The following nodes contains "dummy calls" which don't
  1769.             --  need to be wrapped.
  1770.  
  1771.             when N_Parameter_Specification     |
  1772.                  N_Discriminant_Specification  |
  1773.                  N_Component_Declaration       =>
  1774.                return Empty;
  1775.  
  1776.             --  The expression of a return statement is not to be wrapped
  1777.             --  when the function itself needs wrapping at the outer-level
  1778.  
  1779.             when N_Return_Statement            =>
  1780.                if Requires_Transient_Scope (Return_Type (The_Parent)) then
  1781.                   return Empty;
  1782.                else
  1783.                   return P;
  1784.                end if;
  1785.  
  1786.             --  If we leave a scope without having been able to find a node to
  1787.             --  wrap, something is going wrong
  1788.  
  1789.             when N_Subprogram_Body     |
  1790.                  N_Package_Declaration |
  1791.                  N_Package_Body        |
  1792.                  N_Block_Statement     =>
  1793.                pragma Assert (False); null;
  1794.  
  1795.             --  otherwise continue the search
  1796.  
  1797.             when others =>
  1798.                null;
  1799.          end case;
  1800.       end loop;
  1801.    end Find_Node_To_Be_Wrapped;
  1802.  
  1803.    --------------------------
  1804.    -- Make_Transient_Block --
  1805.    --------------------------
  1806.  
  1807.    --  if finalization is involved, this function just wrap the instruction
  1808.    --  into a block whose name is the transient block entity,
  1809.    --  Expand_Cleanup_Actions (called on the expansion of the handled
  1810.    --  sequence of statements wil do the necessary expansions for
  1811.    --  cleanups). If it is just a matter of releasing the secondary stack
  1812.    --  we don't use the cleanup mechanism which is to costly but rather
  1813.    --  expand the release online, there is a potential of leak in the
  1814.    --  exceptional case but the sec-stack release mechanism will sooner or
  1815.    --  later catchup the leak. Here is the expansion for the latter case:
  1816.  
  1817.    --   declare
  1818.    --      _M : Mark_Id := SS_Mark;
  1819.    --   begin
  1820.    --      <Instruction>;
  1821.    --      SS_Release (M);
  1822.    --   end;
  1823.  
  1824.    function Make_Transient_Block
  1825.      (Loc         : Source_Ptr;
  1826.       Instruction : Node_Id)
  1827.       return        Node_Id
  1828.    is
  1829.       Flist  : constant Entity_Id := Finalization_Chain_Entity (Current_Scope);
  1830.       Decls  : constant List_Id := New_List;
  1831.       Instrs : constant List_Id := New_List (Instruction);
  1832.       Mark  : Entity_Id := Empty;
  1833.  
  1834.    begin
  1835.  
  1836.       if Uses_Sec_Stack (Current_Scope) and then No (Flist) then
  1837.          Mark := Make_Defining_Identifier (Loc, Name_uM);
  1838.          Append_To (Decls,
  1839.            Make_Object_Declaration (Loc,
  1840.              Defining_Identifier => Mark,
  1841.              Object_Definition => New_Reference_To (RTE (RE_Mark_Id), Loc),
  1842.              Expression =>
  1843.                 Make_Function_Call (Loc,
  1844.                   Name => New_Reference_To (RTE (RE_SS_Mark), Loc))));
  1845.  
  1846.          Append_To (Instrs,
  1847.            Make_Procedure_Call_Statement (Loc,
  1848.              Name => New_Reference_To (RTE (RE_SS_Release), Loc),
  1849.              Parameter_Associations => New_List (
  1850.                New_Reference_To (Mark, Loc))));
  1851.          Set_Uses_Sec_Stack (Current_Scope, False);
  1852.       end if;
  1853.  
  1854.       Insert_Actions_In_Scope_Before (First (Instrs));
  1855.  
  1856.       return
  1857.         Make_Block_Statement (Loc,
  1858.           Identifier => New_Reference_To (Current_Scope, Loc),
  1859.           Declarations => Decls,
  1860.           Handled_Statement_Sequence =>
  1861.             Make_Handled_Sequence_Of_Statements (Loc, Statements => Instrs),
  1862.           Has_Created_Identifier => True);
  1863.    end Make_Transient_Block;
  1864.  
  1865.    ----------------
  1866.    -- Make_Clean --
  1867.    ----------------
  1868.  
  1869.    function Make_Clean
  1870.      (Clean     : Entity_Id;
  1871.       Mark      : Entity_Id;
  1872.       Flist     : Entity_Id;
  1873.       Is_Task   : Boolean;
  1874.       Is_Master : Boolean)
  1875.       return      Node_Id
  1876.    is
  1877.       Loc   : constant Source_Ptr := Sloc (Clean);
  1878.       Stmt  : List_Id := New_List;
  1879.       Sbody : Node_Id;
  1880.  
  1881.    begin
  1882.       if Is_Task then
  1883.          Append_To (Stmt, Build_Runtime_Call (Loc, RE_Complete_Task));
  1884.  
  1885.       elsif Is_Master then
  1886.          Append_To (Stmt, Build_Runtime_Call (Loc, RE_Complete_Master));
  1887.       end if;
  1888.  
  1889.       if Present (Flist) then
  1890.          Append_To (Stmt,
  1891.            Make_Procedure_Call_Statement (Loc,
  1892.              Name => New_Reference_To (RTE (RE_Finalize_List), Loc),
  1893.              Parameter_Associations => New_List (
  1894.                     New_Reference_To (Flist, Loc))));
  1895.       end if;
  1896.  
  1897.       if Present (Mark) then
  1898.          Append_To (Stmt,
  1899.            Make_Procedure_Call_Statement (Loc,
  1900.              Name => New_Reference_To (RTE (RE_SS_Release), Loc),
  1901.              Parameter_Associations => New_List (
  1902.                     New_Reference_To (Mark, Loc))));
  1903.       end if;
  1904.  
  1905.       Sbody :=
  1906.         Make_Subprogram_Body (Loc,
  1907.           Specification =>
  1908.             Make_Procedure_Specification (Loc,
  1909.               Defining_Unit_Name => Clean),
  1910.  
  1911.           Declarations  => New_List,
  1912.  
  1913.           Handled_Statement_Sequence =>
  1914.             Make_Handled_Sequence_Of_Statements (Loc,
  1915.               Statements => Stmt));
  1916.  
  1917.       if Present (Flist) or else Is_Task or else Is_Master then
  1918.          Wrap_Cleanup_Procedure (Sbody);
  1919.       end if;
  1920.  
  1921.       return Sbody;
  1922.    end Make_Clean;
  1923.  
  1924. end Exp_Ch7;
  1925.