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_ch5.adb < prev    next >
Text File  |  1996-09-28  |  44KB  |  1,159 lines

  1. ------------------------------------------------------------------------------
  2. --                                                                          --
  3. --                         GNAT COMPILER COMPONENTS                         --
  4. --                                                                          --
  5. --                              E X P _ C H 5                               --
  6. --                                                                          --
  7. --                                 B o d y                                  --
  8. --                                                                          --
  9. --                            $Revision: 1.77 $                             --
  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. with Atree;    use Atree;
  26. with Checks;   use Checks;
  27. with Einfo;    use Einfo;
  28. with Exp_Ch7;  use Exp_Ch7;
  29. with Exp_Pakd; use Exp_Pakd;
  30. with Exp_Util; use Exp_Util;
  31. with Itypes;   use Itypes;
  32. with Nlists;   use Nlists;
  33. with Nmake;    use Nmake;
  34. with Rtsfind;  use Rtsfind;
  35. with Sinfo;    use Sinfo;
  36. with Sem;      use Sem;
  37. with Sem_Res;  use Sem_Res;
  38. with Sem_Util; use Sem_Util;
  39. with Snames;   use Snames;
  40. with Stand;    use Stand;
  41. with Tbuild;   use Tbuild;
  42.  
  43. package body Exp_Ch5 is
  44.  
  45.    function Make_Tag_Ctrl_Assignment
  46.      (N        : Node_Id;
  47.       T        : Entity_Id;
  48.       L, R     : Node_Id)
  49.       return     List_Id;
  50.    --  Generate the necessary code for controlled and Tagged assignment,
  51.    --  that is to say, finalization of the target before, adjustement of
  52.    --  the target after and save and restore of the tag and finalization
  53.    --  pointers which are not 'part of the value' and must not be changed
  54.    --  upon assignment. N is the original Assignment node, T is the type of
  55.    --  the args, L and R are the left and right hand side.
  56.    --  XREF says R is unused, is that really true???
  57.  
  58.    -----------------------------------
  59.    -- Expand_N_Assignment_Statement --
  60.    -----------------------------------
  61.  
  62.    --  For array types, deal with slice assignments and setting the flags
  63.    --  to indicate if it can be statically determined which direction the
  64.    --  move should go in. Also deal with generating length checks.
  65.  
  66.    procedure Expand_N_Assignment_Statement (N : Node_Id) is
  67.       Loc : constant Source_Ptr := Sloc (N);
  68.       Lhs : constant Node_Id    := Name (N);
  69.       Rhs : constant Node_Id    := Expression (N);
  70.       Typ : constant Entity_Id  := Underlying_Type (Etype (Lhs));
  71.  
  72.       L     : List_Id;
  73.  
  74.    begin
  75.       --  First, we do a general transformation of the assignment statement
  76.       --  as follows. What we have in general is:
  77.  
  78.       --    [lhs-actions; lhs + lhs-itypes] := [rhs-actions; rhs + rhs-itypes]
  79.  
  80.       --  Of course in a particular case, the actions and/or itypes may not
  81.       --  be present. In fact in the great majority of cases, neither side
  82.       --  is an expression actions, and neither side has itypes. But if these
  83.       --  components are present, we transform this to:
  84.  
  85.       --    lhs-actions
  86.       --    N_Implicit_Itypes lhs-itypes
  87.       --    rhs-actions
  88.       --    N_Implicit_Itypes rhs-itypes
  89.  
  90.       --  The order of evaluation is important because if the right side is
  91.       --  an aggregate, we need the left hand side types evaluated first.
  92.  
  93.       if Nkind (Lhs) = N_Expression_Actions
  94.          or else (Nkind (Lhs) in N_Has_Itypes
  95.                     and then Present (First_Itype (Lhs)))
  96.          or else Nkind (Rhs) = N_Expression_Actions
  97.          or else (Nkind (Rhs) in N_Has_Itypes
  98.                     and then Present (First_Itype (Rhs)))
  99.       then
  100.          declare
  101.             Inslist : List_Id := New_List;
  102.             Itpnod  : Node_Id;
  103.  
  104.          begin
  105.             if Nkind (Lhs) = N_Expression_Actions then
  106.                Append_List (Actions (Lhs), Inslist);
  107.                Rewrite_Substitute_Tree (Lhs, Expression (Lhs));
  108.             end if;
  109.  
  110.             if Nkind (Lhs) in N_Has_Itypes
  111.               and then Present (First_Itype (Lhs))
  112.             then
  113.                Itpnod := Make_Implicit_Types (Loc);
  114.                Transfer_Itypes (From => Lhs, To => Itpnod);
  115.                Append (Itpnod, Inslist);
  116.             end if;
  117.  
  118.             if Nkind (Rhs) = N_Expression_Actions then
  119.                Append_List (Actions (Rhs), Inslist);
  120.                Rewrite_Substitute_Tree (Rhs, Expression (Rhs));
  121.             end if;
  122.  
  123.             if Nkind (Rhs) in N_Has_Itypes
  124.               and then Present (First_Itype (Rhs))
  125.             then
  126.                Itpnod := Make_Implicit_Types (Loc);
  127.                Transfer_Itypes (From => Rhs, To => Itpnod);
  128.                Append (Itpnod, Inslist);
  129.             end if;
  130.  
  131.             Insert_List_Before (N, Inslist);
  132.          end;
  133.       end if;
  134.  
  135.       --  First, test case of assignment to packed array element
  136.  
  137.       if Nkind (Lhs) = N_Indexed_Component
  138.         and then Is_Packed (Etype (Prefix (Lhs)))
  139.       then
  140.          Expand_Packed_Element_Set (N);
  141.          return;
  142.  
  143.       elsif Is_Tagged_Type (Typ) or else Controlled_Type (Typ) then
  144.  
  145.          --  In the controlled case, we need to make sure that function calls
  146.          --  are evaluated before finalizing the target. In all cases, it
  147.          --  make the expansion easier if the side-effects are remove first.
  148.  
  149.          Remove_Side_Effects (Lhs);
  150.          Remove_Side_Effects (Rhs);
  151.  
  152.          --  Avoid recursion in the mechanism
  153.  
  154.          Set_Analyzed (N);
  155.  
  156.          --  In the class-wide case, rewrite the assignment in a dispatch
  157.          --  call to _assign
  158.  
  159.          if Is_Class_Wide_Type (Typ) then
  160.             L := New_List (
  161.               Make_Procedure_Call_Statement (Loc,
  162.                 Name => New_Reference_To (
  163.                   Find_Prim_Op (Root_Type (Typ), Name_uAssign), Loc),
  164.  
  165.                 Parameter_Associations => New_List (
  166.                   Duplicate_Subexpr (Lhs),
  167.  
  168.                   Make_Type_Conversion (Loc,
  169.                     Subtype_Mark => New_Reference_To (Etype (Lhs), Loc),
  170.                     Expression   => Duplicate_Subexpr (Rhs)))));
  171.  
  172.          else
  173.             L := Make_Tag_Ctrl_Assignment (N, Typ, Lhs, Rhs);
  174.          end if;
  175.  
  176.          --  We can't affort to have destructive Finalization Actions in
  177.          --  the Self assignment case, so if the target and the source are
  178.          --  not obviously different, code is generated to avoid the self
  179.          --  assignment case
  180.  
  181.          if Statically_Different (Lhs, Rhs)
  182.            or else Chars (Current_Scope) = Name_uAssign
  183.          then
  184.             Rewrite_Substitute_Tree (N,
  185.                Make_Block_Statement (Loc,
  186.                  Handled_Statement_Sequence =>
  187.                    Make_Handled_Sequence_Of_Statements (Loc,
  188.                      Statements => L)));
  189.  
  190.          --  Otherwise generate:
  191.          --  if lhs'address /= rhs'address then
  192.          --     <code for controlled and/or tagged assignment>
  193.          --  end if;
  194.  
  195.          else
  196.             Rewrite_Substitute_Tree (N,
  197.               Make_If_Statement (Loc,
  198.                 Condition =>
  199.                   Make_Op_Ne (Loc,
  200.                     Left_Opnd =>
  201.                       Make_Attribute_Reference (Loc,
  202.                         Prefix         => Lhs,
  203.                         Attribute_Name => Name_Address),
  204.  
  205.                      Right_Opnd =>
  206.                       Make_Attribute_Reference (Loc,
  207.                         Prefix         => Rhs,
  208.                         Attribute_Name => Name_Address)),
  209.  
  210.                 Then_Statements => L));
  211.          end if;
  212.  
  213.          Analyze (N);
  214.  
  215.       --  Array types
  216.  
  217.       elsif Is_Array_Type (Typ) then
  218.          Array_Case : declare
  219.             Act_Lhs : constant Node_Id   := Get_Referenced_Object (Lhs);
  220.             Act_Rhs : constant Node_Id   := Get_Referenced_Object (Rhs);
  221.             L_Type  : constant Entity_Id := Get_Actual_Subtype (Act_Lhs);
  222.             R_Type  : constant Entity_Id := Get_Actual_Subtype (Act_Rhs);
  223.  
  224.          begin
  225.             Apply_Length_Check (Act_Rhs, L_Type);
  226.  
  227.             --  For multi-dimensional arrays, all we need is the length check
  228.  
  229.             if Number_Dimensions (L_Type) > 1 then
  230.                Set_Forwards_OK (N);
  231.                Set_Backwards_OK (N);
  232.                return;
  233.             end if;
  234.  
  235.             --  If left hand side is not an explicit slice, then it is
  236.             --  definitely *not* a slice, since any other form (e.g. a
  237.             --  function call or the result of indexing into an array
  238.             --  or the result of a dereference) cannot possibly denote
  239.             --  a slice. This means that it is safe to move in either
  240.             --  direction, since either the left and right hand sides
  241.             --  are disjoint or they denote exactly the same object.
  242.  
  243.             --  Similarly if the right hand side is not an explicit
  244.             --  slice then everything is OK. Both have to be slices
  245.             --  for there to be any trouble in doing the assignment
  246.  
  247.             if Nkind (Act_Lhs) /= N_Slice
  248.               or else Nkind (Act_Rhs) /= N_Slice
  249.             then
  250.                Set_Forwards_OK (N);
  251.                Set_Backwards_OK (N);
  252.                return;
  253.             end if;
  254.  
  255.             --  Both left and right hand sides are slices, so we might
  256.             --  have overlapping storage areas. First deal with possible
  257.             --  renaming of the arrays being sliced.
  258.  
  259.             Slice_Case : declare
  260.                Act_L_Array : constant Node_Id :=
  261.                                Get_Referenced_Object (Prefix (Act_Lhs));
  262.                Act_R_Array : constant Node_Id :=
  263.                                Get_Referenced_Object (Prefix (Act_Rhs));
  264.                L_Index_Typ : constant Node_Id := Etype (First_Index (L_Type));
  265.                R_Index_Typ : constant Node_Id := Etype (First_Index (R_Type));
  266.  
  267.                Left_Lo  : constant Node_Id := Type_Low_Bound  (L_Index_Typ);
  268.                Right_Lo : constant Node_Id := Type_Low_Bound  (R_Index_Typ);
  269.                Right_Hi : constant Node_Id := Type_High_Bound (R_Index_Typ);
  270.  
  271.                Cresult  : Compare_Result;
  272.  
  273.             begin
  274.                --  If both left and right hand arrays are entity names, and
  275.                --  refer to different entities, then we know that the move
  276.                --  is safe (the two storage areas are completely disjoint).
  277.  
  278.                if Is_Entity_Name (Act_L_Array)
  279.                  and then Is_Entity_Name (Act_R_Array)
  280.                  and then Entity (Act_L_Array) /= Entity (Act_R_Array)
  281.                then
  282.                   Set_Forwards_OK (N);
  283.                   Set_Backwards_OK (N);
  284.  
  285.                --  Otherwise, we assume the worst, which is that the two
  286.                --  arrays are the same array. There is no need to check if
  287.                --  we know that is the case, because if we don't know it,
  288.                --  we still have to assume it!
  289.  
  290.                --  Generally if the same array is involved, then we have
  291.                --  an overlapping case. We will have to really assume the
  292.                --  worst (i.e. set neither of the OK flags) unless we can
  293.                --  determine the lower or upper bounds at compile time and
  294.                --  compare them.
  295.  
  296.                else
  297.                   Cresult := Compile_Time_Compare (Left_Lo, Right_Lo);
  298.  
  299.                   if Cresult = Unknown then
  300.                      Cresult := Compile_Time_Compare (Right_Lo, Right_Hi);
  301.                   end if;
  302.  
  303.                   case Cresult is
  304.                      when LT | LE | EQ => Set_Forwards_OK (N);
  305.                      when GT | GE      => Set_Backwards_OK (N);
  306.                      when NE | Unknown => null;
  307.                   end case;
  308.                end if;
  309.  
  310.                --  If we have the overlap case (signalled by one of the two
  311.                --  flags Forwards_OK, or Backwards_OK being unset), then we
  312.                --  generate the following code to do the slice copy:
  313.  
  314.                --  Forwards_OK = True
  315.  
  316.                --    Rnn : right_index := right_index'First;
  317.                --    for Lnn in left-index loop
  318.                --       left (Lnn) := right (Rnn);
  319.                --       Rnn := right_index'Succ (Rnn);
  320.                --    end loop;
  321.  
  322.                --  Forwards_OK = False, Backwards_OK = True
  323.  
  324.                --    Rnn : right_index := right_index'Last;
  325.                --    for Lnn in reverse left-index loop
  326.                --       left (Lnn) := right (Rnn);
  327.                --       Rnn := right_index'Pred (Rnn);
  328.                --    end loop;
  329.  
  330.                --  Note: the above code MUST be analyzed with checks off,
  331.                --  because otherwise the Succ or Pred could overflow. But
  332.                --  in any case this is more efficient!
  333.  
  334.                --  Fowards_OK = Backwards_OK = False
  335.  
  336.                --    if Integer_Address!(left (left-index'First)'Address) <=
  337.                --       Integer_Address!(right (right-index'First)'Address)
  338.                --    then
  339.                --       <code for Forwards_OK = True above>
  340.                --    else
  341.                --       <code for Backwards_OK = True above>
  342.                --    end if;
  343.  
  344.                --  Note: the reason for the unchecked conversion of the
  345.                --  address values to Integer_Address for the comparison
  346.                --  is that we do not have an easy way of making the <=
  347.                --  operation on Address values.
  348.  
  349.                if not Forwards_OK (N)
  350.                   or else not Backwards_OK (N)
  351.                then
  352.                   Overlap_Case : declare
  353.                      Lloc : constant Source_Ptr := Sloc (Lhs);
  354.                      Rloc : constant Source_Ptr := Sloc (Rhs);
  355.  
  356.                      E_Larray : Multi_Use.Exp_Id;
  357.                      E_Rarray : Multi_Use.Exp_Id;
  358.  
  359.                      function Gen_Loop (Rev : Boolean) return Node_Id;
  360.                      --  Generates the declaration and loop for the actual
  361.                      --  move as described above, with Rev indicating if
  362.                      --  REVERSE is present (True = REVERSE case). The
  363.                      --  declaration is inserted (Insert_Before_And_Analyze),
  364.                      --  and the loop statement itself is returned.
  365.  
  366.                      function Gen_Loop (Rev : Boolean) return Node_Id is
  367.                         Lnn : constant Entity_Id :=
  368.                                 Make_Defining_Identifier (Loc,
  369.                                   Chars => New_Internal_Name ('L'));
  370.  
  371.                         Rnn : constant Entity_Id :=
  372.                                 Make_Defining_Identifier (Loc,
  373.                                   Chars => New_Internal_Name ('R'));
  374.  
  375.                         F_Or_L : Name_Id;
  376.                         S_Or_P : Name_Id;
  377.  
  378.                      begin
  379.                         if Rev then
  380.                            F_Or_L := Name_Last;
  381.                            S_Or_P := Name_Pred;
  382.                         else
  383.                            F_Or_L := Name_First;
  384.                            S_Or_P := Name_Succ;
  385.                         end if;
  386.  
  387.                         Insert_Before_And_Analyze (N,
  388.                           Make_Object_Declaration (Loc,
  389.                             Defining_Identifier => Rnn,
  390.                             Object_Definition   =>
  391.                               New_Occurrence_Of (R_Index_Typ, Rloc),
  392.                             Expression =>
  393.                               Make_Attribute_Reference (Loc,
  394.                                 Prefix =>
  395.                                   New_Occurrence_Of (R_Index_Typ, Rloc),
  396.                                   Attribute_Name => F_Or_L)),
  397.                           Suppress => All_Checks);
  398.  
  399.                         return
  400.                           Make_Loop_Statement (Loc,
  401.                             Iteration_Scheme =>
  402.                               Make_Iteration_Scheme (Loc,
  403.                                 Loop_Parameter_Specification =>
  404.                                   Make_Loop_Parameter_Specification (Loc,
  405.                                     Defining_Identifier => Lnn,
  406.                                     Reverse_Present => Rev,
  407.                                     Discrete_Subtype_Definition =>
  408.                                       New_Reference_To (L_Index_Typ, Lloc))),
  409.  
  410.                             Statements => New_List (
  411.                               Make_Assignment_Statement (Loc,
  412.                                 Name =>
  413.                                   Make_Indexed_Component (Lloc,
  414.                                     Prefix => Multi_Use.New_Ref (E_Larray),
  415.                                     Expressions => New_List (
  416.                                       New_Occurrence_Of (Lnn, Lloc))),
  417.  
  418.                                 Expression =>
  419.                                   Make_Indexed_Component (Lloc,
  420.                                     Prefix => Multi_Use.New_Ref (E_Rarray),
  421.                                     Expressions => New_List (
  422.                                       New_Occurrence_Of (Rnn, Lloc)))),
  423.  
  424.                               Make_Assignment_Statement (Loc,
  425.                                 Name => New_Occurrence_Of (Rnn, Loc),
  426.                                 Expression =>
  427.                                   Make_Attribute_Reference (Loc,
  428.                                     Prefix =>
  429.                                       New_Occurrence_Of (R_Index_Typ, Rloc),
  430.                                     Attribute_Name => S_Or_P,
  431.                                     Expressions => New_List (
  432.                                       New_Occurrence_Of (Rnn, Loc))))));
  433.  
  434.                      end Gen_Loop;
  435.  
  436.                   --  Start of processing for Overlap_Case
  437.  
  438.                   begin
  439.                      --  Even in the case where we generate only one loop,
  440.                      --  we need to capture the arrays, since we don't want
  441.                      --  to evaluate them multiple times in the loop.
  442.  
  443.                      Multi_Use.New_Exp_Id (Prefix (Act_Lhs), N, E_Larray);
  444.                      Multi_Use.New_Exp_Id (Prefix (Act_Rhs), N, E_Rarray);
  445.  
  446.                      --  Generate right loop or loops depending on case
  447.  
  448.                      if Forwards_OK (N) then
  449.                         Replace_Substitute_Tree (N, Gen_Loop (False));
  450.  
  451.                      elsif Backwards_OK (N) then
  452.                         Replace_Substitute_Tree (N, Gen_Loop (True));
  453.  
  454.                      else
  455.                         Replace_Substitute_Tree (N,
  456.                           Make_If_Statement (Loc,
  457.                             Condition =>
  458.                               Make_Op_Le (Loc,
  459.                                 Left_Opnd =>
  460.                                   Make_Unchecked_Type_Conversion (Lloc,
  461.                                     Subtype_Mark =>
  462.                                       New_Reference_To
  463.                                         (RTE (RE_Integer_Address), Lloc),
  464.  
  465.                                     Expression =>
  466.                                       Make_Attribute_Reference (Lloc,
  467.                                         Prefix =>
  468.                                           Make_Indexed_Component (Lloc,
  469.                                             Prefix =>
  470.                                               Multi_Use.New_Ref (E_Larray),
  471.                                             Expressions => New_List (
  472.                                               Make_Attribute_Reference (Lloc,
  473.                                                 Prefix =>
  474.                                                   New_Reference_To
  475.                                                     (L_Index_Typ, Lloc),
  476.                                                 Attribute_Name =>
  477.                                                   Name_First))),
  478.                                         Attribute_Name => Name_Address)),
  479.  
  480.                                 Right_Opnd =>
  481.                                   Make_Unchecked_Type_Conversion (Rloc,
  482.                                     Subtype_Mark =>
  483.                                       New_Reference_To
  484.                                         (RTE (RE_Integer_Address), Rloc),
  485.  
  486.                                     Expression =>
  487.                                       Make_Attribute_Reference (Rloc,
  488.                                         Prefix =>
  489.                                           Make_Indexed_Component (Rloc,
  490.                                             Prefix =>
  491.                                               Multi_Use.New_Ref (E_Rarray),
  492.                                             Expressions => New_List (
  493.                                               Make_Attribute_Reference (Rloc,
  494.                                                 Prefix =>
  495.                                                   New_Reference_To
  496.                                                     (R_Index_Typ, Rloc),
  497.                                                 Attribute_Name =>
  498.                                                   Name_First))),
  499.                                         Attribute_Name => Name_Address))),
  500.  
  501.                             Then_Statements => New_List (Gen_Loop (False)),
  502.  
  503.                             Else_Statements => New_List (Gen_Loop (True))));
  504.  
  505.                      end if;
  506.  
  507.                      Analyze (N, Suppress => All_Checks);
  508.                   end Overlap_Case;
  509.                end if;
  510.             end Slice_Case;
  511.  
  512.             --  Merge here for all one dimensional array cases, to generate
  513.             --  the length check for the one dimensional case. We replace
  514.             --  the code for the array assignment by:
  515.  
  516.             --    if left'length /= right'length then
  517.             --       raise Constraint_Error;
  518.             --    elsif left'length /= 0 then
  519.             --       <array assignment code>
  520.             --    end if;
  521.  
  522.             --  TBD ???
  523.  
  524.          end Array_Case;
  525.       end if;
  526.  
  527.    end Expand_N_Assignment_Statement;
  528.  
  529.    ------------------------------
  530.    -- Make_Tag_Ctrl_Assignment --
  531.    ------------------------------
  532.  
  533.    function Make_Tag_Ctrl_Assignment
  534.      (N        : Node_Id;
  535.       T        : Entity_Id;
  536.       L, R     : Node_Id)
  537.       return     List_Id
  538.    is
  539.       Loc        : constant Source_Ptr := Sloc (N);
  540.       In_uAssign : constant Boolean := Chars (Current_Scope) = Name_uAssign;
  541.       In_uInit   : constant Boolean := Chars (Current_Scope) = Name_uInit_Proc;
  542.  
  543.       Ctrl_Act : constant Boolean := Controlled_Type (T) and then not In_uInit;
  544.       Save_Tag : constant Boolean := Is_Tagged_Type (T)
  545.                                        and then not In_uAssign;
  546.       Res      : List_Id;
  547.       Tag_Tmp  : Entity_Id;
  548.       Prev_Tmp : Entity_Id;
  549.       Next_Tmp : Entity_Id;
  550.       Ctrl_Ref : Node_Id;
  551.  
  552.    begin
  553.       Res := New_List;
  554.  
  555.       --  Finalize the target of the assignment when controlled. (not in
  556.       --  the init_proc since it is an initialization more than an
  557.       --  assignment)
  558.  
  559.       if Ctrl_Act then
  560.          Append_List_To (Res,
  561.            Make_Final_Call (
  562.              Ref         => Duplicate_Subexpr (L),
  563.              Typ         => T,
  564.              Flist_Ref   => New_Reference_To (RTE (RE_Global_Final_List), Loc),
  565.              With_Detach => New_Reference_To (Standard_False, Loc)));
  566.       end if;
  567.  
  568.       Next_Tmp := Make_Defining_Identifier (Loc, New_Internal_Name ('C'));
  569.  
  570.       --  Save the Tag in a local variable 'Tag_Tmp'
  571.  
  572.       if Save_Tag then
  573.          Tag_Tmp := Make_Defining_Identifier (Loc, New_Internal_Name ('A'));
  574.          Append_To (Res,
  575.            Make_Object_Declaration (Loc,
  576.              Defining_Identifier => Tag_Tmp,
  577.              Object_Definition => New_Reference_To (RTE (RE_Tag), Loc),
  578.              Expression =>
  579.                Make_Selected_Component (Loc,
  580.                  Prefix        => Duplicate_Subexpr (L),
  581.                  Selector_Name => New_Reference_To (Tag_Component (T), Loc))));
  582.       end if;
  583.  
  584.       --  Save the Finalization Pointers in local variables 'Prev_Tmp' and
  585.       --  'Next_Tmp'.  For 'Has_Controlled' Objects, these pointers are in
  586.       --  the Record_Controller
  587.  
  588.       if Ctrl_Act then
  589.          Ctrl_Ref := Duplicate_Subexpr (L);
  590.  
  591.          if Has_Controlled (T) then
  592.             Ctrl_Ref :=
  593.               Make_Selected_Component (Loc,
  594.                 Prefix => Ctrl_Ref,
  595.                 Selector_Name =>
  596.                   New_Reference_To (Controller_Component (T), Loc));
  597.          end if;
  598.  
  599.          Prev_Tmp := Make_Defining_Identifier (Loc, New_Internal_Name ('B'));
  600.  
  601.          Append_To (Res,
  602.            Make_Object_Declaration (Loc,
  603.              Defining_Identifier => Prev_Tmp,
  604.  
  605.              Object_Definition =>
  606.                New_Reference_To (RTE (RE_Finalizable_Ptr), Loc),
  607.  
  608.              Expression =>
  609.                Make_Selected_Component (Loc,
  610.                  Prefix =>
  611.                    Make_Unchecked_Type_Conversion (Loc,
  612.                      Subtype_Mark =>
  613.                        New_Reference_To (RTE (RE_Finalizable), Loc),
  614.                      Expression => Ctrl_Ref),
  615.                  Selector_Name => Make_Identifier (Loc, Name_Prev))));
  616.  
  617.          Next_Tmp := Make_Defining_Identifier (Loc, New_Internal_Name ('C'));
  618.  
  619.          Append_To (Res,
  620.            Make_Object_Declaration (Loc,
  621.              Defining_Identifier => Next_Tmp,
  622.  
  623.              Object_Definition =>
  624.                New_Reference_To (RTE (RE_Finalizable_Ptr), Loc),
  625.  
  626.              Expression =>
  627.                Make_Selected_Component (Loc,
  628.                  Prefix =>
  629.                    Make_Unchecked_Type_Conversion (Loc,
  630.                      Subtype_Mark =>
  631.                        New_Reference_To (RTE (RE_Finalizable), Loc),
  632.                      Expression => New_Copy_Tree (Ctrl_Ref)),
  633.                  Selector_Name => Make_Identifier (Loc, Name_Next))));
  634.       end if;
  635.  
  636.       --  Do the Assignment
  637.  
  638.       Append_To (Res, Relocate_Node (N));
  639.  
  640.       --  Restore the Tag
  641.  
  642.       if Save_Tag then
  643.          Append_To (Res,
  644.            Make_Assignment_Statement (Loc,
  645.              Name =>
  646.                Make_Selected_Component (Loc,
  647.                  Prefix        => Duplicate_Subexpr (L),
  648.                  Selector_Name => New_Reference_To (Tag_Component (T), Loc)),
  649.              Expression => New_Reference_To (Tag_Tmp, Loc)));
  650.       end if;
  651.  
  652.       --  Restore the finalization pointers
  653.  
  654.       if Ctrl_Act then
  655.          Append_To (Res,
  656.            Make_Assignment_Statement (Loc,
  657.              Name =>
  658.                Make_Selected_Component (Loc,
  659.                  Prefix =>
  660.                    Make_Unchecked_Type_Conversion (Loc,
  661.                      Subtype_Mark =>
  662.                        New_Reference_To (RTE (RE_Finalizable), Loc),
  663.                      Expression => New_Copy_Tree (Ctrl_Ref)),
  664.                  Selector_Name => Make_Identifier (Loc, Name_Prev)),
  665.              Expression => New_Reference_To (Prev_Tmp, Loc)));
  666.  
  667.          Append_To (Res,
  668.            Make_Assignment_Statement (Loc,
  669.              Name =>
  670.                Make_Selected_Component (Loc,
  671.                  Prefix =>
  672.                    Make_Unchecked_Type_Conversion (Loc,
  673.                      Subtype_Mark =>
  674.                        New_Reference_To (RTE (RE_Finalizable), Loc),
  675.                      Expression => New_Copy_Tree (Ctrl_Ref)),
  676.                  Selector_Name => Make_Identifier (Loc, Name_Next)),
  677.              Expression => New_Reference_To (Next_Tmp, Loc)));
  678.       end if;
  679.  
  680.       --  Adjust the target after the assignment when controlled. (not in
  681.       --  the init_proc since it is an initialization more than an
  682.       --  assignment)
  683.  
  684.       if Ctrl_Act then
  685.          Append_List_To (Res,
  686.            Make_Adjust_Call (
  687.              Ref         => Duplicate_Subexpr (L),
  688.              Typ         => T,
  689.              Flist_Ref   => New_Reference_To (RTE (RE_Global_Final_List), Loc),
  690.              With_Attach => New_Reference_To (Standard_False, Loc)));
  691.       end if;
  692.  
  693.       return Res;
  694.    end Make_Tag_Ctrl_Assignment;
  695.  
  696.    -----------------------------
  697.    -- Expand_N_Case_Statement --
  698.    -----------------------------
  699.  
  700.    --  If the last alternative is not an Others choice replace it with an
  701.    --  N_Others_Choice. Note that we do not bother to call Analyze on the
  702.    --  modified case statement, since it's only effect would be to compute
  703.    --  the contents of the Others_Discrete_Choices node laboriously, and of
  704.    --  course we already know the list of choices that corresponds to the
  705.    --  others choice (it's the list we are replacing!)
  706.  
  707.    procedure Expand_N_Case_Statement (N : Node_Id) is
  708.       Altnode     : constant Node_Id := Last (Alternatives (N));
  709.       Others_Node : Node_Id;
  710.  
  711.    begin
  712.       if Nkind (First (Discrete_Choices (Altnode))) /= N_Others_Choice then
  713.          Others_Node := Make_Others_Choice (Sloc (Altnode));
  714.          Set_Others_Discrete_Choices
  715.            (Others_Node, Discrete_Choices (Altnode));
  716.          Set_Discrete_Choices (Altnode, New_List (Others_Node));
  717.       end if;
  718.    end Expand_N_Case_Statement;
  719.  
  720.    ---------------------------
  721.    -- Expand_N_If_Statement --
  722.    ---------------------------
  723.  
  724.    --  Remove elsif parts which have non-empty Condition_Actions and rewrite
  725.    --  as independent if statements. For example:
  726.  
  727.    --     if x then xs
  728.    --     elsif y then ys
  729.    --     ...
  730.    --     end if;
  731.  
  732.    --  becomes
  733.    --
  734.    --     if x then xs
  735.    --     else
  736.    --        <<condition actions of y>>
  737.    --        if y then ys
  738.    --        ...
  739.    --        end if;
  740.    --     end if;
  741.  
  742.    --  This explosing is only needed if at least one elsif part has a
  743.    --  non-empty Condition_Actions
  744.  
  745.    procedure Expand_N_If_Statement (N : Node_Id) is
  746.       CA     : Boolean := False;
  747.       E      : Node_Id;
  748.       EP     : List_Id;
  749.       New_If : Node_Id;
  750.  
  751.    begin
  752.       if Present (Elsif_Parts (N)) then
  753.          E := First (Elsif_Parts (N));
  754.  
  755.          while Present (E) loop
  756.             if Present (Condition_Actions (E)) then
  757.                CA := True;
  758.                exit;
  759.             end if;
  760.  
  761.             E := Next (E);
  762.          end loop;
  763.       end if;
  764.  
  765.       --  Here if at least one ELSIF part has Condition_Actions set
  766.  
  767.       if CA then
  768.          EP := Elsif_Parts (N);
  769.          Set_Elsif_Parts (N, No_List);
  770.  
  771.          --  Loop to find the ELSIF that has Condition_Actions set
  772.  
  773.          loop
  774.             E := Remove_Head (EP);
  775.  
  776.             --  If no condition actions set, leave as elsif
  777.  
  778.             if No (Condition_Actions (E)) then
  779.                if No (Elsif_Parts (N)) then
  780.                   Set_Elsif_Parts (N, New_List (E));
  781.                else
  782.                   Append (E, Elsif_Parts (N));
  783.                end if;
  784.  
  785.             --  Here is the one that needs rewriting
  786.  
  787.             else
  788.                if Is_Empty_List (EP) then
  789.                   EP := No_List;
  790.                end if;
  791.  
  792.                New_If :=
  793.                  Make_If_Statement (Sloc (E),
  794.                    Condition       => Condition (E),
  795.                    Then_Statements => Then_Statements (E),
  796.                    Elsif_Parts     => EP,
  797.                    Else_Statements => Else_Statements (N));
  798.  
  799.                Set_Else_Statements (N, Condition_Actions (E));
  800.                Append (New_If, Else_Statements (N));
  801.  
  802.                --  Analyze this new if, and we are done. Note that this analyze
  803.                --  call will recursively deal with any remaining elsif's that
  804.                --  need processing.
  805.  
  806.                Analyze (New_If);
  807.                return;
  808.             end if;
  809.          end loop;
  810.       end if;
  811.    end Expand_N_If_Statement;
  812.  
  813.    -----------------------------
  814.    -- Expand_N_Loop_Statement --
  815.    -----------------------------
  816.  
  817.    --  1. Deal with loops with a non-standard enumeration type range
  818.    --  2. Deal with while loops where Condition_Actions is set
  819.  
  820.    procedure Expand_N_Loop_Statement (N : Node_Id) is
  821.       Loc  : constant Source_Ptr := Sloc (N);
  822.       Isc  : constant Node_Id    := Iteration_Scheme (N);
  823.  
  824.    begin
  825.       if No (Isc) then
  826.          return;
  827.       end if;
  828.  
  829.       --  Handle the case where we have a for loop with the range type being
  830.       --  an enumeration type with non-standard representation. In this case
  831.       --  we expand:
  832.  
  833.       --    for x in [reverse] a .. b loop
  834.       --       ...
  835.       --    end loop;
  836.  
  837.       --  to
  838.  
  839.       --    for xP in [reverse] integer
  840.       --                          range etype'Pos (a) .. etype'Pos (b) loop
  841.       --       declare
  842.       --          x : constant etype := Pos_To_Rep (xP);
  843.       --       begin
  844.       --          ...
  845.       --       end;
  846.       --    end loop;
  847.  
  848.       if Present (Loop_Parameter_Specification (Isc)) then
  849.          declare
  850.             LPS     : constant Node_Id   := Loop_Parameter_Specification (Isc);
  851.             Loop_Id : constant Entity_Id := Defining_Identifier (LPS);
  852.             Ltype   : constant Entity_Id := Etype (Loop_Id);
  853.             Btype   : constant Entity_Id := Base_Type (Ltype);
  854.             New_Id  : Entity_Id;
  855.             Lo, Hi  : Node_Id;
  856.  
  857.          begin
  858.             if not Is_Enumeration_Type (Btype)
  859.               or else No (Enum_Pos_To_Rep (Btype))
  860.             then
  861.                return;
  862.             end if;
  863.  
  864.             New_Id :=
  865.               Make_Defining_Identifier (Loc,
  866.                 Chars => New_External_Name (Chars (Loop_Id), 'P'));
  867.  
  868.             Lo := Type_Low_Bound (Ltype);
  869.             Hi := Type_High_Bound (Ltype);
  870.  
  871.             Rewrite_Substitute_Tree (N,
  872.  
  873.               Make_Loop_Statement (Loc,
  874.                 Identifier => Identifier (N),
  875.  
  876.                 Iteration_Scheme =>
  877.                   Make_Iteration_Scheme (Loc,
  878.                     Loop_Parameter_Specification =>
  879.                       Make_Loop_Parameter_Specification (Loc,
  880.                         Defining_Identifier => New_Id,
  881.                         Reverse_Present => Reverse_Present (LPS),
  882.  
  883.                         Discrete_Subtype_Definition =>
  884.                           Make_Subtype_Indication (Loc,
  885.  
  886.                             Subtype_Mark =>
  887.                               New_Reference_To (Standard_Natural, Loc),
  888.  
  889.                             Constraint =>
  890.                               Make_Range_Constraint (Loc,
  891.                                 Range_Expression =>
  892.                                   Make_Range (Loc,
  893.  
  894.                                     Low_Bound =>
  895.                                       Make_Attribute_Reference (Loc,
  896.                                         Prefix =>
  897.                                           New_Reference_To (Btype, Loc),
  898.  
  899.                                         Attribute_Name => Name_Pos,
  900.  
  901.                                         Expressions => New_List (
  902.                                           Relocate_Node
  903.                                             (Type_Low_Bound (Ltype)))),
  904.  
  905.                                     High_Bound =>
  906.                                       Make_Attribute_Reference (Loc,
  907.                                         Prefix =>
  908.                                           New_Reference_To (Btype, Loc),
  909.  
  910.                                         Attribute_Name => Name_Pos,
  911.  
  912.                                         Expressions => New_List (
  913.                                           Relocate_Node
  914.                                             (Type_High_Bound (Ltype))))))))),
  915.  
  916.                 Statements => New_List (
  917.                   Make_Block_Statement (Loc,
  918.                     Declarations => New_List (
  919.                       Make_Object_Declaration (Loc,
  920.                         Defining_Identifier => Loop_Id,
  921.                         Constant_Present    => True,
  922.                         Object_Definition   => New_Reference_To (Ltype, Loc),
  923.                         Expression          =>
  924.                           Make_Indexed_Component (Loc,
  925.                             Prefix =>
  926.                               New_Reference_To (Enum_Pos_To_Rep (Btype), Loc),
  927.                             Expressions => New_List (
  928.                               New_Reference_To (New_Id, Loc))))),
  929.  
  930.                     Handled_Statement_Sequence =>
  931.                       Make_Handled_Sequence_Of_Statements (Loc,
  932.                         Statements => Statements (N))))));
  933.  
  934.             Analyze (N);
  935.          end;
  936.  
  937.       --  Second case, if we have a while loop with Condition_Actions set,
  938.       --  then we change it into a plain loop:
  939.  
  940.       --    while C loop
  941.       --       ...
  942.       --    end loop;
  943.  
  944.       --  changed to:
  945.  
  946.       --    loop
  947.       --       <<condition actions>>
  948.       --       exit when not C;
  949.       --       ...
  950.       --    end loop
  951.  
  952.       elsif Present (Isc)
  953.         and then Present (Condition_Actions (Isc))
  954.       then
  955.          declare
  956.             Cond : constant Node_Id    := Condition (Isc);
  957.             ES   : Node_Id;
  958.  
  959.          begin
  960.             ES :=
  961.               Make_Exit_Statement (Sloc (Condition (Isc)),
  962.                 Condition =>
  963.                   Make_Op_Not (Sloc (Condition (Isc)),
  964.                     Right_Opnd => Condition (Isc)));
  965.  
  966.             Prepend (ES, Statements (N));
  967.             Insert_List_Before (ES, Condition_Actions (Isc));
  968.  
  969.             Replace_Substitute_Tree (N,
  970.               Make_Loop_Statement (Sloc (N),
  971.                 Statements => Statements (N)));
  972.  
  973.             Analyze (N);
  974.          end;
  975.       end if;
  976.    end Expand_N_Loop_Statement;
  977.  
  978.    -------------------------------
  979.    -- Expand_N_Return_Statement --
  980.    -------------------------------
  981.  
  982.    procedure Expand_N_Return_Statement (N : Node_Id) is
  983.       Loc       : constant Source_Ptr := Sloc (N);
  984.       Exp       : constant Node_Id := Expression (N);
  985.       T         : Entity_Id;
  986.       Utyp      : Entity_Id;
  987.       Scope_Id  : Entity_Id;
  988.       Kind      : Entity_Kind;
  989.       Call      : Node_Id;
  990.       Acc_Stat  : Node_Id;
  991.       Goto_Stat : Node_Id;
  992.       Lab_Node  : Node_Id;
  993.       Cur_Idx   : Int;
  994.  
  995.    begin
  996.       for J in reverse 0 .. Scope_Stack.Last loop
  997.          Scope_Id := Scope_Stack.Table (J).Entity;
  998.          Cur_Idx := J;
  999.          exit when Ekind (Scope_Id) /= E_Block and then
  1000.                    Ekind (Scope_Id) /= E_Loop;
  1001.       end loop;
  1002.  
  1003.       if No (Exp) then
  1004.          Kind := Ekind (Scope_Id);
  1005.  
  1006.          --  If it is a return from procedures do no extra steps.
  1007.  
  1008.          if Kind = E_Procedure or else Kind = E_Generic_Procedure then
  1009.             return;
  1010.          end if;
  1011.  
  1012.          pragma Assert (Kind = E_Entry or else Kind = E_Entry_Family);
  1013.  
  1014.          --  Look at the enclosing block to see whether the return is from
  1015.          --  an accept statement or an entry body.
  1016.  
  1017.          for J in reverse 0 .. Cur_Idx loop
  1018.             Scope_Id := Scope_Stack.Table (J).Entity;
  1019.             exit when Is_Concurrent_Type (Scope_Id);
  1020.          end loop;
  1021.  
  1022.          --  If it is a return from accept statement it should be expanded
  1023.          --  as a call to RTS Complete_Rendezvous and a goto to the end of
  1024.          --  the accept body.
  1025.  
  1026.          --  (cf : Expand_N_Accept_Statement, Expand_N_Selective_Accept,
  1027.          --   Expand_N_Accept_Alternative in exp_ch9.adb)
  1028.  
  1029.          if Is_Task_Type (Scope_Id) then
  1030.  
  1031.             Call := (Make_Procedure_Call_Statement (Loc,
  1032.                       Name => New_Reference_To
  1033.                         (RTE (RE_Complete_Rendezvous), Loc)));
  1034.             Insert_Before (N, Call);
  1035.             Analyze (Call);
  1036.  
  1037.  
  1038.             Acc_Stat := Parent (N);
  1039.             while Nkind (Acc_Stat) /= N_Accept_Statement loop
  1040.                Acc_Stat := Parent (Acc_Stat);
  1041.             end loop;
  1042.  
  1043.             Lab_Node := Last (Statements
  1044.               (Handled_Statement_Sequence (Acc_Stat)));
  1045.  
  1046.             Goto_Stat := Make_Goto_Statement (Loc,
  1047.               Name => New_Occurrence_Of
  1048.                 (Entity (Identifier (Lab_Node)), Loc));
  1049.  
  1050.             Set_Analyzed (Goto_Stat);
  1051.  
  1052.             Rewrite_Substitute_Tree (N, Goto_Stat);
  1053.             Analyze (N);
  1054.  
  1055.          --  If it is a return from an entry body, put a Complete_Entry_Body
  1056.          --  call in front of the return.
  1057.  
  1058.          elsif Is_Protected_Type (Scope_Id) then
  1059.  
  1060.             Call :=
  1061.               Make_Procedure_Call_Statement (Loc,
  1062.                 Name => New_Reference_To
  1063.                   (RTE (RE_Complete_Entry_Body), Loc),
  1064.                 Parameter_Associations => New_List
  1065.                   (Make_Attribute_Reference (Loc,
  1066.                     Prefix =>
  1067.                       New_Reference_To
  1068.                         (Object_Ref
  1069.                            (Corresponding_Body (Parent (Scope_Id))),
  1070.                         Loc),
  1071.                     Attribute_Name => Name_Unchecked_Access)));
  1072.  
  1073.             Insert_Before (N, Call);
  1074.             Analyze (Call);
  1075.  
  1076.          end if;
  1077.  
  1078.          return;
  1079.       end if;
  1080.  
  1081.       T    := Etype (Exp);
  1082.       Utyp := Underlying_Type (T);
  1083.  
  1084.       --  Check the result expression of a scalar function against
  1085.       --  the subtype of the function by inserting a conversion.
  1086.       --  This conversion must eventually be performed for other
  1087.       --  classes of types, but for now it's only done for scalars.
  1088.       --  ???
  1089.  
  1090.       if Is_Scalar_Type (T) then
  1091.  
  1092.          Rewrite_Substitute_Tree (Exp, Convert_To (Etype (Scope_Id), Exp));
  1093.          Analyze (Exp);
  1094.  
  1095.       end if;
  1096.  
  1097.       --  Allocate the result on the secondary stack for controlled types
  1098.  
  1099.       if Is_Record_Type (Utyp)
  1100.         and then Controlled_Type (Utyp)
  1101.         and then not Is_Return_By_Reference_Type (T)
  1102.       then
  1103.          declare
  1104.             Loc        : constant Source_Ptr := Sloc (N);
  1105.             Temp       : constant Entity_Id :=
  1106.                            Make_Defining_Identifier (Loc,
  1107.                              Chars => New_Internal_Name ('R'));
  1108.             Acc_Typ    : constant Entity_Id :=
  1109.                            Make_Defining_Identifier (Loc,
  1110.                              Chars => New_Internal_Name ('A'));
  1111.             Alloc_Node : Node_Id;
  1112.  
  1113.          begin
  1114.             Set_Ekind (Acc_Typ, E_Access_Type);
  1115.             Set_Associated_Storage_Pool (Acc_Typ, RTE (RE_SS_Pool));
  1116.             Alloc_Node :=
  1117.               Make_Allocator (Loc,
  1118.                 Expression =>
  1119.                   Make_Qualified_Expression (Loc,
  1120.                     Subtype_Mark => New_Reference_To (T, Loc),
  1121.                     Expression => Relocate_Node (Exp)));
  1122.  
  1123.             Insert_List_Before_And_Analyze (N, New_List (
  1124.               Make_Full_Type_Declaration (Loc,
  1125.                 Defining_Identifier => Acc_Typ,
  1126.                 Type_Definition     =>
  1127.                   Make_Access_To_Object_Definition (Loc,
  1128.                     Subtype_Indication =>
  1129.                        New_Reference_To (Etype (Scope_Id), Loc))),
  1130.  
  1131.               Make_Object_Declaration (Loc,
  1132.                 Defining_Identifier => Temp,
  1133.                 Object_Definition   => New_Reference_To (Acc_Typ, Loc),
  1134.                 Expression          => Alloc_Node)));
  1135.  
  1136.             Rewrite_Substitute_Tree (Exp,
  1137.               Make_Explicit_Dereference (Loc,
  1138.               Prefix => New_Reference_To (Temp, Loc)));
  1139.  
  1140.             Analyze (Exp);
  1141.             Resolve (Exp, T);
  1142.  
  1143.             --  Set the Return_By_Ref fag so that gigi will not allocate
  1144.             --  the result twice
  1145.  
  1146.             Set_Returns_By_Ref (Scope_Id);
  1147.          end;
  1148.  
  1149.       elsif Requires_Transient_Scope (Etype (Scope_Id))
  1150.        and then not Is_Return_By_Reference_Type (T)
  1151.       then
  1152.          Set_Storage_Pool      (N, RTE (RE_SS_Pool));
  1153.          Set_Procedure_To_Call (N,
  1154.            Find_Prim_Op (Etype (Storage_Pool (N)), Name_Allocate));
  1155.       end if;
  1156.    end Expand_N_Return_Statement;
  1157.  
  1158. end Exp_Ch5;
  1159.