OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-dev/] [or1k-gcc/] [gcc/] [ada/] [exp_ch5.adb] - Blame information for rev 749

Go to most recent revision | Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.