| 1 | 706 | jeremybenn | ------------------------------------------------------------------------------
 | 
      
         | 2 |  |  | --                                                                          --
 | 
      
         | 3 |  |  | --                         GNAT COMPILER COMPONENTS                         --
 | 
      
         | 4 |  |  | --                                                                          --
 | 
      
         | 5 |  |  | --                              E X P _ C H 5                               --
 | 
      
         | 6 |  |  | --                                                                          --
 | 
      
         | 7 |  |  | --                                 B o d y                                  --
 | 
      
         | 8 |  |  | --                                                                          --
 | 
      
         | 9 |  |  | --          Copyright (C) 1992-2012, Free Software Foundation, Inc.         --
 | 
      
         | 10 |  |  | --                                                                          --
 | 
      
         | 11 |  |  | -- GNAT is free software;  you can  redistribute it  and/or modify it under --
 | 
      
         | 12 |  |  | -- terms of the  GNU General Public License as published  by the Free Soft- --
 | 
      
         | 13 |  |  | -- ware  Foundation;  either version 3,  or (at your option) any later ver- --
 | 
      
         | 14 |  |  | -- sion.  GNAT is distributed in the hope that it will be useful, but WITH- --
 | 
      
         | 15 |  |  | -- OUT ANY WARRANTY;  without even the  implied warranty of MERCHANTABILITY --
 | 
      
         | 16 |  |  | -- or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License --
 | 
      
         | 17 |  |  | -- for  more details.  You should have  received  a copy of the GNU General --
 | 
      
         | 18 |  |  | -- Public License  distributed with GNAT; see file COPYING3.  If not, go to --
 | 
      
         | 19 |  |  | -- http://www.gnu.org/licenses for a complete copy of the license.          --
 | 
      
         | 20 |  |  | --                                                                          --
 | 
      
         | 21 |  |  | -- GNAT was originally developed  by the GNAT team at  New York University. --
 | 
      
         | 22 |  |  | -- Extensive contributions were provided by Ada Core Technologies Inc.      --
 | 
      
         | 23 |  |  | --                                                                          --
 | 
      
         | 24 |  |  | ------------------------------------------------------------------------------
 | 
      
         | 25 |  |  |  
 | 
      
         | 26 |  |  | with Aspects;  use Aspects;
 | 
      
         | 27 |  |  | with Atree;    use Atree;
 | 
      
         | 28 |  |  | with Checks;   use Checks;
 | 
      
         | 29 |  |  | with Debug;    use Debug;
 | 
      
         | 30 |  |  | with Einfo;    use Einfo;
 | 
      
         | 31 |  |  | with Errout;   use Errout;
 | 
      
         | 32 |  |  | with Exp_Aggr; use Exp_Aggr;
 | 
      
         | 33 |  |  | with Exp_Ch6;  use Exp_Ch6;
 | 
      
         | 34 |  |  | with Exp_Ch7;  use Exp_Ch7;
 | 
      
         | 35 |  |  | with Exp_Ch11; use Exp_Ch11;
 | 
      
         | 36 |  |  | with Exp_Dbug; use Exp_Dbug;
 | 
      
         | 37 |  |  | with Exp_Pakd; use Exp_Pakd;
 | 
      
         | 38 |  |  | with Exp_Tss;  use Exp_Tss;
 | 
      
         | 39 |  |  | with Exp_Util; use Exp_Util;
 | 
      
         | 40 |  |  | with Namet;    use Namet;
 | 
      
         | 41 |  |  | with Nlists;   use Nlists;
 | 
      
         | 42 |  |  | with Nmake;    use Nmake;
 | 
      
         | 43 |  |  | with Opt;      use Opt;
 | 
      
         | 44 |  |  | with Restrict; use Restrict;
 | 
      
         | 45 |  |  | with Rident;   use Rident;
 | 
      
         | 46 |  |  | with Rtsfind;  use Rtsfind;
 | 
      
         | 47 |  |  | with Sinfo;    use Sinfo;
 | 
      
         | 48 |  |  | with Sem;      use Sem;
 | 
      
         | 49 |  |  | with Sem_Aux;  use Sem_Aux;
 | 
      
         | 50 |  |  | with Sem_Ch3;  use Sem_Ch3;
 | 
      
         | 51 |  |  | with Sem_Ch8;  use Sem_Ch8;
 | 
      
         | 52 |  |  | with Sem_Ch13; use Sem_Ch13;
 | 
      
         | 53 |  |  | with Sem_Eval; use Sem_Eval;
 | 
      
         | 54 |  |  | with Sem_Res;  use Sem_Res;
 | 
      
         | 55 |  |  | with Sem_Util; use Sem_Util;
 | 
      
         | 56 |  |  | with Snames;   use Snames;
 | 
      
         | 57 |  |  | with Stand;    use Stand;
 | 
      
         | 58 |  |  | with Stringt;  use Stringt;
 | 
      
         | 59 |  |  | with Targparm; use Targparm;
 | 
      
         | 60 |  |  | with Tbuild;   use Tbuild;
 | 
      
         | 61 |  |  | with Validsw;  use Validsw;
 | 
      
         | 62 |  |  |  
 | 
      
         | 63 |  |  | package body Exp_Ch5 is
 | 
      
         | 64 |  |  |  
 | 
      
         | 65 |  |  |    function Change_Of_Representation (N : Node_Id) return Boolean;
 | 
      
         | 66 |  |  |    --  Determine if the right hand side of assignment N is a type conversion
 | 
      
         | 67 |  |  |    --  which requires a change of representation. Called only for the array
 | 
      
         | 68 |  |  |    --  and record cases.
 | 
      
         | 69 |  |  |  
 | 
      
         | 70 |  |  |    procedure Expand_Assign_Array (N : Node_Id; Rhs : Node_Id);
 | 
      
         | 71 |  |  |    --  N is an assignment which assigns an array value. This routine process
 | 
      
         | 72 |  |  |    --  the various special cases and checks required for such assignments,
 | 
      
         | 73 |  |  |    --  including change of representation. Rhs is normally simply the right
 | 
      
         | 74 |  |  |    --  hand side of the assignment, except that if the right hand side is a
 | 
      
         | 75 |  |  |    --  type conversion or a qualified expression, then the RHS is the actual
 | 
      
         | 76 |  |  |    --  expression inside any such type conversions or qualifications.
 | 
      
         | 77 |  |  |  
 | 
      
         | 78 |  |  |    function Expand_Assign_Array_Loop
 | 
      
         | 79 |  |  |      (N      : Node_Id;
 | 
      
         | 80 |  |  |       Larray : Entity_Id;
 | 
      
         | 81 |  |  |       Rarray : Entity_Id;
 | 
      
         | 82 |  |  |       L_Type : Entity_Id;
 | 
      
         | 83 |  |  |       R_Type : Entity_Id;
 | 
      
         | 84 |  |  |       Ndim   : Pos;
 | 
      
         | 85 |  |  |       Rev    : Boolean) return Node_Id;
 | 
      
         | 86 |  |  |    --  N is an assignment statement which assigns an array value. This routine
 | 
      
         | 87 |  |  |    --  expands the assignment into a loop (or nested loops for the case of a
 | 
      
         | 88 |  |  |    --  multi-dimensional array) to do the assignment component by component.
 | 
      
         | 89 |  |  |    --  Larray and Rarray are the entities of the actual arrays on the left
 | 
      
         | 90 |  |  |    --  hand and right hand sides. L_Type and R_Type are the types of these
 | 
      
         | 91 |  |  |    --  arrays (which may not be the same, due to either sliding, or to a
 | 
      
         | 92 |  |  |    --  change of representation case). Ndim is the number of dimensions and
 | 
      
         | 93 |  |  |    --  the parameter Rev indicates if the loops run normally (Rev = False),
 | 
      
         | 94 |  |  |    --  or reversed (Rev = True). The value returned is the constructed
 | 
      
         | 95 |  |  |    --  loop statement. Auxiliary declarations are inserted before node N
 | 
      
         | 96 |  |  |    --  using the standard Insert_Actions mechanism.
 | 
      
         | 97 |  |  |  
 | 
      
         | 98 |  |  |    procedure Expand_Assign_Record (N : Node_Id);
 | 
      
         | 99 |  |  |    --  N is an assignment of a non-tagged record value. This routine handles
 | 
      
         | 100 |  |  |    --  the case where the assignment must be made component by component,
 | 
      
         | 101 |  |  |    --  either because the target is not byte aligned, or there is a change
 | 
      
         | 102 |  |  |    --  of representation, or when we have a tagged type with a representation
 | 
      
         | 103 |  |  |    --  clause (this last case is required because holes in the tagged type
 | 
      
         | 104 |  |  |    --  might be filled with components from child types).
 | 
      
         | 105 |  |  |  
 | 
      
         | 106 |  |  |    procedure Expand_Iterator_Loop (N : Node_Id);
 | 
      
         | 107 |  |  |    --  Expand loop over arrays and containers that uses the form "for X of C"
 | 
      
         | 108 |  |  |    --  with an optional subtype mark, or "for Y in C".
 | 
      
         | 109 |  |  |  
 | 
      
         | 110 |  |  |    procedure Expand_Predicated_Loop (N : Node_Id);
 | 
      
         | 111 |  |  |    --  Expand for loop over predicated subtype
 | 
      
         | 112 |  |  |  
 | 
      
         | 113 |  |  |    function Make_Tag_Ctrl_Assignment (N : Node_Id) return List_Id;
 | 
      
         | 114 |  |  |    --  Generate the necessary code for controlled and tagged assignment, that
 | 
      
         | 115 |  |  |    --  is to say, finalization of the target before, adjustment of the target
 | 
      
         | 116 |  |  |    --  after and save and restore of the tag and finalization pointers which
 | 
      
         | 117 |  |  |    --  are not 'part of the value' and must not be changed upon assignment. N
 | 
      
         | 118 |  |  |    --  is the original Assignment node.
 | 
      
         | 119 |  |  |  
 | 
      
         | 120 |  |  |    ------------------------------
 | 
      
         | 121 |  |  |    -- Change_Of_Representation --
 | 
      
         | 122 |  |  |    ------------------------------
 | 
      
         | 123 |  |  |  
 | 
      
         | 124 |  |  |    function Change_Of_Representation (N : Node_Id) return Boolean is
 | 
      
         | 125 |  |  |       Rhs : constant Node_Id := Expression (N);
 | 
      
         | 126 |  |  |    begin
 | 
      
         | 127 |  |  |       return
 | 
      
         | 128 |  |  |         Nkind (Rhs) = N_Type_Conversion
 | 
      
         | 129 |  |  |           and then
 | 
      
         | 130 |  |  |             not Same_Representation (Etype (Rhs), Etype (Expression (Rhs)));
 | 
      
         | 131 |  |  |    end Change_Of_Representation;
 | 
      
         | 132 |  |  |  
 | 
      
         | 133 |  |  |    -------------------------
 | 
      
         | 134 |  |  |    -- Expand_Assign_Array --
 | 
      
         | 135 |  |  |    -------------------------
 | 
      
         | 136 |  |  |  
 | 
      
         | 137 |  |  |    --  There are two issues here. First, do we let Gigi do a block move, or
 | 
      
         | 138 |  |  |    --  do we expand out into a loop? Second, we need to set the two flags
 | 
      
         | 139 |  |  |    --  Forwards_OK and Backwards_OK which show whether the block move (or
 | 
      
         | 140 |  |  |    --  corresponding loops) can be legitimately done in a forwards (low to
 | 
      
         | 141 |  |  |    --  high) or backwards (high to low) manner.
 | 
      
         | 142 |  |  |  
 | 
      
         | 143 |  |  |    procedure Expand_Assign_Array (N : Node_Id; Rhs : Node_Id) is
 | 
      
         | 144 |  |  |       Loc : constant Source_Ptr := Sloc (N);
 | 
      
         | 145 |  |  |  
 | 
      
         | 146 |  |  |       Lhs : constant Node_Id := Name (N);
 | 
      
         | 147 |  |  |  
 | 
      
         | 148 |  |  |       Act_Lhs : constant Node_Id := Get_Referenced_Object (Lhs);
 | 
      
         | 149 |  |  |       Act_Rhs : Node_Id          := Get_Referenced_Object (Rhs);
 | 
      
         | 150 |  |  |  
 | 
      
         | 151 |  |  |       L_Type : constant Entity_Id :=
 | 
      
         | 152 |  |  |                  Underlying_Type (Get_Actual_Subtype (Act_Lhs));
 | 
      
         | 153 |  |  |       R_Type : Entity_Id :=
 | 
      
         | 154 |  |  |                  Underlying_Type (Get_Actual_Subtype (Act_Rhs));
 | 
      
         | 155 |  |  |  
 | 
      
         | 156 |  |  |       L_Slice : constant Boolean := Nkind (Act_Lhs) = N_Slice;
 | 
      
         | 157 |  |  |       R_Slice : constant Boolean := Nkind (Act_Rhs) = N_Slice;
 | 
      
         | 158 |  |  |  
 | 
      
         | 159 |  |  |       Crep : constant Boolean := Change_Of_Representation (N);
 | 
      
         | 160 |  |  |  
 | 
      
         | 161 |  |  |       Larray  : Node_Id;
 | 
      
         | 162 |  |  |       Rarray  : Node_Id;
 | 
      
         | 163 |  |  |  
 | 
      
         | 164 |  |  |       Ndim : constant Pos := Number_Dimensions (L_Type);
 | 
      
         | 165 |  |  |  
 | 
      
         | 166 |  |  |       Loop_Required : Boolean := False;
 | 
      
         | 167 |  |  |       --  This switch is set to True if the array move must be done using
 | 
      
         | 168 |  |  |       --  an explicit front end generated loop.
 | 
      
         | 169 |  |  |  
 | 
      
         | 170 |  |  |       procedure Apply_Dereference (Arg : Node_Id);
 | 
      
         | 171 |  |  |       --  If the argument is an access to an array, and the assignment is
 | 
      
         | 172 |  |  |       --  converted into a procedure call, apply explicit dereference.
 | 
      
         | 173 |  |  |  
 | 
      
         | 174 |  |  |       function Has_Address_Clause (Exp : Node_Id) return Boolean;
 | 
      
         | 175 |  |  |       --  Test if Exp is a reference to an array whose declaration has
 | 
      
         | 176 |  |  |       --  an address clause, or it is a slice of such an array.
 | 
      
         | 177 |  |  |  
 | 
      
         | 178 |  |  |       function Is_Formal_Array (Exp : Node_Id) return Boolean;
 | 
      
         | 179 |  |  |       --  Test if Exp is a reference to an array which is either a formal
 | 
      
         | 180 |  |  |       --  parameter or a slice of a formal parameter. These are the cases
 | 
      
         | 181 |  |  |       --  where hidden aliasing can occur.
 | 
      
         | 182 |  |  |  
 | 
      
         | 183 |  |  |       function Is_Non_Local_Array (Exp : Node_Id) return Boolean;
 | 
      
         | 184 |  |  |       --  Determine if Exp is a reference to an array variable which is other
 | 
      
         | 185 |  |  |       --  than an object defined in the current scope, or a slice of such
 | 
      
         | 186 |  |  |       --  an object. Such objects can be aliased to parameters (unlike local
 | 
      
         | 187 |  |  |       --  array references).
 | 
      
         | 188 |  |  |  
 | 
      
         | 189 |  |  |       -----------------------
 | 
      
         | 190 |  |  |       -- Apply_Dereference --
 | 
      
         | 191 |  |  |       -----------------------
 | 
      
         | 192 |  |  |  
 | 
      
         | 193 |  |  |       procedure Apply_Dereference (Arg : Node_Id) is
 | 
      
         | 194 |  |  |          Typ : constant Entity_Id := Etype (Arg);
 | 
      
         | 195 |  |  |       begin
 | 
      
         | 196 |  |  |          if Is_Access_Type (Typ) then
 | 
      
         | 197 |  |  |             Rewrite (Arg, Make_Explicit_Dereference (Loc,
 | 
      
         | 198 |  |  |               Prefix => Relocate_Node (Arg)));
 | 
      
         | 199 |  |  |             Analyze_And_Resolve (Arg, Designated_Type (Typ));
 | 
      
         | 200 |  |  |          end if;
 | 
      
         | 201 |  |  |       end Apply_Dereference;
 | 
      
         | 202 |  |  |  
 | 
      
         | 203 |  |  |       ------------------------
 | 
      
         | 204 |  |  |       -- Has_Address_Clause --
 | 
      
         | 205 |  |  |       ------------------------
 | 
      
         | 206 |  |  |  
 | 
      
         | 207 |  |  |       function Has_Address_Clause (Exp : Node_Id) return Boolean is
 | 
      
         | 208 |  |  |       begin
 | 
      
         | 209 |  |  |          return
 | 
      
         | 210 |  |  |            (Is_Entity_Name (Exp) and then
 | 
      
         | 211 |  |  |                               Present (Address_Clause (Entity (Exp))))
 | 
      
         | 212 |  |  |              or else
 | 
      
         | 213 |  |  |            (Nkind (Exp) = N_Slice and then Has_Address_Clause (Prefix (Exp)));
 | 
      
         | 214 |  |  |       end Has_Address_Clause;
 | 
      
         | 215 |  |  |  
 | 
      
         | 216 |  |  |       ---------------------
 | 
      
         | 217 |  |  |       -- Is_Formal_Array --
 | 
      
         | 218 |  |  |       ---------------------
 | 
      
         | 219 |  |  |  
 | 
      
         | 220 |  |  |       function Is_Formal_Array (Exp : Node_Id) return Boolean is
 | 
      
         | 221 |  |  |       begin
 | 
      
         | 222 |  |  |          return
 | 
      
         | 223 |  |  |            (Is_Entity_Name (Exp) and then Is_Formal (Entity (Exp)))
 | 
      
         | 224 |  |  |              or else
 | 
      
         | 225 |  |  |            (Nkind (Exp) = N_Slice and then Is_Formal_Array (Prefix (Exp)));
 | 
      
         | 226 |  |  |       end Is_Formal_Array;
 | 
      
         | 227 |  |  |  
 | 
      
         | 228 |  |  |       ------------------------
 | 
      
         | 229 |  |  |       -- Is_Non_Local_Array --
 | 
      
         | 230 |  |  |       ------------------------
 | 
      
         | 231 |  |  |  
 | 
      
         | 232 |  |  |       function Is_Non_Local_Array (Exp : Node_Id) return Boolean is
 | 
      
         | 233 |  |  |       begin
 | 
      
         | 234 |  |  |          return (Is_Entity_Name (Exp)
 | 
      
         | 235 |  |  |                    and then Scope (Entity (Exp)) /= Current_Scope)
 | 
      
         | 236 |  |  |             or else (Nkind (Exp) = N_Slice
 | 
      
         | 237 |  |  |                        and then Is_Non_Local_Array (Prefix (Exp)));
 | 
      
         | 238 |  |  |       end Is_Non_Local_Array;
 | 
      
         | 239 |  |  |  
 | 
      
         | 240 |  |  |       --  Determine if Lhs, Rhs are formal arrays or nonlocal arrays
 | 
      
         | 241 |  |  |  
 | 
      
         | 242 |  |  |       Lhs_Formal : constant Boolean := Is_Formal_Array (Act_Lhs);
 | 
      
         | 243 |  |  |       Rhs_Formal : constant Boolean := Is_Formal_Array (Act_Rhs);
 | 
      
         | 244 |  |  |  
 | 
      
         | 245 |  |  |       Lhs_Non_Local_Var : constant Boolean := Is_Non_Local_Array (Act_Lhs);
 | 
      
         | 246 |  |  |       Rhs_Non_Local_Var : constant Boolean := Is_Non_Local_Array (Act_Rhs);
 | 
      
         | 247 |  |  |  
 | 
      
         | 248 |  |  |    --  Start of processing for Expand_Assign_Array
 | 
      
         | 249 |  |  |  
 | 
      
         | 250 |  |  |    begin
 | 
      
         | 251 |  |  |       --  Deal with length check. Note that the length check is done with
 | 
      
         | 252 |  |  |       --  respect to the right hand side as given, not a possible underlying
 | 
      
         | 253 |  |  |       --  renamed object, since this would generate incorrect extra checks.
 | 
      
         | 254 |  |  |  
 | 
      
         | 255 |  |  |       Apply_Length_Check (Rhs, L_Type);
 | 
      
         | 256 |  |  |  
 | 
      
         | 257 |  |  |       --  We start by assuming that the move can be done in either direction,
 | 
      
         | 258 |  |  |       --  i.e. that the two sides are completely disjoint.
 | 
      
         | 259 |  |  |  
 | 
      
         | 260 |  |  |       Set_Forwards_OK  (N, True);
 | 
      
         | 261 |  |  |       Set_Backwards_OK (N, True);
 | 
      
         | 262 |  |  |  
 | 
      
         | 263 |  |  |       --  Normally it is only the slice case that can lead to overlap, and
 | 
      
         | 264 |  |  |       --  explicit checks for slices are made below. But there is one case
 | 
      
         | 265 |  |  |       --  where the slice can be implicit and invisible to us: when we have a
 | 
      
         | 266 |  |  |       --  one dimensional array, and either both operands are parameters, or
 | 
      
         | 267 |  |  |       --  one is a parameter (which can be a slice passed by reference) and the
 | 
      
         | 268 |  |  |       --  other is a non-local variable. In this case the parameter could be a
 | 
      
         | 269 |  |  |       --  slice that overlaps with the other operand.
 | 
      
         | 270 |  |  |  
 | 
      
         | 271 |  |  |       --  However, if the array subtype is a constrained first subtype in the
 | 
      
         | 272 |  |  |       --  parameter case, then we don't have to worry about overlap, since
 | 
      
         | 273 |  |  |       --  slice assignments aren't possible (other than for a slice denoting
 | 
      
         | 274 |  |  |       --  the whole array).
 | 
      
         | 275 |  |  |  
 | 
      
         | 276 |  |  |       --  Note: No overlap is possible if there is a change of representation,
 | 
      
         | 277 |  |  |       --  so we can exclude this case.
 | 
      
         | 278 |  |  |  
 | 
      
         | 279 |  |  |       if Ndim = 1
 | 
      
         | 280 |  |  |         and then not Crep
 | 
      
         | 281 |  |  |         and then
 | 
      
         | 282 |  |  |            ((Lhs_Formal and Rhs_Formal)
 | 
      
         | 283 |  |  |               or else
 | 
      
         | 284 |  |  |             (Lhs_Formal and Rhs_Non_Local_Var)
 | 
      
         | 285 |  |  |               or else
 | 
      
         | 286 |  |  |             (Rhs_Formal and Lhs_Non_Local_Var))
 | 
      
         | 287 |  |  |         and then
 | 
      
         | 288 |  |  |            (not Is_Constrained (Etype (Lhs))
 | 
      
         | 289 |  |  |              or else not Is_First_Subtype (Etype (Lhs)))
 | 
      
         | 290 |  |  |  
 | 
      
         | 291 |  |  |          --  In the case of compiling for the Java or .NET Virtual Machine,
 | 
      
         | 292 |  |  |          --  slices are always passed by making a copy, so we don't have to
 | 
      
         | 293 |  |  |          --  worry about overlap. We also want to prevent generation of "<"
 | 
      
         | 294 |  |  |          --  comparisons for array addresses, since that's a meaningless
 | 
      
         | 295 |  |  |          --  operation on the VM.
 | 
      
         | 296 |  |  |  
 | 
      
         | 297 |  |  |         and then VM_Target = No_VM
 | 
      
         | 298 |  |  |       then
 | 
      
         | 299 |  |  |          Set_Forwards_OK  (N, False);
 | 
      
         | 300 |  |  |          Set_Backwards_OK (N, False);
 | 
      
         | 301 |  |  |  
 | 
      
         | 302 |  |  |          --  Note: the bit-packed case is not worrisome here, since if we have
 | 
      
         | 303 |  |  |          --  a slice passed as a parameter, it is always aligned on a byte
 | 
      
         | 304 |  |  |          --  boundary, and if there are no explicit slices, the assignment
 | 
      
         | 305 |  |  |          --  can be performed directly.
 | 
      
         | 306 |  |  |       end if;
 | 
      
         | 307 |  |  |  
 | 
      
         | 308 |  |  |       --  If either operand has an address clause clear Backwards_OK and
 | 
      
         | 309 |  |  |       --  Forwards_OK, since we cannot tell if the operands overlap. We
 | 
      
         | 310 |  |  |       --  exclude this treatment when Rhs is an aggregate, since we know
 | 
      
         | 311 |  |  |       --  that overlap can't occur.
 | 
      
         | 312 |  |  |  
 | 
      
         | 313 |  |  |       if (Has_Address_Clause (Lhs) and then Nkind (Rhs) /= N_Aggregate)
 | 
      
         | 314 |  |  |         or else Has_Address_Clause (Rhs)
 | 
      
         | 315 |  |  |       then
 | 
      
         | 316 |  |  |          Set_Forwards_OK  (N, False);
 | 
      
         | 317 |  |  |          Set_Backwards_OK (N, False);
 | 
      
         | 318 |  |  |       end if;
 | 
      
         | 319 |  |  |  
 | 
      
         | 320 |  |  |       --  We certainly must use a loop for change of representation and also
 | 
      
         | 321 |  |  |       --  we use the operand of the conversion on the right hand side as the
 | 
      
         | 322 |  |  |       --  effective right hand side (the component types must match in this
 | 
      
         | 323 |  |  |       --  situation).
 | 
      
         | 324 |  |  |  
 | 
      
         | 325 |  |  |       if Crep then
 | 
      
         | 326 |  |  |          Act_Rhs := Get_Referenced_Object (Rhs);
 | 
      
         | 327 |  |  |          R_Type  := Get_Actual_Subtype (Act_Rhs);
 | 
      
         | 328 |  |  |          Loop_Required := True;
 | 
      
         | 329 |  |  |  
 | 
      
         | 330 |  |  |       --  We require a loop if the left side is possibly bit unaligned
 | 
      
         | 331 |  |  |  
 | 
      
         | 332 |  |  |       elsif Possible_Bit_Aligned_Component (Lhs)
 | 
      
         | 333 |  |  |               or else
 | 
      
         | 334 |  |  |             Possible_Bit_Aligned_Component (Rhs)
 | 
      
         | 335 |  |  |       then
 | 
      
         | 336 |  |  |          Loop_Required := True;
 | 
      
         | 337 |  |  |  
 | 
      
         | 338 |  |  |       --  Arrays with controlled components are expanded into a loop to force
 | 
      
         | 339 |  |  |       --  calls to Adjust at the component level.
 | 
      
         | 340 |  |  |  
 | 
      
         | 341 |  |  |       elsif Has_Controlled_Component (L_Type) then
 | 
      
         | 342 |  |  |          Loop_Required := True;
 | 
      
         | 343 |  |  |  
 | 
      
         | 344 |  |  |          --  If object is atomic, we cannot tolerate a loop
 | 
      
         | 345 |  |  |  
 | 
      
         | 346 |  |  |       elsif Is_Atomic_Object (Act_Lhs)
 | 
      
         | 347 |  |  |               or else
 | 
      
         | 348 |  |  |             Is_Atomic_Object (Act_Rhs)
 | 
      
         | 349 |  |  |       then
 | 
      
         | 350 |  |  |          return;
 | 
      
         | 351 |  |  |  
 | 
      
         | 352 |  |  |       --  Loop is required if we have atomic components since we have to
 | 
      
         | 353 |  |  |       --  be sure to do any accesses on an element by element basis.
 | 
      
         | 354 |  |  |  
 | 
      
         | 355 |  |  |       elsif Has_Atomic_Components (L_Type)
 | 
      
         | 356 |  |  |         or else Has_Atomic_Components (R_Type)
 | 
      
         | 357 |  |  |         or else Is_Atomic (Component_Type (L_Type))
 | 
      
         | 358 |  |  |         or else Is_Atomic (Component_Type (R_Type))
 | 
      
         | 359 |  |  |       then
 | 
      
         | 360 |  |  |          Loop_Required := True;
 | 
      
         | 361 |  |  |  
 | 
      
         | 362 |  |  |       --  Case where no slice is involved
 | 
      
         | 363 |  |  |  
 | 
      
         | 364 |  |  |       elsif not L_Slice and not R_Slice then
 | 
      
         | 365 |  |  |  
 | 
      
         | 366 |  |  |          --  The following code deals with the case of unconstrained bit packed
 | 
      
         | 367 |  |  |          --  arrays. The problem is that the template for such arrays contains
 | 
      
         | 368 |  |  |          --  the bounds of the actual source level array, but the copy of an
 | 
      
         | 369 |  |  |          --  entire array requires the bounds of the underlying array. It would
 | 
      
         | 370 |  |  |          --  be nice if the back end could take care of this, but right now it
 | 
      
         | 371 |  |  |          --  does not know how, so if we have such a type, then we expand out
 | 
      
         | 372 |  |  |          --  into a loop, which is inefficient but works correctly. If we don't
 | 
      
         | 373 |  |  |          --  do this, we get the wrong length computed for the array to be
 | 
      
         | 374 |  |  |          --  moved. The two cases we need to worry about are:
 | 
      
         | 375 |  |  |  
 | 
      
         | 376 |  |  |          --  Explicit dereference of an unconstrained packed array type as in
 | 
      
         | 377 |  |  |          --  the following example:
 | 
      
         | 378 |  |  |  
 | 
      
         | 379 |  |  |          --    procedure C52 is
 | 
      
         | 380 |  |  |          --       type BITS is array(INTEGER range <>) of BOOLEAN;
 | 
      
         | 381 |  |  |          --       pragma PACK(BITS);
 | 
      
         | 382 |  |  |          --       type A is access BITS;
 | 
      
         | 383 |  |  |          --       P1,P2 : A;
 | 
      
         | 384 |  |  |          --    begin
 | 
      
         | 385 |  |  |          --       P1 := new BITS (1 .. 65_535);
 | 
      
         | 386 |  |  |          --       P2 := new BITS (1 .. 65_535);
 | 
      
         | 387 |  |  |          --       P2.ALL := P1.ALL;
 | 
      
         | 388 |  |  |          --    end C52;
 | 
      
         | 389 |  |  |  
 | 
      
         | 390 |  |  |          --  A formal parameter reference with an unconstrained bit array type
 | 
      
         | 391 |  |  |          --  is the other case we need to worry about (here we assume the same
 | 
      
         | 392 |  |  |          --  BITS type declared above):
 | 
      
         | 393 |  |  |  
 | 
      
         | 394 |  |  |          --    procedure Write_All (File : out BITS; Contents : BITS);
 | 
      
         | 395 |  |  |          --    begin
 | 
      
         | 396 |  |  |          --       File.Storage := Contents;
 | 
      
         | 397 |  |  |          --    end Write_All;
 | 
      
         | 398 |  |  |  
 | 
      
         | 399 |  |  |          --  We expand to a loop in either of these two cases
 | 
      
         | 400 |  |  |  
 | 
      
         | 401 |  |  |          --  Question for future thought. Another potentially more efficient
 | 
      
         | 402 |  |  |          --  approach would be to create the actual subtype, and then do an
 | 
      
         | 403 |  |  |          --  unchecked conversion to this actual subtype ???
 | 
      
         | 404 |  |  |  
 | 
      
         | 405 |  |  |          Check_Unconstrained_Bit_Packed_Array : declare
 | 
      
         | 406 |  |  |  
 | 
      
         | 407 |  |  |             function Is_UBPA_Reference (Opnd : Node_Id) return Boolean;
 | 
      
         | 408 |  |  |             --  Function to perform required test for the first case, above
 | 
      
         | 409 |  |  |             --  (dereference of an unconstrained bit packed array).
 | 
      
         | 410 |  |  |  
 | 
      
         | 411 |  |  |             -----------------------
 | 
      
         | 412 |  |  |             -- Is_UBPA_Reference --
 | 
      
         | 413 |  |  |             -----------------------
 | 
      
         | 414 |  |  |  
 | 
      
         | 415 |  |  |             function Is_UBPA_Reference (Opnd : Node_Id) return Boolean is
 | 
      
         | 416 |  |  |                Typ      : constant Entity_Id := Underlying_Type (Etype (Opnd));
 | 
      
         | 417 |  |  |                P_Type   : Entity_Id;
 | 
      
         | 418 |  |  |                Des_Type : Entity_Id;
 | 
      
         | 419 |  |  |  
 | 
      
         | 420 |  |  |             begin
 | 
      
         | 421 |  |  |                if Present (Packed_Array_Type (Typ))
 | 
      
         | 422 |  |  |                  and then Is_Array_Type (Packed_Array_Type (Typ))
 | 
      
         | 423 |  |  |                  and then not Is_Constrained (Packed_Array_Type (Typ))
 | 
      
         | 424 |  |  |                then
 | 
      
         | 425 |  |  |                   return True;
 | 
      
         | 426 |  |  |  
 | 
      
         | 427 |  |  |                elsif Nkind (Opnd) = N_Explicit_Dereference then
 | 
      
         | 428 |  |  |                   P_Type := Underlying_Type (Etype (Prefix (Opnd)));
 | 
      
         | 429 |  |  |  
 | 
      
         | 430 |  |  |                   if not Is_Access_Type (P_Type) then
 | 
      
         | 431 |  |  |                      return False;
 | 
      
         | 432 |  |  |  
 | 
      
         | 433 |  |  |                   else
 | 
      
         | 434 |  |  |                      Des_Type := Designated_Type (P_Type);
 | 
      
         | 435 |  |  |                      return
 | 
      
         | 436 |  |  |                        Is_Bit_Packed_Array (Des_Type)
 | 
      
         | 437 |  |  |                          and then not Is_Constrained (Des_Type);
 | 
      
         | 438 |  |  |                   end if;
 | 
      
         | 439 |  |  |  
 | 
      
         | 440 |  |  |                else
 | 
      
         | 441 |  |  |                   return False;
 | 
      
         | 442 |  |  |                end if;
 | 
      
         | 443 |  |  |             end Is_UBPA_Reference;
 | 
      
         | 444 |  |  |  
 | 
      
         | 445 |  |  |          --  Start of processing for Check_Unconstrained_Bit_Packed_Array
 | 
      
         | 446 |  |  |  
 | 
      
         | 447 |  |  |          begin
 | 
      
         | 448 |  |  |             if Is_UBPA_Reference (Lhs)
 | 
      
         | 449 |  |  |                  or else
 | 
      
         | 450 |  |  |                Is_UBPA_Reference (Rhs)
 | 
      
         | 451 |  |  |             then
 | 
      
         | 452 |  |  |                Loop_Required := True;
 | 
      
         | 453 |  |  |  
 | 
      
         | 454 |  |  |             --  Here if we do not have the case of a reference to a bit packed
 | 
      
         | 455 |  |  |             --  unconstrained array case. In this case gigi can most certainly
 | 
      
         | 456 |  |  |             --  handle the assignment if a forwards move is allowed.
 | 
      
         | 457 |  |  |  
 | 
      
         | 458 |  |  |             --  (could it handle the backwards case also???)
 | 
      
         | 459 |  |  |  
 | 
      
         | 460 |  |  |             elsif Forwards_OK (N) then
 | 
      
         | 461 |  |  |                return;
 | 
      
         | 462 |  |  |             end if;
 | 
      
         | 463 |  |  |          end Check_Unconstrained_Bit_Packed_Array;
 | 
      
         | 464 |  |  |  
 | 
      
         | 465 |  |  |       --  The back end can always handle the assignment if the right side is a
 | 
      
         | 466 |  |  |       --  string literal (note that overlap is definitely impossible in this
 | 
      
         | 467 |  |  |       --  case). If the type is packed, a string literal is always converted
 | 
      
         | 468 |  |  |       --  into an aggregate, except in the case of a null slice, for which no
 | 
      
         | 469 |  |  |       --  aggregate can be written. In that case, rewrite the assignment as a
 | 
      
         | 470 |  |  |       --  null statement, a length check has already been emitted to verify
 | 
      
         | 471 |  |  |       --  that the range of the left-hand side is empty.
 | 
      
         | 472 |  |  |  
 | 
      
         | 473 |  |  |       --  Note that this code is not executed if we have an assignment of a
 | 
      
         | 474 |  |  |       --  string literal to a non-bit aligned component of a record, a case
 | 
      
         | 475 |  |  |       --  which cannot be handled by the backend.
 | 
      
         | 476 |  |  |  
 | 
      
         | 477 |  |  |       elsif Nkind (Rhs) = N_String_Literal then
 | 
      
         | 478 |  |  |          if String_Length (Strval (Rhs)) = 0
 | 
      
         | 479 |  |  |            and then Is_Bit_Packed_Array (L_Type)
 | 
      
         | 480 |  |  |          then
 | 
      
         | 481 |  |  |             Rewrite (N, Make_Null_Statement (Loc));
 | 
      
         | 482 |  |  |             Analyze (N);
 | 
      
         | 483 |  |  |          end if;
 | 
      
         | 484 |  |  |  
 | 
      
         | 485 |  |  |          return;
 | 
      
         | 486 |  |  |  
 | 
      
         | 487 |  |  |       --  If either operand is bit packed, then we need a loop, since we can't
 | 
      
         | 488 |  |  |       --  be sure that the slice is byte aligned. Similarly, if either operand
 | 
      
         | 489 |  |  |       --  is a possibly unaligned slice, then we need a loop (since the back
 | 
      
         | 490 |  |  |       --  end cannot handle unaligned slices).
 | 
      
         | 491 |  |  |  
 | 
      
         | 492 |  |  |       elsif Is_Bit_Packed_Array (L_Type)
 | 
      
         | 493 |  |  |         or else Is_Bit_Packed_Array (R_Type)
 | 
      
         | 494 |  |  |         or else Is_Possibly_Unaligned_Slice (Lhs)
 | 
      
         | 495 |  |  |         or else Is_Possibly_Unaligned_Slice (Rhs)
 | 
      
         | 496 |  |  |       then
 | 
      
         | 497 |  |  |          Loop_Required := True;
 | 
      
         | 498 |  |  |  
 | 
      
         | 499 |  |  |       --  If we are not bit-packed, and we have only one slice, then no overlap
 | 
      
         | 500 |  |  |       --  is possible except in the parameter case, so we can let the back end
 | 
      
         | 501 |  |  |       --  handle things.
 | 
      
         | 502 |  |  |  
 | 
      
         | 503 |  |  |       elsif not (L_Slice and R_Slice) then
 | 
      
         | 504 |  |  |          if Forwards_OK (N) then
 | 
      
         | 505 |  |  |             return;
 | 
      
         | 506 |  |  |          end if;
 | 
      
         | 507 |  |  |       end if;
 | 
      
         | 508 |  |  |  
 | 
      
         | 509 |  |  |       --  If the right-hand side is a string literal, introduce a temporary for
 | 
      
         | 510 |  |  |       --  it, for use in the generated loop that will follow.
 | 
      
         | 511 |  |  |  
 | 
      
         | 512 |  |  |       if Nkind (Rhs) = N_String_Literal then
 | 
      
         | 513 |  |  |          declare
 | 
      
         | 514 |  |  |             Temp : constant Entity_Id := Make_Temporary (Loc, 'T', Rhs);
 | 
      
         | 515 |  |  |             Decl : Node_Id;
 | 
      
         | 516 |  |  |  
 | 
      
         | 517 |  |  |          begin
 | 
      
         | 518 |  |  |             Decl :=
 | 
      
         | 519 |  |  |               Make_Object_Declaration (Loc,
 | 
      
         | 520 |  |  |                  Defining_Identifier => Temp,
 | 
      
         | 521 |  |  |                  Object_Definition => New_Occurrence_Of (L_Type, Loc),
 | 
      
         | 522 |  |  |                  Expression => Relocate_Node (Rhs));
 | 
      
         | 523 |  |  |  
 | 
      
         | 524 |  |  |             Insert_Action (N, Decl);
 | 
      
         | 525 |  |  |             Rewrite (Rhs, New_Occurrence_Of (Temp, Loc));
 | 
      
         | 526 |  |  |             R_Type := Etype (Temp);
 | 
      
         | 527 |  |  |          end;
 | 
      
         | 528 |  |  |       end if;
 | 
      
         | 529 |  |  |  
 | 
      
         | 530 |  |  |       --  Come here to complete the analysis
 | 
      
         | 531 |  |  |  
 | 
      
         | 532 |  |  |       --    Loop_Required: Set to True if we know that a loop is required
 | 
      
         | 533 |  |  |       --                   regardless of overlap considerations.
 | 
      
         | 534 |  |  |  
 | 
      
         | 535 |  |  |       --    Forwards_OK:   Set to False if we already know that a forwards
 | 
      
         | 536 |  |  |       --                   move is not safe, else set to True.
 | 
      
         | 537 |  |  |  
 | 
      
         | 538 |  |  |       --    Backwards_OK:  Set to False if we already know that a backwards
 | 
      
         | 539 |  |  |       --                   move is not safe, else set to True
 | 
      
         | 540 |  |  |  
 | 
      
         | 541 |  |  |       --  Our task at this stage is to complete the overlap analysis, which can
 | 
      
         | 542 |  |  |       --  result in possibly setting Forwards_OK or Backwards_OK to False, and
 | 
      
         | 543 |  |  |       --  then generating the final code, either by deciding that it is OK
 | 
      
         | 544 |  |  |       --  after all to let Gigi handle it, or by generating appropriate code
 | 
      
         | 545 |  |  |       --  in the front end.
 | 
      
         | 546 |  |  |  
 | 
      
         | 547 |  |  |       declare
 | 
      
         | 548 |  |  |          L_Index_Typ : constant Node_Id := Etype (First_Index (L_Type));
 | 
      
         | 549 |  |  |          R_Index_Typ : constant Node_Id := Etype (First_Index (R_Type));
 | 
      
         | 550 |  |  |  
 | 
      
         | 551 |  |  |          Left_Lo  : constant Node_Id := Type_Low_Bound  (L_Index_Typ);
 | 
      
         | 552 |  |  |          Left_Hi  : constant Node_Id := Type_High_Bound (L_Index_Typ);
 | 
      
         | 553 |  |  |          Right_Lo : constant Node_Id := Type_Low_Bound  (R_Index_Typ);
 | 
      
         | 554 |  |  |          Right_Hi : constant Node_Id := Type_High_Bound (R_Index_Typ);
 | 
      
         | 555 |  |  |  
 | 
      
         | 556 |  |  |          Act_L_Array : Node_Id;
 | 
      
         | 557 |  |  |          Act_R_Array : Node_Id;
 | 
      
         | 558 |  |  |  
 | 
      
         | 559 |  |  |          Cleft_Lo  : Node_Id;
 | 
      
         | 560 |  |  |          Cright_Lo : Node_Id;
 | 
      
         | 561 |  |  |          Condition : Node_Id;
 | 
      
         | 562 |  |  |  
 | 
      
         | 563 |  |  |          Cresult : Compare_Result;
 | 
      
         | 564 |  |  |  
 | 
      
         | 565 |  |  |       begin
 | 
      
         | 566 |  |  |          --  Get the expressions for the arrays. If we are dealing with a
 | 
      
         | 567 |  |  |          --  private type, then convert to the underlying type. We can do
 | 
      
         | 568 |  |  |          --  direct assignments to an array that is a private type, but we
 | 
      
         | 569 |  |  |          --  cannot assign to elements of the array without this extra
 | 
      
         | 570 |  |  |          --  unchecked conversion.
 | 
      
         | 571 |  |  |  
 | 
      
         | 572 |  |  |          --  Note: We propagate Parent to the conversion nodes to generate
 | 
      
         | 573 |  |  |          --  a well-formed subtree.
 | 
      
         | 574 |  |  |  
 | 
      
         | 575 |  |  |          if Nkind (Act_Lhs) = N_Slice then
 | 
      
         | 576 |  |  |             Larray := Prefix (Act_Lhs);
 | 
      
         | 577 |  |  |          else
 | 
      
         | 578 |  |  |             Larray := Act_Lhs;
 | 
      
         | 579 |  |  |  
 | 
      
         | 580 |  |  |             if Is_Private_Type (Etype (Larray)) then
 | 
      
         | 581 |  |  |                declare
 | 
      
         | 582 |  |  |                   Par : constant Node_Id := Parent (Larray);
 | 
      
         | 583 |  |  |                begin
 | 
      
         | 584 |  |  |                   Larray :=
 | 
      
         | 585 |  |  |                     Unchecked_Convert_To
 | 
      
         | 586 |  |  |                       (Underlying_Type (Etype (Larray)), Larray);
 | 
      
         | 587 |  |  |                   Set_Parent (Larray, Par);
 | 
      
         | 588 |  |  |                end;
 | 
      
         | 589 |  |  |             end if;
 | 
      
         | 590 |  |  |          end if;
 | 
      
         | 591 |  |  |  
 | 
      
         | 592 |  |  |          if Nkind (Act_Rhs) = N_Slice then
 | 
      
         | 593 |  |  |             Rarray := Prefix (Act_Rhs);
 | 
      
         | 594 |  |  |          else
 | 
      
         | 595 |  |  |             Rarray := Act_Rhs;
 | 
      
         | 596 |  |  |  
 | 
      
         | 597 |  |  |             if Is_Private_Type (Etype (Rarray)) then
 | 
      
         | 598 |  |  |                declare
 | 
      
         | 599 |  |  |                   Par : constant Node_Id := Parent (Rarray);
 | 
      
         | 600 |  |  |                begin
 | 
      
         | 601 |  |  |                   Rarray :=
 | 
      
         | 602 |  |  |                     Unchecked_Convert_To
 | 
      
         | 603 |  |  |                       (Underlying_Type (Etype (Rarray)), Rarray);
 | 
      
         | 604 |  |  |                   Set_Parent (Rarray, Par);
 | 
      
         | 605 |  |  |                end;
 | 
      
         | 606 |  |  |             end if;
 | 
      
         | 607 |  |  |          end if;
 | 
      
         | 608 |  |  |  
 | 
      
         | 609 |  |  |          --  If both sides are slices, we must figure out whether it is safe
 | 
      
         | 610 |  |  |          --  to do the move in one direction or the other. It is always safe
 | 
      
         | 611 |  |  |          --  if there is a change of representation since obviously two arrays
 | 
      
         | 612 |  |  |          --  with different representations cannot possibly overlap.
 | 
      
         | 613 |  |  |  
 | 
      
         | 614 |  |  |          if (not Crep) and L_Slice and R_Slice then
 | 
      
         | 615 |  |  |             Act_L_Array := Get_Referenced_Object (Prefix (Act_Lhs));
 | 
      
         | 616 |  |  |             Act_R_Array := Get_Referenced_Object (Prefix (Act_Rhs));
 | 
      
         | 617 |  |  |  
 | 
      
         | 618 |  |  |             --  If both left and right hand arrays are entity names, and refer
 | 
      
         | 619 |  |  |             --  to different entities, then we know that the move is safe (the
 | 
      
         | 620 |  |  |             --  two storage areas are completely disjoint).
 | 
      
         | 621 |  |  |  
 | 
      
         | 622 |  |  |             if Is_Entity_Name (Act_L_Array)
 | 
      
         | 623 |  |  |               and then Is_Entity_Name (Act_R_Array)
 | 
      
         | 624 |  |  |               and then Entity (Act_L_Array) /= Entity (Act_R_Array)
 | 
      
         | 625 |  |  |             then
 | 
      
         | 626 |  |  |                null;
 | 
      
         | 627 |  |  |  
 | 
      
         | 628 |  |  |             --  Otherwise, we assume the worst, which is that the two arrays
 | 
      
         | 629 |  |  |             --  are the same array. There is no need to check if we know that
 | 
      
         | 630 |  |  |             --  is the case, because if we don't know it, we still have to
 | 
      
         | 631 |  |  |             --  assume it!
 | 
      
         | 632 |  |  |  
 | 
      
         | 633 |  |  |             --  Generally if the same array is involved, then we have an
 | 
      
         | 634 |  |  |             --  overlapping case. We will have to really assume the worst (i.e.
 | 
      
         | 635 |  |  |             --  set neither of the OK flags) unless we can determine the lower
 | 
      
         | 636 |  |  |             --  or upper bounds at compile time and compare them.
 | 
      
         | 637 |  |  |  
 | 
      
         | 638 |  |  |             else
 | 
      
         | 639 |  |  |                Cresult :=
 | 
      
         | 640 |  |  |                  Compile_Time_Compare
 | 
      
         | 641 |  |  |                    (Left_Lo, Right_Lo, Assume_Valid => True);
 | 
      
         | 642 |  |  |  
 | 
      
         | 643 |  |  |                if Cresult = Unknown then
 | 
      
         | 644 |  |  |                   Cresult :=
 | 
      
         | 645 |  |  |                     Compile_Time_Compare
 | 
      
         | 646 |  |  |                       (Left_Hi, Right_Hi, Assume_Valid => True);
 | 
      
         | 647 |  |  |                end if;
 | 
      
         | 648 |  |  |  
 | 
      
         | 649 |  |  |                case Cresult is
 | 
      
         | 650 |  |  |                   when LT | LE | EQ => Set_Backwards_OK (N, False);
 | 
      
         | 651 |  |  |                   when GT | GE      => Set_Forwards_OK  (N, False);
 | 
      
         | 652 |  |  |                   when NE | Unknown => Set_Backwards_OK (N, False);
 | 
      
         | 653 |  |  |                                        Set_Forwards_OK  (N, False);
 | 
      
         | 654 |  |  |                end case;
 | 
      
         | 655 |  |  |             end if;
 | 
      
         | 656 |  |  |          end if;
 | 
      
         | 657 |  |  |  
 | 
      
         | 658 |  |  |          --  If after that analysis Loop_Required is False, meaning that we
 | 
      
         | 659 |  |  |          --  have not discovered some non-overlap reason for requiring a loop,
 | 
      
         | 660 |  |  |          --  then the outcome depends on the capabilities of the back end.
 | 
      
         | 661 |  |  |  
 | 
      
         | 662 |  |  |          if not Loop_Required then
 | 
      
         | 663 |  |  |  
 | 
      
         | 664 |  |  |             --  The GCC back end can deal with all cases of overlap by falling
 | 
      
         | 665 |  |  |             --  back to memmove if it cannot use a more efficient approach.
 | 
      
         | 666 |  |  |  
 | 
      
         | 667 |  |  |             if VM_Target = No_VM and not AAMP_On_Target then
 | 
      
         | 668 |  |  |                return;
 | 
      
         | 669 |  |  |  
 | 
      
         | 670 |  |  |             --  Assume other back ends can handle it if Forwards_OK is set
 | 
      
         | 671 |  |  |  
 | 
      
         | 672 |  |  |             elsif Forwards_OK (N) then
 | 
      
         | 673 |  |  |                return;
 | 
      
         | 674 |  |  |  
 | 
      
         | 675 |  |  |             --  If Forwards_OK is not set, the back end will need something
 | 
      
         | 676 |  |  |             --  like memmove to handle the move. For now, this processing is
 | 
      
         | 677 |  |  |             --  activated using the .s debug flag (-gnatd.s).
 | 
      
         | 678 |  |  |  
 | 
      
         | 679 |  |  |             elsif Debug_Flag_Dot_S then
 | 
      
         | 680 |  |  |                return;
 | 
      
         | 681 |  |  |             end if;
 | 
      
         | 682 |  |  |          end if;
 | 
      
         | 683 |  |  |  
 | 
      
         | 684 |  |  |          --  At this stage we have to generate an explicit loop, and we have
 | 
      
         | 685 |  |  |          --  the following cases:
 | 
      
         | 686 |  |  |  
 | 
      
         | 687 |  |  |          --  Forwards_OK = True
 | 
      
         | 688 |  |  |  
 | 
      
         | 689 |  |  |          --    Rnn : right_index := right_index'First;
 | 
      
         | 690 |  |  |          --    for Lnn in left-index loop
 | 
      
         | 691 |  |  |          --       left (Lnn) := right (Rnn);
 | 
      
         | 692 |  |  |          --       Rnn := right_index'Succ (Rnn);
 | 
      
         | 693 |  |  |          --    end loop;
 | 
      
         | 694 |  |  |  
 | 
      
         | 695 |  |  |          --    Note: the above code MUST be analyzed with checks off, because
 | 
      
         | 696 |  |  |          --    otherwise the Succ could overflow. But in any case this is more
 | 
      
         | 697 |  |  |          --    efficient!
 | 
      
         | 698 |  |  |  
 | 
      
         | 699 |  |  |          --  Forwards_OK = False, Backwards_OK = True
 | 
      
         | 700 |  |  |  
 | 
      
         | 701 |  |  |          --    Rnn : right_index := right_index'Last;
 | 
      
         | 702 |  |  |          --    for Lnn in reverse left-index loop
 | 
      
         | 703 |  |  |          --       left (Lnn) := right (Rnn);
 | 
      
         | 704 |  |  |          --       Rnn := right_index'Pred (Rnn);
 | 
      
         | 705 |  |  |          --    end loop;
 | 
      
         | 706 |  |  |  
 | 
      
         | 707 |  |  |          --    Note: the above code MUST be analyzed with checks off, because
 | 
      
         | 708 |  |  |          --    otherwise the Pred could overflow. But in any case this is more
 | 
      
         | 709 |  |  |          --    efficient!
 | 
      
         | 710 |  |  |  
 | 
      
         | 711 |  |  |          --  Forwards_OK = Backwards_OK = False
 | 
      
         | 712 |  |  |  
 | 
      
         | 713 |  |  |          --    This only happens if we have the same array on each side. It is
 | 
      
         | 714 |  |  |          --    possible to create situations using overlays that violate this,
 | 
      
         | 715 |  |  |          --    but we simply do not promise to get this "right" in this case.
 | 
      
         | 716 |  |  |  
 | 
      
         | 717 |  |  |          --    There are two possible subcases. If the No_Implicit_Conditionals
 | 
      
         | 718 |  |  |          --    restriction is set, then we generate the following code:
 | 
      
         | 719 |  |  |  
 | 
      
         | 720 |  |  |          --      declare
 | 
      
         | 721 |  |  |          --        T : constant <operand-type> := rhs;
 | 
      
         | 722 |  |  |          --      begin
 | 
      
         | 723 |  |  |          --        lhs := T;
 | 
      
         | 724 |  |  |          --      end;
 | 
      
         | 725 |  |  |  
 | 
      
         | 726 |  |  |          --    If implicit conditionals are permitted, then we generate:
 | 
      
         | 727 |  |  |  
 | 
      
         | 728 |  |  |          --      if Left_Lo <= Right_Lo then
 | 
      
         | 729 |  |  |          --         <code for Forwards_OK = True above>
 | 
      
         | 730 |  |  |          --      else
 | 
      
         | 731 |  |  |          --         <code for Backwards_OK = True above>
 | 
      
         | 732 |  |  |          --      end if;
 | 
      
         | 733 |  |  |  
 | 
      
         | 734 |  |  |          --  In order to detect possible aliasing, we examine the renamed
 | 
      
         | 735 |  |  |          --  expression when the source or target is a renaming. However,
 | 
      
         | 736 |  |  |          --  the renaming may be intended to capture an address that may be
 | 
      
         | 737 |  |  |          --  affected by subsequent code, and therefore we must recover
 | 
      
         | 738 |  |  |          --  the actual entity for the expansion that follows, not the
 | 
      
         | 739 |  |  |          --  object it renames. In particular, if source or target designate
 | 
      
         | 740 |  |  |          --  a portion of a dynamically allocated object, the pointer to it
 | 
      
         | 741 |  |  |          --  may be reassigned but the renaming preserves the proper location.
 | 
      
         | 742 |  |  |  
 | 
      
         | 743 |  |  |          if Is_Entity_Name (Rhs)
 | 
      
         | 744 |  |  |            and then
 | 
      
         | 745 |  |  |              Nkind (Parent (Entity (Rhs))) = N_Object_Renaming_Declaration
 | 
      
         | 746 |  |  |            and then Nkind (Act_Rhs) = N_Slice
 | 
      
         | 747 |  |  |          then
 | 
      
         | 748 |  |  |             Rarray := Rhs;
 | 
      
         | 749 |  |  |          end if;
 | 
      
         | 750 |  |  |  
 | 
      
         | 751 |  |  |          if Is_Entity_Name (Lhs)
 | 
      
         | 752 |  |  |            and then
 | 
      
         | 753 |  |  |              Nkind (Parent (Entity (Lhs))) = N_Object_Renaming_Declaration
 | 
      
         | 754 |  |  |            and then Nkind (Act_Lhs) = N_Slice
 | 
      
         | 755 |  |  |          then
 | 
      
         | 756 |  |  |             Larray := Lhs;
 | 
      
         | 757 |  |  |          end if;
 | 
      
         | 758 |  |  |  
 | 
      
         | 759 |  |  |          --  Cases where either Forwards_OK or Backwards_OK is true
 | 
      
         | 760 |  |  |  
 | 
      
         | 761 |  |  |          if Forwards_OK (N) or else Backwards_OK (N) then
 | 
      
         | 762 |  |  |             if Needs_Finalization (Component_Type (L_Type))
 | 
      
         | 763 |  |  |               and then Base_Type (L_Type) = Base_Type (R_Type)
 | 
      
         | 764 |  |  |               and then Ndim = 1
 | 
      
         | 765 |  |  |               and then not No_Ctrl_Actions (N)
 | 
      
         | 766 |  |  |             then
 | 
      
         | 767 |  |  |                declare
 | 
      
         | 768 |  |  |                   Proc    : constant Entity_Id :=
 | 
      
         | 769 |  |  |                               TSS (Base_Type (L_Type), TSS_Slice_Assign);
 | 
      
         | 770 |  |  |                   Actuals : List_Id;
 | 
      
         | 771 |  |  |  
 | 
      
         | 772 |  |  |                begin
 | 
      
         | 773 |  |  |                   Apply_Dereference (Larray);
 | 
      
         | 774 |  |  |                   Apply_Dereference (Rarray);
 | 
      
         | 775 |  |  |                   Actuals := New_List (
 | 
      
         | 776 |  |  |                     Duplicate_Subexpr (Larray,   Name_Req => True),
 | 
      
         | 777 |  |  |                     Duplicate_Subexpr (Rarray,   Name_Req => True),
 | 
      
         | 778 |  |  |                     Duplicate_Subexpr (Left_Lo,  Name_Req => True),
 | 
      
         | 779 |  |  |                     Duplicate_Subexpr (Left_Hi,  Name_Req => True),
 | 
      
         | 780 |  |  |                     Duplicate_Subexpr (Right_Lo, Name_Req => True),
 | 
      
         | 781 |  |  |                     Duplicate_Subexpr (Right_Hi, Name_Req => True));
 | 
      
         | 782 |  |  |  
 | 
      
         | 783 |  |  |                   Append_To (Actuals,
 | 
      
         | 784 |  |  |                     New_Occurrence_Of (
 | 
      
         | 785 |  |  |                       Boolean_Literals (not Forwards_OK (N)), Loc));
 | 
      
         | 786 |  |  |  
 | 
      
         | 787 |  |  |                   Rewrite (N,
 | 
      
         | 788 |  |  |                     Make_Procedure_Call_Statement (Loc,
 | 
      
         | 789 |  |  |                       Name => New_Reference_To (Proc, Loc),
 | 
      
         | 790 |  |  |                       Parameter_Associations => Actuals));
 | 
      
         | 791 |  |  |                end;
 | 
      
         | 792 |  |  |  
 | 
      
         | 793 |  |  |             else
 | 
      
         | 794 |  |  |                Rewrite (N,
 | 
      
         | 795 |  |  |                  Expand_Assign_Array_Loop
 | 
      
         | 796 |  |  |                    (N, Larray, Rarray, L_Type, R_Type, Ndim,
 | 
      
         | 797 |  |  |                     Rev => not Forwards_OK (N)));
 | 
      
         | 798 |  |  |             end if;
 | 
      
         | 799 |  |  |  
 | 
      
         | 800 |  |  |          --  Case of both are false with No_Implicit_Conditionals
 | 
      
         | 801 |  |  |  
 | 
      
         | 802 |  |  |          elsif Restriction_Active (No_Implicit_Conditionals) then
 | 
      
         | 803 |  |  |             declare
 | 
      
         | 804 |  |  |                   T : constant Entity_Id :=
 | 
      
         | 805 |  |  |                         Make_Defining_Identifier (Loc, Chars => Name_T);
 | 
      
         | 806 |  |  |  
 | 
      
         | 807 |  |  |             begin
 | 
      
         | 808 |  |  |                Rewrite (N,
 | 
      
         | 809 |  |  |                  Make_Block_Statement (Loc,
 | 
      
         | 810 |  |  |                   Declarations => New_List (
 | 
      
         | 811 |  |  |                     Make_Object_Declaration (Loc,
 | 
      
         | 812 |  |  |                       Defining_Identifier => T,
 | 
      
         | 813 |  |  |                       Constant_Present  => True,
 | 
      
         | 814 |  |  |                       Object_Definition =>
 | 
      
         | 815 |  |  |                         New_Occurrence_Of (Etype (Rhs), Loc),
 | 
      
         | 816 |  |  |                       Expression        => Relocate_Node (Rhs))),
 | 
      
         | 817 |  |  |  
 | 
      
         | 818 |  |  |                     Handled_Statement_Sequence =>
 | 
      
         | 819 |  |  |                       Make_Handled_Sequence_Of_Statements (Loc,
 | 
      
         | 820 |  |  |                         Statements => New_List (
 | 
      
         | 821 |  |  |                           Make_Assignment_Statement (Loc,
 | 
      
         | 822 |  |  |                             Name       => Relocate_Node (Lhs),
 | 
      
         | 823 |  |  |                             Expression => New_Occurrence_Of (T, Loc))))));
 | 
      
         | 824 |  |  |             end;
 | 
      
         | 825 |  |  |  
 | 
      
         | 826 |  |  |          --  Case of both are false with implicit conditionals allowed
 | 
      
         | 827 |  |  |  
 | 
      
         | 828 |  |  |          else
 | 
      
         | 829 |  |  |             --  Before we generate this code, we must ensure that the left and
 | 
      
         | 830 |  |  |             --  right side array types are defined. They may be itypes, and we
 | 
      
         | 831 |  |  |             --  cannot let them be defined inside the if, since the first use
 | 
      
         | 832 |  |  |             --  in the then may not be executed.
 | 
      
         | 833 |  |  |  
 | 
      
         | 834 |  |  |             Ensure_Defined (L_Type, N);
 | 
      
         | 835 |  |  |             Ensure_Defined (R_Type, N);
 | 
      
         | 836 |  |  |  
 | 
      
         | 837 |  |  |             --  We normally compare addresses to find out which way round to
 | 
      
         | 838 |  |  |             --  do the loop, since this is reliable, and handles the cases of
 | 
      
         | 839 |  |  |             --  parameters, conversions etc. But we can't do that in the bit
 | 
      
         | 840 |  |  |             --  packed case or the VM case, because addresses don't work there.
 | 
      
         | 841 |  |  |  
 | 
      
         | 842 |  |  |             if not Is_Bit_Packed_Array (L_Type) and then VM_Target = No_VM then
 | 
      
         | 843 |  |  |                Condition :=
 | 
      
         | 844 |  |  |                  Make_Op_Le (Loc,
 | 
      
         | 845 |  |  |                    Left_Opnd =>
 | 
      
         | 846 |  |  |                      Unchecked_Convert_To (RTE (RE_Integer_Address),
 | 
      
         | 847 |  |  |                        Make_Attribute_Reference (Loc,
 | 
      
         | 848 |  |  |                          Prefix =>
 | 
      
         | 849 |  |  |                            Make_Indexed_Component (Loc,
 | 
      
         | 850 |  |  |                              Prefix =>
 | 
      
         | 851 |  |  |                                Duplicate_Subexpr_Move_Checks (Larray, True),
 | 
      
         | 852 |  |  |                              Expressions => New_List (
 | 
      
         | 853 |  |  |                                Make_Attribute_Reference (Loc,
 | 
      
         | 854 |  |  |                                  Prefix =>
 | 
      
         | 855 |  |  |                                    New_Reference_To
 | 
      
         | 856 |  |  |                                      (L_Index_Typ, Loc),
 | 
      
         | 857 |  |  |                                  Attribute_Name => Name_First))),
 | 
      
         | 858 |  |  |                          Attribute_Name => Name_Address)),
 | 
      
         | 859 |  |  |  
 | 
      
         | 860 |  |  |                    Right_Opnd =>
 | 
      
         | 861 |  |  |                      Unchecked_Convert_To (RTE (RE_Integer_Address),
 | 
      
         | 862 |  |  |                        Make_Attribute_Reference (Loc,
 | 
      
         | 863 |  |  |                          Prefix =>
 | 
      
         | 864 |  |  |                            Make_Indexed_Component (Loc,
 | 
      
         | 865 |  |  |                              Prefix =>
 | 
      
         | 866 |  |  |                                Duplicate_Subexpr_Move_Checks (Rarray, True),
 | 
      
         | 867 |  |  |                              Expressions => New_List (
 | 
      
         | 868 |  |  |                                Make_Attribute_Reference (Loc,
 | 
      
         | 869 |  |  |                                  Prefix =>
 | 
      
         | 870 |  |  |                                    New_Reference_To
 | 
      
         | 871 |  |  |                                      (R_Index_Typ, Loc),
 | 
      
         | 872 |  |  |                                  Attribute_Name => Name_First))),
 | 
      
         | 873 |  |  |                          Attribute_Name => Name_Address)));
 | 
      
         | 874 |  |  |  
 | 
      
         | 875 |  |  |             --  For the bit packed and VM cases we use the bounds. That's OK,
 | 
      
         | 876 |  |  |             --  because we don't have to worry about parameters, since they
 | 
      
         | 877 |  |  |             --  cannot cause overlap. Perhaps we should worry about weird slice
 | 
      
         | 878 |  |  |             --  conversions ???
 | 
      
         | 879 |  |  |  
 | 
      
         | 880 |  |  |             else
 | 
      
         | 881 |  |  |                --  Copy the bounds
 | 
      
         | 882 |  |  |  
 | 
      
         | 883 |  |  |                Cleft_Lo  := New_Copy_Tree (Left_Lo);
 | 
      
         | 884 |  |  |                Cright_Lo := New_Copy_Tree (Right_Lo);
 | 
      
         | 885 |  |  |  
 | 
      
         | 886 |  |  |                --  If the types do not match we add an implicit conversion
 | 
      
         | 887 |  |  |                --  here to ensure proper match
 | 
      
         | 888 |  |  |  
 | 
      
         | 889 |  |  |                if Etype (Left_Lo) /= Etype (Right_Lo) then
 | 
      
         | 890 |  |  |                   Cright_Lo :=
 | 
      
         | 891 |  |  |                     Unchecked_Convert_To (Etype (Left_Lo), Cright_Lo);
 | 
      
         | 892 |  |  |                end if;
 | 
      
         | 893 |  |  |  
 | 
      
         | 894 |  |  |                --  Reset the Analyzed flag, because the bounds of the index
 | 
      
         | 895 |  |  |                --  type itself may be universal, and must must be reanalyzed
 | 
      
         | 896 |  |  |                --  to acquire the proper type for the back end.
 | 
      
         | 897 |  |  |  
 | 
      
         | 898 |  |  |                Set_Analyzed (Cleft_Lo, False);
 | 
      
         | 899 |  |  |                Set_Analyzed (Cright_Lo, False);
 | 
      
         | 900 |  |  |  
 | 
      
         | 901 |  |  |                Condition :=
 | 
      
         | 902 |  |  |                  Make_Op_Le (Loc,
 | 
      
         | 903 |  |  |                    Left_Opnd  => Cleft_Lo,
 | 
      
         | 904 |  |  |                    Right_Opnd => Cright_Lo);
 | 
      
         | 905 |  |  |             end if;
 | 
      
         | 906 |  |  |  
 | 
      
         | 907 |  |  |             if Needs_Finalization (Component_Type (L_Type))
 | 
      
         | 908 |  |  |               and then Base_Type (L_Type) = Base_Type (R_Type)
 | 
      
         | 909 |  |  |               and then Ndim = 1
 | 
      
         | 910 |  |  |               and then not No_Ctrl_Actions (N)
 | 
      
         | 911 |  |  |             then
 | 
      
         | 912 |  |  |  
 | 
      
         | 913 |  |  |                --  Call TSS procedure for array assignment, passing the
 | 
      
         | 914 |  |  |                --  explicit bounds of right and left hand sides.
 | 
      
         | 915 |  |  |  
 | 
      
         | 916 |  |  |                declare
 | 
      
         | 917 |  |  |                   Proc    : constant Entity_Id :=
 | 
      
         | 918 |  |  |                               TSS (Base_Type (L_Type), TSS_Slice_Assign);
 | 
      
         | 919 |  |  |                   Actuals : List_Id;
 | 
      
         | 920 |  |  |  
 | 
      
         | 921 |  |  |                begin
 | 
      
         | 922 |  |  |                   Apply_Dereference (Larray);
 | 
      
         | 923 |  |  |                   Apply_Dereference (Rarray);
 | 
      
         | 924 |  |  |                   Actuals := New_List (
 | 
      
         | 925 |  |  |                     Duplicate_Subexpr (Larray,   Name_Req => True),
 | 
      
         | 926 |  |  |                     Duplicate_Subexpr (Rarray,   Name_Req => True),
 | 
      
         | 927 |  |  |                     Duplicate_Subexpr (Left_Lo,  Name_Req => True),
 | 
      
         | 928 |  |  |                     Duplicate_Subexpr (Left_Hi,  Name_Req => True),
 | 
      
         | 929 |  |  |                     Duplicate_Subexpr (Right_Lo, Name_Req => True),
 | 
      
         | 930 |  |  |                     Duplicate_Subexpr (Right_Hi, Name_Req => True));
 | 
      
         | 931 |  |  |  
 | 
      
         | 932 |  |  |                   Append_To (Actuals,
 | 
      
         | 933 |  |  |                      Make_Op_Not (Loc,
 | 
      
         | 934 |  |  |                        Right_Opnd => Condition));
 | 
      
         | 935 |  |  |  
 | 
      
         | 936 |  |  |                   Rewrite (N,
 | 
      
         | 937 |  |  |                     Make_Procedure_Call_Statement (Loc,
 | 
      
         | 938 |  |  |                       Name => New_Reference_To (Proc, Loc),
 | 
      
         | 939 |  |  |                       Parameter_Associations => Actuals));
 | 
      
         | 940 |  |  |                end;
 | 
      
         | 941 |  |  |  
 | 
      
         | 942 |  |  |             else
 | 
      
         | 943 |  |  |                Rewrite (N,
 | 
      
         | 944 |  |  |                  Make_Implicit_If_Statement (N,
 | 
      
         | 945 |  |  |                    Condition => Condition,
 | 
      
         | 946 |  |  |  
 | 
      
         | 947 |  |  |                    Then_Statements => New_List (
 | 
      
         | 948 |  |  |                      Expand_Assign_Array_Loop
 | 
      
         | 949 |  |  |                       (N, Larray, Rarray, L_Type, R_Type, Ndim,
 | 
      
         | 950 |  |  |                        Rev => False)),
 | 
      
         | 951 |  |  |  
 | 
      
         | 952 |  |  |                    Else_Statements => New_List (
 | 
      
         | 953 |  |  |                      Expand_Assign_Array_Loop
 | 
      
         | 954 |  |  |                       (N, Larray, Rarray, L_Type, R_Type, Ndim,
 | 
      
         | 955 |  |  |                        Rev => True))));
 | 
      
         | 956 |  |  |             end if;
 | 
      
         | 957 |  |  |          end if;
 | 
      
         | 958 |  |  |  
 | 
      
         | 959 |  |  |          Analyze (N, Suppress => All_Checks);
 | 
      
         | 960 |  |  |       end;
 | 
      
         | 961 |  |  |  
 | 
      
         | 962 |  |  |    exception
 | 
      
         | 963 |  |  |       when RE_Not_Available =>
 | 
      
         | 964 |  |  |          return;
 | 
      
         | 965 |  |  |    end Expand_Assign_Array;
 | 
      
         | 966 |  |  |  
 | 
      
         | 967 |  |  |    ------------------------------
 | 
      
         | 968 |  |  |    -- Expand_Assign_Array_Loop --
 | 
      
         | 969 |  |  |    ------------------------------
 | 
      
         | 970 |  |  |  
 | 
      
         | 971 |  |  |    --  The following is an example of the loop generated for the case of a
 | 
      
         | 972 |  |  |    --  two-dimensional array:
 | 
      
         | 973 |  |  |  
 | 
      
         | 974 |  |  |    --    declare
 | 
      
         | 975 |  |  |    --       R2b : Tm1X1 := 1;
 | 
      
         | 976 |  |  |    --    begin
 | 
      
         | 977 |  |  |    --       for L1b in 1 .. 100 loop
 | 
      
         | 978 |  |  |    --          declare
 | 
      
         | 979 |  |  |    --             R4b : Tm1X2 := 1;
 | 
      
         | 980 |  |  |    --          begin
 | 
      
         | 981 |  |  |    --             for L3b in 1 .. 100 loop
 | 
      
         | 982 |  |  |    --                vm1 (L1b, L3b) := vm2 (R2b, R4b);
 | 
      
         | 983 |  |  |    --                R4b := Tm1X2'succ(R4b);
 | 
      
         | 984 |  |  |    --             end loop;
 | 
      
         | 985 |  |  |    --          end;
 | 
      
         | 986 |  |  |    --          R2b := Tm1X1'succ(R2b);
 | 
      
         | 987 |  |  |    --       end loop;
 | 
      
         | 988 |  |  |    --    end;
 | 
      
         | 989 |  |  |  
 | 
      
         | 990 |  |  |    --  Here Rev is False, and Tm1Xn are the subscript types for the right hand
 | 
      
         | 991 |  |  |    --  side. The declarations of R2b and R4b are inserted before the original
 | 
      
         | 992 |  |  |    --  assignment statement.
 | 
      
         | 993 |  |  |  
 | 
      
         | 994 |  |  |    function Expand_Assign_Array_Loop
 | 
      
         | 995 |  |  |      (N      : Node_Id;
 | 
      
         | 996 |  |  |       Larray : Entity_Id;
 | 
      
         | 997 |  |  |       Rarray : Entity_Id;
 | 
      
         | 998 |  |  |       L_Type : Entity_Id;
 | 
      
         | 999 |  |  |       R_Type : Entity_Id;
 | 
      
         | 1000 |  |  |       Ndim   : Pos;
 | 
      
         | 1001 |  |  |       Rev    : Boolean) return Node_Id
 | 
      
         | 1002 |  |  |    is
 | 
      
         | 1003 |  |  |       Loc  : constant Source_Ptr := Sloc (N);
 | 
      
         | 1004 |  |  |  
 | 
      
         | 1005 |  |  |       Lnn : array (1 .. Ndim) of Entity_Id;
 | 
      
         | 1006 |  |  |       Rnn : array (1 .. Ndim) of Entity_Id;
 | 
      
         | 1007 |  |  |       --  Entities used as subscripts on left and right sides
 | 
      
         | 1008 |  |  |  
 | 
      
         | 1009 |  |  |       L_Index_Type : array (1 .. Ndim) of Entity_Id;
 | 
      
         | 1010 |  |  |       R_Index_Type : array (1 .. Ndim) of Entity_Id;
 | 
      
         | 1011 |  |  |       --  Left and right index types
 | 
      
         | 1012 |  |  |  
 | 
      
         | 1013 |  |  |       Assign : Node_Id;
 | 
      
         | 1014 |  |  |  
 | 
      
         | 1015 |  |  |       F_Or_L : Name_Id;
 | 
      
         | 1016 |  |  |       S_Or_P : Name_Id;
 | 
      
         | 1017 |  |  |  
 | 
      
         | 1018 |  |  |       function Build_Step (J : Nat) return Node_Id;
 | 
      
         | 1019 |  |  |       --  The increment step for the index of the right-hand side is written
 | 
      
         | 1020 |  |  |       --  as an attribute reference (Succ or Pred). This function returns
 | 
      
         | 1021 |  |  |       --  the corresponding node, which is placed at the end of the loop body.
 | 
      
         | 1022 |  |  |  
 | 
      
         | 1023 |  |  |       ----------------
 | 
      
         | 1024 |  |  |       -- Build_Step --
 | 
      
         | 1025 |  |  |       ----------------
 | 
      
         | 1026 |  |  |  
 | 
      
         | 1027 |  |  |       function Build_Step (J : Nat) return Node_Id is
 | 
      
         | 1028 |  |  |          Step : Node_Id;
 | 
      
         | 1029 |  |  |          Lim  : Name_Id;
 | 
      
         | 1030 |  |  |  
 | 
      
         | 1031 |  |  |       begin
 | 
      
         | 1032 |  |  |          if Rev then
 | 
      
         | 1033 |  |  |             Lim := Name_First;
 | 
      
         | 1034 |  |  |          else
 | 
      
         | 1035 |  |  |             Lim := Name_Last;
 | 
      
         | 1036 |  |  |          end if;
 | 
      
         | 1037 |  |  |  
 | 
      
         | 1038 |  |  |          Step :=
 | 
      
         | 1039 |  |  |             Make_Assignment_Statement (Loc,
 | 
      
         | 1040 |  |  |                Name => New_Occurrence_Of (Rnn (J), Loc),
 | 
      
         | 1041 |  |  |                Expression =>
 | 
      
         | 1042 |  |  |                  Make_Attribute_Reference (Loc,
 | 
      
         | 1043 |  |  |                    Prefix =>
 | 
      
         | 1044 |  |  |                      New_Occurrence_Of (R_Index_Type (J), Loc),
 | 
      
         | 1045 |  |  |                    Attribute_Name => S_Or_P,
 | 
      
         | 1046 |  |  |                    Expressions => New_List (
 | 
      
         | 1047 |  |  |                      New_Occurrence_Of (Rnn (J), Loc))));
 | 
      
         | 1048 |  |  |  
 | 
      
         | 1049 |  |  |       --  Note that on the last iteration of the loop, the index is increased
 | 
      
         | 1050 |  |  |       --  (or decreased) past the corresponding bound. This is consistent with
 | 
      
         | 1051 |  |  |       --  the C semantics of the back-end, where such an off-by-one value on a
 | 
      
         | 1052 |  |  |       --  dead index variable is OK. However, in CodePeer mode this leads to
 | 
      
         | 1053 |  |  |       --  spurious warnings, and thus we place a guard around the attribute
 | 
      
         | 1054 |  |  |       --  reference. For obvious reasons we only do this for CodePeer.
 | 
      
         | 1055 |  |  |  
 | 
      
         | 1056 |  |  |          if CodePeer_Mode then
 | 
      
         | 1057 |  |  |             Step :=
 | 
      
         | 1058 |  |  |               Make_If_Statement (Loc,
 | 
      
         | 1059 |  |  |                  Condition =>
 | 
      
         | 1060 |  |  |                     Make_Op_Ne (Loc,
 | 
      
         | 1061 |  |  |                        Left_Opnd  => New_Occurrence_Of (Lnn (J), Loc),
 | 
      
         | 1062 |  |  |                        Right_Opnd =>
 | 
      
         | 1063 |  |  |                          Make_Attribute_Reference (Loc,
 | 
      
         | 1064 |  |  |                            Prefix => New_Occurrence_Of (L_Index_Type (J), Loc),
 | 
      
         | 1065 |  |  |                            Attribute_Name => Lim)),
 | 
      
         | 1066 |  |  |                  Then_Statements => New_List (Step));
 | 
      
         | 1067 |  |  |          end if;
 | 
      
         | 1068 |  |  |  
 | 
      
         | 1069 |  |  |          return Step;
 | 
      
         | 1070 |  |  |       end Build_Step;
 | 
      
         | 1071 |  |  |  
 | 
      
         | 1072 |  |  |    --  Start of processing for Expand_Assign_Array_Loop
 | 
      
         | 1073 |  |  |  
 | 
      
         | 1074 |  |  |    begin
 | 
      
         | 1075 |  |  |       if Rev then
 | 
      
         | 1076 |  |  |          F_Or_L := Name_Last;
 | 
      
         | 1077 |  |  |          S_Or_P := Name_Pred;
 | 
      
         | 1078 |  |  |       else
 | 
      
         | 1079 |  |  |          F_Or_L := Name_First;
 | 
      
         | 1080 |  |  |          S_Or_P := Name_Succ;
 | 
      
         | 1081 |  |  |       end if;
 | 
      
         | 1082 |  |  |  
 | 
      
         | 1083 |  |  |       --  Setup index types and subscript entities
 | 
      
         | 1084 |  |  |  
 | 
      
         | 1085 |  |  |       declare
 | 
      
         | 1086 |  |  |          L_Index : Node_Id;
 | 
      
         | 1087 |  |  |          R_Index : Node_Id;
 | 
      
         | 1088 |  |  |  
 | 
      
         | 1089 |  |  |       begin
 | 
      
         | 1090 |  |  |          L_Index := First_Index (L_Type);
 | 
      
         | 1091 |  |  |          R_Index := First_Index (R_Type);
 | 
      
         | 1092 |  |  |  
 | 
      
         | 1093 |  |  |          for J in 1 .. Ndim loop
 | 
      
         | 1094 |  |  |             Lnn (J) := Make_Temporary (Loc, 'L');
 | 
      
         | 1095 |  |  |             Rnn (J) := Make_Temporary (Loc, 'R');
 | 
      
         | 1096 |  |  |  
 | 
      
         | 1097 |  |  |             L_Index_Type (J) := Etype (L_Index);
 | 
      
         | 1098 |  |  |             R_Index_Type (J) := Etype (R_Index);
 | 
      
         | 1099 |  |  |  
 | 
      
         | 1100 |  |  |             Next_Index (L_Index);
 | 
      
         | 1101 |  |  |             Next_Index (R_Index);
 | 
      
         | 1102 |  |  |          end loop;
 | 
      
         | 1103 |  |  |       end;
 | 
      
         | 1104 |  |  |  
 | 
      
         | 1105 |  |  |       --  Now construct the assignment statement
 | 
      
         | 1106 |  |  |  
 | 
      
         | 1107 |  |  |       declare
 | 
      
         | 1108 |  |  |          ExprL : constant List_Id := New_List;
 | 
      
         | 1109 |  |  |          ExprR : constant List_Id := New_List;
 | 
      
         | 1110 |  |  |  
 | 
      
         | 1111 |  |  |       begin
 | 
      
         | 1112 |  |  |          for J in 1 .. Ndim loop
 | 
      
         | 1113 |  |  |             Append_To (ExprL, New_Occurrence_Of (Lnn (J), Loc));
 | 
      
         | 1114 |  |  |             Append_To (ExprR, New_Occurrence_Of (Rnn (J), Loc));
 | 
      
         | 1115 |  |  |          end loop;
 | 
      
         | 1116 |  |  |  
 | 
      
         | 1117 |  |  |          Assign :=
 | 
      
         | 1118 |  |  |            Make_Assignment_Statement (Loc,
 | 
      
         | 1119 |  |  |              Name =>
 | 
      
         | 1120 |  |  |                Make_Indexed_Component (Loc,
 | 
      
         | 1121 |  |  |                  Prefix      => Duplicate_Subexpr (Larray, Name_Req => True),
 | 
      
         | 1122 |  |  |                  Expressions => ExprL),
 | 
      
         | 1123 |  |  |              Expression =>
 | 
      
         | 1124 |  |  |                Make_Indexed_Component (Loc,
 | 
      
         | 1125 |  |  |                  Prefix      => Duplicate_Subexpr (Rarray, Name_Req => True),
 | 
      
         | 1126 |  |  |                  Expressions => ExprR));
 | 
      
         | 1127 |  |  |  
 | 
      
         | 1128 |  |  |          --  We set assignment OK, since there are some cases, e.g. in object
 | 
      
         | 1129 |  |  |          --  declarations, where we are actually assigning into a constant.
 | 
      
         | 1130 |  |  |          --  If there really is an illegality, it was caught long before now,
 | 
      
         | 1131 |  |  |          --  and was flagged when the original assignment was analyzed.
 | 
      
         | 1132 |  |  |  
 | 
      
         | 1133 |  |  |          Set_Assignment_OK (Name (Assign));
 | 
      
         | 1134 |  |  |  
 | 
      
         | 1135 |  |  |          --  Propagate the No_Ctrl_Actions flag to individual assignments
 | 
      
         | 1136 |  |  |  
 | 
      
         | 1137 |  |  |          Set_No_Ctrl_Actions (Assign, No_Ctrl_Actions (N));
 | 
      
         | 1138 |  |  |       end;
 | 
      
         | 1139 |  |  |  
 | 
      
         | 1140 |  |  |       --  Now construct the loop from the inside out, with the last subscript
 | 
      
         | 1141 |  |  |       --  varying most rapidly. Note that Assign is first the raw assignment
 | 
      
         | 1142 |  |  |       --  statement, and then subsequently the loop that wraps it up.
 | 
      
         | 1143 |  |  |  
 | 
      
         | 1144 |  |  |       for J in reverse 1 .. Ndim loop
 | 
      
         | 1145 |  |  |          Assign :=
 | 
      
         | 1146 |  |  |            Make_Block_Statement (Loc,
 | 
      
         | 1147 |  |  |              Declarations => New_List (
 | 
      
         | 1148 |  |  |               Make_Object_Declaration (Loc,
 | 
      
         | 1149 |  |  |                 Defining_Identifier => Rnn (J),
 | 
      
         | 1150 |  |  |                 Object_Definition =>
 | 
      
         | 1151 |  |  |                   New_Occurrence_Of (R_Index_Type (J), Loc),
 | 
      
         | 1152 |  |  |                 Expression =>
 | 
      
         | 1153 |  |  |                   Make_Attribute_Reference (Loc,
 | 
      
         | 1154 |  |  |                     Prefix => New_Occurrence_Of (R_Index_Type (J), Loc),
 | 
      
         | 1155 |  |  |                     Attribute_Name => F_Or_L))),
 | 
      
         | 1156 |  |  |  
 | 
      
         | 1157 |  |  |            Handled_Statement_Sequence =>
 | 
      
         | 1158 |  |  |              Make_Handled_Sequence_Of_Statements (Loc,
 | 
      
         | 1159 |  |  |                Statements => New_List (
 | 
      
         | 1160 |  |  |                  Make_Implicit_Loop_Statement (N,
 | 
      
         | 1161 |  |  |                    Iteration_Scheme =>
 | 
      
         | 1162 |  |  |                      Make_Iteration_Scheme (Loc,
 | 
      
         | 1163 |  |  |                        Loop_Parameter_Specification =>
 | 
      
         | 1164 |  |  |                          Make_Loop_Parameter_Specification (Loc,
 | 
      
         | 1165 |  |  |                            Defining_Identifier => Lnn (J),
 | 
      
         | 1166 |  |  |                            Reverse_Present => Rev,
 | 
      
         | 1167 |  |  |                            Discrete_Subtype_Definition =>
 | 
      
         | 1168 |  |  |                              New_Reference_To (L_Index_Type (J), Loc))),
 | 
      
         | 1169 |  |  |  
 | 
      
         | 1170 |  |  |                    Statements => New_List (Assign, Build_Step (J))))));
 | 
      
         | 1171 |  |  |       end loop;
 | 
      
         | 1172 |  |  |  
 | 
      
         | 1173 |  |  |       return Assign;
 | 
      
         | 1174 |  |  |    end Expand_Assign_Array_Loop;
 | 
      
         | 1175 |  |  |  
 | 
      
         | 1176 |  |  |    --------------------------
 | 
      
         | 1177 |  |  |    -- Expand_Assign_Record --
 | 
      
         | 1178 |  |  |    --------------------------
 | 
      
         | 1179 |  |  |  
 | 
      
         | 1180 |  |  |    procedure Expand_Assign_Record (N : Node_Id) is
 | 
      
         | 1181 |  |  |       Lhs   : constant Node_Id    := Name (N);
 | 
      
         | 1182 |  |  |       Rhs   : Node_Id             := Expression (N);
 | 
      
         | 1183 |  |  |       L_Typ : constant Entity_Id  := Base_Type (Etype (Lhs));
 | 
      
         | 1184 |  |  |  
 | 
      
         | 1185 |  |  |    begin
 | 
      
         | 1186 |  |  |       --  If change of representation, then extract the real right hand side
 | 
      
         | 1187 |  |  |       --  from the type conversion, and proceed with component-wise assignment,
 | 
      
         | 1188 |  |  |       --  since the two types are not the same as far as the back end is
 | 
      
         | 1189 |  |  |       --  concerned.
 | 
      
         | 1190 |  |  |  
 | 
      
         | 1191 |  |  |       if Change_Of_Representation (N) then
 | 
      
         | 1192 |  |  |          Rhs := Expression (Rhs);
 | 
      
         | 1193 |  |  |  
 | 
      
         | 1194 |  |  |       --  If this may be a case of a large bit aligned component, then proceed
 | 
      
         | 1195 |  |  |       --  with component-wise assignment, to avoid possible clobbering of other
 | 
      
         | 1196 |  |  |       --  components sharing bits in the first or last byte of the component to
 | 
      
         | 1197 |  |  |       --  be assigned.
 | 
      
         | 1198 |  |  |  
 | 
      
         | 1199 |  |  |       elsif Possible_Bit_Aligned_Component (Lhs)
 | 
      
         | 1200 |  |  |               or
 | 
      
         | 1201 |  |  |             Possible_Bit_Aligned_Component (Rhs)
 | 
      
         | 1202 |  |  |       then
 | 
      
         | 1203 |  |  |          null;
 | 
      
         | 1204 |  |  |  
 | 
      
         | 1205 |  |  |       --  If we have a tagged type that has a complete record representation
 | 
      
         | 1206 |  |  |       --  clause, we must do we must do component-wise assignments, since child
 | 
      
         | 1207 |  |  |       --  types may have used gaps for their components, and we might be
 | 
      
         | 1208 |  |  |       --  dealing with a view conversion.
 | 
      
         | 1209 |  |  |  
 | 
      
         | 1210 |  |  |       elsif Is_Fully_Repped_Tagged_Type (L_Typ) then
 | 
      
         | 1211 |  |  |          null;
 | 
      
         | 1212 |  |  |  
 | 
      
         | 1213 |  |  |       --  If neither condition met, then nothing special to do, the back end
 | 
      
         | 1214 |  |  |       --  can handle assignment of the entire component as a single entity.
 | 
      
         | 1215 |  |  |  
 | 
      
         | 1216 |  |  |       else
 | 
      
         | 1217 |  |  |          return;
 | 
      
         | 1218 |  |  |       end if;
 | 
      
         | 1219 |  |  |  
 | 
      
         | 1220 |  |  |       --  At this stage we know that we must do a component wise assignment
 | 
      
         | 1221 |  |  |  
 | 
      
         | 1222 |  |  |       declare
 | 
      
         | 1223 |  |  |          Loc   : constant Source_Ptr := Sloc (N);
 | 
      
         | 1224 |  |  |          R_Typ : constant Entity_Id  := Base_Type (Etype (Rhs));
 | 
      
         | 1225 |  |  |          Decl  : constant Node_Id    := Declaration_Node (R_Typ);
 | 
      
         | 1226 |  |  |          RDef  : Node_Id;
 | 
      
         | 1227 |  |  |          F     : Entity_Id;
 | 
      
         | 1228 |  |  |  
 | 
      
         | 1229 |  |  |          function Find_Component
 | 
      
         | 1230 |  |  |            (Typ  : Entity_Id;
 | 
      
         | 1231 |  |  |             Comp : Entity_Id) return Entity_Id;
 | 
      
         | 1232 |  |  |          --  Find the component with the given name in the underlying record
 | 
      
         | 1233 |  |  |          --  declaration for Typ. We need to use the actual entity because the
 | 
      
         | 1234 |  |  |          --  type may be private and resolution by identifier alone would fail.
 | 
      
         | 1235 |  |  |  
 | 
      
         | 1236 |  |  |          function Make_Component_List_Assign
 | 
      
         | 1237 |  |  |            (CL  : Node_Id;
 | 
      
         | 1238 |  |  |             U_U : Boolean := False) return List_Id;
 | 
      
         | 1239 |  |  |          --  Returns a sequence of statements to assign the components that
 | 
      
         | 1240 |  |  |          --  are referenced in the given component list. The flag U_U is
 | 
      
         | 1241 |  |  |          --  used to force the usage of the inferred value of the variant
 | 
      
         | 1242 |  |  |          --  part expression as the switch for the generated case statement.
 | 
      
         | 1243 |  |  |  
 | 
      
         | 1244 |  |  |          function Make_Field_Assign
 | 
      
         | 1245 |  |  |            (C   : Entity_Id;
 | 
      
         | 1246 |  |  |             U_U : Boolean := False) return Node_Id;
 | 
      
         | 1247 |  |  |          --  Given C, the entity for a discriminant or component, build an
 | 
      
         | 1248 |  |  |          --  assignment for the corresponding field values. The flag U_U
 | 
      
         | 1249 |  |  |          --  signals the presence of an Unchecked_Union and forces the usage
 | 
      
         | 1250 |  |  |          --  of the inferred discriminant value of C as the right hand side
 | 
      
         | 1251 |  |  |          --  of the assignment.
 | 
      
         | 1252 |  |  |  
 | 
      
         | 1253 |  |  |          function Make_Field_Assigns (CI : List_Id) return List_Id;
 | 
      
         | 1254 |  |  |          --  Given CI, a component items list, construct series of statements
 | 
      
         | 1255 |  |  |          --  for fieldwise assignment of the corresponding components.
 | 
      
         | 1256 |  |  |  
 | 
      
         | 1257 |  |  |          --------------------
 | 
      
         | 1258 |  |  |          -- Find_Component --
 | 
      
         | 1259 |  |  |          --------------------
 | 
      
         | 1260 |  |  |  
 | 
      
         | 1261 |  |  |          function Find_Component
 | 
      
         | 1262 |  |  |            (Typ  : Entity_Id;
 | 
      
         | 1263 |  |  |             Comp : Entity_Id) return Entity_Id
 | 
      
         | 1264 |  |  |          is
 | 
      
         | 1265 |  |  |             Utyp : constant Entity_Id := Underlying_Type (Typ);
 | 
      
         | 1266 |  |  |             C    : Entity_Id;
 | 
      
         | 1267 |  |  |  
 | 
      
         | 1268 |  |  |          begin
 | 
      
         | 1269 |  |  |             C := First_Entity (Utyp);
 | 
      
         | 1270 |  |  |             while Present (C) loop
 | 
      
         | 1271 |  |  |                if Chars (C) = Chars (Comp) then
 | 
      
         | 1272 |  |  |                   return C;
 | 
      
         | 1273 |  |  |                end if;
 | 
      
         | 1274 |  |  |  
 | 
      
         | 1275 |  |  |                Next_Entity (C);
 | 
      
         | 1276 |  |  |             end loop;
 | 
      
         | 1277 |  |  |  
 | 
      
         | 1278 |  |  |             raise Program_Error;
 | 
      
         | 1279 |  |  |          end Find_Component;
 | 
      
         | 1280 |  |  |  
 | 
      
         | 1281 |  |  |          --------------------------------
 | 
      
         | 1282 |  |  |          -- Make_Component_List_Assign --
 | 
      
         | 1283 |  |  |          --------------------------------
 | 
      
         | 1284 |  |  |  
 | 
      
         | 1285 |  |  |          function Make_Component_List_Assign
 | 
      
         | 1286 |  |  |            (CL  : Node_Id;
 | 
      
         | 1287 |  |  |             U_U : Boolean := False) return List_Id
 | 
      
         | 1288 |  |  |          is
 | 
      
         | 1289 |  |  |             CI : constant List_Id := Component_Items (CL);
 | 
      
         | 1290 |  |  |             VP : constant Node_Id := Variant_Part (CL);
 | 
      
         | 1291 |  |  |  
 | 
      
         | 1292 |  |  |             Alts   : List_Id;
 | 
      
         | 1293 |  |  |             DC     : Node_Id;
 | 
      
         | 1294 |  |  |             DCH    : List_Id;
 | 
      
         | 1295 |  |  |             Expr   : Node_Id;
 | 
      
         | 1296 |  |  |             Result : List_Id;
 | 
      
         | 1297 |  |  |             V      : Node_Id;
 | 
      
         | 1298 |  |  |  
 | 
      
         | 1299 |  |  |          begin
 | 
      
         | 1300 |  |  |             Result := Make_Field_Assigns (CI);
 | 
      
         | 1301 |  |  |  
 | 
      
         | 1302 |  |  |             if Present (VP) then
 | 
      
         | 1303 |  |  |                V := First_Non_Pragma (Variants (VP));
 | 
      
         | 1304 |  |  |                Alts := New_List;
 | 
      
         | 1305 |  |  |                while Present (V) loop
 | 
      
         | 1306 |  |  |                   DCH := New_List;
 | 
      
         | 1307 |  |  |                   DC := First (Discrete_Choices (V));
 | 
      
         | 1308 |  |  |                   while Present (DC) loop
 | 
      
         | 1309 |  |  |                      Append_To (DCH, New_Copy_Tree (DC));
 | 
      
         | 1310 |  |  |                      Next (DC);
 | 
      
         | 1311 |  |  |                   end loop;
 | 
      
         | 1312 |  |  |  
 | 
      
         | 1313 |  |  |                   Append_To (Alts,
 | 
      
         | 1314 |  |  |                     Make_Case_Statement_Alternative (Loc,
 | 
      
         | 1315 |  |  |                       Discrete_Choices => DCH,
 | 
      
         | 1316 |  |  |                       Statements =>
 | 
      
         | 1317 |  |  |                         Make_Component_List_Assign (Component_List (V))));
 | 
      
         | 1318 |  |  |                   Next_Non_Pragma (V);
 | 
      
         | 1319 |  |  |                end loop;
 | 
      
         | 1320 |  |  |  
 | 
      
         | 1321 |  |  |                --  If we have an Unchecked_Union, use the value of the inferred
 | 
      
         | 1322 |  |  |                --  discriminant of the variant part expression as the switch
 | 
      
         | 1323 |  |  |                --  for the case statement. The case statement may later be
 | 
      
         | 1324 |  |  |                --  folded.
 | 
      
         | 1325 |  |  |  
 | 
      
         | 1326 |  |  |                if U_U then
 | 
      
         | 1327 |  |  |                   Expr :=
 | 
      
         | 1328 |  |  |                     New_Copy (Get_Discriminant_Value (
 | 
      
         | 1329 |  |  |                       Entity (Name (VP)),
 | 
      
         | 1330 |  |  |                       Etype (Rhs),
 | 
      
         | 1331 |  |  |                       Discriminant_Constraint (Etype (Rhs))));
 | 
      
         | 1332 |  |  |                else
 | 
      
         | 1333 |  |  |                   Expr :=
 | 
      
         | 1334 |  |  |                     Make_Selected_Component (Loc,
 | 
      
         | 1335 |  |  |                       Prefix        => Duplicate_Subexpr (Rhs),
 | 
      
         | 1336 |  |  |                       Selector_Name =>
 | 
      
         | 1337 |  |  |                         Make_Identifier (Loc, Chars (Name (VP))));
 | 
      
         | 1338 |  |  |                end if;
 | 
      
         | 1339 |  |  |  
 | 
      
         | 1340 |  |  |                Append_To (Result,
 | 
      
         | 1341 |  |  |                  Make_Case_Statement (Loc,
 | 
      
         | 1342 |  |  |                    Expression => Expr,
 | 
      
         | 1343 |  |  |                    Alternatives => Alts));
 | 
      
         | 1344 |  |  |             end if;
 | 
      
         | 1345 |  |  |  
 | 
      
         | 1346 |  |  |             return Result;
 | 
      
         | 1347 |  |  |          end Make_Component_List_Assign;
 | 
      
         | 1348 |  |  |  
 | 
      
         | 1349 |  |  |          -----------------------
 | 
      
         | 1350 |  |  |          -- Make_Field_Assign --
 | 
      
         | 1351 |  |  |          -----------------------
 | 
      
         | 1352 |  |  |  
 | 
      
         | 1353 |  |  |          function Make_Field_Assign
 | 
      
         | 1354 |  |  |            (C   : Entity_Id;
 | 
      
         | 1355 |  |  |             U_U : Boolean := False) return Node_Id
 | 
      
         | 1356 |  |  |          is
 | 
      
         | 1357 |  |  |             A    : Node_Id;
 | 
      
         | 1358 |  |  |             Expr : Node_Id;
 | 
      
         | 1359 |  |  |  
 | 
      
         | 1360 |  |  |          begin
 | 
      
         | 1361 |  |  |             --  In the case of an Unchecked_Union, use the discriminant
 | 
      
         | 1362 |  |  |             --  constraint value as on the right hand side of the assignment.
 | 
      
         | 1363 |  |  |  
 | 
      
         | 1364 |  |  |             if U_U then
 | 
      
         | 1365 |  |  |                Expr :=
 | 
      
         | 1366 |  |  |                  New_Copy (Get_Discriminant_Value (C,
 | 
      
         | 1367 |  |  |                    Etype (Rhs),
 | 
      
         | 1368 |  |  |                    Discriminant_Constraint (Etype (Rhs))));
 | 
      
         | 1369 |  |  |             else
 | 
      
         | 1370 |  |  |                Expr :=
 | 
      
         | 1371 |  |  |                  Make_Selected_Component (Loc,
 | 
      
         | 1372 |  |  |                    Prefix        => Duplicate_Subexpr (Rhs),
 | 
      
         | 1373 |  |  |                    Selector_Name => New_Occurrence_Of (C, Loc));
 | 
      
         | 1374 |  |  |             end if;
 | 
      
         | 1375 |  |  |  
 | 
      
         | 1376 |  |  |             A :=
 | 
      
         | 1377 |  |  |               Make_Assignment_Statement (Loc,
 | 
      
         | 1378 |  |  |                 Name =>
 | 
      
         | 1379 |  |  |                   Make_Selected_Component (Loc,
 | 
      
         | 1380 |  |  |                     Prefix        => Duplicate_Subexpr (Lhs),
 | 
      
         | 1381 |  |  |                     Selector_Name =>
 | 
      
         | 1382 |  |  |                       New_Occurrence_Of (Find_Component (L_Typ, C), Loc)),
 | 
      
         | 1383 |  |  |                 Expression => Expr);
 | 
      
         | 1384 |  |  |  
 | 
      
         | 1385 |  |  |             --  Set Assignment_OK, so discriminants can be assigned
 | 
      
         | 1386 |  |  |  
 | 
      
         | 1387 |  |  |             Set_Assignment_OK (Name (A), True);
 | 
      
         | 1388 |  |  |  
 | 
      
         | 1389 |  |  |             if Componentwise_Assignment (N)
 | 
      
         | 1390 |  |  |               and then Nkind (Name (A)) = N_Selected_Component
 | 
      
         | 1391 |  |  |               and then Chars (Selector_Name (Name (A))) = Name_uParent
 | 
      
         | 1392 |  |  |             then
 | 
      
         | 1393 |  |  |                Set_Componentwise_Assignment (A);
 | 
      
         | 1394 |  |  |             end if;
 | 
      
         | 1395 |  |  |  
 | 
      
         | 1396 |  |  |             return A;
 | 
      
         | 1397 |  |  |          end Make_Field_Assign;
 | 
      
         | 1398 |  |  |  
 | 
      
         | 1399 |  |  |          ------------------------
 | 
      
         | 1400 |  |  |          -- Make_Field_Assigns --
 | 
      
         | 1401 |  |  |          ------------------------
 | 
      
         | 1402 |  |  |  
 | 
      
         | 1403 |  |  |          function Make_Field_Assigns (CI : List_Id) return List_Id is
 | 
      
         | 1404 |  |  |             Item   : Node_Id;
 | 
      
         | 1405 |  |  |             Result : List_Id;
 | 
      
         | 1406 |  |  |  
 | 
      
         | 1407 |  |  |          begin
 | 
      
         | 1408 |  |  |             Item := First (CI);
 | 
      
         | 1409 |  |  |             Result := New_List;
 | 
      
         | 1410 |  |  |  
 | 
      
         | 1411 |  |  |             while Present (Item) loop
 | 
      
         | 1412 |  |  |  
 | 
      
         | 1413 |  |  |                --  Look for components, but exclude _tag field assignment if
 | 
      
         | 1414 |  |  |                --  the special Componentwise_Assignment flag is set.
 | 
      
         | 1415 |  |  |  
 | 
      
         | 1416 |  |  |                if Nkind (Item) = N_Component_Declaration
 | 
      
         | 1417 |  |  |                  and then not (Is_Tag (Defining_Identifier (Item))
 | 
      
         | 1418 |  |  |                                  and then Componentwise_Assignment (N))
 | 
      
         | 1419 |  |  |                then
 | 
      
         | 1420 |  |  |                   Append_To
 | 
      
         | 1421 |  |  |                     (Result, Make_Field_Assign (Defining_Identifier (Item)));
 | 
      
         | 1422 |  |  |                end if;
 | 
      
         | 1423 |  |  |  
 | 
      
         | 1424 |  |  |                Next (Item);
 | 
      
         | 1425 |  |  |             end loop;
 | 
      
         | 1426 |  |  |  
 | 
      
         | 1427 |  |  |             return Result;
 | 
      
         | 1428 |  |  |          end Make_Field_Assigns;
 | 
      
         | 1429 |  |  |  
 | 
      
         | 1430 |  |  |       --  Start of processing for Expand_Assign_Record
 | 
      
         | 1431 |  |  |  
 | 
      
         | 1432 |  |  |       begin
 | 
      
         | 1433 |  |  |          --  Note that we use the base types for this processing. This results
 | 
      
         | 1434 |  |  |          --  in some extra work in the constrained case, but the change of
 | 
      
         | 1435 |  |  |          --  representation case is so unusual that it is not worth the effort.
 | 
      
         | 1436 |  |  |  
 | 
      
         | 1437 |  |  |          --  First copy the discriminants. This is done unconditionally. It
 | 
      
         | 1438 |  |  |          --  is required in the unconstrained left side case, and also in the
 | 
      
         | 1439 |  |  |          --  case where this assignment was constructed during the expansion
 | 
      
         | 1440 |  |  |          --  of a type conversion (since initialization of discriminants is
 | 
      
         | 1441 |  |  |          --  suppressed in this case). It is unnecessary but harmless in
 | 
      
         | 1442 |  |  |          --  other cases.
 | 
      
         | 1443 |  |  |  
 | 
      
         | 1444 |  |  |          if Has_Discriminants (L_Typ) then
 | 
      
         | 1445 |  |  |             F := First_Discriminant (R_Typ);
 | 
      
         | 1446 |  |  |             while Present (F) loop
 | 
      
         | 1447 |  |  |  
 | 
      
         | 1448 |  |  |                --  If we are expanding the initialization of a derived record
 | 
      
         | 1449 |  |  |                --  that constrains or renames discriminants of the parent, we
 | 
      
         | 1450 |  |  |                --  must use the corresponding discriminant in the parent.
 | 
      
         | 1451 |  |  |  
 | 
      
         | 1452 |  |  |                declare
 | 
      
         | 1453 |  |  |                   CF : Entity_Id;
 | 
      
         | 1454 |  |  |  
 | 
      
         | 1455 |  |  |                begin
 | 
      
         | 1456 |  |  |                   if Inside_Init_Proc
 | 
      
         | 1457 |  |  |                     and then Present (Corresponding_Discriminant (F))
 | 
      
         | 1458 |  |  |                   then
 | 
      
         | 1459 |  |  |                      CF := Corresponding_Discriminant (F);
 | 
      
         | 1460 |  |  |                   else
 | 
      
         | 1461 |  |  |                      CF := F;
 | 
      
         | 1462 |  |  |                   end if;
 | 
      
         | 1463 |  |  |  
 | 
      
         | 1464 |  |  |                   if Is_Unchecked_Union (Base_Type (R_Typ)) then
 | 
      
         | 1465 |  |  |  
 | 
      
         | 1466 |  |  |                      --  Within an initialization procedure this is the
 | 
      
         | 1467 |  |  |                      --  assignment to an unchecked union component, in which
 | 
      
         | 1468 |  |  |                      --  case there is no discriminant to initialize.
 | 
      
         | 1469 |  |  |  
 | 
      
         | 1470 |  |  |                      if Inside_Init_Proc then
 | 
      
         | 1471 |  |  |                         null;
 | 
      
         | 1472 |  |  |  
 | 
      
         | 1473 |  |  |                      else
 | 
      
         | 1474 |  |  |                         --  The assignment is part of a conversion from a
 | 
      
         | 1475 |  |  |                         --  derived unchecked union type with an inferable
 | 
      
         | 1476 |  |  |                         --  discriminant, to a parent type.
 | 
      
         | 1477 |  |  |  
 | 
      
         | 1478 |  |  |                         Insert_Action (N, Make_Field_Assign (CF, True));
 | 
      
         | 1479 |  |  |                      end if;
 | 
      
         | 1480 |  |  |  
 | 
      
         | 1481 |  |  |                   else
 | 
      
         | 1482 |  |  |                      Insert_Action (N, Make_Field_Assign (CF));
 | 
      
         | 1483 |  |  |                   end if;
 | 
      
         | 1484 |  |  |  
 | 
      
         | 1485 |  |  |                   Next_Discriminant (F);
 | 
      
         | 1486 |  |  |                end;
 | 
      
         | 1487 |  |  |             end loop;
 | 
      
         | 1488 |  |  |          end if;
 | 
      
         | 1489 |  |  |  
 | 
      
         | 1490 |  |  |          --  We know the underlying type is a record, but its current view
 | 
      
         | 1491 |  |  |          --  may be private. We must retrieve the usable record declaration.
 | 
      
         | 1492 |  |  |  
 | 
      
         | 1493 |  |  |          if Nkind_In (Decl, N_Private_Type_Declaration,
 | 
      
         | 1494 |  |  |                             N_Private_Extension_Declaration)
 | 
      
         | 1495 |  |  |            and then Present (Full_View (R_Typ))
 | 
      
         | 1496 |  |  |          then
 | 
      
         | 1497 |  |  |             RDef := Type_Definition (Declaration_Node (Full_View (R_Typ)));
 | 
      
         | 1498 |  |  |          else
 | 
      
         | 1499 |  |  |             RDef := Type_Definition (Decl);
 | 
      
         | 1500 |  |  |          end if;
 | 
      
         | 1501 |  |  |  
 | 
      
         | 1502 |  |  |          if Nkind (RDef) = N_Derived_Type_Definition then
 | 
      
         | 1503 |  |  |             RDef := Record_Extension_Part (RDef);
 | 
      
         | 1504 |  |  |          end if;
 | 
      
         | 1505 |  |  |  
 | 
      
         | 1506 |  |  |          if Nkind (RDef) = N_Record_Definition
 | 
      
         | 1507 |  |  |            and then Present (Component_List (RDef))
 | 
      
         | 1508 |  |  |          then
 | 
      
         | 1509 |  |  |             if Is_Unchecked_Union (R_Typ) then
 | 
      
         | 1510 |  |  |                Insert_Actions (N,
 | 
      
         | 1511 |  |  |                  Make_Component_List_Assign (Component_List (RDef), True));
 | 
      
         | 1512 |  |  |             else
 | 
      
         | 1513 |  |  |                Insert_Actions
 | 
      
         | 1514 |  |  |                  (N, Make_Component_List_Assign (Component_List (RDef)));
 | 
      
         | 1515 |  |  |             end if;
 | 
      
         | 1516 |  |  |  
 | 
      
         | 1517 |  |  |             Rewrite (N, Make_Null_Statement (Loc));
 | 
      
         | 1518 |  |  |          end if;
 | 
      
         | 1519 |  |  |       end;
 | 
      
         | 1520 |  |  |    end Expand_Assign_Record;
 | 
      
         | 1521 |  |  |  
 | 
      
         | 1522 |  |  |    -----------------------------------
 | 
      
         | 1523 |  |  |    -- Expand_N_Assignment_Statement --
 | 
      
         | 1524 |  |  |    -----------------------------------
 | 
      
         | 1525 |  |  |  
 | 
      
         | 1526 |  |  |    --  This procedure implements various cases where an assignment statement
 | 
      
         | 1527 |  |  |    --  cannot just be passed on to the back end in untransformed state.
 | 
      
         | 1528 |  |  |  
 | 
      
         | 1529 |  |  |    procedure Expand_N_Assignment_Statement (N : Node_Id) is
 | 
      
         | 1530 |  |  |       Loc  : constant Source_Ptr := Sloc (N);
 | 
      
         | 1531 |  |  |       Crep : constant Boolean    := Change_Of_Representation (N);
 | 
      
         | 1532 |  |  |       Lhs  : constant Node_Id    := Name (N);
 | 
      
         | 1533 |  |  |       Rhs  : constant Node_Id    := Expression (N);
 | 
      
         | 1534 |  |  |       Typ  : constant Entity_Id  := Underlying_Type (Etype (Lhs));
 | 
      
         | 1535 |  |  |       Exp  : Node_Id;
 | 
      
         | 1536 |  |  |  
 | 
      
         | 1537 |  |  |    begin
 | 
      
         | 1538 |  |  |       --  Special case to check right away, if the Componentwise_Assignment
 | 
      
         | 1539 |  |  |       --  flag is set, this is a reanalysis from the expansion of the primitive
 | 
      
         | 1540 |  |  |       --  assignment procedure for a tagged type, and all we need to do is to
 | 
      
         | 1541 |  |  |       --  expand to assignment of components, because otherwise, we would get
 | 
      
         | 1542 |  |  |       --  infinite recursion (since this looks like a tagged assignment which
 | 
      
         | 1543 |  |  |       --  would normally try to *call* the primitive assignment procedure).
 | 
      
         | 1544 |  |  |  
 | 
      
         | 1545 |  |  |       if Componentwise_Assignment (N) then
 | 
      
         | 1546 |  |  |          Expand_Assign_Record (N);
 | 
      
         | 1547 |  |  |          return;
 | 
      
         | 1548 |  |  |       end if;
 | 
      
         | 1549 |  |  |  
 | 
      
         | 1550 |  |  |       --  Defend against invalid subscripts on left side if we are in standard
 | 
      
         | 1551 |  |  |       --  validity checking mode. No need to do this if we are checking all
 | 
      
         | 1552 |  |  |       --  subscripts.
 | 
      
         | 1553 |  |  |  
 | 
      
         | 1554 |  |  |       --  Note that we do this right away, because there are some early return
 | 
      
         | 1555 |  |  |       --  paths in this procedure, and this is required on all paths.
 | 
      
         | 1556 |  |  |  
 | 
      
         | 1557 |  |  |       if Validity_Checks_On
 | 
      
         | 1558 |  |  |         and then Validity_Check_Default
 | 
      
         | 1559 |  |  |         and then not Validity_Check_Subscripts
 | 
      
         | 1560 |  |  |       then
 | 
      
         | 1561 |  |  |          Check_Valid_Lvalue_Subscripts (Lhs);
 | 
      
         | 1562 |  |  |       end if;
 | 
      
         | 1563 |  |  |  
 | 
      
         | 1564 |  |  |       --  Ada 2005 (AI-327): Handle assignment to priority of protected object
 | 
      
         | 1565 |  |  |  
 | 
      
         | 1566 |  |  |       --  Rewrite an assignment to X'Priority into a run-time call
 | 
      
         | 1567 |  |  |  
 | 
      
         | 1568 |  |  |       --   For example:         X'Priority := New_Prio_Expr;
 | 
      
         | 1569 |  |  |       --   ...is expanded into  Set_Ceiling (X._Object, New_Prio_Expr);
 | 
      
         | 1570 |  |  |  
 | 
      
         | 1571 |  |  |       --  Note that although X'Priority is notionally an object, it is quite
 | 
      
         | 1572 |  |  |       --  deliberately not defined as an aliased object in the RM. This means
 | 
      
         | 1573 |  |  |       --  that it works fine to rewrite it as a call, without having to worry
 | 
      
         | 1574 |  |  |       --  about complications that would other arise from X'Priority'Access,
 | 
      
         | 1575 |  |  |       --  which is illegal, because of the lack of aliasing.
 | 
      
         | 1576 |  |  |  
 | 
      
         | 1577 |  |  |       if Ada_Version >= Ada_2005 then
 | 
      
         | 1578 |  |  |          declare
 | 
      
         | 1579 |  |  |             Call           : Node_Id;
 | 
      
         | 1580 |  |  |             Conctyp        : Entity_Id;
 | 
      
         | 1581 |  |  |             Ent            : Entity_Id;
 | 
      
         | 1582 |  |  |             Subprg         : Entity_Id;
 | 
      
         | 1583 |  |  |             RT_Subprg_Name : Node_Id;
 | 
      
         | 1584 |  |  |  
 | 
      
         | 1585 |  |  |          begin
 | 
      
         | 1586 |  |  |             --  Handle chains of renamings
 | 
      
         | 1587 |  |  |  
 | 
      
         | 1588 |  |  |             Ent := Name (N);
 | 
      
         | 1589 |  |  |             while Nkind (Ent) in N_Has_Entity
 | 
      
         | 1590 |  |  |               and then Present (Entity (Ent))
 | 
      
         | 1591 |  |  |               and then Present (Renamed_Object (Entity (Ent)))
 | 
      
         | 1592 |  |  |             loop
 | 
      
         | 1593 |  |  |                Ent := Renamed_Object (Entity (Ent));
 | 
      
         | 1594 |  |  |             end loop;
 | 
      
         | 1595 |  |  |  
 | 
      
         | 1596 |  |  |             --  The attribute Priority applied to protected objects has been
 | 
      
         | 1597 |  |  |             --  previously expanded into a call to the Get_Ceiling run-time
 | 
      
         | 1598 |  |  |             --  subprogram.
 | 
      
         | 1599 |  |  |  
 | 
      
         | 1600 |  |  |             if Nkind (Ent) = N_Function_Call
 | 
      
         | 1601 |  |  |               and then (Entity (Name (Ent)) = RTE (RE_Get_Ceiling)
 | 
      
         | 1602 |  |  |                           or else
 | 
      
         | 1603 |  |  |                         Entity (Name (Ent)) = RTE (RO_PE_Get_Ceiling))
 | 
      
         | 1604 |  |  |             then
 | 
      
         | 1605 |  |  |                --  Look for the enclosing concurrent type
 | 
      
         | 1606 |  |  |  
 | 
      
         | 1607 |  |  |                Conctyp := Current_Scope;
 | 
      
         | 1608 |  |  |                while not Is_Concurrent_Type (Conctyp) loop
 | 
      
         | 1609 |  |  |                   Conctyp := Scope (Conctyp);
 | 
      
         | 1610 |  |  |                end loop;
 | 
      
         | 1611 |  |  |  
 | 
      
         | 1612 |  |  |                pragma Assert (Is_Protected_Type (Conctyp));
 | 
      
         | 1613 |  |  |  
 | 
      
         | 1614 |  |  |                --  Generate the first actual of the call
 | 
      
         | 1615 |  |  |  
 | 
      
         | 1616 |  |  |                Subprg := Current_Scope;
 | 
      
         | 1617 |  |  |                while not Present (Protected_Body_Subprogram (Subprg)) loop
 | 
      
         | 1618 |  |  |                   Subprg := Scope (Subprg);
 | 
      
         | 1619 |  |  |                end loop;
 | 
      
         | 1620 |  |  |  
 | 
      
         | 1621 |  |  |                --  Select the appropriate run-time call
 | 
      
         | 1622 |  |  |  
 | 
      
         | 1623 |  |  |                if Number_Entries (Conctyp) = 0 then
 | 
      
         | 1624 |  |  |                   RT_Subprg_Name :=
 | 
      
         | 1625 |  |  |                     New_Reference_To (RTE (RE_Set_Ceiling), Loc);
 | 
      
         | 1626 |  |  |                else
 | 
      
         | 1627 |  |  |                   RT_Subprg_Name :=
 | 
      
         | 1628 |  |  |                     New_Reference_To (RTE (RO_PE_Set_Ceiling), Loc);
 | 
      
         | 1629 |  |  |                end if;
 | 
      
         | 1630 |  |  |  
 | 
      
         | 1631 |  |  |                Call :=
 | 
      
         | 1632 |  |  |                  Make_Procedure_Call_Statement (Loc,
 | 
      
         | 1633 |  |  |                    Name => RT_Subprg_Name,
 | 
      
         | 1634 |  |  |                    Parameter_Associations => New_List (
 | 
      
         | 1635 |  |  |                      New_Copy_Tree (First (Parameter_Associations (Ent))),
 | 
      
         | 1636 |  |  |                      Relocate_Node (Expression (N))));
 | 
      
         | 1637 |  |  |  
 | 
      
         | 1638 |  |  |                Rewrite (N, Call);
 | 
      
         | 1639 |  |  |                Analyze (N);
 | 
      
         | 1640 |  |  |                return;
 | 
      
         | 1641 |  |  |             end if;
 | 
      
         | 1642 |  |  |          end;
 | 
      
         | 1643 |  |  |       end if;
 | 
      
         | 1644 |  |  |  
 | 
      
         | 1645 |  |  |       --  Deal with assignment checks unless suppressed
 | 
      
         | 1646 |  |  |  
 | 
      
         | 1647 |  |  |       if not Suppress_Assignment_Checks (N) then
 | 
      
         | 1648 |  |  |  
 | 
      
         | 1649 |  |  |          --  First deal with generation of range check if required
 | 
      
         | 1650 |  |  |  
 | 
      
         | 1651 |  |  |          if Do_Range_Check (Rhs) then
 | 
      
         | 1652 |  |  |             Set_Do_Range_Check (Rhs, False);
 | 
      
         | 1653 |  |  |             Generate_Range_Check (Rhs, Typ, CE_Range_Check_Failed);
 | 
      
         | 1654 |  |  |          end if;
 | 
      
         | 1655 |  |  |  
 | 
      
         | 1656 |  |  |          --  Then generate predicate check if required
 | 
      
         | 1657 |  |  |  
 | 
      
         | 1658 |  |  |          Apply_Predicate_Check (Rhs, Typ);
 | 
      
         | 1659 |  |  |       end if;
 | 
      
         | 1660 |  |  |  
 | 
      
         | 1661 |  |  |       --  Check for a special case where a high level transformation is
 | 
      
         | 1662 |  |  |       --  required. If we have either of:
 | 
      
         | 1663 |  |  |  
 | 
      
         | 1664 |  |  |       --    P.field := rhs;
 | 
      
         | 1665 |  |  |       --    P (sub) := rhs;
 | 
      
         | 1666 |  |  |  
 | 
      
         | 1667 |  |  |       --  where P is a reference to a bit packed array, then we have to unwind
 | 
      
         | 1668 |  |  |       --  the assignment. The exact meaning of being a reference to a bit
 | 
      
         | 1669 |  |  |       --  packed array is as follows:
 | 
      
         | 1670 |  |  |  
 | 
      
         | 1671 |  |  |       --    An indexed component whose prefix is a bit packed array is a
 | 
      
         | 1672 |  |  |       --    reference to a bit packed array.
 | 
      
         | 1673 |  |  |  
 | 
      
         | 1674 |  |  |       --    An indexed component or selected component whose prefix is a
 | 
      
         | 1675 |  |  |       --    reference to a bit packed array is itself a reference ot a
 | 
      
         | 1676 |  |  |       --    bit packed array.
 | 
      
         | 1677 |  |  |  
 | 
      
         | 1678 |  |  |       --  The required transformation is
 | 
      
         | 1679 |  |  |  
 | 
      
         | 1680 |  |  |       --     Tnn : prefix_type := P;
 | 
      
         | 1681 |  |  |       --     Tnn.field := rhs;
 | 
      
         | 1682 |  |  |       --     P := Tnn;
 | 
      
         | 1683 |  |  |  
 | 
      
         | 1684 |  |  |       --  or
 | 
      
         | 1685 |  |  |  
 | 
      
         | 1686 |  |  |       --     Tnn : prefix_type := P;
 | 
      
         | 1687 |  |  |       --     Tnn (subscr) := rhs;
 | 
      
         | 1688 |  |  |       --     P := Tnn;
 | 
      
         | 1689 |  |  |  
 | 
      
         | 1690 |  |  |       --  Since P is going to be evaluated more than once, any subscripts
 | 
      
         | 1691 |  |  |       --  in P must have their evaluation forced.
 | 
      
         | 1692 |  |  |  
 | 
      
         | 1693 |  |  |       if Nkind_In (Lhs, N_Indexed_Component, N_Selected_Component)
 | 
      
         | 1694 |  |  |         and then Is_Ref_To_Bit_Packed_Array (Prefix (Lhs))
 | 
      
         | 1695 |  |  |       then
 | 
      
         | 1696 |  |  |          declare
 | 
      
         | 1697 |  |  |             BPAR_Expr : constant Node_Id   := Relocate_Node (Prefix (Lhs));
 | 
      
         | 1698 |  |  |             BPAR_Typ  : constant Entity_Id := Etype (BPAR_Expr);
 | 
      
         | 1699 |  |  |             Tnn       : constant Entity_Id :=
 | 
      
         | 1700 |  |  |                           Make_Temporary (Loc, 'T', BPAR_Expr);
 | 
      
         | 1701 |  |  |  
 | 
      
         | 1702 |  |  |          begin
 | 
      
         | 1703 |  |  |             --  Insert the post assignment first, because we want to copy the
 | 
      
         | 1704 |  |  |             --  BPAR_Expr tree before it gets analyzed in the context of the
 | 
      
         | 1705 |  |  |             --  pre assignment. Note that we do not analyze the post assignment
 | 
      
         | 1706 |  |  |             --  yet (we cannot till we have completed the analysis of the pre
 | 
      
         | 1707 |  |  |             --  assignment). As usual, the analysis of this post assignment
 | 
      
         | 1708 |  |  |             --  will happen on its own when we "run into" it after finishing
 | 
      
         | 1709 |  |  |             --  the current assignment.
 | 
      
         | 1710 |  |  |  
 | 
      
         | 1711 |  |  |             Insert_After (N,
 | 
      
         | 1712 |  |  |               Make_Assignment_Statement (Loc,
 | 
      
         | 1713 |  |  |                 Name       => New_Copy_Tree (BPAR_Expr),
 | 
      
         | 1714 |  |  |                 Expression => New_Occurrence_Of (Tnn, Loc)));
 | 
      
         | 1715 |  |  |  
 | 
      
         | 1716 |  |  |             --  At this stage BPAR_Expr is a reference to a bit packed array
 | 
      
         | 1717 |  |  |             --  where the reference was not expanded in the original tree,
 | 
      
         | 1718 |  |  |             --  since it was on the left side of an assignment. But in the
 | 
      
         | 1719 |  |  |             --  pre-assignment statement (the object definition), BPAR_Expr
 | 
      
         | 1720 |  |  |             --  will end up on the right hand side, and must be reexpanded. To
 | 
      
         | 1721 |  |  |             --  achieve this, we reset the analyzed flag of all selected and
 | 
      
         | 1722 |  |  |             --  indexed components down to the actual indexed component for
 | 
      
         | 1723 |  |  |             --  the packed array.
 | 
      
         | 1724 |  |  |  
 | 
      
         | 1725 |  |  |             Exp := BPAR_Expr;
 | 
      
         | 1726 |  |  |             loop
 | 
      
         | 1727 |  |  |                Set_Analyzed (Exp, False);
 | 
      
         | 1728 |  |  |  
 | 
      
         | 1729 |  |  |                if Nkind_In
 | 
      
         | 1730 |  |  |                    (Exp, N_Selected_Component, N_Indexed_Component)
 | 
      
         | 1731 |  |  |                then
 | 
      
         | 1732 |  |  |                   Exp := Prefix (Exp);
 | 
      
         | 1733 |  |  |                else
 | 
      
         | 1734 |  |  |                   exit;
 | 
      
         | 1735 |  |  |                end if;
 | 
      
         | 1736 |  |  |             end loop;
 | 
      
         | 1737 |  |  |  
 | 
      
         | 1738 |  |  |             --  Now we can insert and analyze the pre-assignment
 | 
      
         | 1739 |  |  |  
 | 
      
         | 1740 |  |  |             --  If the right-hand side requires a transient scope, it has
 | 
      
         | 1741 |  |  |             --  already been placed on the stack. However, the declaration is
 | 
      
         | 1742 |  |  |             --  inserted in the tree outside of this scope, and must reflect
 | 
      
         | 1743 |  |  |             --  the proper scope for its variable. This awkward bit is forced
 | 
      
         | 1744 |  |  |             --  by the stricter scope discipline imposed by GCC 2.97.
 | 
      
         | 1745 |  |  |  
 | 
      
         | 1746 |  |  |             declare
 | 
      
         | 1747 |  |  |                Uses_Transient_Scope : constant Boolean :=
 | 
      
         | 1748 |  |  |                                         Scope_Is_Transient
 | 
      
         | 1749 |  |  |                                           and then N = Node_To_Be_Wrapped;
 | 
      
         | 1750 |  |  |  
 | 
      
         | 1751 |  |  |             begin
 | 
      
         | 1752 |  |  |                if Uses_Transient_Scope then
 | 
      
         | 1753 |  |  |                   Push_Scope (Scope (Current_Scope));
 | 
      
         | 1754 |  |  |                end if;
 | 
      
         | 1755 |  |  |  
 | 
      
         | 1756 |  |  |                Insert_Before_And_Analyze (N,
 | 
      
         | 1757 |  |  |                  Make_Object_Declaration (Loc,
 | 
      
         | 1758 |  |  |                    Defining_Identifier => Tnn,
 | 
      
         | 1759 |  |  |                    Object_Definition   => New_Occurrence_Of (BPAR_Typ, Loc),
 | 
      
         | 1760 |  |  |                    Expression          => BPAR_Expr));
 | 
      
         | 1761 |  |  |  
 | 
      
         | 1762 |  |  |                if Uses_Transient_Scope then
 | 
      
         | 1763 |  |  |                   Pop_Scope;
 | 
      
         | 1764 |  |  |                end if;
 | 
      
         | 1765 |  |  |             end;
 | 
      
         | 1766 |  |  |  
 | 
      
         | 1767 |  |  |             --  Now fix up the original assignment and continue processing
 | 
      
         | 1768 |  |  |  
 | 
      
         | 1769 |  |  |             Rewrite (Prefix (Lhs),
 | 
      
         | 1770 |  |  |               New_Occurrence_Of (Tnn, Loc));
 | 
      
         | 1771 |  |  |  
 | 
      
         | 1772 |  |  |             --  We do not need to reanalyze that assignment, and we do not need
 | 
      
         | 1773 |  |  |             --  to worry about references to the temporary, but we do need to
 | 
      
         | 1774 |  |  |             --  make sure that the temporary is not marked as a true constant
 | 
      
         | 1775 |  |  |             --  since we now have a generated assignment to it!
 | 
      
         | 1776 |  |  |  
 | 
      
         | 1777 |  |  |             Set_Is_True_Constant (Tnn, False);
 | 
      
         | 1778 |  |  |          end;
 | 
      
         | 1779 |  |  |       end if;
 | 
      
         | 1780 |  |  |  
 | 
      
         | 1781 |  |  |       --  When we have the appropriate type of aggregate in the expression (it
 | 
      
         | 1782 |  |  |       --  has been determined during analysis of the aggregate by setting the
 | 
      
         | 1783 |  |  |       --  delay flag), let's perform in place assignment and thus avoid
 | 
      
         | 1784 |  |  |       --  creating a temporary.
 | 
      
         | 1785 |  |  |  
 | 
      
         | 1786 |  |  |       if Is_Delayed_Aggregate (Rhs) then
 | 
      
         | 1787 |  |  |          Convert_Aggr_In_Assignment (N);
 | 
      
         | 1788 |  |  |          Rewrite (N, Make_Null_Statement (Loc));
 | 
      
         | 1789 |  |  |          Analyze (N);
 | 
      
         | 1790 |  |  |          return;
 | 
      
         | 1791 |  |  |       end if;
 | 
      
         | 1792 |  |  |  
 | 
      
         | 1793 |  |  |       --  Apply discriminant check if required. If Lhs is an access type to a
 | 
      
         | 1794 |  |  |       --  designated type with discriminants, we must always check.
 | 
      
         | 1795 |  |  |  
 | 
      
         | 1796 |  |  |       if Has_Discriminants (Etype (Lhs)) then
 | 
      
         | 1797 |  |  |  
 | 
      
         | 1798 |  |  |          --  Skip discriminant check if change of representation. Will be
 | 
      
         | 1799 |  |  |          --  done when the change of representation is expanded out.
 | 
      
         | 1800 |  |  |  
 | 
      
         | 1801 |  |  |          if not Crep then
 | 
      
         | 1802 |  |  |             Apply_Discriminant_Check (Rhs, Etype (Lhs), Lhs);
 | 
      
         | 1803 |  |  |          end if;
 | 
      
         | 1804 |  |  |  
 | 
      
         | 1805 |  |  |       --  If the type is private without discriminants, and the full type
 | 
      
         | 1806 |  |  |       --  has discriminants (necessarily with defaults) a check may still be
 | 
      
         | 1807 |  |  |       --  necessary if the Lhs is aliased. The private discriminants must be
 | 
      
         | 1808 |  |  |       --  visible to build the discriminant constraints.
 | 
      
         | 1809 |  |  |  
 | 
      
         | 1810 |  |  |       --  Only an explicit dereference that comes from source indicates
 | 
      
         | 1811 |  |  |       --  aliasing. Access to formals of protected operations and entries
 | 
      
         | 1812 |  |  |       --  create dereferences but are not semantic aliasings.
 | 
      
         | 1813 |  |  |  
 | 
      
         | 1814 |  |  |       elsif Is_Private_Type (Etype (Lhs))
 | 
      
         | 1815 |  |  |         and then Has_Discriminants (Typ)
 | 
      
         | 1816 |  |  |         and then Nkind (Lhs) = N_Explicit_Dereference
 | 
      
         | 1817 |  |  |         and then Comes_From_Source (Lhs)
 | 
      
         | 1818 |  |  |       then
 | 
      
         | 1819 |  |  |          declare
 | 
      
         | 1820 |  |  |             Lt  : constant Entity_Id := Etype (Lhs);
 | 
      
         | 1821 |  |  |             Ubt : Entity_Id          := Base_Type (Typ);
 | 
      
         | 1822 |  |  |  
 | 
      
         | 1823 |  |  |          begin
 | 
      
         | 1824 |  |  |             --  In the case of an expander-generated record subtype whose base
 | 
      
         | 1825 |  |  |             --  type still appears private, Typ will have been set to that
 | 
      
         | 1826 |  |  |             --  private type rather than the underlying record type (because
 | 
      
         | 1827 |  |  |             --  Underlying type will have returned the record subtype), so it's
 | 
      
         | 1828 |  |  |             --  necessary to apply Underlying_Type again to the base type to
 | 
      
         | 1829 |  |  |             --  get the record type we need for the discriminant check. Such
 | 
      
         | 1830 |  |  |             --  subtypes can be created for assignments in certain cases, such
 | 
      
         | 1831 |  |  |             --  as within an instantiation passed this kind of private type.
 | 
      
         | 1832 |  |  |             --  It would be good to avoid this special test, but making changes
 | 
      
         | 1833 |  |  |             --  to prevent this odd form of record subtype seems difficult. ???
 | 
      
         | 1834 |  |  |  
 | 
      
         | 1835 |  |  |             if Is_Private_Type (Ubt) then
 | 
      
         | 1836 |  |  |                Ubt := Underlying_Type (Ubt);
 | 
      
         | 1837 |  |  |             end if;
 | 
      
         | 1838 |  |  |  
 | 
      
         | 1839 |  |  |             Set_Etype (Lhs, Ubt);
 | 
      
         | 1840 |  |  |             Rewrite (Rhs, OK_Convert_To (Base_Type (Ubt), Rhs));
 | 
      
         | 1841 |  |  |             Apply_Discriminant_Check (Rhs, Ubt, Lhs);
 | 
      
         | 1842 |  |  |             Set_Etype (Lhs, Lt);
 | 
      
         | 1843 |  |  |          end;
 | 
      
         | 1844 |  |  |  
 | 
      
         | 1845 |  |  |          --  If the Lhs has a private type with unknown discriminants, it
 | 
      
         | 1846 |  |  |          --  may have a full view with discriminants, but those are nameable
 | 
      
         | 1847 |  |  |          --  only in the underlying type, so convert the Rhs to it before
 | 
      
         | 1848 |  |  |          --  potential checking.
 | 
      
         | 1849 |  |  |  
 | 
      
         | 1850 |  |  |       elsif Has_Unknown_Discriminants (Base_Type (Etype (Lhs)))
 | 
      
         | 1851 |  |  |         and then Has_Discriminants (Typ)
 | 
      
         | 1852 |  |  |       then
 | 
      
         | 1853 |  |  |          Rewrite (Rhs, OK_Convert_To (Base_Type (Typ), Rhs));
 | 
      
         | 1854 |  |  |          Apply_Discriminant_Check (Rhs, Typ, Lhs);
 | 
      
         | 1855 |  |  |  
 | 
      
         | 1856 |  |  |       --  In the access type case, we need the same discriminant check, and
 | 
      
         | 1857 |  |  |       --  also range checks if we have an access to constrained array.
 | 
      
         | 1858 |  |  |  
 | 
      
         | 1859 |  |  |       elsif Is_Access_Type (Etype (Lhs))
 | 
      
         | 1860 |  |  |         and then Is_Constrained (Designated_Type (Etype (Lhs)))
 | 
      
         | 1861 |  |  |       then
 | 
      
         | 1862 |  |  |          if Has_Discriminants (Designated_Type (Etype (Lhs))) then
 | 
      
         | 1863 |  |  |  
 | 
      
         | 1864 |  |  |             --  Skip discriminant check if change of representation. Will be
 | 
      
         | 1865 |  |  |             --  done when the change of representation is expanded out.
 | 
      
         | 1866 |  |  |  
 | 
      
         | 1867 |  |  |             if not Crep then
 | 
      
         | 1868 |  |  |                Apply_Discriminant_Check (Rhs, Etype (Lhs));
 | 
      
         | 1869 |  |  |             end if;
 | 
      
         | 1870 |  |  |  
 | 
      
         | 1871 |  |  |          elsif Is_Array_Type (Designated_Type (Etype (Lhs))) then
 | 
      
         | 1872 |  |  |             Apply_Range_Check (Rhs, Etype (Lhs));
 | 
      
         | 1873 |  |  |  
 | 
      
         | 1874 |  |  |             if Is_Constrained (Etype (Lhs)) then
 | 
      
         | 1875 |  |  |                Apply_Length_Check (Rhs, Etype (Lhs));
 | 
      
         | 1876 |  |  |             end if;
 | 
      
         | 1877 |  |  |  
 | 
      
         | 1878 |  |  |             if Nkind (Rhs) = N_Allocator then
 | 
      
         | 1879 |  |  |                declare
 | 
      
         | 1880 |  |  |                   Target_Typ : constant Entity_Id := Etype (Expression (Rhs));
 | 
      
         | 1881 |  |  |                   C_Es       : Check_Result;
 | 
      
         | 1882 |  |  |  
 | 
      
         | 1883 |  |  |                begin
 | 
      
         | 1884 |  |  |                   C_Es :=
 | 
      
         | 1885 |  |  |                     Get_Range_Checks
 | 
      
         | 1886 |  |  |                       (Lhs,
 | 
      
         | 1887 |  |  |                        Target_Typ,
 | 
      
         | 1888 |  |  |                        Etype (Designated_Type (Etype (Lhs))));
 | 
      
         | 1889 |  |  |  
 | 
      
         | 1890 |  |  |                   Insert_Range_Checks
 | 
      
         | 1891 |  |  |                     (C_Es,
 | 
      
         | 1892 |  |  |                      N,
 | 
      
         | 1893 |  |  |                      Target_Typ,
 | 
      
         | 1894 |  |  |                      Sloc (Lhs),
 | 
      
         | 1895 |  |  |                      Lhs);
 | 
      
         | 1896 |  |  |                end;
 | 
      
         | 1897 |  |  |             end if;
 | 
      
         | 1898 |  |  |          end if;
 | 
      
         | 1899 |  |  |  
 | 
      
         | 1900 |  |  |       --  Apply range check for access type case
 | 
      
         | 1901 |  |  |  
 | 
      
         | 1902 |  |  |       elsif Is_Access_Type (Etype (Lhs))
 | 
      
         | 1903 |  |  |         and then Nkind (Rhs) = N_Allocator
 | 
      
         | 1904 |  |  |         and then Nkind (Expression (Rhs)) = N_Qualified_Expression
 | 
      
         | 1905 |  |  |       then
 | 
      
         | 1906 |  |  |          Analyze_And_Resolve (Expression (Rhs));
 | 
      
         | 1907 |  |  |          Apply_Range_Check
 | 
      
         | 1908 |  |  |            (Expression (Rhs), Designated_Type (Etype (Lhs)));
 | 
      
         | 1909 |  |  |       end if;
 | 
      
         | 1910 |  |  |  
 | 
      
         | 1911 |  |  |       --  Ada 2005 (AI-231): Generate the run-time check
 | 
      
         | 1912 |  |  |  
 | 
      
         | 1913 |  |  |       if Is_Access_Type (Typ)
 | 
      
         | 1914 |  |  |         and then Can_Never_Be_Null (Etype (Lhs))
 | 
      
         | 1915 |  |  |         and then not Can_Never_Be_Null (Etype (Rhs))
 | 
      
         | 1916 |  |  |       then
 | 
      
         | 1917 |  |  |          Apply_Constraint_Check (Rhs, Etype (Lhs));
 | 
      
         | 1918 |  |  |       end if;
 | 
      
         | 1919 |  |  |  
 | 
      
         | 1920 |  |  |       --  Ada 2012 (AI05-148): Update current accessibility level if Rhs is a
 | 
      
         | 1921 |  |  |       --  stand-alone obj of an anonymous access type.
 | 
      
         | 1922 |  |  |  
 | 
      
         | 1923 |  |  |       if Is_Access_Type (Typ)
 | 
      
         | 1924 |  |  |         and then Is_Entity_Name (Lhs)
 | 
      
         | 1925 |  |  |         and then Present (Effective_Extra_Accessibility (Entity (Lhs))) then
 | 
      
         | 1926 |  |  |          declare
 | 
      
         | 1927 |  |  |             function Lhs_Entity return Entity_Id;
 | 
      
         | 1928 |  |  |             --  Look through renames to find the underlying entity.
 | 
      
         | 1929 |  |  |             --  For assignment to a rename, we don't care about the
 | 
      
         | 1930 |  |  |             --  Enclosing_Dynamic_Scope of the rename declaration.
 | 
      
         | 1931 |  |  |  
 | 
      
         | 1932 |  |  |             ----------------
 | 
      
         | 1933 |  |  |             -- Lhs_Entity --
 | 
      
         | 1934 |  |  |             ----------------
 | 
      
         | 1935 |  |  |  
 | 
      
         | 1936 |  |  |             function Lhs_Entity return Entity_Id is
 | 
      
         | 1937 |  |  |                Result : Entity_Id := Entity (Lhs);
 | 
      
         | 1938 |  |  |  
 | 
      
         | 1939 |  |  |             begin
 | 
      
         | 1940 |  |  |                while Present (Renamed_Object (Result)) loop
 | 
      
         | 1941 |  |  |  
 | 
      
         | 1942 |  |  |                   --  Renamed_Object must return an Entity_Name here
 | 
      
         | 1943 |  |  |                   --  because of preceding "Present (E_E_A (...))" test.
 | 
      
         | 1944 |  |  |  
 | 
      
         | 1945 |  |  |                   Result := Entity (Renamed_Object (Result));
 | 
      
         | 1946 |  |  |                end loop;
 | 
      
         | 1947 |  |  |  
 | 
      
         | 1948 |  |  |                return Result;
 | 
      
         | 1949 |  |  |             end Lhs_Entity;
 | 
      
         | 1950 |  |  |  
 | 
      
         | 1951 |  |  |             --  Local Declarations
 | 
      
         | 1952 |  |  |  
 | 
      
         | 1953 |  |  |             Access_Check : constant Node_Id :=
 | 
      
         | 1954 |  |  |                              Make_Raise_Program_Error (Loc,
 | 
      
         | 1955 |  |  |                                Condition =>
 | 
      
         | 1956 |  |  |                                  Make_Op_Gt (Loc,
 | 
      
         | 1957 |  |  |                                    Left_Opnd  =>
 | 
      
         | 1958 |  |  |                                      Dynamic_Accessibility_Level (Rhs),
 | 
      
         | 1959 |  |  |                                    Right_Opnd =>
 | 
      
         | 1960 |  |  |                                      Make_Integer_Literal (Loc,
 | 
      
         | 1961 |  |  |                                        Intval =>
 | 
      
         | 1962 |  |  |                                          Scope_Depth
 | 
      
         | 1963 |  |  |                                            (Enclosing_Dynamic_Scope
 | 
      
         | 1964 |  |  |                                              (Lhs_Entity)))),
 | 
      
         | 1965 |  |  |                                Reason => PE_Accessibility_Check_Failed);
 | 
      
         | 1966 |  |  |  
 | 
      
         | 1967 |  |  |             Access_Level_Update : constant Node_Id :=
 | 
      
         | 1968 |  |  |                                     Make_Assignment_Statement (Loc,
 | 
      
         | 1969 |  |  |                                      Name       =>
 | 
      
         | 1970 |  |  |                                        New_Occurrence_Of
 | 
      
         | 1971 |  |  |                                          (Effective_Extra_Accessibility
 | 
      
         | 1972 |  |  |                                             (Entity (Lhs)), Loc),
 | 
      
         | 1973 |  |  |                                      Expression =>
 | 
      
         | 1974 |  |  |                                         Dynamic_Accessibility_Level (Rhs));
 | 
      
         | 1975 |  |  |  
 | 
      
         | 1976 |  |  |          begin
 | 
      
         | 1977 |  |  |             if not Accessibility_Checks_Suppressed (Entity (Lhs)) then
 | 
      
         | 1978 |  |  |                Insert_Action (N, Access_Check);
 | 
      
         | 1979 |  |  |             end if;
 | 
      
         | 1980 |  |  |  
 | 
      
         | 1981 |  |  |             Insert_Action (N, Access_Level_Update);
 | 
      
         | 1982 |  |  |          end;
 | 
      
         | 1983 |  |  |       end if;
 | 
      
         | 1984 |  |  |  
 | 
      
         | 1985 |  |  |       --  Case of assignment to a bit packed array element. If there is a
 | 
      
         | 1986 |  |  |       --  change of representation this must be expanded into components,
 | 
      
         | 1987 |  |  |       --  otherwise this is a bit-field assignment.
 | 
      
         | 1988 |  |  |  
 | 
      
         | 1989 |  |  |       if Nkind (Lhs) = N_Indexed_Component
 | 
      
         | 1990 |  |  |         and then Is_Bit_Packed_Array (Etype (Prefix (Lhs)))
 | 
      
         | 1991 |  |  |       then
 | 
      
         | 1992 |  |  |          --  Normal case, no change of representation
 | 
      
         | 1993 |  |  |  
 | 
      
         | 1994 |  |  |          if not Crep then
 | 
      
         | 1995 |  |  |             Expand_Bit_Packed_Element_Set (N);
 | 
      
         | 1996 |  |  |             return;
 | 
      
         | 1997 |  |  |  
 | 
      
         | 1998 |  |  |          --  Change of representation case
 | 
      
         | 1999 |  |  |  
 | 
      
         | 2000 |  |  |          else
 | 
      
         | 2001 |  |  |             --  Generate the following, to force component-by-component
 | 
      
         | 2002 |  |  |             --  assignments in an efficient way. Otherwise each component
 | 
      
         | 2003 |  |  |             --  will require a temporary and two bit-field manipulations.
 | 
      
         | 2004 |  |  |  
 | 
      
         | 2005 |  |  |             --  T1 : Elmt_Type;
 | 
      
         | 2006 |  |  |             --  T1 := RhS;
 | 
      
         | 2007 |  |  |             --  Lhs := T1;
 | 
      
         | 2008 |  |  |  
 | 
      
         | 2009 |  |  |             declare
 | 
      
         | 2010 |  |  |                Tnn : constant Entity_Id := Make_Temporary (Loc, 'T');
 | 
      
         | 2011 |  |  |                Stats : List_Id;
 | 
      
         | 2012 |  |  |  
 | 
      
         | 2013 |  |  |             begin
 | 
      
         | 2014 |  |  |                Stats :=
 | 
      
         | 2015 |  |  |                  New_List (
 | 
      
         | 2016 |  |  |                    Make_Object_Declaration (Loc,
 | 
      
         | 2017 |  |  |                      Defining_Identifier => Tnn,
 | 
      
         | 2018 |  |  |                      Object_Definition   =>
 | 
      
         | 2019 |  |  |                        New_Occurrence_Of (Etype (Lhs), Loc)),
 | 
      
         | 2020 |  |  |                    Make_Assignment_Statement (Loc,
 | 
      
         | 2021 |  |  |                      Name       => New_Occurrence_Of (Tnn, Loc),
 | 
      
         | 2022 |  |  |                      Expression => Relocate_Node (Rhs)),
 | 
      
         | 2023 |  |  |                    Make_Assignment_Statement (Loc,
 | 
      
         | 2024 |  |  |                      Name       => Relocate_Node (Lhs),
 | 
      
         | 2025 |  |  |                      Expression => New_Occurrence_Of (Tnn, Loc)));
 | 
      
         | 2026 |  |  |  
 | 
      
         | 2027 |  |  |                Insert_Actions (N, Stats);
 | 
      
         | 2028 |  |  |                Rewrite (N, Make_Null_Statement (Loc));
 | 
      
         | 2029 |  |  |                Analyze (N);
 | 
      
         | 2030 |  |  |             end;
 | 
      
         | 2031 |  |  |          end if;
 | 
      
         | 2032 |  |  |  
 | 
      
         | 2033 |  |  |       --  Build-in-place function call case. Note that we're not yet doing
 | 
      
         | 2034 |  |  |       --  build-in-place for user-written assignment statements (the assignment
 | 
      
         | 2035 |  |  |       --  here came from an aggregate.)
 | 
      
         | 2036 |  |  |  
 | 
      
         | 2037 |  |  |       elsif Ada_Version >= Ada_2005
 | 
      
         | 2038 |  |  |         and then Is_Build_In_Place_Function_Call (Rhs)
 | 
      
         | 2039 |  |  |       then
 | 
      
         | 2040 |  |  |          Make_Build_In_Place_Call_In_Assignment (N, Rhs);
 | 
      
         | 2041 |  |  |  
 | 
      
         | 2042 |  |  |       elsif Is_Tagged_Type (Typ) and then Is_Value_Type (Etype (Lhs)) then
 | 
      
         | 2043 |  |  |  
 | 
      
         | 2044 |  |  |          --  Nothing to do for valuetypes
 | 
      
         | 2045 |  |  |          --  ??? Set_Scope_Is_Transient (False);
 | 
      
         | 2046 |  |  |  
 | 
      
         | 2047 |  |  |          return;
 | 
      
         | 2048 |  |  |  
 | 
      
         | 2049 |  |  |       elsif Is_Tagged_Type (Typ)
 | 
      
         | 2050 |  |  |         or else (Needs_Finalization (Typ) and then not Is_Array_Type (Typ))
 | 
      
         | 2051 |  |  |       then
 | 
      
         | 2052 |  |  |          Tagged_Case : declare
 | 
      
         | 2053 |  |  |             L                   : List_Id := No_List;
 | 
      
         | 2054 |  |  |             Expand_Ctrl_Actions : constant Boolean := not No_Ctrl_Actions (N);
 | 
      
         | 2055 |  |  |  
 | 
      
         | 2056 |  |  |          begin
 | 
      
         | 2057 |  |  |             --  In the controlled case, we ensure that function calls are
 | 
      
         | 2058 |  |  |             --  evaluated before finalizing the target. In all cases, it makes
 | 
      
         | 2059 |  |  |             --  the expansion easier if the side-effects are removed first.
 | 
      
         | 2060 |  |  |  
 | 
      
         | 2061 |  |  |             Remove_Side_Effects (Lhs);
 | 
      
         | 2062 |  |  |             Remove_Side_Effects (Rhs);
 | 
      
         | 2063 |  |  |  
 | 
      
         | 2064 |  |  |             --  Avoid recursion in the mechanism
 | 
      
         | 2065 |  |  |  
 | 
      
         | 2066 |  |  |             Set_Analyzed (N);
 | 
      
         | 2067 |  |  |  
 | 
      
         | 2068 |  |  |             --  If dispatching assignment, we need to dispatch to _assign
 | 
      
         | 2069 |  |  |  
 | 
      
         | 2070 |  |  |             if Is_Class_Wide_Type (Typ)
 | 
      
         | 2071 |  |  |  
 | 
      
         | 2072 |  |  |                --  If the type is tagged, we may as well use the predefined
 | 
      
         | 2073 |  |  |                --  primitive assignment. This avoids inlining a lot of code
 | 
      
         | 2074 |  |  |                --  and in the class-wide case, the assignment is replaced
 | 
      
         | 2075 |  |  |                --  by a dispatching call to _assign. It is suppressed in the
 | 
      
         | 2076 |  |  |                --  case of assignments created by the expander that correspond
 | 
      
         | 2077 |  |  |                --  to initializations, where we do want to copy the tag
 | 
      
         | 2078 |  |  |                --  (Expand_Ctrl_Actions flag is set True in this case). It is
 | 
      
         | 2079 |  |  |                --  also suppressed if restriction No_Dispatching_Calls is in
 | 
      
         | 2080 |  |  |                --  force because in that case predefined primitives are not
 | 
      
         | 2081 |  |  |                --  generated.
 | 
      
         | 2082 |  |  |  
 | 
      
         | 2083 |  |  |                or else (Is_Tagged_Type (Typ)
 | 
      
         | 2084 |  |  |                          and then not Is_Value_Type (Etype (Lhs))
 | 
      
         | 2085 |  |  |                          and then Chars (Current_Scope) /= Name_uAssign
 | 
      
         | 2086 |  |  |                          and then Expand_Ctrl_Actions
 | 
      
         | 2087 |  |  |                          and then
 | 
      
         | 2088 |  |  |                            not Restriction_Active (No_Dispatching_Calls))
 | 
      
         | 2089 |  |  |             then
 | 
      
         | 2090 |  |  |                if Is_Limited_Type (Typ) then
 | 
      
         | 2091 |  |  |  
 | 
      
         | 2092 |  |  |                   --  This can happen in an instance when the formal is an
 | 
      
         | 2093 |  |  |                   --  extension of a limited interface, and the actual is
 | 
      
         | 2094 |  |  |                   --  limited. This is an error according to AI05-0087, but
 | 
      
         | 2095 |  |  |                   --  is not caught at the point of instantiation in earlier
 | 
      
         | 2096 |  |  |                   --  versions.
 | 
      
         | 2097 |  |  |  
 | 
      
         | 2098 |  |  |                   --  This is wrong, error messages cannot be issued during
 | 
      
         | 2099 |  |  |                   --  expansion, since they would be missed in -gnatc mode ???
 | 
      
         | 2100 |  |  |  
 | 
      
         | 2101 |  |  |                   Error_Msg_N ("assignment not available on limited type", N);
 | 
      
         | 2102 |  |  |                   return;
 | 
      
         | 2103 |  |  |                end if;
 | 
      
         | 2104 |  |  |  
 | 
      
         | 2105 |  |  |                --  Fetch the primitive op _assign and proper type to call it.
 | 
      
         | 2106 |  |  |                --  Because of possible conflicts between private and full view,
 | 
      
         | 2107 |  |  |                --  fetch the proper type directly from the operation profile.
 | 
      
         | 2108 |  |  |  
 | 
      
         | 2109 |  |  |                declare
 | 
      
         | 2110 |  |  |                   Op    : constant Entity_Id :=
 | 
      
         | 2111 |  |  |                             Find_Prim_Op (Typ, Name_uAssign);
 | 
      
         | 2112 |  |  |                   F_Typ : Entity_Id := Etype (First_Formal (Op));
 | 
      
         | 2113 |  |  |  
 | 
      
         | 2114 |  |  |                begin
 | 
      
         | 2115 |  |  |                   --  If the assignment is dispatching, make sure to use the
 | 
      
         | 2116 |  |  |                   --  proper type.
 | 
      
         | 2117 |  |  |  
 | 
      
         | 2118 |  |  |                   if Is_Class_Wide_Type (Typ) then
 | 
      
         | 2119 |  |  |                      F_Typ := Class_Wide_Type (F_Typ);
 | 
      
         | 2120 |  |  |                   end if;
 | 
      
         | 2121 |  |  |  
 | 
      
         | 2122 |  |  |                   L := New_List;
 | 
      
         | 2123 |  |  |  
 | 
      
         | 2124 |  |  |                   --  In case of assignment to a class-wide tagged type, before
 | 
      
         | 2125 |  |  |                   --  the assignment we generate run-time check to ensure that
 | 
      
         | 2126 |  |  |                   --  the tags of source and target match.
 | 
      
         | 2127 |  |  |  
 | 
      
         | 2128 |  |  |                   if Is_Class_Wide_Type (Typ)
 | 
      
         | 2129 |  |  |                     and then Is_Tagged_Type (Typ)
 | 
      
         | 2130 |  |  |                     and then Is_Tagged_Type (Underlying_Type (Etype (Rhs)))
 | 
      
         | 2131 |  |  |                   then
 | 
      
         | 2132 |  |  |                      Append_To (L,
 | 
      
         | 2133 |  |  |                        Make_Raise_Constraint_Error (Loc,
 | 
      
         | 2134 |  |  |                          Condition =>
 | 
      
         | 2135 |  |  |                            Make_Op_Ne (Loc,
 | 
      
         | 2136 |  |  |                              Left_Opnd =>
 | 
      
         | 2137 |  |  |                                Make_Selected_Component (Loc,
 | 
      
         | 2138 |  |  |                                  Prefix        => Duplicate_Subexpr (Lhs),
 | 
      
         | 2139 |  |  |                                  Selector_Name =>
 | 
      
         | 2140 |  |  |                                    Make_Identifier (Loc, Name_uTag)),
 | 
      
         | 2141 |  |  |                              Right_Opnd =>
 | 
      
         | 2142 |  |  |                                Make_Selected_Component (Loc,
 | 
      
         | 2143 |  |  |                                  Prefix        => Duplicate_Subexpr (Rhs),
 | 
      
         | 2144 |  |  |                                  Selector_Name =>
 | 
      
         | 2145 |  |  |                                    Make_Identifier (Loc, Name_uTag))),
 | 
      
         | 2146 |  |  |                          Reason => CE_Tag_Check_Failed));
 | 
      
         | 2147 |  |  |                   end if;
 | 
      
         | 2148 |  |  |  
 | 
      
         | 2149 |  |  |                   declare
 | 
      
         | 2150 |  |  |                      Left_N  : Node_Id := Duplicate_Subexpr (Lhs);
 | 
      
         | 2151 |  |  |                      Right_N : Node_Id := Duplicate_Subexpr (Rhs);
 | 
      
         | 2152 |  |  |  
 | 
      
         | 2153 |  |  |                   begin
 | 
      
         | 2154 |  |  |                      --  In order to dispatch the call to _assign the type of
 | 
      
         | 2155 |  |  |                      --  the actuals must match. Add conversion (if required).
 | 
      
         | 2156 |  |  |  
 | 
      
         | 2157 |  |  |                      if Etype (Lhs) /= F_Typ then
 | 
      
         | 2158 |  |  |                         Left_N := Unchecked_Convert_To (F_Typ, Left_N);
 | 
      
         | 2159 |  |  |                      end if;
 | 
      
         | 2160 |  |  |  
 | 
      
         | 2161 |  |  |                      if Etype (Rhs) /= F_Typ then
 | 
      
         | 2162 |  |  |                         Right_N := Unchecked_Convert_To (F_Typ, Right_N);
 | 
      
         | 2163 |  |  |                      end if;
 | 
      
         | 2164 |  |  |  
 | 
      
         | 2165 |  |  |                      Append_To (L,
 | 
      
         | 2166 |  |  |                        Make_Procedure_Call_Statement (Loc,
 | 
      
         | 2167 |  |  |                          Name => New_Reference_To (Op, Loc),
 | 
      
         | 2168 |  |  |                          Parameter_Associations => New_List (
 | 
      
         | 2169 |  |  |                            Node1 => Left_N,
 | 
      
         | 2170 |  |  |                            Node2 => Right_N)));
 | 
      
         | 2171 |  |  |                   end;
 | 
      
         | 2172 |  |  |                end;
 | 
      
         | 2173 |  |  |  
 | 
      
         | 2174 |  |  |             else
 | 
      
         | 2175 |  |  |                L := Make_Tag_Ctrl_Assignment (N);
 | 
      
         | 2176 |  |  |  
 | 
      
         | 2177 |  |  |                --  We can't afford to have destructive Finalization Actions in
 | 
      
         | 2178 |  |  |                --  the Self assignment case, so if the target and the source
 | 
      
         | 2179 |  |  |                --  are not obviously different, code is generated to avoid the
 | 
      
         | 2180 |  |  |                --  self assignment case:
 | 
      
         | 2181 |  |  |  
 | 
      
         | 2182 |  |  |                --    if lhs'address /= rhs'address then
 | 
      
         | 2183 |  |  |                --       <code for controlled and/or tagged assignment>
 | 
      
         | 2184 |  |  |                --    end if;
 | 
      
         | 2185 |  |  |  
 | 
      
         | 2186 |  |  |                --  Skip this if Restriction (No_Finalization) is active
 | 
      
         | 2187 |  |  |  
 | 
      
         | 2188 |  |  |                if not Statically_Different (Lhs, Rhs)
 | 
      
         | 2189 |  |  |                  and then Expand_Ctrl_Actions
 | 
      
         | 2190 |  |  |                  and then not Restriction_Active (No_Finalization)
 | 
      
         | 2191 |  |  |                then
 | 
      
         | 2192 |  |  |                   L := New_List (
 | 
      
         | 2193 |  |  |                     Make_Implicit_If_Statement (N,
 | 
      
         | 2194 |  |  |                       Condition =>
 | 
      
         | 2195 |  |  |                         Make_Op_Ne (Loc,
 | 
      
         | 2196 |  |  |                           Left_Opnd =>
 | 
      
         | 2197 |  |  |                             Make_Attribute_Reference (Loc,
 | 
      
         | 2198 |  |  |                               Prefix         => Duplicate_Subexpr (Lhs),
 | 
      
         | 2199 |  |  |                               Attribute_Name => Name_Address),
 | 
      
         | 2200 |  |  |  
 | 
      
         | 2201 |  |  |                            Right_Opnd =>
 | 
      
         | 2202 |  |  |                             Make_Attribute_Reference (Loc,
 | 
      
         | 2203 |  |  |                               Prefix         => Duplicate_Subexpr (Rhs),
 | 
      
         | 2204 |  |  |                               Attribute_Name => Name_Address)),
 | 
      
         | 2205 |  |  |  
 | 
      
         | 2206 |  |  |                       Then_Statements => L));
 | 
      
         | 2207 |  |  |                end if;
 | 
      
         | 2208 |  |  |  
 | 
      
         | 2209 |  |  |                --  We need to set up an exception handler for implementing
 | 
      
         | 2210 |  |  |                --  7.6.1(18). The remaining adjustments are tackled by the
 | 
      
         | 2211 |  |  |                --  implementation of adjust for record_controllers (see
 | 
      
         | 2212 |  |  |                --  s-finimp.adb).
 | 
      
         | 2213 |  |  |  
 | 
      
         | 2214 |  |  |                --  This is skipped if we have no finalization
 | 
      
         | 2215 |  |  |  
 | 
      
         | 2216 |  |  |                if Expand_Ctrl_Actions
 | 
      
         | 2217 |  |  |                  and then not Restriction_Active (No_Finalization)
 | 
      
         | 2218 |  |  |                then
 | 
      
         | 2219 |  |  |                   L := New_List (
 | 
      
         | 2220 |  |  |                     Make_Block_Statement (Loc,
 | 
      
         | 2221 |  |  |                       Handled_Statement_Sequence =>
 | 
      
         | 2222 |  |  |                         Make_Handled_Sequence_Of_Statements (Loc,
 | 
      
         | 2223 |  |  |                           Statements => L,
 | 
      
         | 2224 |  |  |                           Exception_Handlers => New_List (
 | 
      
         | 2225 |  |  |                             Make_Handler_For_Ctrl_Operation (Loc)))));
 | 
      
         | 2226 |  |  |                end if;
 | 
      
         | 2227 |  |  |             end if;
 | 
      
         | 2228 |  |  |  
 | 
      
         | 2229 |  |  |             Rewrite (N,
 | 
      
         | 2230 |  |  |               Make_Block_Statement (Loc,
 | 
      
         | 2231 |  |  |                 Handled_Statement_Sequence =>
 | 
      
         | 2232 |  |  |                   Make_Handled_Sequence_Of_Statements (Loc, Statements => L)));
 | 
      
         | 2233 |  |  |  
 | 
      
         | 2234 |  |  |             --  If no restrictions on aborts, protect the whole assignment
 | 
      
         | 2235 |  |  |             --  for controlled objects as per 9.8(11).
 | 
      
         | 2236 |  |  |  
 | 
      
         | 2237 |  |  |             if Needs_Finalization (Typ)
 | 
      
         | 2238 |  |  |               and then Expand_Ctrl_Actions
 | 
      
         | 2239 |  |  |               and then Abort_Allowed
 | 
      
         | 2240 |  |  |             then
 | 
      
         | 2241 |  |  |                declare
 | 
      
         | 2242 |  |  |                   Blk : constant Entity_Id :=
 | 
      
         | 2243 |  |  |                           New_Internal_Entity
 | 
      
         | 2244 |  |  |                             (E_Block, Current_Scope, Sloc (N), 'B');
 | 
      
         | 2245 |  |  |  
 | 
      
         | 2246 |  |  |                begin
 | 
      
         | 2247 |  |  |                   Set_Scope (Blk, Current_Scope);
 | 
      
         | 2248 |  |  |                   Set_Etype (Blk, Standard_Void_Type);
 | 
      
         | 2249 |  |  |                   Set_Identifier (N, New_Occurrence_Of (Blk, Sloc (N)));
 | 
      
         | 2250 |  |  |  
 | 
      
         | 2251 |  |  |                   Prepend_To (L, Build_Runtime_Call (Loc, RE_Abort_Defer));
 | 
      
         | 2252 |  |  |                   Set_At_End_Proc (Handled_Statement_Sequence (N),
 | 
      
         | 2253 |  |  |                     New_Occurrence_Of (RTE (RE_Abort_Undefer_Direct), Loc));
 | 
      
         | 2254 |  |  |                   Expand_At_End_Handler
 | 
      
         | 2255 |  |  |                     (Handled_Statement_Sequence (N), Blk);
 | 
      
         | 2256 |  |  |                end;
 | 
      
         | 2257 |  |  |             end if;
 | 
      
         | 2258 |  |  |  
 | 
      
         | 2259 |  |  |             --  N has been rewritten to a block statement for which it is
 | 
      
         | 2260 |  |  |             --  known by construction that no checks are necessary: analyze
 | 
      
         | 2261 |  |  |             --  it with all checks suppressed.
 | 
      
         | 2262 |  |  |  
 | 
      
         | 2263 |  |  |             Analyze (N, Suppress => All_Checks);
 | 
      
         | 2264 |  |  |             return;
 | 
      
         | 2265 |  |  |          end Tagged_Case;
 | 
      
         | 2266 |  |  |  
 | 
      
         | 2267 |  |  |       --  Array types
 | 
      
         | 2268 |  |  |  
 | 
      
         | 2269 |  |  |       elsif Is_Array_Type (Typ) then
 | 
      
         | 2270 |  |  |          declare
 | 
      
         | 2271 |  |  |             Actual_Rhs : Node_Id := Rhs;
 | 
      
         | 2272 |  |  |  
 | 
      
         | 2273 |  |  |          begin
 | 
      
         | 2274 |  |  |             while Nkind_In (Actual_Rhs, N_Type_Conversion,
 | 
      
         | 2275 |  |  |                                         N_Qualified_Expression)
 | 
      
         | 2276 |  |  |             loop
 | 
      
         | 2277 |  |  |                Actual_Rhs := Expression (Actual_Rhs);
 | 
      
         | 2278 |  |  |             end loop;
 | 
      
         | 2279 |  |  |  
 | 
      
         | 2280 |  |  |             Expand_Assign_Array (N, Actual_Rhs);
 | 
      
         | 2281 |  |  |             return;
 | 
      
         | 2282 |  |  |          end;
 | 
      
         | 2283 |  |  |  
 | 
      
         | 2284 |  |  |       --  Record types
 | 
      
         | 2285 |  |  |  
 | 
      
         | 2286 |  |  |       elsif Is_Record_Type (Typ) then
 | 
      
         | 2287 |  |  |          Expand_Assign_Record (N);
 | 
      
         | 2288 |  |  |          return;
 | 
      
         | 2289 |  |  |  
 | 
      
         | 2290 |  |  |       --  Scalar types. This is where we perform the processing related to the
 | 
      
         | 2291 |  |  |       --  requirements of (RM 13.9.1(9-11)) concerning the handling of invalid
 | 
      
         | 2292 |  |  |       --  scalar values.
 | 
      
         | 2293 |  |  |  
 | 
      
         | 2294 |  |  |       elsif Is_Scalar_Type (Typ) then
 | 
      
         | 2295 |  |  |  
 | 
      
         | 2296 |  |  |          --  Case where right side is known valid
 | 
      
         | 2297 |  |  |  
 | 
      
         | 2298 |  |  |          if Expr_Known_Valid (Rhs) then
 | 
      
         | 2299 |  |  |  
 | 
      
         | 2300 |  |  |             --  Here the right side is valid, so it is fine. The case to deal
 | 
      
         | 2301 |  |  |             --  with is when the left side is a local variable reference whose
 | 
      
         | 2302 |  |  |             --  value is not currently known to be valid. If this is the case,
 | 
      
         | 2303 |  |  |             --  and the assignment appears in an unconditional context, then
 | 
      
         | 2304 |  |  |             --  we can mark the left side as now being valid if one of these
 | 
      
         | 2305 |  |  |             --  conditions holds:
 | 
      
         | 2306 |  |  |  
 | 
      
         | 2307 |  |  |             --    The expression of the right side has Do_Range_Check set so
 | 
      
         | 2308 |  |  |             --    that we know a range check will be performed. Note that it
 | 
      
         | 2309 |  |  |             --    can be the case that a range check is omitted because we
 | 
      
         | 2310 |  |  |             --    make the assumption that we can assume validity for operands
 | 
      
         | 2311 |  |  |             --    appearing in the right side in determining whether a range
 | 
      
         | 2312 |  |  |             --    check is required
 | 
      
         | 2313 |  |  |  
 | 
      
         | 2314 |  |  |             --    The subtype of the right side matches the subtype of the
 | 
      
         | 2315 |  |  |             --    left side. In this case, even though we have not checked
 | 
      
         | 2316 |  |  |             --    the range of the right side, we know it is in range of its
 | 
      
         | 2317 |  |  |             --    subtype if the expression is valid.
 | 
      
         | 2318 |  |  |  
 | 
      
         | 2319 |  |  |             if Is_Local_Variable_Reference (Lhs)
 | 
      
         | 2320 |  |  |               and then not Is_Known_Valid (Entity (Lhs))
 | 
      
         | 2321 |  |  |               and then In_Unconditional_Context (N)
 | 
      
         | 2322 |  |  |             then
 | 
      
         | 2323 |  |  |                if Do_Range_Check (Rhs)
 | 
      
         | 2324 |  |  |                  or else Etype (Lhs) = Etype (Rhs)
 | 
      
         | 2325 |  |  |                then
 | 
      
         | 2326 |  |  |                   Set_Is_Known_Valid (Entity (Lhs), True);
 | 
      
         | 2327 |  |  |                end if;
 | 
      
         | 2328 |  |  |             end if;
 | 
      
         | 2329 |  |  |  
 | 
      
         | 2330 |  |  |          --  Case where right side may be invalid in the sense of the RM
 | 
      
         | 2331 |  |  |          --  reference above. The RM does not require that we check for the
 | 
      
         | 2332 |  |  |          --  validity on an assignment, but it does require that the assignment
 | 
      
         | 2333 |  |  |          --  of an invalid value not cause erroneous behavior.
 | 
      
         | 2334 |  |  |  
 | 
      
         | 2335 |  |  |          --  The general approach in GNAT is to use the Is_Known_Valid flag
 | 
      
         | 2336 |  |  |          --  to avoid the need for validity checking on assignments. However
 | 
      
         | 2337 |  |  |          --  in some cases, we have to do validity checking in order to make
 | 
      
         | 2338 |  |  |          --  sure that the setting of this flag is correct.
 | 
      
         | 2339 |  |  |  
 | 
      
         | 2340 |  |  |          else
 | 
      
         | 2341 |  |  |             --  Validate right side if we are validating copies
 | 
      
         | 2342 |  |  |  
 | 
      
         | 2343 |  |  |             if Validity_Checks_On
 | 
      
         | 2344 |  |  |               and then Validity_Check_Copies
 | 
      
         | 2345 |  |  |             then
 | 
      
         | 2346 |  |  |                --  Skip this if left hand side is an array or record component
 | 
      
         | 2347 |  |  |                --  and elementary component validity checks are suppressed.
 | 
      
         | 2348 |  |  |  
 | 
      
         | 2349 |  |  |                if Nkind_In (Lhs, N_Selected_Component, N_Indexed_Component)
 | 
      
         | 2350 |  |  |                  and then not Validity_Check_Components
 | 
      
         | 2351 |  |  |                then
 | 
      
         | 2352 |  |  |                   null;
 | 
      
         | 2353 |  |  |                else
 | 
      
         | 2354 |  |  |                   Ensure_Valid (Rhs);
 | 
      
         | 2355 |  |  |                end if;
 | 
      
         | 2356 |  |  |  
 | 
      
         | 2357 |  |  |                --  We can propagate this to the left side where appropriate
 | 
      
         | 2358 |  |  |  
 | 
      
         | 2359 |  |  |                if Is_Local_Variable_Reference (Lhs)
 | 
      
         | 2360 |  |  |                  and then not Is_Known_Valid (Entity (Lhs))
 | 
      
         | 2361 |  |  |                  and then In_Unconditional_Context (N)
 | 
      
         | 2362 |  |  |                then
 | 
      
         | 2363 |  |  |                   Set_Is_Known_Valid (Entity (Lhs), True);
 | 
      
         | 2364 |  |  |                end if;
 | 
      
         | 2365 |  |  |  
 | 
      
         | 2366 |  |  |             --  Otherwise check to see what should be done
 | 
      
         | 2367 |  |  |  
 | 
      
         | 2368 |  |  |             --  If left side is a local variable, then we just set its flag to
 | 
      
         | 2369 |  |  |             --  indicate that its value may no longer be valid, since we are
 | 
      
         | 2370 |  |  |             --  copying a potentially invalid value.
 | 
      
         | 2371 |  |  |  
 | 
      
         | 2372 |  |  |             elsif Is_Local_Variable_Reference (Lhs) then
 | 
      
         | 2373 |  |  |                Set_Is_Known_Valid (Entity (Lhs), False);
 | 
      
         | 2374 |  |  |  
 | 
      
         | 2375 |  |  |             --  Check for case of a nonlocal variable on the left side which
 | 
      
         | 2376 |  |  |             --  is currently known to be valid. In this case, we simply ensure
 | 
      
         | 2377 |  |  |             --  that the right side is valid. We only play the game of copying
 | 
      
         | 2378 |  |  |             --  validity status for local variables, since we are doing this
 | 
      
         | 2379 |  |  |             --  statically, not by tracing the full flow graph.
 | 
      
         | 2380 |  |  |  
 | 
      
         | 2381 |  |  |             elsif Is_Entity_Name (Lhs)
 | 
      
         | 2382 |  |  |               and then Is_Known_Valid (Entity (Lhs))
 | 
      
         | 2383 |  |  |             then
 | 
      
         | 2384 |  |  |                --  Note: If Validity_Checking mode is set to none, we ignore
 | 
      
         | 2385 |  |  |                --  the Ensure_Valid call so don't worry about that case here.
 | 
      
         | 2386 |  |  |  
 | 
      
         | 2387 |  |  |                Ensure_Valid (Rhs);
 | 
      
         | 2388 |  |  |  
 | 
      
         | 2389 |  |  |             --  In all other cases, we can safely copy an invalid value without
 | 
      
         | 2390 |  |  |             --  worrying about the status of the left side. Since it is not a
 | 
      
         | 2391 |  |  |             --  variable reference it will not be considered
 | 
      
         | 2392 |  |  |             --  as being known to be valid in any case.
 | 
      
         | 2393 |  |  |  
 | 
      
         | 2394 |  |  |             else
 | 
      
         | 2395 |  |  |                null;
 | 
      
         | 2396 |  |  |             end if;
 | 
      
         | 2397 |  |  |          end if;
 | 
      
         | 2398 |  |  |       end if;
 | 
      
         | 2399 |  |  |  
 | 
      
         | 2400 |  |  |    exception
 | 
      
         | 2401 |  |  |       when RE_Not_Available =>
 | 
      
         | 2402 |  |  |          return;
 | 
      
         | 2403 |  |  |    end Expand_N_Assignment_Statement;
 | 
      
         | 2404 |  |  |  
 | 
      
         | 2405 |  |  |    ------------------------------
 | 
      
         | 2406 |  |  |    -- Expand_N_Block_Statement --
 | 
      
         | 2407 |  |  |    ------------------------------
 | 
      
         | 2408 |  |  |  
 | 
      
         | 2409 |  |  |    --  Encode entity names defined in block statement
 | 
      
         | 2410 |  |  |  
 | 
      
         | 2411 |  |  |    procedure Expand_N_Block_Statement (N : Node_Id) is
 | 
      
         | 2412 |  |  |    begin
 | 
      
         | 2413 |  |  |       Qualify_Entity_Names (N);
 | 
      
         | 2414 |  |  |    end Expand_N_Block_Statement;
 | 
      
         | 2415 |  |  |  
 | 
      
         | 2416 |  |  |    -----------------------------
 | 
      
         | 2417 |  |  |    -- Expand_N_Case_Statement --
 | 
      
         | 2418 |  |  |    -----------------------------
 | 
      
         | 2419 |  |  |  
 | 
      
         | 2420 |  |  |    procedure Expand_N_Case_Statement (N : Node_Id) is
 | 
      
         | 2421 |  |  |       Loc    : constant Source_Ptr := Sloc (N);
 | 
      
         | 2422 |  |  |       Expr   : constant Node_Id    := Expression (N);
 | 
      
         | 2423 |  |  |       Alt    : Node_Id;
 | 
      
         | 2424 |  |  |       Len    : Nat;
 | 
      
         | 2425 |  |  |       Cond   : Node_Id;
 | 
      
         | 2426 |  |  |       Choice : Node_Id;
 | 
      
         | 2427 |  |  |       Chlist : List_Id;
 | 
      
         | 2428 |  |  |  
 | 
      
         | 2429 |  |  |    begin
 | 
      
         | 2430 |  |  |       --  Check for the situation where we know at compile time which branch
 | 
      
         | 2431 |  |  |       --  will be taken
 | 
      
         | 2432 |  |  |  
 | 
      
         | 2433 |  |  |       if Compile_Time_Known_Value (Expr) then
 | 
      
         | 2434 |  |  |          Alt := Find_Static_Alternative (N);
 | 
      
         | 2435 |  |  |  
 | 
      
         | 2436 |  |  |          Process_Statements_For_Controlled_Objects (Alt);
 | 
      
         | 2437 |  |  |  
 | 
      
         | 2438 |  |  |          --  Move statements from this alternative after the case statement.
 | 
      
         | 2439 |  |  |          --  They are already analyzed, so will be skipped by the analyzer.
 | 
      
         | 2440 |  |  |  
 | 
      
         | 2441 |  |  |          Insert_List_After (N, Statements (Alt));
 | 
      
         | 2442 |  |  |  
 | 
      
         | 2443 |  |  |          --  That leaves the case statement as a shell. So now we can kill all
 | 
      
         | 2444 |  |  |          --  other alternatives in the case statement.
 | 
      
         | 2445 |  |  |  
 | 
      
         | 2446 |  |  |          Kill_Dead_Code (Expression (N));
 | 
      
         | 2447 |  |  |  
 | 
      
         | 2448 |  |  |          declare
 | 
      
         | 2449 |  |  |             Dead_Alt : Node_Id;
 | 
      
         | 2450 |  |  |  
 | 
      
         | 2451 |  |  |          begin
 | 
      
         | 2452 |  |  |             --  Loop through case alternatives, skipping pragmas, and skipping
 | 
      
         | 2453 |  |  |             --  the one alternative that we select (and therefore retain).
 | 
      
         | 2454 |  |  |  
 | 
      
         | 2455 |  |  |             Dead_Alt := First (Alternatives (N));
 | 
      
         | 2456 |  |  |             while Present (Dead_Alt) loop
 | 
      
         | 2457 |  |  |                if Dead_Alt /= Alt
 | 
      
         | 2458 |  |  |                  and then Nkind (Dead_Alt) = N_Case_Statement_Alternative
 | 
      
         | 2459 |  |  |                then
 | 
      
         | 2460 |  |  |                   Kill_Dead_Code (Statements (Dead_Alt), Warn_On_Deleted_Code);
 | 
      
         | 2461 |  |  |                end if;
 | 
      
         | 2462 |  |  |  
 | 
      
         | 2463 |  |  |                Next (Dead_Alt);
 | 
      
         | 2464 |  |  |             end loop;
 | 
      
         | 2465 |  |  |          end;
 | 
      
         | 2466 |  |  |  
 | 
      
         | 2467 |  |  |          Rewrite (N, Make_Null_Statement (Loc));
 | 
      
         | 2468 |  |  |          return;
 | 
      
         | 2469 |  |  |       end if;
 | 
      
         | 2470 |  |  |  
 | 
      
         | 2471 |  |  |       --  Here if the choice is not determined at compile time
 | 
      
         | 2472 |  |  |  
 | 
      
         | 2473 |  |  |       declare
 | 
      
         | 2474 |  |  |          Last_Alt : constant Node_Id := Last (Alternatives (N));
 | 
      
         | 2475 |  |  |  
 | 
      
         | 2476 |  |  |          Others_Present : Boolean;
 | 
      
         | 2477 |  |  |          Others_Node    : Node_Id;
 | 
      
         | 2478 |  |  |  
 | 
      
         | 2479 |  |  |          Then_Stms : List_Id;
 | 
      
         | 2480 |  |  |          Else_Stms : List_Id;
 | 
      
         | 2481 |  |  |  
 | 
      
         | 2482 |  |  |       begin
 | 
      
         | 2483 |  |  |          if Nkind (First (Discrete_Choices (Last_Alt))) = N_Others_Choice then
 | 
      
         | 2484 |  |  |             Others_Present := True;
 | 
      
         | 2485 |  |  |             Others_Node    := Last_Alt;
 | 
      
         | 2486 |  |  |          else
 | 
      
         | 2487 |  |  |             Others_Present := False;
 | 
      
         | 2488 |  |  |          end if;
 | 
      
         | 2489 |  |  |  
 | 
      
         | 2490 |  |  |          --  First step is to worry about possible invalid argument. The RM
 | 
      
         | 2491 |  |  |          --  requires (RM 5.4(13)) that if the result is invalid (e.g. it is
 | 
      
         | 2492 |  |  |          --  outside the base range), then Constraint_Error must be raised.
 | 
      
         | 2493 |  |  |  
 | 
      
         | 2494 |  |  |          --  Case of validity check required (validity checks are on, the
 | 
      
         | 2495 |  |  |          --  expression is not known to be valid, and the case statement
 | 
      
         | 2496 |  |  |          --  comes from source -- no need to validity check internally
 | 
      
         | 2497 |  |  |          --  generated case statements).
 | 
      
         | 2498 |  |  |  
 | 
      
         | 2499 |  |  |          if Validity_Check_Default then
 | 
      
         | 2500 |  |  |             Ensure_Valid (Expr);
 | 
      
         | 2501 |  |  |          end if;
 | 
      
         | 2502 |  |  |  
 | 
      
         | 2503 |  |  |          --  If there is only a single alternative, just replace it with the
 | 
      
         | 2504 |  |  |          --  sequence of statements since obviously that is what is going to
 | 
      
         | 2505 |  |  |          --  be executed in all cases.
 | 
      
         | 2506 |  |  |  
 | 
      
         | 2507 |  |  |          Len := List_Length (Alternatives (N));
 | 
      
         | 2508 |  |  |  
 | 
      
         | 2509 |  |  |          if Len = 1 then
 | 
      
         | 2510 |  |  |  
 | 
      
         | 2511 |  |  |             --  We still need to evaluate the expression if it has any side
 | 
      
         | 2512 |  |  |             --  effects.
 | 
      
         | 2513 |  |  |  
 | 
      
         | 2514 |  |  |             Remove_Side_Effects (Expression (N));
 | 
      
         | 2515 |  |  |  
 | 
      
         | 2516 |  |  |             Alt := First (Alternatives (N));
 | 
      
         | 2517 |  |  |  
 | 
      
         | 2518 |  |  |             Process_Statements_For_Controlled_Objects (Alt);
 | 
      
         | 2519 |  |  |             Insert_List_After (N, Statements (Alt));
 | 
      
         | 2520 |  |  |  
 | 
      
         | 2521 |  |  |             --  That leaves the case statement as a shell. The alternative that
 | 
      
         | 2522 |  |  |             --  will be executed is reset to a null list. So now we can kill
 | 
      
         | 2523 |  |  |             --  the entire case statement.
 | 
      
         | 2524 |  |  |  
 | 
      
         | 2525 |  |  |             Kill_Dead_Code (Expression (N));
 | 
      
         | 2526 |  |  |             Rewrite (N, Make_Null_Statement (Loc));
 | 
      
         | 2527 |  |  |             return;
 | 
      
         | 2528 |  |  |  
 | 
      
         | 2529 |  |  |          --  An optimization. If there are only two alternatives, and only
 | 
      
         | 2530 |  |  |          --  a single choice, then rewrite the whole case statement as an
 | 
      
         | 2531 |  |  |          --  if statement, since this can result in subsequent optimizations.
 | 
      
         | 2532 |  |  |          --  This helps not only with case statements in the source of a
 | 
      
         | 2533 |  |  |          --  simple form, but also with generated code (discriminant check
 | 
      
         | 2534 |  |  |          --  functions in particular)
 | 
      
         | 2535 |  |  |  
 | 
      
         | 2536 |  |  |          elsif Len = 2 then
 | 
      
         | 2537 |  |  |             Chlist := Discrete_Choices (First (Alternatives (N)));
 | 
      
         | 2538 |  |  |  
 | 
      
         | 2539 |  |  |             if List_Length (Chlist) = 1 then
 | 
      
         | 2540 |  |  |                Choice := First (Chlist);
 | 
      
         | 2541 |  |  |  
 | 
      
         | 2542 |  |  |                Then_Stms := Statements (First (Alternatives (N)));
 | 
      
         | 2543 |  |  |                Else_Stms := Statements (Last  (Alternatives (N)));
 | 
      
         | 2544 |  |  |  
 | 
      
         | 2545 |  |  |                --  For TRUE, generate "expression", not expression = true
 | 
      
         | 2546 |  |  |  
 | 
      
         | 2547 |  |  |                if Nkind (Choice) = N_Identifier
 | 
      
         | 2548 |  |  |                  and then Entity (Choice) = Standard_True
 | 
      
         | 2549 |  |  |                then
 | 
      
         | 2550 |  |  |                   Cond := Expression (N);
 | 
      
         | 2551 |  |  |  
 | 
      
         | 2552 |  |  |                --  For FALSE, generate "expression" and switch then/else
 | 
      
         | 2553 |  |  |  
 | 
      
         | 2554 |  |  |                elsif Nkind (Choice) = N_Identifier
 | 
      
         | 2555 |  |  |                  and then Entity (Choice) = Standard_False
 | 
      
         | 2556 |  |  |                then
 | 
      
         | 2557 |  |  |                   Cond := Expression (N);
 | 
      
         | 2558 |  |  |                   Else_Stms := Statements (First (Alternatives (N)));
 | 
      
         | 2559 |  |  |                   Then_Stms := Statements (Last  (Alternatives (N)));
 | 
      
         | 2560 |  |  |  
 | 
      
         | 2561 |  |  |                --  For a range, generate "expression in range"
 | 
      
         | 2562 |  |  |  
 | 
      
         | 2563 |  |  |                elsif Nkind (Choice) = N_Range
 | 
      
         | 2564 |  |  |                  or else (Nkind (Choice) = N_Attribute_Reference
 | 
      
         | 2565 |  |  |                            and then Attribute_Name (Choice) = Name_Range)
 | 
      
         | 2566 |  |  |                  or else (Is_Entity_Name (Choice)
 | 
      
         | 2567 |  |  |                            and then Is_Type (Entity (Choice)))
 | 
      
         | 2568 |  |  |                  or else Nkind (Choice) = N_Subtype_Indication
 | 
      
         | 2569 |  |  |                then
 | 
      
         | 2570 |  |  |                   Cond :=
 | 
      
         | 2571 |  |  |                     Make_In (Loc,
 | 
      
         | 2572 |  |  |                       Left_Opnd  => Expression (N),
 | 
      
         | 2573 |  |  |                       Right_Opnd => Relocate_Node (Choice));
 | 
      
         | 2574 |  |  |  
 | 
      
         | 2575 |  |  |                --  For any other subexpression "expression = value"
 | 
      
         | 2576 |  |  |  
 | 
      
         | 2577 |  |  |                else
 | 
      
         | 2578 |  |  |                   Cond :=
 | 
      
         | 2579 |  |  |                     Make_Op_Eq (Loc,
 | 
      
         | 2580 |  |  |                       Left_Opnd  => Expression (N),
 | 
      
         | 2581 |  |  |                       Right_Opnd => Relocate_Node (Choice));
 | 
      
         | 2582 |  |  |                end if;
 | 
      
         | 2583 |  |  |  
 | 
      
         | 2584 |  |  |                --  Now rewrite the case as an IF
 | 
      
         | 2585 |  |  |  
 | 
      
         | 2586 |  |  |                Rewrite (N,
 | 
      
         | 2587 |  |  |                  Make_If_Statement (Loc,
 | 
      
         | 2588 |  |  |                    Condition => Cond,
 | 
      
         | 2589 |  |  |                    Then_Statements => Then_Stms,
 | 
      
         | 2590 |  |  |                    Else_Statements => Else_Stms));
 | 
      
         | 2591 |  |  |                Analyze (N);
 | 
      
         | 2592 |  |  |                return;
 | 
      
         | 2593 |  |  |             end if;
 | 
      
         | 2594 |  |  |          end if;
 | 
      
         | 2595 |  |  |  
 | 
      
         | 2596 |  |  |          --  If the last alternative is not an Others choice, replace it with
 | 
      
         | 2597 |  |  |          --  an N_Others_Choice. Note that we do not bother to call Analyze on
 | 
      
         | 2598 |  |  |          --  the modified case statement, since it's only effect would be to
 | 
      
         | 2599 |  |  |          --  compute the contents of the Others_Discrete_Choices which is not
 | 
      
         | 2600 |  |  |          --  needed by the back end anyway.
 | 
      
         | 2601 |  |  |  
 | 
      
         | 2602 |  |  |          --  The reason we do this is that the back end always needs some
 | 
      
         | 2603 |  |  |          --  default for a switch, so if we have not supplied one in the
 | 
      
         | 2604 |  |  |          --  processing above for validity checking, then we need to supply
 | 
      
         | 2605 |  |  |          --  one here.
 | 
      
         | 2606 |  |  |  
 | 
      
         | 2607 |  |  |          if not Others_Present then
 | 
      
         | 2608 |  |  |             Others_Node := Make_Others_Choice (Sloc (Last_Alt));
 | 
      
         | 2609 |  |  |             Set_Others_Discrete_Choices
 | 
      
         | 2610 |  |  |               (Others_Node, Discrete_Choices (Last_Alt));
 | 
      
         | 2611 |  |  |             Set_Discrete_Choices (Last_Alt, New_List (Others_Node));
 | 
      
         | 2612 |  |  |          end if;
 | 
      
         | 2613 |  |  |  
 | 
      
         | 2614 |  |  |          Alt := First (Alternatives (N));
 | 
      
         | 2615 |  |  |          while Present (Alt)
 | 
      
         | 2616 |  |  |            and then Nkind (Alt) = N_Case_Statement_Alternative
 | 
      
         | 2617 |  |  |          loop
 | 
      
         | 2618 |  |  |             Process_Statements_For_Controlled_Objects (Alt);
 | 
      
         | 2619 |  |  |             Next (Alt);
 | 
      
         | 2620 |  |  |          end loop;
 | 
      
         | 2621 |  |  |       end;
 | 
      
         | 2622 |  |  |    end Expand_N_Case_Statement;
 | 
      
         | 2623 |  |  |  
 | 
      
         | 2624 |  |  |    -----------------------------
 | 
      
         | 2625 |  |  |    -- Expand_N_Exit_Statement --
 | 
      
         | 2626 |  |  |    -----------------------------
 | 
      
         | 2627 |  |  |  
 | 
      
         | 2628 |  |  |    --  The only processing required is to deal with a possible C/Fortran
 | 
      
         | 2629 |  |  |    --  boolean value used as the condition for the exit statement.
 | 
      
         | 2630 |  |  |  
 | 
      
         | 2631 |  |  |    procedure Expand_N_Exit_Statement (N : Node_Id) is
 | 
      
         | 2632 |  |  |    begin
 | 
      
         | 2633 |  |  |       Adjust_Condition (Condition (N));
 | 
      
         | 2634 |  |  |    end Expand_N_Exit_Statement;
 | 
      
         | 2635 |  |  |  
 | 
      
         | 2636 |  |  |    -----------------------------
 | 
      
         | 2637 |  |  |    -- Expand_N_Goto_Statement --
 | 
      
         | 2638 |  |  |    -----------------------------
 | 
      
         | 2639 |  |  |  
 | 
      
         | 2640 |  |  |    --  Add poll before goto if polling active
 | 
      
         | 2641 |  |  |  
 | 
      
         | 2642 |  |  |    procedure Expand_N_Goto_Statement (N : Node_Id) is
 | 
      
         | 2643 |  |  |    begin
 | 
      
         | 2644 |  |  |       Generate_Poll_Call (N);
 | 
      
         | 2645 |  |  |    end Expand_N_Goto_Statement;
 | 
      
         | 2646 |  |  |  
 | 
      
         | 2647 |  |  |    ---------------------------
 | 
      
         | 2648 |  |  |    -- Expand_N_If_Statement --
 | 
      
         | 2649 |  |  |    ---------------------------
 | 
      
         | 2650 |  |  |  
 | 
      
         | 2651 |  |  |    --  First we deal with the case of C and Fortran convention boolean values,
 | 
      
         | 2652 |  |  |    --  with zero/non-zero semantics.
 | 
      
         | 2653 |  |  |  
 | 
      
         | 2654 |  |  |    --  Second, we deal with the obvious rewriting for the cases where the
 | 
      
         | 2655 |  |  |    --  condition of the IF is known at compile time to be True or False.
 | 
      
         | 2656 |  |  |  
 | 
      
         | 2657 |  |  |    --  Third, we remove elsif parts which have non-empty Condition_Actions and
 | 
      
         | 2658 |  |  |    --  rewrite as independent if statements. For example:
 | 
      
         | 2659 |  |  |  
 | 
      
         | 2660 |  |  |    --     if x then xs
 | 
      
         | 2661 |  |  |    --     elsif y then ys
 | 
      
         | 2662 |  |  |    --     ...
 | 
      
         | 2663 |  |  |    --     end if;
 | 
      
         | 2664 |  |  |  
 | 
      
         | 2665 |  |  |    --  becomes
 | 
      
         | 2666 |  |  |    --
 | 
      
         | 2667 |  |  |    --     if x then xs
 | 
      
         | 2668 |  |  |    --     else
 | 
      
         | 2669 |  |  |    --        <<condition actions of y>>
 | 
      
         | 2670 |  |  |    --        if y then ys
 | 
      
         | 2671 |  |  |    --        ...
 | 
      
         | 2672 |  |  |    --        end if;
 | 
      
         | 2673 |  |  |    --     end if;
 | 
      
         | 2674 |  |  |  
 | 
      
         | 2675 |  |  |    --  This rewriting is needed if at least one elsif part has a non-empty
 | 
      
         | 2676 |  |  |    --  Condition_Actions list. We also do the same processing if there is a
 | 
      
         | 2677 |  |  |    --  constant condition in an elsif part (in conjunction with the first
 | 
      
         | 2678 |  |  |    --  processing step mentioned above, for the recursive call made to deal
 | 
      
         | 2679 |  |  |    --  with the created inner if, this deals with properly optimizing the
 | 
      
         | 2680 |  |  |    --  cases of constant elsif conditions).
 | 
      
         | 2681 |  |  |  
 | 
      
         | 2682 |  |  |    procedure Expand_N_If_Statement (N : Node_Id) is
 | 
      
         | 2683 |  |  |       Loc    : constant Source_Ptr := Sloc (N);
 | 
      
         | 2684 |  |  |       Hed    : Node_Id;
 | 
      
         | 2685 |  |  |       E      : Node_Id;
 | 
      
         | 2686 |  |  |       New_If : Node_Id;
 | 
      
         | 2687 |  |  |  
 | 
      
         | 2688 |  |  |       Warn_If_Deleted : constant Boolean :=
 | 
      
         | 2689 |  |  |                           Warn_On_Deleted_Code and then Comes_From_Source (N);
 | 
      
         | 2690 |  |  |       --  Indicates whether we want warnings when we delete branches of the
 | 
      
         | 2691 |  |  |       --  if statement based on constant condition analysis. We never want
 | 
      
         | 2692 |  |  |       --  these warnings for expander generated code.
 | 
      
         | 2693 |  |  |  
 | 
      
         | 2694 |  |  |    begin
 | 
      
         | 2695 |  |  |       Process_Statements_For_Controlled_Objects (N);
 | 
      
         | 2696 |  |  |  
 | 
      
         | 2697 |  |  |       Adjust_Condition (Condition (N));
 | 
      
         | 2698 |  |  |  
 | 
      
         | 2699 |  |  |       --  The following loop deals with constant conditions for the IF. We
 | 
      
         | 2700 |  |  |       --  need a loop because as we eliminate False conditions, we grab the
 | 
      
         | 2701 |  |  |       --  first elsif condition and use it as the primary condition.
 | 
      
         | 2702 |  |  |  
 | 
      
         | 2703 |  |  |       while Compile_Time_Known_Value (Condition (N)) loop
 | 
      
         | 2704 |  |  |  
 | 
      
         | 2705 |  |  |          --  If condition is True, we can simply rewrite the if statement now
 | 
      
         | 2706 |  |  |          --  by replacing it by the series of then statements.
 | 
      
         | 2707 |  |  |  
 | 
      
         | 2708 |  |  |          if Is_True (Expr_Value (Condition (N))) then
 | 
      
         | 2709 |  |  |  
 | 
      
         | 2710 |  |  |             --  All the else parts can be killed
 | 
      
         | 2711 |  |  |  
 | 
      
         | 2712 |  |  |             Kill_Dead_Code (Elsif_Parts (N), Warn_If_Deleted);
 | 
      
         | 2713 |  |  |             Kill_Dead_Code (Else_Statements (N), Warn_If_Deleted);
 | 
      
         | 2714 |  |  |  
 | 
      
         | 2715 |  |  |             Hed := Remove_Head (Then_Statements (N));
 | 
      
         | 2716 |  |  |             Insert_List_After (N, Then_Statements (N));
 | 
      
         | 2717 |  |  |             Rewrite (N, Hed);
 | 
      
         | 2718 |  |  |             return;
 | 
      
         | 2719 |  |  |  
 | 
      
         | 2720 |  |  |          --  If condition is False, then we can delete the condition and
 | 
      
         | 2721 |  |  |          --  the Then statements
 | 
      
         | 2722 |  |  |  
 | 
      
         | 2723 |  |  |          else
 | 
      
         | 2724 |  |  |             --  We do not delete the condition if constant condition warnings
 | 
      
         | 2725 |  |  |             --  are enabled, since otherwise we end up deleting the desired
 | 
      
         | 2726 |  |  |             --  warning. Of course the backend will get rid of this True/False
 | 
      
         | 2727 |  |  |             --  test anyway, so nothing is lost here.
 | 
      
         | 2728 |  |  |  
 | 
      
         | 2729 |  |  |             if not Constant_Condition_Warnings then
 | 
      
         | 2730 |  |  |                Kill_Dead_Code (Condition (N));
 | 
      
         | 2731 |  |  |             end if;
 | 
      
         | 2732 |  |  |  
 | 
      
         | 2733 |  |  |             Kill_Dead_Code (Then_Statements (N), Warn_If_Deleted);
 | 
      
         | 2734 |  |  |  
 | 
      
         | 2735 |  |  |             --  If there are no elsif statements, then we simply replace the
 | 
      
         | 2736 |  |  |             --  entire if statement by the sequence of else statements.
 | 
      
         | 2737 |  |  |  
 | 
      
         | 2738 |  |  |             if No (Elsif_Parts (N)) then
 | 
      
         | 2739 |  |  |                if No (Else_Statements (N))
 | 
      
         | 2740 |  |  |                  or else Is_Empty_List (Else_Statements (N))
 | 
      
         | 2741 |  |  |                then
 | 
      
         | 2742 |  |  |                   Rewrite (N,
 | 
      
         | 2743 |  |  |                     Make_Null_Statement (Sloc (N)));
 | 
      
         | 2744 |  |  |                else
 | 
      
         | 2745 |  |  |                   Hed := Remove_Head (Else_Statements (N));
 | 
      
         | 2746 |  |  |                   Insert_List_After (N, Else_Statements (N));
 | 
      
         | 2747 |  |  |                   Rewrite (N, Hed);
 | 
      
         | 2748 |  |  |                end if;
 | 
      
         | 2749 |  |  |  
 | 
      
         | 2750 |  |  |                return;
 | 
      
         | 2751 |  |  |  
 | 
      
         | 2752 |  |  |             --  If there are elsif statements, the first of them becomes the
 | 
      
         | 2753 |  |  |             --  if/then section of the rebuilt if statement This is the case
 | 
      
         | 2754 |  |  |             --  where we loop to reprocess this copied condition.
 | 
      
         | 2755 |  |  |  
 | 
      
         | 2756 |  |  |             else
 | 
      
         | 2757 |  |  |                Hed := Remove_Head (Elsif_Parts (N));
 | 
      
         | 2758 |  |  |                Insert_Actions      (N, Condition_Actions (Hed));
 | 
      
         | 2759 |  |  |                Set_Condition       (N, Condition (Hed));
 | 
      
         | 2760 |  |  |                Set_Then_Statements (N, Then_Statements (Hed));
 | 
      
         | 2761 |  |  |  
 | 
      
         | 2762 |  |  |                --  Hed might have been captured as the condition determining
 | 
      
         | 2763 |  |  |                --  the current value for an entity. Now it is detached from
 | 
      
         | 2764 |  |  |                --  the tree, so a Current_Value pointer in the condition might
 | 
      
         | 2765 |  |  |                --  need to be updated.
 | 
      
         | 2766 |  |  |  
 | 
      
         | 2767 |  |  |                Set_Current_Value_Condition (N);
 | 
      
         | 2768 |  |  |  
 | 
      
         | 2769 |  |  |                if Is_Empty_List (Elsif_Parts (N)) then
 | 
      
         | 2770 |  |  |                   Set_Elsif_Parts (N, No_List);
 | 
      
         | 2771 |  |  |                end if;
 | 
      
         | 2772 |  |  |             end if;
 | 
      
         | 2773 |  |  |          end if;
 | 
      
         | 2774 |  |  |       end loop;
 | 
      
         | 2775 |  |  |  
 | 
      
         | 2776 |  |  |       --  Loop through elsif parts, dealing with constant conditions and
 | 
      
         | 2777 |  |  |       --  possible expression actions that are present.
 | 
      
         | 2778 |  |  |  
 | 
      
         | 2779 |  |  |       if Present (Elsif_Parts (N)) then
 | 
      
         | 2780 |  |  |          E := First (Elsif_Parts (N));
 | 
      
         | 2781 |  |  |          while Present (E) loop
 | 
      
         | 2782 |  |  |             Process_Statements_For_Controlled_Objects (E);
 | 
      
         | 2783 |  |  |  
 | 
      
         | 2784 |  |  |             Adjust_Condition (Condition (E));
 | 
      
         | 2785 |  |  |  
 | 
      
         | 2786 |  |  |             --  If there are condition actions, then rewrite the if statement
 | 
      
         | 2787 |  |  |             --  as indicated above. We also do the same rewrite for a True or
 | 
      
         | 2788 |  |  |             --  False condition. The further processing of this constant
 | 
      
         | 2789 |  |  |             --  condition is then done by the recursive call to expand the
 | 
      
         | 2790 |  |  |             --  newly created if statement
 | 
      
         | 2791 |  |  |  
 | 
      
         | 2792 |  |  |             if Present (Condition_Actions (E))
 | 
      
         | 2793 |  |  |               or else Compile_Time_Known_Value (Condition (E))
 | 
      
         | 2794 |  |  |             then
 | 
      
         | 2795 |  |  |                --  Note this is not an implicit if statement, since it is part
 | 
      
         | 2796 |  |  |                --  of an explicit if statement in the source (or of an implicit
 | 
      
         | 2797 |  |  |                --  if statement that has already been tested).
 | 
      
         | 2798 |  |  |  
 | 
      
         | 2799 |  |  |                New_If :=
 | 
      
         | 2800 |  |  |                  Make_If_Statement (Sloc (E),
 | 
      
         | 2801 |  |  |                    Condition       => Condition (E),
 | 
      
         | 2802 |  |  |                    Then_Statements => Then_Statements (E),
 | 
      
         | 2803 |  |  |                    Elsif_Parts     => No_List,
 | 
      
         | 2804 |  |  |                    Else_Statements => Else_Statements (N));
 | 
      
         | 2805 |  |  |  
 | 
      
         | 2806 |  |  |                --  Elsif parts for new if come from remaining elsif's of parent
 | 
      
         | 2807 |  |  |  
 | 
      
         | 2808 |  |  |                while Present (Next (E)) loop
 | 
      
         | 2809 |  |  |                   if No (Elsif_Parts (New_If)) then
 | 
      
         | 2810 |  |  |                      Set_Elsif_Parts (New_If, New_List);
 | 
      
         | 2811 |  |  |                   end if;
 | 
      
         | 2812 |  |  |  
 | 
      
         | 2813 |  |  |                   Append (Remove_Next (E), Elsif_Parts (New_If));
 | 
      
         | 2814 |  |  |                end loop;
 | 
      
         | 2815 |  |  |  
 | 
      
         | 2816 |  |  |                Set_Else_Statements (N, New_List (New_If));
 | 
      
         | 2817 |  |  |  
 | 
      
         | 2818 |  |  |                if Present (Condition_Actions (E)) then
 | 
      
         | 2819 |  |  |                   Insert_List_Before (New_If, Condition_Actions (E));
 | 
      
         | 2820 |  |  |                end if;
 | 
      
         | 2821 |  |  |  
 | 
      
         | 2822 |  |  |                Remove (E);
 | 
      
         | 2823 |  |  |  
 | 
      
         | 2824 |  |  |                if Is_Empty_List (Elsif_Parts (N)) then
 | 
      
         | 2825 |  |  |                   Set_Elsif_Parts (N, No_List);
 | 
      
         | 2826 |  |  |                end if;
 | 
      
         | 2827 |  |  |  
 | 
      
         | 2828 |  |  |                Analyze (New_If);
 | 
      
         | 2829 |  |  |                return;
 | 
      
         | 2830 |  |  |  
 | 
      
         | 2831 |  |  |             --  No special processing for that elsif part, move to next
 | 
      
         | 2832 |  |  |  
 | 
      
         | 2833 |  |  |             else
 | 
      
         | 2834 |  |  |                Next (E);
 | 
      
         | 2835 |  |  |             end if;
 | 
      
         | 2836 |  |  |          end loop;
 | 
      
         | 2837 |  |  |       end if;
 | 
      
         | 2838 |  |  |  
 | 
      
         | 2839 |  |  |       --  Some more optimizations applicable if we still have an IF statement
 | 
      
         | 2840 |  |  |  
 | 
      
         | 2841 |  |  |       if Nkind (N) /= N_If_Statement then
 | 
      
         | 2842 |  |  |          return;
 | 
      
         | 2843 |  |  |       end if;
 | 
      
         | 2844 |  |  |  
 | 
      
         | 2845 |  |  |       --  Another optimization, special cases that can be simplified
 | 
      
         | 2846 |  |  |  
 | 
      
         | 2847 |  |  |       --     if expression then
 | 
      
         | 2848 |  |  |       --        return true;
 | 
      
         | 2849 |  |  |       --     else
 | 
      
         | 2850 |  |  |       --        return false;
 | 
      
         | 2851 |  |  |       --     end if;
 | 
      
         | 2852 |  |  |  
 | 
      
         | 2853 |  |  |       --  can be changed to:
 | 
      
         | 2854 |  |  |  
 | 
      
         | 2855 |  |  |       --     return expression;
 | 
      
         | 2856 |  |  |  
 | 
      
         | 2857 |  |  |       --  and
 | 
      
         | 2858 |  |  |  
 | 
      
         | 2859 |  |  |       --     if expression then
 | 
      
         | 2860 |  |  |       --        return false;
 | 
      
         | 2861 |  |  |       --     else
 | 
      
         | 2862 |  |  |       --        return true;
 | 
      
         | 2863 |  |  |       --     end if;
 | 
      
         | 2864 |  |  |  
 | 
      
         | 2865 |  |  |       --  can be changed to:
 | 
      
         | 2866 |  |  |  
 | 
      
         | 2867 |  |  |       --     return not (expression);
 | 
      
         | 2868 |  |  |  
 | 
      
         | 2869 |  |  |       --  Only do these optimizations if we are at least at -O1 level and
 | 
      
         | 2870 |  |  |       --  do not do them if control flow optimizations are suppressed.
 | 
      
         | 2871 |  |  |  
 | 
      
         | 2872 |  |  |       if Optimization_Level > 0
 | 
      
         | 2873 |  |  |         and then not Opt.Suppress_Control_Flow_Optimizations
 | 
      
         | 2874 |  |  |       then
 | 
      
         | 2875 |  |  |          if Nkind (N) = N_If_Statement
 | 
      
         | 2876 |  |  |            and then No (Elsif_Parts (N))
 | 
      
         | 2877 |  |  |            and then Present (Else_Statements (N))
 | 
      
         | 2878 |  |  |            and then List_Length (Then_Statements (N)) = 1
 | 
      
         | 2879 |  |  |            and then List_Length (Else_Statements (N)) = 1
 | 
      
         | 2880 |  |  |          then
 | 
      
         | 2881 |  |  |             declare
 | 
      
         | 2882 |  |  |                Then_Stm : constant Node_Id := First (Then_Statements (N));
 | 
      
         | 2883 |  |  |                Else_Stm : constant Node_Id := First (Else_Statements (N));
 | 
      
         | 2884 |  |  |  
 | 
      
         | 2885 |  |  |             begin
 | 
      
         | 2886 |  |  |                if Nkind (Then_Stm) = N_Simple_Return_Statement
 | 
      
         | 2887 |  |  |                     and then
 | 
      
         | 2888 |  |  |                   Nkind (Else_Stm) = N_Simple_Return_Statement
 | 
      
         | 2889 |  |  |                then
 | 
      
         | 2890 |  |  |                   declare
 | 
      
         | 2891 |  |  |                      Then_Expr : constant Node_Id := Expression (Then_Stm);
 | 
      
         | 2892 |  |  |                      Else_Expr : constant Node_Id := Expression (Else_Stm);
 | 
      
         | 2893 |  |  |  
 | 
      
         | 2894 |  |  |                   begin
 | 
      
         | 2895 |  |  |                      if Nkind (Then_Expr) = N_Identifier
 | 
      
         | 2896 |  |  |                           and then
 | 
      
         | 2897 |  |  |                         Nkind (Else_Expr) = N_Identifier
 | 
      
         | 2898 |  |  |                      then
 | 
      
         | 2899 |  |  |                         if Entity (Then_Expr) = Standard_True
 | 
      
         | 2900 |  |  |                           and then Entity (Else_Expr) = Standard_False
 | 
      
         | 2901 |  |  |                         then
 | 
      
         | 2902 |  |  |                            Rewrite (N,
 | 
      
         | 2903 |  |  |                              Make_Simple_Return_Statement (Loc,
 | 
      
         | 2904 |  |  |                                Expression => Relocate_Node (Condition (N))));
 | 
      
         | 2905 |  |  |                            Analyze (N);
 | 
      
         | 2906 |  |  |                            return;
 | 
      
         | 2907 |  |  |  
 | 
      
         | 2908 |  |  |                         elsif Entity (Then_Expr) = Standard_False
 | 
      
         | 2909 |  |  |                           and then Entity (Else_Expr) = Standard_True
 | 
      
         | 2910 |  |  |                         then
 | 
      
         | 2911 |  |  |                            Rewrite (N,
 | 
      
         | 2912 |  |  |                              Make_Simple_Return_Statement (Loc,
 | 
      
         | 2913 |  |  |                                Expression =>
 | 
      
         | 2914 |  |  |                                  Make_Op_Not (Loc,
 | 
      
         | 2915 |  |  |                                    Right_Opnd =>
 | 
      
         | 2916 |  |  |                                      Relocate_Node (Condition (N)))));
 | 
      
         | 2917 |  |  |                            Analyze (N);
 | 
      
         | 2918 |  |  |                            return;
 | 
      
         | 2919 |  |  |                         end if;
 | 
      
         | 2920 |  |  |                      end if;
 | 
      
         | 2921 |  |  |                   end;
 | 
      
         | 2922 |  |  |                end if;
 | 
      
         | 2923 |  |  |             end;
 | 
      
         | 2924 |  |  |          end if;
 | 
      
         | 2925 |  |  |       end if;
 | 
      
         | 2926 |  |  |    end Expand_N_If_Statement;
 | 
      
         | 2927 |  |  |  
 | 
      
         | 2928 |  |  |    --------------------------
 | 
      
         | 2929 |  |  |    -- Expand_Iterator_Loop --
 | 
      
         | 2930 |  |  |    --------------------------
 | 
      
         | 2931 |  |  |  
 | 
      
         | 2932 |  |  |    procedure Expand_Iterator_Loop (N : Node_Id) is
 | 
      
         | 2933 |  |  |       Isc    : constant Node_Id    := Iteration_Scheme (N);
 | 
      
         | 2934 |  |  |       I_Spec : constant Node_Id    := Iterator_Specification (Isc);
 | 
      
         | 2935 |  |  |       Id     : constant Entity_Id  := Defining_Identifier (I_Spec);
 | 
      
         | 2936 |  |  |       Loc    : constant Source_Ptr := Sloc (N);
 | 
      
         | 2937 |  |  |  
 | 
      
         | 2938 |  |  |       Container     : constant Node_Id   := Name (I_Spec);
 | 
      
         | 2939 |  |  |       Container_Typ : constant Entity_Id := Base_Type (Etype (Container));
 | 
      
         | 2940 |  |  |       Cursor        : Entity_Id;
 | 
      
         | 2941 |  |  |       Iterator      : Entity_Id;
 | 
      
         | 2942 |  |  |       New_Loop      : Node_Id;
 | 
      
         | 2943 |  |  |       Stats         : List_Id := Statements (N);
 | 
      
         | 2944 |  |  |  
 | 
      
         | 2945 |  |  |    begin
 | 
      
         | 2946 |  |  |       --  Processing for arrays
 | 
      
         | 2947 |  |  |  
 | 
      
         | 2948 |  |  |       if Is_Array_Type (Container_Typ) then
 | 
      
         | 2949 |  |  |  
 | 
      
         | 2950 |  |  |          --  for Element of Array loop
 | 
      
         | 2951 |  |  |          --
 | 
      
         | 2952 |  |  |          --  This case requires an internally generated cursor to iterate over
 | 
      
         | 2953 |  |  |          --  the array.
 | 
      
         | 2954 |  |  |  
 | 
      
         | 2955 |  |  |          if Of_Present (I_Spec) then
 | 
      
         | 2956 |  |  |             Iterator := Make_Temporary (Loc, 'C');
 | 
      
         | 2957 |  |  |  
 | 
      
         | 2958 |  |  |             --  Generate:
 | 
      
         | 2959 |  |  |             --    Element : Component_Type renames Container (Iterator);
 | 
      
         | 2960 |  |  |  
 | 
      
         | 2961 |  |  |             Prepend_To (Stats,
 | 
      
         | 2962 |  |  |               Make_Object_Renaming_Declaration (Loc,
 | 
      
         | 2963 |  |  |                 Defining_Identifier => Id,
 | 
      
         | 2964 |  |  |                 Subtype_Mark =>
 | 
      
         | 2965 |  |  |                   New_Reference_To (Component_Type (Container_Typ), Loc),
 | 
      
         | 2966 |  |  |                 Name =>
 | 
      
         | 2967 |  |  |                   Make_Indexed_Component (Loc,
 | 
      
         | 2968 |  |  |                     Prefix => Relocate_Node (Container),
 | 
      
         | 2969 |  |  |                     Expressions => New_List (
 | 
      
         | 2970 |  |  |                       New_Reference_To (Iterator, Loc)))));
 | 
      
         | 2971 |  |  |  
 | 
      
         | 2972 |  |  |          --  for Index in Array loop
 | 
      
         | 2973 |  |  |  
 | 
      
         | 2974 |  |  |          --  This case utilizes the already given iterator name
 | 
      
         | 2975 |  |  |  
 | 
      
         | 2976 |  |  |          else
 | 
      
         | 2977 |  |  |             Iterator := Id;
 | 
      
         | 2978 |  |  |          end if;
 | 
      
         | 2979 |  |  |  
 | 
      
         | 2980 |  |  |          --  Generate:
 | 
      
         | 2981 |  |  |          --    for Iterator in [reverse] Container'Range loop
 | 
      
         | 2982 |  |  |          --       Element : Component_Type renames Container (Iterator);
 | 
      
         | 2983 |  |  |          --       --  for the "of" form
 | 
      
         | 2984 |  |  |  
 | 
      
         | 2985 |  |  |          --       <original loop statements>
 | 
      
         | 2986 |  |  |          --    end loop;
 | 
      
         | 2987 |  |  |  
 | 
      
         | 2988 |  |  |          New_Loop :=
 | 
      
         | 2989 |  |  |            Make_Loop_Statement (Loc,
 | 
      
         | 2990 |  |  |              Iteration_Scheme =>
 | 
      
         | 2991 |  |  |                Make_Iteration_Scheme (Loc,
 | 
      
         | 2992 |  |  |                  Loop_Parameter_Specification =>
 | 
      
         | 2993 |  |  |                    Make_Loop_Parameter_Specification (Loc,
 | 
      
         | 2994 |  |  |                      Defining_Identifier => Iterator,
 | 
      
         | 2995 |  |  |                        Discrete_Subtype_Definition =>
 | 
      
         | 2996 |  |  |                          Make_Attribute_Reference (Loc,
 | 
      
         | 2997 |  |  |                            Prefix => Relocate_Node (Container),
 | 
      
         | 2998 |  |  |                            Attribute_Name => Name_Range),
 | 
      
         | 2999 |  |  |                       Reverse_Present => Reverse_Present (I_Spec))),
 | 
      
         | 3000 |  |  |               Statements => Stats,
 | 
      
         | 3001 |  |  |               End_Label  => Empty);
 | 
      
         | 3002 |  |  |  
 | 
      
         | 3003 |  |  |       --  Processing for containers
 | 
      
         | 3004 |  |  |  
 | 
      
         | 3005 |  |  |       else
 | 
      
         | 3006 |  |  |          --  For an "of" iterator the name is a container expression, which
 | 
      
         | 3007 |  |  |          --  is transformed into a call to the default iterator.
 | 
      
         | 3008 |  |  |  
 | 
      
         | 3009 |  |  |          --  For an iterator of the form "in" the name is a function call
 | 
      
         | 3010 |  |  |          --  that delivers an iterator type.
 | 
      
         | 3011 |  |  |  
 | 
      
         | 3012 |  |  |          --  In both cases, analysis of the iterator has introduced an object
 | 
      
         | 3013 |  |  |          --  declaration to capture the domain, so that Container is an entity.
 | 
      
         | 3014 |  |  |  
 | 
      
         | 3015 |  |  |          --  The for loop is expanded into a while loop which uses a container
 | 
      
         | 3016 |  |  |          --  specific cursor to desgnate each element.
 | 
      
         | 3017 |  |  |  
 | 
      
         | 3018 |  |  |          --    Iter : Iterator_Type := Container.Iterate;
 | 
      
         | 3019 |  |  |          --    Cursor : Cursor_type := First (Iter);
 | 
      
         | 3020 |  |  |          --    while Has_Element (Iter) loop
 | 
      
         | 3021 |  |  |          --       declare
 | 
      
         | 3022 |  |  |          --       --  The block is added when Element_Type is controlled
 | 
      
         | 3023 |  |  |  
 | 
      
         | 3024 |  |  |          --          Obj : Pack.Element_Type := Element (Cursor);
 | 
      
         | 3025 |  |  |          --          --  for the "of" loop form
 | 
      
         | 3026 |  |  |          --       begin
 | 
      
         | 3027 |  |  |          --          <original loop statements>
 | 
      
         | 3028 |  |  |          --       end;
 | 
      
         | 3029 |  |  |  
 | 
      
         | 3030 |  |  |          --       Cursor := Iter.Next (Cursor);
 | 
      
         | 3031 |  |  |          --    end loop;
 | 
      
         | 3032 |  |  |  
 | 
      
         | 3033 |  |  |          --  If "reverse" is present, then the initialization of the cursor
 | 
      
         | 3034 |  |  |          --  uses Last and the step becomes Prev. Pack is the name of the
 | 
      
         | 3035 |  |  |          --  scope where the container package is instantiated.
 | 
      
         | 3036 |  |  |  
 | 
      
         | 3037 |  |  |          declare
 | 
      
         | 3038 |  |  |             Element_Type : constant Entity_Id := Etype (Id);
 | 
      
         | 3039 |  |  |             Iter_Type    : Entity_Id;
 | 
      
         | 3040 |  |  |             Pack         : Entity_Id;
 | 
      
         | 3041 |  |  |             Decl         : Node_Id;
 | 
      
         | 3042 |  |  |             Name_Init    : Name_Id;
 | 
      
         | 3043 |  |  |             Name_Step    : Name_Id;
 | 
      
         | 3044 |  |  |  
 | 
      
         | 3045 |  |  |          begin
 | 
      
         | 3046 |  |  |             --  The type of the iterator is the return type of the Iterate
 | 
      
         | 3047 |  |  |             --  function used. For the "of" form this is the default iterator
 | 
      
         | 3048 |  |  |             --  for the type, otherwise it is the type of the explicit
 | 
      
         | 3049 |  |  |             --  function used in the iterator specification. The most common
 | 
      
         | 3050 |  |  |             --  case will be an Iterate function in the container package.
 | 
      
         | 3051 |  |  |  
 | 
      
         | 3052 |  |  |             --  The primitive operations of the container type may not be
 | 
      
         | 3053 |  |  |             --  use-visible, so we introduce the name of the enclosing package
 | 
      
         | 3054 |  |  |             --  in the declarations below. The Iterator type is declared in a
 | 
      
         | 3055 |  |  |             --  an instance within the container package itself.
 | 
      
         | 3056 |  |  |  
 | 
      
         | 3057 |  |  |             --  If the container type is a derived type, the cursor type is
 | 
      
         | 3058 |  |  |             --  found in the package of the parent type.
 | 
      
         | 3059 |  |  |  
 | 
      
         | 3060 |  |  |             if Is_Derived_Type (Container_Typ) then
 | 
      
         | 3061 |  |  |                Pack := Scope (Root_Type (Container_Typ));
 | 
      
         | 3062 |  |  |             else
 | 
      
         | 3063 |  |  |                Pack := Scope (Container_Typ);
 | 
      
         | 3064 |  |  |             end if;
 | 
      
         | 3065 |  |  |  
 | 
      
         | 3066 |  |  |             Iter_Type := Etype (Name (I_Spec));
 | 
      
         | 3067 |  |  |  
 | 
      
         | 3068 |  |  |             --  The "of" case uses an internally generated cursor whose type
 | 
      
         | 3069 |  |  |             --  is found in the container package. The domain of iteration
 | 
      
         | 3070 |  |  |             --  is expanded into a call to the default Iterator function, but
 | 
      
         | 3071 |  |  |             --  this expansion does not take place in quantified expressions
 | 
      
         | 3072 |  |  |             --  that are analyzed with expansion disabled, and in that case the
 | 
      
         | 3073 |  |  |             --  type of the iterator must be obtained from the aspect.
 | 
      
         | 3074 |  |  |  
 | 
      
         | 3075 |  |  |             if Of_Present (I_Spec) then
 | 
      
         | 3076 |  |  |                declare
 | 
      
         | 3077 |  |  |                   Default_Iter : constant Entity_Id :=
 | 
      
         | 3078 |  |  |                                    Entity
 | 
      
         | 3079 |  |  |                                      (Find_Aspect
 | 
      
         | 3080 |  |  |                                        (Etype (Container),
 | 
      
         | 3081 |  |  |                                         Aspect_Default_Iterator));
 | 
      
         | 3082 |  |  |  
 | 
      
         | 3083 |  |  |                   Container_Arg : Node_Id;
 | 
      
         | 3084 |  |  |                   Ent           : Entity_Id;
 | 
      
         | 3085 |  |  |  
 | 
      
         | 3086 |  |  |                begin
 | 
      
         | 3087 |  |  |                   Cursor := Make_Temporary (Loc, 'I');
 | 
      
         | 3088 |  |  |  
 | 
      
         | 3089 |  |  |                   --  For an container element iterator, the iterator type
 | 
      
         | 3090 |  |  |                   --  is obtained from the corresponding aspect.
 | 
      
         | 3091 |  |  |  
 | 
      
         | 3092 |  |  |                   Iter_Type := Etype (Default_Iter);
 | 
      
         | 3093 |  |  |                   Pack := Scope (Iter_Type);
 | 
      
         | 3094 |  |  |  
 | 
      
         | 3095 |  |  |                   --  Rewrite domain of iteration as a call to the default
 | 
      
         | 3096 |  |  |                   --  iterator for the container type. If the container is
 | 
      
         | 3097 |  |  |                   --  a derived type and the aspect is inherited, convert
 | 
      
         | 3098 |  |  |                   --  container to parent type. The Cursor type is also
 | 
      
         | 3099 |  |  |                   --  inherited from the scope of the parent.
 | 
      
         | 3100 |  |  |  
 | 
      
         | 3101 |  |  |                   if Base_Type (Etype (Container)) =
 | 
      
         | 3102 |  |  |                      Base_Type (Etype (First_Formal (Default_Iter)))
 | 
      
         | 3103 |  |  |                   then
 | 
      
         | 3104 |  |  |                      Container_Arg := New_Copy_Tree (Container);
 | 
      
         | 3105 |  |  |  
 | 
      
         | 3106 |  |  |                   else
 | 
      
         | 3107 |  |  |                      Container_Arg :=
 | 
      
         | 3108 |  |  |                        Make_Type_Conversion (Loc,
 | 
      
         | 3109 |  |  |                          Subtype_Mark =>
 | 
      
         | 3110 |  |  |                            New_Occurrence_Of
 | 
      
         | 3111 |  |  |                              (Etype (First_Formal (Default_Iter)), Loc),
 | 
      
         | 3112 |  |  |                          Expression => New_Copy_Tree (Container));
 | 
      
         | 3113 |  |  |                   end if;
 | 
      
         | 3114 |  |  |  
 | 
      
         | 3115 |  |  |                   Rewrite (Name (I_Spec),
 | 
      
         | 3116 |  |  |                     Make_Function_Call (Loc,
 | 
      
         | 3117 |  |  |                       Name => New_Occurrence_Of (Default_Iter, Loc),
 | 
      
         | 3118 |  |  |                       Parameter_Associations =>
 | 
      
         | 3119 |  |  |                         New_List (Container_Arg)));
 | 
      
         | 3120 |  |  |                   Analyze_And_Resolve (Name (I_Spec));
 | 
      
         | 3121 |  |  |  
 | 
      
         | 3122 |  |  |                   --  Find cursor type in proper iterator package, which is an
 | 
      
         | 3123 |  |  |                   --  instantiation of Iterator_Interfaces.
 | 
      
         | 3124 |  |  |  
 | 
      
         | 3125 |  |  |                   Ent := First_Entity (Pack);
 | 
      
         | 3126 |  |  |                   while Present (Ent) loop
 | 
      
         | 3127 |  |  |                      if Chars (Ent) = Name_Cursor then
 | 
      
         | 3128 |  |  |                         Set_Etype (Cursor, Etype (Ent));
 | 
      
         | 3129 |  |  |                         exit;
 | 
      
         | 3130 |  |  |                      end if;
 | 
      
         | 3131 |  |  |                      Next_Entity (Ent);
 | 
      
         | 3132 |  |  |                   end loop;
 | 
      
         | 3133 |  |  |  
 | 
      
         | 3134 |  |  |                   --  Generate:
 | 
      
         | 3135 |  |  |                   --    Id : Element_Type renames Container (Cursor);
 | 
      
         | 3136 |  |  |                   --  This assumes that the container type has an indexing
 | 
      
         | 3137 |  |  |                   --  operation with Cursor. The check that this operation
 | 
      
         | 3138 |  |  |                   --  exists is performed in Check_Container_Indexing.
 | 
      
         | 3139 |  |  |  
 | 
      
         | 3140 |  |  |                   Decl :=
 | 
      
         | 3141 |  |  |                     Make_Object_Renaming_Declaration (Loc,
 | 
      
         | 3142 |  |  |                       Defining_Identifier => Id,
 | 
      
         | 3143 |  |  |                       Subtype_Mark     =>
 | 
      
         | 3144 |  |  |                         New_Reference_To (Element_Type, Loc),
 | 
      
         | 3145 |  |  |                       Name             =>
 | 
      
         | 3146 |  |  |                         Make_Indexed_Component (Loc,
 | 
      
         | 3147 |  |  |                           Prefix      => Relocate_Node (Container_Arg),
 | 
      
         | 3148 |  |  |                           Expressions =>
 | 
      
         | 3149 |  |  |                             New_List (New_Occurrence_Of (Cursor, Loc))));
 | 
      
         | 3150 |  |  |  
 | 
      
         | 3151 |  |  |                   --  If the container holds controlled objects, wrap the loop
 | 
      
         | 3152 |  |  |                   --  statements and element renaming declaration with a block.
 | 
      
         | 3153 |  |  |                   --  This ensures that the result of Element (Cusor) is
 | 
      
         | 3154 |  |  |                   --  cleaned up after each iteration of the loop.
 | 
      
         | 3155 |  |  |  
 | 
      
         | 3156 |  |  |                   if Needs_Finalization (Element_Type) then
 | 
      
         | 3157 |  |  |  
 | 
      
         | 3158 |  |  |                      --  Generate:
 | 
      
         | 3159 |  |  |                      --    declare
 | 
      
         | 3160 |  |  |                      --       Id : Element_Type := Element (curosr);
 | 
      
         | 3161 |  |  |                      --    begin
 | 
      
         | 3162 |  |  |                      --       <original loop statements>
 | 
      
         | 3163 |  |  |                      --    end;
 | 
      
         | 3164 |  |  |  
 | 
      
         | 3165 |  |  |                      Stats := New_List (
 | 
      
         | 3166 |  |  |                        Make_Block_Statement (Loc,
 | 
      
         | 3167 |  |  |                          Declarations               => New_List (Decl),
 | 
      
         | 3168 |  |  |                          Handled_Statement_Sequence =>
 | 
      
         | 3169 |  |  |                            Make_Handled_Sequence_Of_Statements (Loc,
 | 
      
         | 3170 |  |  |                               Statements => Stats)));
 | 
      
         | 3171 |  |  |  
 | 
      
         | 3172 |  |  |                   --  Elements do not need finalization
 | 
      
         | 3173 |  |  |  
 | 
      
         | 3174 |  |  |                   else
 | 
      
         | 3175 |  |  |                      Prepend_To (Stats, Decl);
 | 
      
         | 3176 |  |  |                   end if;
 | 
      
         | 3177 |  |  |                end;
 | 
      
         | 3178 |  |  |  
 | 
      
         | 3179 |  |  |             --  X in Iterate (S) : type of iterator is type of explicitly
 | 
      
         | 3180 |  |  |             --  given Iterate function, and the loop variable is the cursor.
 | 
      
         | 3181 |  |  |             --  It will be assigned in the loop and must be a variable.
 | 
      
         | 3182 |  |  |  
 | 
      
         | 3183 |  |  |             else
 | 
      
         | 3184 |  |  |                Cursor := Id;
 | 
      
         | 3185 |  |  |                Set_Ekind (Cursor, E_Variable);
 | 
      
         | 3186 |  |  |             end if;
 | 
      
         | 3187 |  |  |  
 | 
      
         | 3188 |  |  |             Iterator := Make_Temporary (Loc, 'I');
 | 
      
         | 3189 |  |  |  
 | 
      
         | 3190 |  |  |             --  Determine the advancement and initialization steps for the
 | 
      
         | 3191 |  |  |             --  cursor.
 | 
      
         | 3192 |  |  |  
 | 
      
         | 3193 |  |  |             --  Analysis of the expanded loop will verify that the container
 | 
      
         | 3194 |  |  |             --  has a reverse iterator.
 | 
      
         | 3195 |  |  |  
 | 
      
         | 3196 |  |  |             if Reverse_Present (I_Spec) then
 | 
      
         | 3197 |  |  |                Name_Init := Name_Last;
 | 
      
         | 3198 |  |  |                Name_Step := Name_Previous;
 | 
      
         | 3199 |  |  |  
 | 
      
         | 3200 |  |  |             else
 | 
      
         | 3201 |  |  |                Name_Init := Name_First;
 | 
      
         | 3202 |  |  |                Name_Step := Name_Next;
 | 
      
         | 3203 |  |  |             end if;
 | 
      
         | 3204 |  |  |  
 | 
      
         | 3205 |  |  |             --  For both iterator forms, add a call to the step operation to
 | 
      
         | 3206 |  |  |             --  advance the cursor. Generate:
 | 
      
         | 3207 |  |  |  
 | 
      
         | 3208 |  |  |             --     Cursor := Iterator.Next (Cursor);
 | 
      
         | 3209 |  |  |  
 | 
      
         | 3210 |  |  |             --   or else
 | 
      
         | 3211 |  |  |  
 | 
      
         | 3212 |  |  |             --     Cursor := Next (Cursor);
 | 
      
         | 3213 |  |  |  
 | 
      
         | 3214 |  |  |             declare
 | 
      
         | 3215 |  |  |                Rhs : Node_Id;
 | 
      
         | 3216 |  |  |  
 | 
      
         | 3217 |  |  |             begin
 | 
      
         | 3218 |  |  |                Rhs :=
 | 
      
         | 3219 |  |  |                  Make_Function_Call (Loc,
 | 
      
         | 3220 |  |  |                    Name                   =>
 | 
      
         | 3221 |  |  |                      Make_Selected_Component (Loc,
 | 
      
         | 3222 |  |  |                        Prefix        => New_Reference_To (Iterator, Loc),
 | 
      
         | 3223 |  |  |                        Selector_Name => Make_Identifier (Loc, Name_Step)),
 | 
      
         | 3224 |  |  |                    Parameter_Associations => New_List (
 | 
      
         | 3225 |  |  |                       New_Reference_To (Cursor, Loc)));
 | 
      
         | 3226 |  |  |  
 | 
      
         | 3227 |  |  |                Append_To (Stats,
 | 
      
         | 3228 |  |  |                  Make_Assignment_Statement (Loc,
 | 
      
         | 3229 |  |  |                     Name       => New_Occurrence_Of (Cursor, Loc),
 | 
      
         | 3230 |  |  |                     Expression => Rhs));
 | 
      
         | 3231 |  |  |             end;
 | 
      
         | 3232 |  |  |  
 | 
      
         | 3233 |  |  |             --  Generate:
 | 
      
         | 3234 |  |  |             --    while Iterator.Has_Element loop
 | 
      
         | 3235 |  |  |             --       <Stats>
 | 
      
         | 3236 |  |  |             --    end loop;
 | 
      
         | 3237 |  |  |  
 | 
      
         | 3238 |  |  |             --   Has_Element is the second actual in the iterator package
 | 
      
         | 3239 |  |  |  
 | 
      
         | 3240 |  |  |             New_Loop :=
 | 
      
         | 3241 |  |  |               Make_Loop_Statement (Loc,
 | 
      
         | 3242 |  |  |                 Iteration_Scheme =>
 | 
      
         | 3243 |  |  |                   Make_Iteration_Scheme (Loc,
 | 
      
         | 3244 |  |  |                     Condition =>
 | 
      
         | 3245 |  |  |                       Make_Function_Call (Loc,
 | 
      
         | 3246 |  |  |                         Name                   =>
 | 
      
         | 3247 |  |  |                           New_Occurrence_Of (
 | 
      
         | 3248 |  |  |                            Next_Entity (First_Entity (Pack)), Loc),
 | 
      
         | 3249 |  |  |                         Parameter_Associations =>
 | 
      
         | 3250 |  |  |                           New_List (
 | 
      
         | 3251 |  |  |                             New_Reference_To (Cursor, Loc)))),
 | 
      
         | 3252 |  |  |  
 | 
      
         | 3253 |  |  |                 Statements => Stats,
 | 
      
         | 3254 |  |  |                 End_Label  => Empty);
 | 
      
         | 3255 |  |  |  
 | 
      
         | 3256 |  |  |             --  Create the declarations for Iterator and cursor and insert them
 | 
      
         | 3257 |  |  |             --  before the source loop. Given that the domain of iteration is
 | 
      
         | 3258 |  |  |             --  already an entity, the iterator is just a renaming of that
 | 
      
         | 3259 |  |  |             --  entity. Possible optimization ???
 | 
      
         | 3260 |  |  |             --  Generate:
 | 
      
         | 3261 |  |  |  
 | 
      
         | 3262 |  |  |             --    I : Iterator_Type renames Container;
 | 
      
         | 3263 |  |  |             --    C : Cursor_Type := Container.[First | Last];
 | 
      
         | 3264 |  |  |  
 | 
      
         | 3265 |  |  |             Insert_Action (N,
 | 
      
         | 3266 |  |  |               Make_Object_Renaming_Declaration (Loc,
 | 
      
         | 3267 |  |  |                 Defining_Identifier => Iterator,
 | 
      
         | 3268 |  |  |                 Subtype_Mark  => New_Occurrence_Of (Iter_Type, Loc),
 | 
      
         | 3269 |  |  |                 Name          => Relocate_Node (Name (I_Spec))));
 | 
      
         | 3270 |  |  |  
 | 
      
         | 3271 |  |  |             --  Create declaration for cursor
 | 
      
         | 3272 |  |  |  
 | 
      
         | 3273 |  |  |             declare
 | 
      
         | 3274 |  |  |                Decl : Node_Id;
 | 
      
         | 3275 |  |  |  
 | 
      
         | 3276 |  |  |             begin
 | 
      
         | 3277 |  |  |                Decl :=
 | 
      
         | 3278 |  |  |                  Make_Object_Declaration (Loc,
 | 
      
         | 3279 |  |  |                    Defining_Identifier => Cursor,
 | 
      
         | 3280 |  |  |                    Object_Definition   =>
 | 
      
         | 3281 |  |  |                      New_Occurrence_Of (Etype (Cursor), Loc),
 | 
      
         | 3282 |  |  |                    Expression          =>
 | 
      
         | 3283 |  |  |                      Make_Selected_Component (Loc,
 | 
      
         | 3284 |  |  |                        Prefix        => New_Reference_To (Iterator, Loc),
 | 
      
         | 3285 |  |  |                        Selector_Name =>
 | 
      
         | 3286 |  |  |                          Make_Identifier (Loc, Name_Init)));
 | 
      
         | 3287 |  |  |  
 | 
      
         | 3288 |  |  |                --  The cursor is only modified in expanded code, so it appears
 | 
      
         | 3289 |  |  |                --  as unassigned to the warning machinery. We must suppress
 | 
      
         | 3290 |  |  |                --  this spurious warning explicitly.
 | 
      
         | 3291 |  |  |  
 | 
      
         | 3292 |  |  |                Set_Warnings_Off (Cursor);
 | 
      
         | 3293 |  |  |                Set_Assignment_OK (Decl);
 | 
      
         | 3294 |  |  |  
 | 
      
         | 3295 |  |  |                Insert_Action (N, Decl);
 | 
      
         | 3296 |  |  |             end;
 | 
      
         | 3297 |  |  |  
 | 
      
         | 3298 |  |  |             --  If the range of iteration is given by a function call that
 | 
      
         | 3299 |  |  |             --  returns a container, the finalization actions have been saved
 | 
      
         | 3300 |  |  |             --  in the Condition_Actions of the iterator. Insert them now at
 | 
      
         | 3301 |  |  |             --  the head of the loop.
 | 
      
         | 3302 |  |  |  
 | 
      
         | 3303 |  |  |             if Present (Condition_Actions (Isc)) then
 | 
      
         | 3304 |  |  |                Insert_List_Before (N, Condition_Actions (Isc));
 | 
      
         | 3305 |  |  |             end if;
 | 
      
         | 3306 |  |  |          end;
 | 
      
         | 3307 |  |  |       end if;
 | 
      
         | 3308 |  |  |  
 | 
      
         | 3309 |  |  |       Rewrite (N, New_Loop);
 | 
      
         | 3310 |  |  |       Analyze (N);
 | 
      
         | 3311 |  |  |    end Expand_Iterator_Loop;
 | 
      
         | 3312 |  |  |  
 | 
      
         | 3313 |  |  |    -----------------------------
 | 
      
         | 3314 |  |  |    -- Expand_N_Loop_Statement --
 | 
      
         | 3315 |  |  |    -----------------------------
 | 
      
         | 3316 |  |  |  
 | 
      
         | 3317 |  |  |    --  1. Remove null loop entirely
 | 
      
         | 3318 |  |  |    --  2. Deal with while condition for C/Fortran boolean
 | 
      
         | 3319 |  |  |    --  3. Deal with loops with a non-standard enumeration type range
 | 
      
         | 3320 |  |  |    --  4. Deal with while loops where Condition_Actions is set
 | 
      
         | 3321 |  |  |    --  5. Deal with loops over predicated subtypes
 | 
      
         | 3322 |  |  |    --  6. Deal with loops with iterators over arrays and containers
 | 
      
         | 3323 |  |  |    --  7. Insert polling call if required
 | 
      
         | 3324 |  |  |  
 | 
      
         | 3325 |  |  |    procedure Expand_N_Loop_Statement (N : Node_Id) is
 | 
      
         | 3326 |  |  |       Loc  : constant Source_Ptr := Sloc (N);
 | 
      
         | 3327 |  |  |       Isc  : constant Node_Id    := Iteration_Scheme (N);
 | 
      
         | 3328 |  |  |  
 | 
      
         | 3329 |  |  |    begin
 | 
      
         | 3330 |  |  |       --  Delete null loop
 | 
      
         | 3331 |  |  |  
 | 
      
         | 3332 |  |  |       if Is_Null_Loop (N) then
 | 
      
         | 3333 |  |  |          Rewrite (N, Make_Null_Statement (Loc));
 | 
      
         | 3334 |  |  |          return;
 | 
      
         | 3335 |  |  |       end if;
 | 
      
         | 3336 |  |  |  
 | 
      
         | 3337 |  |  |       Process_Statements_For_Controlled_Objects (N);
 | 
      
         | 3338 |  |  |  
 | 
      
         | 3339 |  |  |       --  Deal with condition for C/Fortran Boolean
 | 
      
         | 3340 |  |  |  
 | 
      
         | 3341 |  |  |       if Present (Isc) then
 | 
      
         | 3342 |  |  |          Adjust_Condition (Condition (Isc));
 | 
      
         | 3343 |  |  |       end if;
 | 
      
         | 3344 |  |  |  
 | 
      
         | 3345 |  |  |       --  Generate polling call
 | 
      
         | 3346 |  |  |  
 | 
      
         | 3347 |  |  |       if Is_Non_Empty_List (Statements (N)) then
 | 
      
         | 3348 |  |  |          Generate_Poll_Call (First (Statements (N)));
 | 
      
         | 3349 |  |  |       end if;
 | 
      
         | 3350 |  |  |  
 | 
      
         | 3351 |  |  |       --  Nothing more to do for plain loop with no iteration scheme
 | 
      
         | 3352 |  |  |  
 | 
      
         | 3353 |  |  |       if No (Isc) then
 | 
      
         | 3354 |  |  |          null;
 | 
      
         | 3355 |  |  |  
 | 
      
         | 3356 |  |  |       --  Case of for loop (Loop_Parameter_Specification present)
 | 
      
         | 3357 |  |  |  
 | 
      
         | 3358 |  |  |       --  Note: we do not have to worry about validity checking of the for loop
 | 
      
         | 3359 |  |  |       --  range bounds here, since they were frozen with constant declarations
 | 
      
         | 3360 |  |  |       --  and it is during that process that the validity checking is done.
 | 
      
         | 3361 |  |  |  
 | 
      
         | 3362 |  |  |       elsif Present (Loop_Parameter_Specification (Isc)) then
 | 
      
         | 3363 |  |  |          declare
 | 
      
         | 3364 |  |  |             LPS     : constant Node_Id   := Loop_Parameter_Specification (Isc);
 | 
      
         | 3365 |  |  |             Loop_Id : constant Entity_Id := Defining_Identifier (LPS);
 | 
      
         | 3366 |  |  |             Ltype   : constant Entity_Id := Etype (Loop_Id);
 | 
      
         | 3367 |  |  |             Btype   : constant Entity_Id := Base_Type (Ltype);
 | 
      
         | 3368 |  |  |             Expr    : Node_Id;
 | 
      
         | 3369 |  |  |             New_Id  : Entity_Id;
 | 
      
         | 3370 |  |  |  
 | 
      
         | 3371 |  |  |          begin
 | 
      
         | 3372 |  |  |             --  Deal with loop over predicates
 | 
      
         | 3373 |  |  |  
 | 
      
         | 3374 |  |  |             if Is_Discrete_Type (Ltype)
 | 
      
         | 3375 |  |  |               and then Present (Predicate_Function (Ltype))
 | 
      
         | 3376 |  |  |             then
 | 
      
         | 3377 |  |  |                Expand_Predicated_Loop (N);
 | 
      
         | 3378 |  |  |  
 | 
      
         | 3379 |  |  |             --  Handle the case where we have a for loop with the range type
 | 
      
         | 3380 |  |  |             --  being an enumeration type with non-standard representation.
 | 
      
         | 3381 |  |  |             --  In this case we expand:
 | 
      
         | 3382 |  |  |  
 | 
      
         | 3383 |  |  |             --    for x in [reverse] a .. b loop
 | 
      
         | 3384 |  |  |             --       ...
 | 
      
         | 3385 |  |  |             --    end loop;
 | 
      
         | 3386 |  |  |  
 | 
      
         | 3387 |  |  |             --  to
 | 
      
         | 3388 |  |  |  
 | 
      
         | 3389 |  |  |             --    for xP in [reverse] integer
 | 
      
         | 3390 |  |  |             --      range etype'Pos (a) .. etype'Pos (b)
 | 
      
         | 3391 |  |  |             --    loop
 | 
      
         | 3392 |  |  |             --       declare
 | 
      
         | 3393 |  |  |             --          x : constant etype := Pos_To_Rep (xP);
 | 
      
         | 3394 |  |  |             --       begin
 | 
      
         | 3395 |  |  |             --          ...
 | 
      
         | 3396 |  |  |             --       end;
 | 
      
         | 3397 |  |  |             --    end loop;
 | 
      
         | 3398 |  |  |  
 | 
      
         | 3399 |  |  |             elsif Is_Enumeration_Type (Btype)
 | 
      
         | 3400 |  |  |               and then Present (Enum_Pos_To_Rep (Btype))
 | 
      
         | 3401 |  |  |             then
 | 
      
         | 3402 |  |  |                New_Id :=
 | 
      
         | 3403 |  |  |                  Make_Defining_Identifier (Loc,
 | 
      
         | 3404 |  |  |                    Chars => New_External_Name (Chars (Loop_Id), 'P'));
 | 
      
         | 3405 |  |  |  
 | 
      
         | 3406 |  |  |                --  If the type has a contiguous representation, successive
 | 
      
         | 3407 |  |  |                --  values can be generated as offsets from the first literal.
 | 
      
         | 3408 |  |  |  
 | 
      
         | 3409 |  |  |                if Has_Contiguous_Rep (Btype) then
 | 
      
         | 3410 |  |  |                   Expr :=
 | 
      
         | 3411 |  |  |                      Unchecked_Convert_To (Btype,
 | 
      
         | 3412 |  |  |                        Make_Op_Add (Loc,
 | 
      
         | 3413 |  |  |                          Left_Opnd =>
 | 
      
         | 3414 |  |  |                             Make_Integer_Literal (Loc,
 | 
      
         | 3415 |  |  |                               Enumeration_Rep (First_Literal (Btype))),
 | 
      
         | 3416 |  |  |                          Right_Opnd => New_Reference_To (New_Id, Loc)));
 | 
      
         | 3417 |  |  |                else
 | 
      
         | 3418 |  |  |                   --  Use the constructed array Enum_Pos_To_Rep
 | 
      
         | 3419 |  |  |  
 | 
      
         | 3420 |  |  |                   Expr :=
 | 
      
         | 3421 |  |  |                     Make_Indexed_Component (Loc,
 | 
      
         | 3422 |  |  |                       Prefix      =>
 | 
      
         | 3423 |  |  |                         New_Reference_To (Enum_Pos_To_Rep (Btype), Loc),
 | 
      
         | 3424 |  |  |                       Expressions =>
 | 
      
         | 3425 |  |  |                         New_List (New_Reference_To (New_Id, Loc)));
 | 
      
         | 3426 |  |  |                end if;
 | 
      
         | 3427 |  |  |  
 | 
      
         | 3428 |  |  |                Rewrite (N,
 | 
      
         | 3429 |  |  |                  Make_Loop_Statement (Loc,
 | 
      
         | 3430 |  |  |                    Identifier => Identifier (N),
 | 
      
         | 3431 |  |  |  
 | 
      
         | 3432 |  |  |                    Iteration_Scheme =>
 | 
      
         | 3433 |  |  |                      Make_Iteration_Scheme (Loc,
 | 
      
         | 3434 |  |  |                        Loop_Parameter_Specification =>
 | 
      
         | 3435 |  |  |                          Make_Loop_Parameter_Specification (Loc,
 | 
      
         | 3436 |  |  |                            Defining_Identifier => New_Id,
 | 
      
         | 3437 |  |  |                            Reverse_Present => Reverse_Present (LPS),
 | 
      
         | 3438 |  |  |  
 | 
      
         | 3439 |  |  |                            Discrete_Subtype_Definition =>
 | 
      
         | 3440 |  |  |                              Make_Subtype_Indication (Loc,
 | 
      
         | 3441 |  |  |  
 | 
      
         | 3442 |  |  |                                Subtype_Mark =>
 | 
      
         | 3443 |  |  |                                  New_Reference_To (Standard_Natural, Loc),
 | 
      
         | 3444 |  |  |  
 | 
      
         | 3445 |  |  |                                Constraint =>
 | 
      
         | 3446 |  |  |                                  Make_Range_Constraint (Loc,
 | 
      
         | 3447 |  |  |                                    Range_Expression =>
 | 
      
         | 3448 |  |  |                                      Make_Range (Loc,
 | 
      
         | 3449 |  |  |  
 | 
      
         | 3450 |  |  |                                        Low_Bound =>
 | 
      
         | 3451 |  |  |                                          Make_Attribute_Reference (Loc,
 | 
      
         | 3452 |  |  |                                            Prefix =>
 | 
      
         | 3453 |  |  |                                              New_Reference_To (Btype, Loc),
 | 
      
         | 3454 |  |  |  
 | 
      
         | 3455 |  |  |                                            Attribute_Name => Name_Pos,
 | 
      
         | 3456 |  |  |  
 | 
      
         | 3457 |  |  |                                            Expressions => New_List (
 | 
      
         | 3458 |  |  |                                              Relocate_Node
 | 
      
         | 3459 |  |  |                                                (Type_Low_Bound (Ltype)))),
 | 
      
         | 3460 |  |  |  
 | 
      
         | 3461 |  |  |                                        High_Bound =>
 | 
      
         | 3462 |  |  |                                          Make_Attribute_Reference (Loc,
 | 
      
         | 3463 |  |  |                                            Prefix =>
 | 
      
         | 3464 |  |  |                                              New_Reference_To (Btype, Loc),
 | 
      
         | 3465 |  |  |  
 | 
      
         | 3466 |  |  |                                            Attribute_Name => Name_Pos,
 | 
      
         | 3467 |  |  |  
 | 
      
         | 3468 |  |  |                                            Expressions => New_List (
 | 
      
         | 3469 |  |  |                                              Relocate_Node
 | 
      
         | 3470 |  |  |                                                (Type_High_Bound
 | 
      
         | 3471 |  |  |                                                   (Ltype))))))))),
 | 
      
         | 3472 |  |  |  
 | 
      
         | 3473 |  |  |                    Statements => New_List (
 | 
      
         | 3474 |  |  |                      Make_Block_Statement (Loc,
 | 
      
         | 3475 |  |  |                        Declarations => New_List (
 | 
      
         | 3476 |  |  |                          Make_Object_Declaration (Loc,
 | 
      
         | 3477 |  |  |                            Defining_Identifier => Loop_Id,
 | 
      
         | 3478 |  |  |                            Constant_Present    => True,
 | 
      
         | 3479 |  |  |                            Object_Definition   =>
 | 
      
         | 3480 |  |  |                              New_Reference_To (Ltype, Loc),
 | 
      
         | 3481 |  |  |                            Expression          => Expr)),
 | 
      
         | 3482 |  |  |  
 | 
      
         | 3483 |  |  |                        Handled_Statement_Sequence =>
 | 
      
         | 3484 |  |  |                          Make_Handled_Sequence_Of_Statements (Loc,
 | 
      
         | 3485 |  |  |                            Statements => Statements (N)))),
 | 
      
         | 3486 |  |  |  
 | 
      
         | 3487 |  |  |                    End_Label => End_Label (N)));
 | 
      
         | 3488 |  |  |  
 | 
      
         | 3489 |  |  |                --  The loop parameter's entity must be removed from the loop
 | 
      
         | 3490 |  |  |                --  scope's entity list, since it will now be located in the
 | 
      
         | 3491 |  |  |                --  new block scope. Any other entities already associated with
 | 
      
         | 3492 |  |  |                --  the loop scope, such as the loop parameter's subtype, will
 | 
      
         | 3493 |  |  |                --  remain there.
 | 
      
         | 3494 |  |  |  
 | 
      
         | 3495 |  |  |                pragma Assert (First_Entity (Scope (Loop_Id)) = Loop_Id);
 | 
      
         | 3496 |  |  |                Set_First_Entity (Scope (Loop_Id), Next_Entity (Loop_Id));
 | 
      
         | 3497 |  |  |  
 | 
      
         | 3498 |  |  |                if Last_Entity (Scope (Loop_Id)) = Loop_Id then
 | 
      
         | 3499 |  |  |                   Set_Last_Entity (Scope (Loop_Id), Empty);
 | 
      
         | 3500 |  |  |                end if;
 | 
      
         | 3501 |  |  |  
 | 
      
         | 3502 |  |  |                Analyze (N);
 | 
      
         | 3503 |  |  |  
 | 
      
         | 3504 |  |  |             --  Nothing to do with other cases of for loops
 | 
      
         | 3505 |  |  |  
 | 
      
         | 3506 |  |  |             else
 | 
      
         | 3507 |  |  |                null;
 | 
      
         | 3508 |  |  |             end if;
 | 
      
         | 3509 |  |  |          end;
 | 
      
         | 3510 |  |  |  
 | 
      
         | 3511 |  |  |       --  Second case, if we have a while loop with Condition_Actions set, then
 | 
      
         | 3512 |  |  |       --  we change it into a plain loop:
 | 
      
         | 3513 |  |  |  
 | 
      
         | 3514 |  |  |       --    while C loop
 | 
      
         | 3515 |  |  |       --       ...
 | 
      
         | 3516 |  |  |       --    end loop;
 | 
      
         | 3517 |  |  |  
 | 
      
         | 3518 |  |  |       --  changed to:
 | 
      
         | 3519 |  |  |  
 | 
      
         | 3520 |  |  |       --    loop
 | 
      
         | 3521 |  |  |       --       <<condition actions>>
 | 
      
         | 3522 |  |  |       --       exit when not C;
 | 
      
         | 3523 |  |  |       --       ...
 | 
      
         | 3524 |  |  |       --    end loop
 | 
      
         | 3525 |  |  |  
 | 
      
         | 3526 |  |  |       elsif Present (Isc)
 | 
      
         | 3527 |  |  |         and then Present (Condition_Actions (Isc))
 | 
      
         | 3528 |  |  |         and then Present (Condition (Isc))
 | 
      
         | 3529 |  |  |       then
 | 
      
         | 3530 |  |  |          declare
 | 
      
         | 3531 |  |  |             ES : Node_Id;
 | 
      
         | 3532 |  |  |  
 | 
      
         | 3533 |  |  |          begin
 | 
      
         | 3534 |  |  |             ES :=
 | 
      
         | 3535 |  |  |               Make_Exit_Statement (Sloc (Condition (Isc)),
 | 
      
         | 3536 |  |  |                 Condition =>
 | 
      
         | 3537 |  |  |                   Make_Op_Not (Sloc (Condition (Isc)),
 | 
      
         | 3538 |  |  |                     Right_Opnd => Condition (Isc)));
 | 
      
         | 3539 |  |  |  
 | 
      
         | 3540 |  |  |             Prepend (ES, Statements (N));
 | 
      
         | 3541 |  |  |             Insert_List_Before (ES, Condition_Actions (Isc));
 | 
      
         | 3542 |  |  |  
 | 
      
         | 3543 |  |  |             --  This is not an implicit loop, since it is generated in response
 | 
      
         | 3544 |  |  |             --  to the loop statement being processed. If this is itself
 | 
      
         | 3545 |  |  |             --  implicit, the restriction has already been checked. If not,
 | 
      
         | 3546 |  |  |             --  it is an explicit loop.
 | 
      
         | 3547 |  |  |  
 | 
      
         | 3548 |  |  |             Rewrite (N,
 | 
      
         | 3549 |  |  |               Make_Loop_Statement (Sloc (N),
 | 
      
         | 3550 |  |  |                 Identifier => Identifier (N),
 | 
      
         | 3551 |  |  |                 Statements => Statements (N),
 | 
      
         | 3552 |  |  |                 End_Label  => End_Label  (N)));
 | 
      
         | 3553 |  |  |  
 | 
      
         | 3554 |  |  |             Analyze (N);
 | 
      
         | 3555 |  |  |          end;
 | 
      
         | 3556 |  |  |  
 | 
      
         | 3557 |  |  |       --  Here to deal with iterator case
 | 
      
         | 3558 |  |  |  
 | 
      
         | 3559 |  |  |       elsif Present (Isc)
 | 
      
         | 3560 |  |  |         and then Present (Iterator_Specification (Isc))
 | 
      
         | 3561 |  |  |       then
 | 
      
         | 3562 |  |  |          Expand_Iterator_Loop (N);
 | 
      
         | 3563 |  |  |       end if;
 | 
      
         | 3564 |  |  |    end Expand_N_Loop_Statement;
 | 
      
         | 3565 |  |  |  
 | 
      
         | 3566 |  |  |    ----------------------------
 | 
      
         | 3567 |  |  |    -- Expand_Predicated_Loop --
 | 
      
         | 3568 |  |  |    ----------------------------
 | 
      
         | 3569 |  |  |  
 | 
      
         | 3570 |  |  |    --  Note: the expander can handle generation of loops over predicated
 | 
      
         | 3571 |  |  |    --  subtypes for both the dynamic and static cases. Depending on what
 | 
      
         | 3572 |  |  |    --  we decide is allowed in Ada 2012 mode and/or extensions allowed
 | 
      
         | 3573 |  |  |    --  mode, the semantic analyzer may disallow one or both forms.
 | 
      
         | 3574 |  |  |  
 | 
      
         | 3575 |  |  |    procedure Expand_Predicated_Loop (N : Node_Id) is
 | 
      
         | 3576 |  |  |       Loc     : constant Source_Ptr := Sloc (N);
 | 
      
         | 3577 |  |  |       Isc     : constant Node_Id    := Iteration_Scheme (N);
 | 
      
         | 3578 |  |  |       LPS     : constant Node_Id    := Loop_Parameter_Specification (Isc);
 | 
      
         | 3579 |  |  |       Loop_Id : constant Entity_Id  := Defining_Identifier (LPS);
 | 
      
         | 3580 |  |  |       Ltype   : constant Entity_Id  := Etype (Loop_Id);
 | 
      
         | 3581 |  |  |       Stat    : constant List_Id    := Static_Predicate (Ltype);
 | 
      
         | 3582 |  |  |       Stmts   : constant List_Id    := Statements (N);
 | 
      
         | 3583 |  |  |  
 | 
      
         | 3584 |  |  |    begin
 | 
      
         | 3585 |  |  |       --  Case of iteration over non-static predicate, should not be possible
 | 
      
         | 3586 |  |  |       --  since this is not allowed by the semantics and should have been
 | 
      
         | 3587 |  |  |       --  caught during analysis of the loop statement.
 | 
      
         | 3588 |  |  |  
 | 
      
         | 3589 |  |  |       if No (Stat) then
 | 
      
         | 3590 |  |  |          raise Program_Error;
 | 
      
         | 3591 |  |  |  
 | 
      
         | 3592 |  |  |       --  If the predicate list is empty, that corresponds to a predicate of
 | 
      
         | 3593 |  |  |       --  False, in which case the loop won't run at all, and we rewrite the
 | 
      
         | 3594 |  |  |       --  entire loop as a null statement.
 | 
      
         | 3595 |  |  |  
 | 
      
         | 3596 |  |  |       elsif Is_Empty_List (Stat) then
 | 
      
         | 3597 |  |  |          Rewrite (N, Make_Null_Statement (Loc));
 | 
      
         | 3598 |  |  |          Analyze (N);
 | 
      
         | 3599 |  |  |  
 | 
      
         | 3600 |  |  |       --  For expansion over a static predicate we generate the following
 | 
      
         | 3601 |  |  |  
 | 
      
         | 3602 |  |  |       --     declare
 | 
      
         | 3603 |  |  |       --        J : Ltype := min-val;
 | 
      
         | 3604 |  |  |       --     begin
 | 
      
         | 3605 |  |  |       --        loop
 | 
      
         | 3606 |  |  |       --           body
 | 
      
         | 3607 |  |  |       --           case J is
 | 
      
         | 3608 |  |  |       --              when endpoint => J := startpoint;
 | 
      
         | 3609 |  |  |       --              when endpoint => J := startpoint;
 | 
      
         | 3610 |  |  |       --              ...
 | 
      
         | 3611 |  |  |       --              when max-val  => exit;
 | 
      
         | 3612 |  |  |       --              when others   => J := Lval'Succ (J);
 | 
      
         | 3613 |  |  |       --           end case;
 | 
      
         | 3614 |  |  |       --        end loop;
 | 
      
         | 3615 |  |  |       --     end;
 | 
      
         | 3616 |  |  |  
 | 
      
         | 3617 |  |  |       --  To make this a little clearer, let's take a specific example:
 | 
      
         | 3618 |  |  |  
 | 
      
         | 3619 |  |  |       --        type Int is range 1 .. 10;
 | 
      
         | 3620 |  |  |       --        subtype L is Int with
 | 
      
         | 3621 |  |  |       --          predicate => L in 3 | 10 | 5 .. 7;
 | 
      
         | 3622 |  |  |       --          ...
 | 
      
         | 3623 |  |  |       --        for L in StaticP loop
 | 
      
         | 3624 |  |  |       --           Put_Line ("static:" & J'Img);
 | 
      
         | 3625 |  |  |       --        end loop;
 | 
      
         | 3626 |  |  |  
 | 
      
         | 3627 |  |  |       --  In this case, the loop is transformed into
 | 
      
         | 3628 |  |  |  
 | 
      
         | 3629 |  |  |       --     begin
 | 
      
         | 3630 |  |  |       --        J : L := 3;
 | 
      
         | 3631 |  |  |       --        loop
 | 
      
         | 3632 |  |  |       --           body
 | 
      
         | 3633 |  |  |       --           case J is
 | 
      
         | 3634 |  |  |       --              when 3  => J := 5;
 | 
      
         | 3635 |  |  |       --              when 7  => J := 10;
 | 
      
         | 3636 |  |  |       --              when 10 => exit;
 | 
      
         | 3637 |  |  |       --              when others  => J := L'Succ (J);
 | 
      
         | 3638 |  |  |       --           end case;
 | 
      
         | 3639 |  |  |       --        end loop;
 | 
      
         | 3640 |  |  |       --     end;
 | 
      
         | 3641 |  |  |  
 | 
      
         | 3642 |  |  |       else
 | 
      
         | 3643 |  |  |          Static_Predicate : declare
 | 
      
         | 3644 |  |  |             S    : Node_Id;
 | 
      
         | 3645 |  |  |             D    : Node_Id;
 | 
      
         | 3646 |  |  |             P    : Node_Id;
 | 
      
         | 3647 |  |  |             Alts : List_Id;
 | 
      
         | 3648 |  |  |             Cstm : Node_Id;
 | 
      
         | 3649 |  |  |  
 | 
      
         | 3650 |  |  |             function Lo_Val (N : Node_Id) return Node_Id;
 | 
      
         | 3651 |  |  |             --  Given static expression or static range, returns an identifier
 | 
      
         | 3652 |  |  |             --  whose value is the low bound of the expression value or range.
 | 
      
         | 3653 |  |  |  
 | 
      
         | 3654 |  |  |             function Hi_Val (N : Node_Id) return Node_Id;
 | 
      
         | 3655 |  |  |             --  Given static expression or static range, returns an identifier
 | 
      
         | 3656 |  |  |             --  whose value is the high bound of the expression value or range.
 | 
      
         | 3657 |  |  |  
 | 
      
         | 3658 |  |  |             ------------
 | 
      
         | 3659 |  |  |             -- Hi_Val --
 | 
      
         | 3660 |  |  |             ------------
 | 
      
         | 3661 |  |  |  
 | 
      
         | 3662 |  |  |             function Hi_Val (N : Node_Id) return Node_Id is
 | 
      
         | 3663 |  |  |             begin
 | 
      
         | 3664 |  |  |                if Is_Static_Expression (N) then
 | 
      
         | 3665 |  |  |                   return New_Copy (N);
 | 
      
         | 3666 |  |  |                else
 | 
      
         | 3667 |  |  |                   pragma Assert (Nkind (N) = N_Range);
 | 
      
         | 3668 |  |  |                   return New_Copy (High_Bound (N));
 | 
      
         | 3669 |  |  |                end if;
 | 
      
         | 3670 |  |  |             end Hi_Val;
 | 
      
         | 3671 |  |  |  
 | 
      
         | 3672 |  |  |             ------------
 | 
      
         | 3673 |  |  |             -- Lo_Val --
 | 
      
         | 3674 |  |  |             ------------
 | 
      
         | 3675 |  |  |  
 | 
      
         | 3676 |  |  |             function Lo_Val (N : Node_Id) return Node_Id is
 | 
      
         | 3677 |  |  |             begin
 | 
      
         | 3678 |  |  |                if Is_Static_Expression (N) then
 | 
      
         | 3679 |  |  |                   return New_Copy (N);
 | 
      
         | 3680 |  |  |                else
 | 
      
         | 3681 |  |  |                   pragma Assert (Nkind (N) = N_Range);
 | 
      
         | 3682 |  |  |                   return New_Copy (Low_Bound (N));
 | 
      
         | 3683 |  |  |                end if;
 | 
      
         | 3684 |  |  |             end Lo_Val;
 | 
      
         | 3685 |  |  |  
 | 
      
         | 3686 |  |  |          --  Start of processing for Static_Predicate
 | 
      
         | 3687 |  |  |  
 | 
      
         | 3688 |  |  |          begin
 | 
      
         | 3689 |  |  |             --  Convert loop identifier to normal variable and reanalyze it so
 | 
      
         | 3690 |  |  |             --  that this conversion works. We have to use the same defining
 | 
      
         | 3691 |  |  |             --  identifier, since there may be references in the loop body.
 | 
      
         | 3692 |  |  |  
 | 
      
         | 3693 |  |  |             Set_Analyzed (Loop_Id, False);
 | 
      
         | 3694 |  |  |             Set_Ekind    (Loop_Id, E_Variable);
 | 
      
         | 3695 |  |  |  
 | 
      
         | 3696 |  |  |             --  Loop to create branches of case statement
 | 
      
         | 3697 |  |  |  
 | 
      
         | 3698 |  |  |             Alts := New_List;
 | 
      
         | 3699 |  |  |             P := First (Stat);
 | 
      
         | 3700 |  |  |             while Present (P) loop
 | 
      
         | 3701 |  |  |                if No (Next (P)) then
 | 
      
         | 3702 |  |  |                   S := Make_Exit_Statement (Loc);
 | 
      
         | 3703 |  |  |                else
 | 
      
         | 3704 |  |  |                   S :=
 | 
      
         | 3705 |  |  |                     Make_Assignment_Statement (Loc,
 | 
      
         | 3706 |  |  |                       Name       => New_Occurrence_Of (Loop_Id, Loc),
 | 
      
         | 3707 |  |  |                       Expression => Lo_Val (Next (P)));
 | 
      
         | 3708 |  |  |                   Set_Suppress_Assignment_Checks (S);
 | 
      
         | 3709 |  |  |                end if;
 | 
      
         | 3710 |  |  |  
 | 
      
         | 3711 |  |  |                Append_To (Alts,
 | 
      
         | 3712 |  |  |                  Make_Case_Statement_Alternative (Loc,
 | 
      
         | 3713 |  |  |                    Statements       => New_List (S),
 | 
      
         | 3714 |  |  |                    Discrete_Choices => New_List (Hi_Val (P))));
 | 
      
         | 3715 |  |  |  
 | 
      
         | 3716 |  |  |                Next (P);
 | 
      
         | 3717 |  |  |             end loop;
 | 
      
         | 3718 |  |  |  
 | 
      
         | 3719 |  |  |             --  Add others choice
 | 
      
         | 3720 |  |  |  
 | 
      
         | 3721 |  |  |             S :=
 | 
      
         | 3722 |  |  |                Make_Assignment_Statement (Loc,
 | 
      
         | 3723 |  |  |                  Name       => New_Occurrence_Of (Loop_Id, Loc),
 | 
      
         | 3724 |  |  |                  Expression =>
 | 
      
         | 3725 |  |  |                    Make_Attribute_Reference (Loc,
 | 
      
         | 3726 |  |  |                      Prefix => New_Occurrence_Of (Ltype, Loc),
 | 
      
         | 3727 |  |  |                      Attribute_Name => Name_Succ,
 | 
      
         | 3728 |  |  |                      Expressions    => New_List (
 | 
      
         | 3729 |  |  |                        New_Occurrence_Of (Loop_Id, Loc))));
 | 
      
         | 3730 |  |  |             Set_Suppress_Assignment_Checks (S);
 | 
      
         | 3731 |  |  |  
 | 
      
         | 3732 |  |  |             Append_To (Alts,
 | 
      
         | 3733 |  |  |               Make_Case_Statement_Alternative (Loc,
 | 
      
         | 3734 |  |  |                 Discrete_Choices => New_List (Make_Others_Choice (Loc)),
 | 
      
         | 3735 |  |  |                 Statements       => New_List (S)));
 | 
      
         | 3736 |  |  |  
 | 
      
         | 3737 |  |  |             --  Construct case statement and append to body statements
 | 
      
         | 3738 |  |  |  
 | 
      
         | 3739 |  |  |             Cstm :=
 | 
      
         | 3740 |  |  |               Make_Case_Statement (Loc,
 | 
      
         | 3741 |  |  |                 Expression   => New_Occurrence_Of (Loop_Id, Loc),
 | 
      
         | 3742 |  |  |                 Alternatives => Alts);
 | 
      
         | 3743 |  |  |             Append_To (Stmts, Cstm);
 | 
      
         | 3744 |  |  |  
 | 
      
         | 3745 |  |  |             --  Rewrite the loop
 | 
      
         | 3746 |  |  |  
 | 
      
         | 3747 |  |  |             D :=
 | 
      
         | 3748 |  |  |                Make_Object_Declaration (Loc,
 | 
      
         | 3749 |  |  |                  Defining_Identifier => Loop_Id,
 | 
      
         | 3750 |  |  |                  Object_Definition   => New_Occurrence_Of (Ltype, Loc),
 | 
      
         | 3751 |  |  |                  Expression          => Lo_Val (First (Stat)));
 | 
      
         | 3752 |  |  |             Set_Suppress_Assignment_Checks (D);
 | 
      
         | 3753 |  |  |  
 | 
      
         | 3754 |  |  |             Rewrite (N,
 | 
      
         | 3755 |  |  |               Make_Block_Statement (Loc,
 | 
      
         | 3756 |  |  |                 Declarations               => New_List (D),
 | 
      
         | 3757 |  |  |                 Handled_Statement_Sequence =>
 | 
      
         | 3758 |  |  |                   Make_Handled_Sequence_Of_Statements (Loc,
 | 
      
         | 3759 |  |  |                     Statements => New_List (
 | 
      
         | 3760 |  |  |                       Make_Loop_Statement (Loc,
 | 
      
         | 3761 |  |  |                         Statements => Stmts,
 | 
      
         | 3762 |  |  |                         End_Label  => Empty)))));
 | 
      
         | 3763 |  |  |  
 | 
      
         | 3764 |  |  |             Analyze (N);
 | 
      
         | 3765 |  |  |          end Static_Predicate;
 | 
      
         | 3766 |  |  |       end if;
 | 
      
         | 3767 |  |  |    end Expand_Predicated_Loop;
 | 
      
         | 3768 |  |  |  
 | 
      
         | 3769 |  |  |    ------------------------------
 | 
      
         | 3770 |  |  |    -- Make_Tag_Ctrl_Assignment --
 | 
      
         | 3771 |  |  |    ------------------------------
 | 
      
         | 3772 |  |  |  
 | 
      
         | 3773 |  |  |    function Make_Tag_Ctrl_Assignment (N : Node_Id) return List_Id is
 | 
      
         | 3774 |  |  |       Asn : constant Node_Id    := Relocate_Node (N);
 | 
      
         | 3775 |  |  |       L   : constant Node_Id    := Name (N);
 | 
      
         | 3776 |  |  |       Loc : constant Source_Ptr := Sloc (N);
 | 
      
         | 3777 |  |  |       Res : constant List_Id    := New_List;
 | 
      
         | 3778 |  |  |       T   : constant Entity_Id  := Underlying_Type (Etype (L));
 | 
      
         | 3779 |  |  |  
 | 
      
         | 3780 |  |  |       Comp_Asn : constant Boolean := Is_Fully_Repped_Tagged_Type (T);
 | 
      
         | 3781 |  |  |       Ctrl_Act : constant Boolean := Needs_Finalization (T)
 | 
      
         | 3782 |  |  |                                        and then not No_Ctrl_Actions (N);
 | 
      
         | 3783 |  |  |       Save_Tag : constant Boolean := Is_Tagged_Type (T)
 | 
      
         | 3784 |  |  |                                        and then not Comp_Asn
 | 
      
         | 3785 |  |  |                                        and then not No_Ctrl_Actions (N)
 | 
      
         | 3786 |  |  |                                        and then Tagged_Type_Expansion;
 | 
      
         | 3787 |  |  |       --  Tags are not saved and restored when VM_Target because VM tags are
 | 
      
         | 3788 |  |  |       --  represented implicitly in objects.
 | 
      
         | 3789 |  |  |  
 | 
      
         | 3790 |  |  |       Next_Id : Entity_Id;
 | 
      
         | 3791 |  |  |       Prev_Id : Entity_Id;
 | 
      
         | 3792 |  |  |       Tag_Id  : Entity_Id;
 | 
      
         | 3793 |  |  |  
 | 
      
         | 3794 |  |  |    begin
 | 
      
         | 3795 |  |  |       --  Finalize the target of the assignment when controlled
 | 
      
         | 3796 |  |  |  
 | 
      
         | 3797 |  |  |       --  We have two exceptions here:
 | 
      
         | 3798 |  |  |  
 | 
      
         | 3799 |  |  |       --   1. If we are in an init proc since it is an initialization more
 | 
      
         | 3800 |  |  |       --      than an assignment.
 | 
      
         | 3801 |  |  |  
 | 
      
         | 3802 |  |  |       --   2. If the left-hand side is a temporary that was not initialized
 | 
      
         | 3803 |  |  |       --      (or the parent part of a temporary since it is the case in
 | 
      
         | 3804 |  |  |       --      extension aggregates). Such a temporary does not come from
 | 
      
         | 3805 |  |  |       --      source. We must examine the original node for the prefix, because
 | 
      
         | 3806 |  |  |       --      it may be a component of an entry formal, in which case it has
 | 
      
         | 3807 |  |  |       --      been rewritten and does not appear to come from source either.
 | 
      
         | 3808 |  |  |  
 | 
      
         | 3809 |  |  |       --  Case of init proc
 | 
      
         | 3810 |  |  |  
 | 
      
         | 3811 |  |  |       if not Ctrl_Act then
 | 
      
         | 3812 |  |  |          null;
 | 
      
         | 3813 |  |  |  
 | 
      
         | 3814 |  |  |       --  The left hand side is an uninitialized temporary object
 | 
      
         | 3815 |  |  |  
 | 
      
         | 3816 |  |  |       elsif Nkind (L) = N_Type_Conversion
 | 
      
         | 3817 |  |  |         and then Is_Entity_Name (Expression (L))
 | 
      
         | 3818 |  |  |         and then Nkind (Parent (Entity (Expression (L)))) =
 | 
      
         | 3819 |  |  |                                               N_Object_Declaration
 | 
      
         | 3820 |  |  |         and then No_Initialization (Parent (Entity (Expression (L))))
 | 
      
         | 3821 |  |  |       then
 | 
      
         | 3822 |  |  |          null;
 | 
      
         | 3823 |  |  |  
 | 
      
         | 3824 |  |  |       else
 | 
      
         | 3825 |  |  |          Append_To (Res,
 | 
      
         | 3826 |  |  |            Make_Final_Call
 | 
      
         | 3827 |  |  |              (Obj_Ref => Duplicate_Subexpr_No_Checks (L),
 | 
      
         | 3828 |  |  |               Typ     => Etype (L)));
 | 
      
         | 3829 |  |  |       end if;
 | 
      
         | 3830 |  |  |  
 | 
      
         | 3831 |  |  |       --  Save the Tag in a local variable Tag_Id
 | 
      
         | 3832 |  |  |  
 | 
      
         | 3833 |  |  |       if Save_Tag then
 | 
      
         | 3834 |  |  |          Tag_Id := Make_Temporary (Loc, 'A');
 | 
      
         | 3835 |  |  |  
 | 
      
         | 3836 |  |  |          Append_To (Res,
 | 
      
         | 3837 |  |  |            Make_Object_Declaration (Loc,
 | 
      
         | 3838 |  |  |              Defining_Identifier => Tag_Id,
 | 
      
         | 3839 |  |  |              Object_Definition   => New_Reference_To (RTE (RE_Tag), Loc),
 | 
      
         | 3840 |  |  |              Expression          =>
 | 
      
         | 3841 |  |  |                Make_Selected_Component (Loc,
 | 
      
         | 3842 |  |  |                  Prefix        => Duplicate_Subexpr_No_Checks (L),
 | 
      
         | 3843 |  |  |                  Selector_Name =>
 | 
      
         | 3844 |  |  |                    New_Reference_To (First_Tag_Component (T), Loc))));
 | 
      
         | 3845 |  |  |  
 | 
      
         | 3846 |  |  |       --  Otherwise Tag_Id is not used
 | 
      
         | 3847 |  |  |  
 | 
      
         | 3848 |  |  |       else
 | 
      
         | 3849 |  |  |          Tag_Id := Empty;
 | 
      
         | 3850 |  |  |       end if;
 | 
      
         | 3851 |  |  |  
 | 
      
         | 3852 |  |  |       --  Save the Prev and Next fields on .NET/JVM. This is not needed on non
 | 
      
         | 3853 |  |  |       --  VM targets since the fields are not part of the object.
 | 
      
         | 3854 |  |  |  
 | 
      
         | 3855 |  |  |       if VM_Target /= No_VM
 | 
      
         | 3856 |  |  |         and then Is_Controlled (T)
 | 
      
         | 3857 |  |  |       then
 | 
      
         | 3858 |  |  |          Prev_Id := Make_Temporary (Loc, 'P');
 | 
      
         | 3859 |  |  |          Next_Id := Make_Temporary (Loc, 'N');
 | 
      
         | 3860 |  |  |  
 | 
      
         | 3861 |  |  |          --  Generate:
 | 
      
         | 3862 |  |  |          --    Pnn : Root_Controlled_Ptr := Root_Controlled (L).Prev;
 | 
      
         | 3863 |  |  |  
 | 
      
         | 3864 |  |  |          Append_To (Res,
 | 
      
         | 3865 |  |  |            Make_Object_Declaration (Loc,
 | 
      
         | 3866 |  |  |              Defining_Identifier => Prev_Id,
 | 
      
         | 3867 |  |  |              Object_Definition   =>
 | 
      
         | 3868 |  |  |                New_Reference_To (RTE (RE_Root_Controlled_Ptr), Loc),
 | 
      
         | 3869 |  |  |              Expression          =>
 | 
      
         | 3870 |  |  |                Make_Selected_Component (Loc,
 | 
      
         | 3871 |  |  |                  Prefix        =>
 | 
      
         | 3872 |  |  |                    Unchecked_Convert_To
 | 
      
         | 3873 |  |  |                      (RTE (RE_Root_Controlled), New_Copy_Tree (L)),
 | 
      
         | 3874 |  |  |                  Selector_Name =>
 | 
      
         | 3875 |  |  |                    Make_Identifier (Loc, Name_Prev))));
 | 
      
         | 3876 |  |  |  
 | 
      
         | 3877 |  |  |          --  Generate:
 | 
      
         | 3878 |  |  |          --    Nnn : Root_Controlled_Ptr := Root_Controlled (L).Next;
 | 
      
         | 3879 |  |  |  
 | 
      
         | 3880 |  |  |          Append_To (Res,
 | 
      
         | 3881 |  |  |            Make_Object_Declaration (Loc,
 | 
      
         | 3882 |  |  |              Defining_Identifier => Next_Id,
 | 
      
         | 3883 |  |  |              Object_Definition   =>
 | 
      
         | 3884 |  |  |                New_Reference_To (RTE (RE_Root_Controlled_Ptr), Loc),
 | 
      
         | 3885 |  |  |              Expression          =>
 | 
      
         | 3886 |  |  |                Make_Selected_Component (Loc,
 | 
      
         | 3887 |  |  |                  Prefix        =>
 | 
      
         | 3888 |  |  |                    Unchecked_Convert_To
 | 
      
         | 3889 |  |  |                      (RTE (RE_Root_Controlled), New_Copy_Tree (L)),
 | 
      
         | 3890 |  |  |                  Selector_Name =>
 | 
      
         | 3891 |  |  |                    Make_Identifier (Loc, Name_Next))));
 | 
      
         | 3892 |  |  |       end if;
 | 
      
         | 3893 |  |  |  
 | 
      
         | 3894 |  |  |       --  If the tagged type has a full rep clause, expand the assignment into
 | 
      
         | 3895 |  |  |       --  component-wise assignments. Mark the node as unanalyzed in order to
 | 
      
         | 3896 |  |  |       --  generate the proper code and propagate this scenario by setting a
 | 
      
         | 3897 |  |  |       --  flag to avoid infinite recursion.
 | 
      
         | 3898 |  |  |  
 | 
      
         | 3899 |  |  |       if Comp_Asn then
 | 
      
         | 3900 |  |  |          Set_Analyzed (Asn, False);
 | 
      
         | 3901 |  |  |          Set_Componentwise_Assignment (Asn, True);
 | 
      
         | 3902 |  |  |       end if;
 | 
      
         | 3903 |  |  |  
 | 
      
         | 3904 |  |  |       Append_To (Res, Asn);
 | 
      
         | 3905 |  |  |  
 | 
      
         | 3906 |  |  |       --  Restore the tag
 | 
      
         | 3907 |  |  |  
 | 
      
         | 3908 |  |  |       if Save_Tag then
 | 
      
         | 3909 |  |  |          Append_To (Res,
 | 
      
         | 3910 |  |  |            Make_Assignment_Statement (Loc,
 | 
      
         | 3911 |  |  |              Name       =>
 | 
      
         | 3912 |  |  |                Make_Selected_Component (Loc,
 | 
      
         | 3913 |  |  |                  Prefix        => Duplicate_Subexpr_No_Checks (L),
 | 
      
         | 3914 |  |  |                  Selector_Name =>
 | 
      
         | 3915 |  |  |                    New_Reference_To (First_Tag_Component (T), Loc)),
 | 
      
         | 3916 |  |  |              Expression => New_Reference_To (Tag_Id, Loc)));
 | 
      
         | 3917 |  |  |       end if;
 | 
      
         | 3918 |  |  |  
 | 
      
         | 3919 |  |  |       --  Restore the Prev and Next fields on .NET/JVM
 | 
      
         | 3920 |  |  |  
 | 
      
         | 3921 |  |  |       if VM_Target /= No_VM
 | 
      
         | 3922 |  |  |         and then Is_Controlled (T)
 | 
      
         | 3923 |  |  |       then
 | 
      
         | 3924 |  |  |          --  Generate:
 | 
      
         | 3925 |  |  |          --    Root_Controlled (L).Prev := Prev_Id;
 | 
      
         | 3926 |  |  |  
 | 
      
         | 3927 |  |  |          Append_To (Res,
 | 
      
         | 3928 |  |  |            Make_Assignment_Statement (Loc,
 | 
      
         | 3929 |  |  |              Name       =>
 | 
      
         | 3930 |  |  |                Make_Selected_Component (Loc,
 | 
      
         | 3931 |  |  |                  Prefix        =>
 | 
      
         | 3932 |  |  |                    Unchecked_Convert_To
 | 
      
         | 3933 |  |  |                      (RTE (RE_Root_Controlled), New_Copy_Tree (L)),
 | 
      
         | 3934 |  |  |                  Selector_Name =>
 | 
      
         | 3935 |  |  |                    Make_Identifier (Loc, Name_Prev)),
 | 
      
         | 3936 |  |  |              Expression => New_Reference_To (Prev_Id, Loc)));
 | 
      
         | 3937 |  |  |  
 | 
      
         | 3938 |  |  |          --  Generate:
 | 
      
         | 3939 |  |  |          --    Root_Controlled (L).Next := Next_Id;
 | 
      
         | 3940 |  |  |  
 | 
      
         | 3941 |  |  |          Append_To (Res,
 | 
      
         | 3942 |  |  |            Make_Assignment_Statement (Loc,
 | 
      
         | 3943 |  |  |              Name       =>
 | 
      
         | 3944 |  |  |                Make_Selected_Component (Loc,
 | 
      
         | 3945 |  |  |                  Prefix        =>
 | 
      
         | 3946 |  |  |                    Unchecked_Convert_To
 | 
      
         | 3947 |  |  |                      (RTE (RE_Root_Controlled), New_Copy_Tree (L)),
 | 
      
         | 3948 |  |  |                  Selector_Name => Make_Identifier (Loc, Name_Next)),
 | 
      
         | 3949 |  |  |              Expression => New_Reference_To (Next_Id, Loc)));
 | 
      
         | 3950 |  |  |       end if;
 | 
      
         | 3951 |  |  |  
 | 
      
         | 3952 |  |  |       --  Adjust the target after the assignment when controlled (not in the
 | 
      
         | 3953 |  |  |       --  init proc since it is an initialization more than an assignment).
 | 
      
         | 3954 |  |  |  
 | 
      
         | 3955 |  |  |       if Ctrl_Act then
 | 
      
         | 3956 |  |  |          Append_To (Res,
 | 
      
         | 3957 |  |  |            Make_Adjust_Call
 | 
      
         | 3958 |  |  |              (Obj_Ref => Duplicate_Subexpr_Move_Checks (L),
 | 
      
         | 3959 |  |  |               Typ     => Etype (L)));
 | 
      
         | 3960 |  |  |       end if;
 | 
      
         | 3961 |  |  |  
 | 
      
         | 3962 |  |  |       return Res;
 | 
      
         | 3963 |  |  |  
 | 
      
         | 3964 |  |  |    exception
 | 
      
         | 3965 |  |  |  
 | 
      
         | 3966 |  |  |       --  Could use comment here ???
 | 
      
         | 3967 |  |  |  
 | 
      
         | 3968 |  |  |       when RE_Not_Available =>
 | 
      
         | 3969 |  |  |          return Empty_List;
 | 
      
         | 3970 |  |  |    end Make_Tag_Ctrl_Assignment;
 | 
      
         | 3971 |  |  |  
 | 
      
         | 3972 |  |  | end Exp_Ch5;
 |