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