OSDN Git Service

* sysdep.c: Problem discovered during IA64 VMS port.
[pf3gnuchains/gcc-fork.git] / gcc / ada / checks.adb
1 ------------------------------------------------------------------------------
2 --                                                                          --
3 --                         GNAT COMPILER COMPONENTS                         --
4 --                                                                          --
5 --                               C H E C K S                                --
6 --                                                                          --
7 --                                 B o d y                                  --
8 --                                                                          --
9 --          Copyright (C) 1992-2003 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 2,  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 COPYING.  If not, write --
19 -- to  the Free Software Foundation,  59 Temple Place - Suite 330,  Boston, --
20 -- MA 02111-1307, USA.                                                      --
21 --                                                                          --
22 -- GNAT was originally developed  by the GNAT team at  New York University. --
23 -- Extensive contributions were provided by Ada Core Technologies Inc.      --
24 --                                                                          --
25 ------------------------------------------------------------------------------
26
27 with Atree;    use Atree;
28 with Debug;    use Debug;
29 with Einfo;    use Einfo;
30 with Errout;   use Errout;
31 with Exp_Ch2;  use Exp_Ch2;
32 with Exp_Util; use Exp_Util;
33 with Elists;   use Elists;
34 with Freeze;   use Freeze;
35 with Lib;      use Lib;
36 with Nlists;   use Nlists;
37 with Nmake;    use Nmake;
38 with Opt;      use Opt;
39 with Output;   use Output;
40 with Restrict; use Restrict;
41 with Rtsfind;  use Rtsfind;
42 with Sem;      use Sem;
43 with Sem_Eval; use Sem_Eval;
44 with Sem_Ch8;  use Sem_Ch8;
45 with Sem_Res;  use Sem_Res;
46 with Sem_Util; use Sem_Util;
47 with Sem_Warn; use Sem_Warn;
48 with Sinfo;    use Sinfo;
49 with Sinput;   use Sinput;
50 with Snames;   use Snames;
51 with Sprint;   use Sprint;
52 with Stand;    use Stand;
53 with Targparm; use Targparm;
54 with Tbuild;   use Tbuild;
55 with Ttypes;   use Ttypes;
56 with Urealp;   use Urealp;
57 with Validsw;  use Validsw;
58
59 package body Checks is
60
61    --  General note: many of these routines are concerned with generating
62    --  checking code to make sure that constraint error is raised at runtime.
63    --  Clearly this code is only needed if the expander is active, since
64    --  otherwise we will not be generating code or going into the runtime
65    --  execution anyway.
66
67    --  We therefore disconnect most of these checks if the expander is
68    --  inactive. This has the additional benefit that we do not need to
69    --  worry about the tree being messed up by previous errors (since errors
70    --  turn off expansion anyway).
71
72    --  There are a few exceptions to the above rule. For instance routines
73    --  such as Apply_Scalar_Range_Check that do not insert any code can be
74    --  safely called even when the Expander is inactive (but Errors_Detected
75    --  is 0). The benefit of executing this code when expansion is off, is
76    --  the ability to emit constraint error warning for static expressions
77    --  even when we are not generating code.
78
79    -------------------------------------
80    -- Suppression of Redundant Checks --
81    -------------------------------------
82
83    --  This unit implements a limited circuit for removal of redundant
84    --  checks. The processing is based on a tracing of simple sequential
85    --  flow. For any sequence of statements, we save expressions that are
86    --  marked to be checked, and then if the same expression appears later
87    --  with the same check, then under certain circumstances, the second
88    --  check can be suppressed.
89
90    --  Basically, we can suppress the check if we know for certain that
91    --  the previous expression has been elaborated (together with its
92    --  check), and we know that the exception frame is the same, and that
93    --  nothing has happened to change the result of the exception.
94
95    --  Let us examine each of these three conditions in turn to describe
96    --  how we ensure that this condition is met.
97
98    --  First, we need to know for certain that the previous expression has
99    --  been executed. This is done principly by the mechanism of calling
100    --  Conditional_Statements_Begin at the start of any statement sequence
101    --  and Conditional_Statements_End at the end. The End call causes all
102    --  checks remembered since the Begin call to be discarded. This does
103    --  miss a few cases, notably the case of a nested BEGIN-END block with
104    --  no exception handlers. But the important thing is to be conservative.
105    --  The other protection is that all checks are discarded if a label
106    --  is encountered, since then the assumption of sequential execution
107    --  is violated, and we don't know enough about the flow.
108
109    --  Second, we need to know that the exception frame is the same. We
110    --  do this by killing all remembered checks when we enter a new frame.
111    --  Again, that's over-conservative, but generally the cases we can help
112    --  with are pretty local anyway (like the body of a loop for example).
113
114    --  Third, we must be sure to forget any checks which are no longer valid.
115    --  This is done by two mechanisms, first the Kill_Checks_Variable call is
116    --  used to note any changes to local variables. We only attempt to deal
117    --  with checks involving local variables, so we do not need to worry
118    --  about global variables. Second, a call to any non-global procedure
119    --  causes us to abandon all stored checks, since such a all may affect
120    --  the values of any local variables.
121
122    --  The following define the data structures used to deal with remembering
123    --  checks so that redundant checks can be eliminated as described above.
124
125    --  Right now, the only expressions that we deal with are of the form of
126    --  simple local objects (either declared locally, or IN parameters) or
127    --  such objects plus/minus a compile time known constant. We can do
128    --  more later on if it seems worthwhile, but this catches many simple
129    --  cases in practice.
130
131    --  The following record type reflects a single saved check. An entry
132    --  is made in the stack of saved checks if and only if the expression
133    --  has been elaborated with the indicated checks.
134
135    type Saved_Check is record
136       Killed : Boolean;
137       --  Set True if entry is killed by Kill_Checks
138
139       Entity : Entity_Id;
140       --  The entity involved in the expression that is checked
141
142       Offset : Uint;
143       --  A compile time value indicating the result of adding or
144       --  subtracting a compile time value. This value is to be
145       --  added to the value of the Entity. A value of zero is
146       --  used for the case of a simple entity reference.
147
148       Check_Type : Character;
149       --  This is set to 'R' for a range check (in which case Target_Type
150       --  is set to the target type for the range check) or to 'O' for an
151       --  overflow check (in which case Target_Type is set to Empty).
152
153       Target_Type : Entity_Id;
154       --  Used only if Do_Range_Check is set. Records the target type for
155       --  the check. We need this, because a check is a duplicate only if
156       --  it has a the same target type (or more accurately one with a
157       --  range that is smaller or equal to the stored target type of a
158       --  saved check).
159    end record;
160
161    --  The following table keeps track of saved checks. Rather than use an
162    --  extensible table. We just use a table of fixed size, and we discard
163    --  any saved checks that do not fit. That's very unlikely to happen and
164    --  this is only an optimization in any case.
165
166    Saved_Checks : array (Int range 1 .. 200) of Saved_Check;
167    --  Array of saved checks
168
169    Num_Saved_Checks : Nat := 0;
170    --  Number of saved checks
171
172    --  The following stack keeps track of statement ranges. It is treated
173    --  as a stack. When Conditional_Statements_Begin is called, an entry
174    --  is pushed onto this stack containing the value of Num_Saved_Checks
175    --  at the time of the call. Then when Conditional_Statements_End is
176    --  called, this value is popped off and used to reset Num_Saved_Checks.
177
178    --  Note: again, this is a fixed length stack with a size that should
179    --  always be fine. If the value of the stack pointer goes above the
180    --  limit, then we just forget all saved checks.
181
182    Saved_Checks_Stack : array (Int range 1 .. 100) of Nat;
183    Saved_Checks_TOS : Nat := 0;
184
185    -----------------------
186    -- Local Subprograms --
187    -----------------------
188
189    procedure Apply_Selected_Length_Checks
190      (Ck_Node    : Node_Id;
191       Target_Typ : Entity_Id;
192       Source_Typ : Entity_Id;
193       Do_Static  : Boolean);
194    --  This is the subprogram that does all the work for Apply_Length_Check
195    --  and Apply_Static_Length_Check. Expr, Target_Typ and Source_Typ are as
196    --  described for the above routines. The Do_Static flag indicates that
197    --  only a static check is to be done.
198
199    procedure Apply_Selected_Range_Checks
200      (Ck_Node    : Node_Id;
201       Target_Typ : Entity_Id;
202       Source_Typ : Entity_Id;
203       Do_Static  : Boolean);
204    --  This is the subprogram that does all the work for Apply_Range_Check.
205    --  Expr, Target_Typ and Source_Typ are as described for the above
206    --  routine. The Do_Static flag indicates that only a static check is
207    --  to be done.
208
209    procedure Find_Check
210      (Expr        : Node_Id;
211       Check_Type  : Character;
212       Target_Type : Entity_Id;
213       Entry_OK    : out Boolean;
214       Check_Num   : out Nat;
215       Ent         : out Entity_Id;
216       Ofs         : out Uint);
217    --  This routine is used by Enable_Range_Check and Enable_Overflow_Check
218    --  to see if a check is of the form for optimization, and if so, to see
219    --  if it has already been performed. Expr is the expression to check,
220    --  and Check_Type is 'R' for a range check, 'O' for an overflow check.
221    --  Target_Type is the target type for a range check, and Empty for an
222    --  overflow check. If the entry is not of the form for optimization,
223    --  then Entry_OK is set to False, and the remaining out parameters
224    --  are undefined. If the entry is OK, then Ent/Ofs are set to the
225    --  entity and offset from the expression. Check_Num is the number of
226    --  a matching saved entry in Saved_Checks, or zero if no such entry
227    --  is located.
228
229    function Get_Discriminal (E : Entity_Id; Bound : Node_Id) return Node_Id;
230    --  If a discriminal is used in constraining a prival, Return reference
231    --  to the discriminal of the protected body (which renames the parameter
232    --  of the enclosing protected operation). This clumsy transformation is
233    --  needed because privals are created too late and their actual subtypes
234    --  are not available when analysing the bodies of the protected operations.
235    --  To be cleaned up???
236
237    function Guard_Access
238      (Cond    : Node_Id;
239       Loc     : Source_Ptr;
240       Ck_Node : Node_Id)
241       return    Node_Id;
242    --  In the access type case, guard the test with a test to ensure
243    --  that the access value is non-null, since the checks do not
244    --  not apply to null access values.
245
246    procedure Install_Static_Check (R_Cno : Node_Id; Loc : Source_Ptr);
247    --  Called by Apply_{Length,Range}_Checks to rewrite the tree with the
248    --  Constraint_Error node.
249
250    function Selected_Length_Checks
251      (Ck_Node    : Node_Id;
252       Target_Typ : Entity_Id;
253       Source_Typ : Entity_Id;
254       Warn_Node  : Node_Id)
255       return       Check_Result;
256    --  Like Apply_Selected_Length_Checks, except it doesn't modify
257    --  anything, just returns a list of nodes as described in the spec of
258    --  this package for the Range_Check function.
259
260    function Selected_Range_Checks
261      (Ck_Node    : Node_Id;
262       Target_Typ : Entity_Id;
263       Source_Typ : Entity_Id;
264       Warn_Node  : Node_Id)
265       return       Check_Result;
266    --  Like Apply_Selected_Range_Checks, except it doesn't modify anything,
267    --  just returns a list of nodes as described in the spec of this package
268    --  for the Range_Check function.
269
270    ------------------------------
271    -- Access_Checks_Suppressed --
272    ------------------------------
273
274    function Access_Checks_Suppressed (E : Entity_Id) return Boolean is
275    begin
276       if Present (E) and then Checks_May_Be_Suppressed (E) then
277          return Is_Check_Suppressed (E, Access_Check);
278       else
279          return Scope_Suppress (Access_Check);
280       end if;
281    end Access_Checks_Suppressed;
282
283    -------------------------------------
284    -- Accessibility_Checks_Suppressed --
285    -------------------------------------
286
287    function Accessibility_Checks_Suppressed (E : Entity_Id) return Boolean is
288    begin
289       if Present (E) and then Checks_May_Be_Suppressed (E) then
290          return Is_Check_Suppressed (E, Accessibility_Check);
291       else
292          return Scope_Suppress (Accessibility_Check);
293       end if;
294    end Accessibility_Checks_Suppressed;
295
296    -------------------------
297    -- Append_Range_Checks --
298    -------------------------
299
300    procedure Append_Range_Checks
301      (Checks       : Check_Result;
302       Stmts        : List_Id;
303       Suppress_Typ : Entity_Id;
304       Static_Sloc  : Source_Ptr;
305       Flag_Node    : Node_Id)
306    is
307       Internal_Flag_Node   : constant Node_Id    := Flag_Node;
308       Internal_Static_Sloc : constant Source_Ptr := Static_Sloc;
309
310       Checks_On : constant Boolean :=
311                     (not Index_Checks_Suppressed (Suppress_Typ))
312                        or else
313                     (not Range_Checks_Suppressed (Suppress_Typ));
314
315    begin
316       --  For now we just return if Checks_On is false, however this should
317       --  be enhanced to check for an always True value in the condition
318       --  and to generate a compilation warning???
319
320       if not Checks_On then
321          return;
322       end if;
323
324       for J in 1 .. 2 loop
325          exit when No (Checks (J));
326
327          if Nkind (Checks (J)) = N_Raise_Constraint_Error
328            and then Present (Condition (Checks (J)))
329          then
330             if not Has_Dynamic_Range_Check (Internal_Flag_Node) then
331                Append_To (Stmts, Checks (J));
332                Set_Has_Dynamic_Range_Check (Internal_Flag_Node);
333             end if;
334
335          else
336             Append_To
337               (Stmts,
338                 Make_Raise_Constraint_Error (Internal_Static_Sloc,
339                   Reason => CE_Range_Check_Failed));
340          end if;
341       end loop;
342    end Append_Range_Checks;
343
344    ------------------------
345    -- Apply_Access_Check --
346    ------------------------
347
348    procedure Apply_Access_Check (N : Node_Id) is
349       P : constant Node_Id := Prefix (N);
350
351    begin
352       if Inside_A_Generic then
353          return;
354       end if;
355
356       if Is_Entity_Name (P) then
357          Check_Unset_Reference (P);
358       end if;
359
360       --  Don't need access check if prefix is known to be non-null
361
362       if Known_Non_Null (P) then
363          return;
364
365       --  Don't need access checks if they are suppressed on the type
366
367       elsif Access_Checks_Suppressed (Etype (P)) then
368          return;
369       end if;
370
371       --  Case where P is an entity name
372
373       if Is_Entity_Name (P) then
374          declare
375             Ent : constant Entity_Id := Entity (P);
376
377          begin
378             if Access_Checks_Suppressed (Ent) then
379                return;
380             end if;
381
382             --  Otherwise we are going to generate an access check, and
383             --  are we have done it, the entity will now be known non null
384             --  But we have to check for safe sequential semantics here!
385
386             if Safe_To_Capture_Value (N, Ent) then
387                Set_Is_Known_Non_Null (Ent);
388             end if;
389          end;
390       end if;
391
392       --  Access check is required
393
394       declare
395          Loc : constant Source_Ptr := Sloc (N);
396
397       begin
398          Insert_Action (N,
399            Make_Raise_Constraint_Error (Sloc (N),
400               Condition =>
401                 Make_Op_Eq (Loc,
402                   Left_Opnd => Duplicate_Subexpr_Move_Checks (P),
403                   Right_Opnd =>
404                     Make_Null (Loc)),
405               Reason => CE_Access_Check_Failed));
406       end;
407    end Apply_Access_Check;
408
409    -------------------------------
410    -- Apply_Accessibility_Check --
411    -------------------------------
412
413    procedure Apply_Accessibility_Check (N : Node_Id; Typ : Entity_Id) is
414       Loc         : constant Source_Ptr := Sloc (N);
415       Param_Ent   : constant Entity_Id  := Param_Entity (N);
416       Param_Level : Node_Id;
417       Type_Level  : Node_Id;
418
419    begin
420       if Inside_A_Generic then
421          return;
422
423       --  Only apply the run-time check if the access parameter
424       --  has an associated extra access level parameter and
425       --  when the level of the type is less deep than the level
426       --  of the access parameter.
427
428       elsif Present (Param_Ent)
429          and then Present (Extra_Accessibility (Param_Ent))
430          and then UI_Gt (Object_Access_Level (N),
431                          Type_Access_Level (Typ))
432          and then not Accessibility_Checks_Suppressed (Param_Ent)
433          and then not Accessibility_Checks_Suppressed (Typ)
434       then
435          Param_Level :=
436            New_Occurrence_Of (Extra_Accessibility (Param_Ent), Loc);
437
438          Type_Level :=
439            Make_Integer_Literal (Loc, Type_Access_Level (Typ));
440
441          --  Raise Program_Error if the accessibility level of the
442          --  the access parameter is deeper than the level of the
443          --  target access type.
444
445          Insert_Action (N,
446            Make_Raise_Program_Error (Loc,
447              Condition =>
448                Make_Op_Gt (Loc,
449                  Left_Opnd  => Param_Level,
450                  Right_Opnd => Type_Level),
451              Reason => PE_Accessibility_Check_Failed));
452
453          Analyze_And_Resolve (N);
454       end if;
455    end Apply_Accessibility_Check;
456
457    ---------------------------
458    -- Apply_Alignment_Check --
459    ---------------------------
460
461    procedure Apply_Alignment_Check (E : Entity_Id; N : Node_Id) is
462       AC   : constant Node_Id := Address_Clause (E);
463       Expr : Node_Id;
464       Loc  : Source_Ptr;
465
466    begin
467       --  See if check needed. Note that we never need a check if the
468       --  maximum alignment is one, since the check will always succeed
469
470       if No (AC)
471         or else not Check_Address_Alignment (AC)
472         or else Maximum_Alignment = 1
473       then
474          return;
475       end if;
476
477       Loc  := Sloc (AC);
478       Expr := Expression (AC);
479
480       if Nkind (Expr) = N_Unchecked_Type_Conversion then
481          Expr := Expression (Expr);
482
483       elsif Nkind (Expr) = N_Function_Call
484         and then Is_RTE (Entity (Name (Expr)), RE_To_Address)
485       then
486          Expr := First (Parameter_Associations (Expr));
487
488          if Nkind (Expr) = N_Parameter_Association then
489             Expr := Explicit_Actual_Parameter (Expr);
490          end if;
491       end if;
492
493       --  Here Expr is the address value. See if we know that the
494       --  value is unacceptable at compile time.
495
496       if Compile_Time_Known_Value (Expr)
497         and then Known_Alignment (E)
498       then
499          if Expr_Value (Expr) mod Alignment (E) /= 0 then
500             Insert_Action (N,
501                Make_Raise_Program_Error (Loc,
502                  Reason => PE_Misaligned_Address_Value));
503             Error_Msg_NE
504               ("?specified address for& not " &
505                "consistent with alignment", Expr, E);
506          end if;
507
508       --  Here we do not know if the value is acceptable, generate
509       --  code to raise PE if alignment is inappropriate.
510
511       else
512          --  Skip generation of this code if we don't want elab code
513
514          if not Restrictions (No_Elaboration_Code) then
515             Insert_After_And_Analyze (N,
516               Make_Raise_Program_Error (Loc,
517                 Condition =>
518                   Make_Op_Ne (Loc,
519                     Left_Opnd =>
520                       Make_Op_Mod (Loc,
521                         Left_Opnd =>
522                           Unchecked_Convert_To
523                            (RTE (RE_Integer_Address),
524                             Duplicate_Subexpr_No_Checks (Expr)),
525                         Right_Opnd =>
526                           Make_Attribute_Reference (Loc,
527                             Prefix => New_Occurrence_Of (E, Loc),
528                             Attribute_Name => Name_Alignment)),
529                     Right_Opnd => Make_Integer_Literal (Loc, Uint_0)),
530                 Reason => PE_Misaligned_Address_Value),
531               Suppress => All_Checks);
532          end if;
533       end if;
534
535       return;
536
537    exception
538       when RE_Not_Available =>
539          return;
540    end Apply_Alignment_Check;
541
542    -------------------------------------
543    -- Apply_Arithmetic_Overflow_Check --
544    -------------------------------------
545
546    --  This routine is called only if the type is an integer type, and
547    --  a software arithmetic overflow check must be performed for op
548    --  (add, subtract, multiply). The check is performed only if
549    --  Software_Overflow_Checking is enabled and Do_Overflow_Check
550    --  is set. In this case we expand the operation into a more complex
551    --  sequence of tests that ensures that overflow is properly caught.
552
553    procedure Apply_Arithmetic_Overflow_Check (N : Node_Id) is
554       Loc   : constant Source_Ptr := Sloc (N);
555       Typ   : constant Entity_Id  := Etype (N);
556       Rtyp  : constant Entity_Id  := Root_Type (Typ);
557       Siz   : constant Int        := UI_To_Int (Esize (Rtyp));
558       Dsiz  : constant Int        := Siz * 2;
559       Opnod : Node_Id;
560       Ctyp  : Entity_Id;
561       Opnd  : Node_Id;
562       Cent  : RE_Id;
563
564    begin
565       --  Skip this if overflow checks are done in back end, or the overflow
566       --  flag is not set anyway, or we are not doing code expansion.
567
568       if Backend_Overflow_Checks_On_Target
569         or not Do_Overflow_Check (N)
570         or not Expander_Active
571       then
572          return;
573       end if;
574
575       --  Otherwise, we generate the full general code for front end overflow
576       --  detection, which works by doing arithmetic in a larger type:
577
578       --    x op y
579
580       --  is expanded into
581
582       --    Typ (Checktyp (x) op Checktyp (y));
583
584       --  where Typ is the type of the original expression, and Checktyp is
585       --  an integer type of sufficient length to hold the largest possible
586       --  result.
587
588       --  In the case where check type exceeds the size of Long_Long_Integer,
589       --  we use a different approach, expanding to:
590
591       --    typ (xxx_With_Ovflo_Check (Integer_64 (x), Integer (y)))
592
593       --  where xxx is Add, Multiply or Subtract as appropriate
594
595       --  Find check type if one exists
596
597       if Dsiz <= Standard_Integer_Size then
598          Ctyp := Standard_Integer;
599
600       elsif Dsiz <= Standard_Long_Long_Integer_Size then
601          Ctyp := Standard_Long_Long_Integer;
602
603       --  No check type exists, use runtime call
604
605       else
606          if Nkind (N) = N_Op_Add then
607             Cent := RE_Add_With_Ovflo_Check;
608
609          elsif Nkind (N) = N_Op_Multiply then
610             Cent := RE_Multiply_With_Ovflo_Check;
611
612          else
613             pragma Assert (Nkind (N) = N_Op_Subtract);
614             Cent := RE_Subtract_With_Ovflo_Check;
615          end if;
616
617          Rewrite (N,
618            OK_Convert_To (Typ,
619              Make_Function_Call (Loc,
620                Name => New_Reference_To (RTE (Cent), Loc),
621                Parameter_Associations => New_List (
622                  OK_Convert_To (RTE (RE_Integer_64), Left_Opnd  (N)),
623                  OK_Convert_To (RTE (RE_Integer_64), Right_Opnd (N))))));
624
625          Analyze_And_Resolve (N, Typ);
626          return;
627       end if;
628
629       --  If we fall through, we have the case where we do the arithmetic in
630       --  the next higher type and get the check by conversion. In these cases
631       --  Ctyp is set to the type to be used as the check type.
632
633       Opnod := Relocate_Node (N);
634
635       Opnd := OK_Convert_To (Ctyp, Left_Opnd (Opnod));
636
637       Analyze (Opnd);
638       Set_Etype (Opnd, Ctyp);
639       Set_Analyzed (Opnd, True);
640       Set_Left_Opnd (Opnod, Opnd);
641
642       Opnd := OK_Convert_To (Ctyp, Right_Opnd (Opnod));
643
644       Analyze (Opnd);
645       Set_Etype (Opnd, Ctyp);
646       Set_Analyzed (Opnd, True);
647       Set_Right_Opnd (Opnod, Opnd);
648
649       --  The type of the operation changes to the base type of the check
650       --  type, and we reset the overflow check indication, since clearly
651       --  no overflow is possible now that we are using a double length
652       --  type. We also set the Analyzed flag to avoid a recursive attempt
653       --  to expand the node.
654
655       Set_Etype             (Opnod, Base_Type (Ctyp));
656       Set_Do_Overflow_Check (Opnod, False);
657       Set_Analyzed          (Opnod, True);
658
659       --  Now build the outer conversion
660
661       Opnd := OK_Convert_To (Typ, Opnod);
662       Analyze (Opnd);
663       Set_Etype (Opnd, Typ);
664
665       --  In the discrete type case, we directly generate the range check
666       --  for the outer operand. This range check will implement the required
667       --  overflow check.
668
669       if Is_Discrete_Type (Typ) then
670          Rewrite (N, Opnd);
671          Generate_Range_Check (Expression (N), Typ, CE_Overflow_Check_Failed);
672
673       --  For other types, we enable overflow checking on the conversion,
674       --  after setting the node as analyzed to prevent recursive attempts
675       --  to expand the conversion node.
676
677       else
678          Set_Analyzed (Opnd, True);
679          Enable_Overflow_Check (Opnd);
680          Rewrite (N, Opnd);
681       end if;
682
683    exception
684       when RE_Not_Available =>
685          return;
686    end Apply_Arithmetic_Overflow_Check;
687
688    ----------------------------
689    -- Apply_Array_Size_Check --
690    ----------------------------
691
692    --  Note: Really of course this entre check should be in the backend,
693    --  and perhaps this is not quite the right value, but it is good
694    --  enough to catch the normal cases (and the relevant ACVC tests!)
695
696    procedure Apply_Array_Size_Check (N : Node_Id; Typ : Entity_Id) is
697       Loc  : constant Source_Ptr := Sloc (N);
698       Ctyp : constant Entity_Id  := Component_Type (Typ);
699       Ent  : constant Entity_Id  := Defining_Identifier (N);
700       Decl : Node_Id;
701       Lo   : Node_Id;
702       Hi   : Node_Id;
703       Lob  : Uint;
704       Hib  : Uint;
705       Siz  : Uint;
706       Xtyp : Entity_Id;
707       Indx : Node_Id;
708       Sizx : Node_Id;
709       Code : Node_Id;
710
711       Static : Boolean := True;
712       --  Set false if any index subtye bound is non-static
713
714       Umark : constant Uintp.Save_Mark := Uintp.Mark;
715       --  We can throw away all the Uint computations here, since they are
716       --  done only to generate boolean test results.
717
718       Check_Siz : Uint;
719       --  Size to check against
720
721       function Is_Address_Or_Import (Decl : Node_Id) return Boolean;
722       --  Determines if Decl is an address clause or Import/Interface pragma
723       --  that references the defining identifier of the current declaration.
724
725       --------------------------
726       -- Is_Address_Or_Import --
727       --------------------------
728
729       function Is_Address_Or_Import (Decl : Node_Id) return Boolean is
730       begin
731          if Nkind (Decl) = N_At_Clause then
732             return Chars (Identifier (Decl)) = Chars (Ent);
733
734          elsif Nkind (Decl) = N_Attribute_Definition_Clause then
735             return
736               Chars (Decl) = Name_Address
737                 and then
738               Nkind (Name (Decl)) = N_Identifier
739                 and then
740               Chars (Name (Decl)) = Chars (Ent);
741
742          elsif Nkind (Decl) = N_Pragma then
743             if (Chars (Decl) = Name_Import
744                  or else
745                 Chars (Decl) = Name_Interface)
746               and then Present (Pragma_Argument_Associations (Decl))
747             then
748                declare
749                   F : constant Node_Id :=
750                         First (Pragma_Argument_Associations (Decl));
751
752                begin
753                   return
754                     Present (F)
755                       and then
756                     Present (Next (F))
757                       and then
758                     Nkind (Expression (Next (F))) = N_Identifier
759                       and then
760                     Chars (Expression (Next (F))) = Chars (Ent);
761                end;
762
763             else
764                return False;
765             end if;
766
767          else
768             return False;
769          end if;
770       end Is_Address_Or_Import;
771
772    --  Start of processing for Apply_Array_Size_Check
773
774    begin
775       if not Expander_Active
776         or else Storage_Checks_Suppressed (Typ)
777       then
778          return;
779       end if;
780
781       --  It is pointless to insert this check inside an  init proc, because
782       --  that's too late, we have already built the object to be the right
783       --  size, and if it's too large, too bad!
784
785       if Inside_Init_Proc then
786          return;
787       end if;
788
789       --  Look head for pragma interface/import or address clause applying
790       --  to this entity. If found, we suppress the check entirely. For now
791       --  we only look ahead 20 declarations to stop this becoming too slow
792       --  Note that eventually this whole routine gets moved to gigi.
793
794       Decl := N;
795       for Ctr in 1 .. 20 loop
796          Next (Decl);
797          exit when No (Decl);
798
799          if Is_Address_Or_Import (Decl) then
800             return;
801          end if;
802       end loop;
803
804       --  First step is to calculate the maximum number of elements. For this
805       --  calculation, we use the actual size of the subtype if it is static,
806       --  and if a bound of a subtype is non-static, we go to the bound of the
807       --  base type.
808
809       Siz := Uint_1;
810       Indx := First_Index (Typ);
811       while Present (Indx) loop
812          Xtyp := Etype (Indx);
813          Lo := Type_Low_Bound (Xtyp);
814          Hi := Type_High_Bound (Xtyp);
815
816          --  If any bound raises constraint error, we will never get this
817          --  far, so there is no need to generate any kind of check.
818
819          if Raises_Constraint_Error (Lo)
820               or else
821             Raises_Constraint_Error (Hi)
822          then
823             Uintp.Release (Umark);
824             return;
825          end if;
826
827          --  Otherwise get bounds values
828
829          if Is_Static_Expression (Lo) then
830             Lob := Expr_Value (Lo);
831          else
832             Lob := Expr_Value (Type_Low_Bound (Base_Type (Xtyp)));
833             Static := False;
834          end if;
835
836          if Is_Static_Expression (Hi) then
837             Hib := Expr_Value (Hi);
838          else
839             Hib := Expr_Value (Type_High_Bound (Base_Type (Xtyp)));
840             Static := False;
841          end if;
842
843          Siz := Siz *  UI_Max (Hib - Lob + 1, Uint_0);
844          Next_Index (Indx);
845       end loop;
846
847       --  Compute the limit against which we want to check. For subprograms,
848       --  where the array will go on the stack, we use 8*2**24, which (in
849       --  bits) is the size of a 16 megabyte array.
850
851       if Is_Subprogram (Scope (Ent)) then
852          Check_Siz := Uint_2 ** 27;
853       else
854          Check_Siz := Uint_2 ** 31;
855       end if;
856
857       --  If we have all static bounds and Siz is too large, then we know we
858       --  know we have a storage error right now, so generate message
859
860       if Static and then Siz >= Check_Siz then
861          Insert_Action (N,
862            Make_Raise_Storage_Error (Loc,
863              Reason => SE_Object_Too_Large));
864          Error_Msg_N ("?Storage_Error will be raised at run-time", N);
865          Uintp.Release (Umark);
866          return;
867       end if;
868
869       --  Case of component size known at compile time. If the array
870       --  size is definitely in range, then we do not need a check.
871
872       if Known_Esize (Ctyp)
873         and then Siz * Esize (Ctyp) < Check_Siz
874       then
875          Uintp.Release (Umark);
876          return;
877       end if;
878
879       --  Here if a dynamic check is required
880
881       --  What we do is to build an expression for the size of the array,
882       --  which is computed as the 'Size of the array component, times
883       --  the size of each dimension.
884
885       Uintp.Release (Umark);
886
887       Sizx :=
888         Make_Attribute_Reference (Loc,
889           Prefix         => New_Occurrence_Of (Ctyp, Loc),
890           Attribute_Name => Name_Size);
891
892       Indx := First_Index (Typ);
893
894       for J in 1 .. Number_Dimensions (Typ) loop
895          if Sloc (Etype (Indx)) = Sloc (N) then
896             Ensure_Defined (Etype (Indx), N);
897          end if;
898
899          Sizx :=
900            Make_Op_Multiply (Loc,
901              Left_Opnd  => Sizx,
902              Right_Opnd =>
903                Make_Attribute_Reference (Loc,
904                  Prefix => New_Occurrence_Of (Typ, Loc),
905                  Attribute_Name => Name_Length,
906                  Expressions => New_List (
907                    Make_Integer_Literal (Loc, J))));
908          Next_Index (Indx);
909       end loop;
910
911       Code :=
912         Make_Raise_Storage_Error (Loc,
913           Condition =>
914             Make_Op_Ge (Loc,
915               Left_Opnd  => Sizx,
916               Right_Opnd =>
917                 Make_Integer_Literal (Loc, Check_Siz)),
918             Reason => SE_Object_Too_Large);
919
920       Set_Size_Check_Code (Defining_Identifier (N), Code);
921       Insert_Action (N, Code);
922    end Apply_Array_Size_Check;
923
924    ----------------------------
925    -- Apply_Constraint_Check --
926    ----------------------------
927
928    procedure Apply_Constraint_Check
929      (N          : Node_Id;
930       Typ        : Entity_Id;
931       No_Sliding : Boolean := False)
932    is
933       Desig_Typ : Entity_Id;
934
935    begin
936       if Inside_A_Generic then
937          return;
938
939       elsif Is_Scalar_Type (Typ) then
940          Apply_Scalar_Range_Check (N, Typ);
941
942       elsif Is_Array_Type (Typ) then
943
944          --  A useful optimization: an aggregate with only an Others clause
945          --  always has the right bounds.
946
947          if Nkind (N) = N_Aggregate
948            and then No (Expressions (N))
949            and then Nkind
950             (First (Choices (First (Component_Associations (N)))))
951               = N_Others_Choice
952          then
953             return;
954          end if;
955
956          if Is_Constrained (Typ) then
957             Apply_Length_Check (N, Typ);
958
959             if No_Sliding then
960                Apply_Range_Check (N, Typ);
961             end if;
962          else
963             Apply_Range_Check (N, Typ);
964          end if;
965
966       elsif (Is_Record_Type (Typ)
967                or else Is_Private_Type (Typ))
968         and then Has_Discriminants (Base_Type (Typ))
969         and then Is_Constrained (Typ)
970       then
971          Apply_Discriminant_Check (N, Typ);
972
973       elsif Is_Access_Type (Typ) then
974
975          Desig_Typ := Designated_Type (Typ);
976
977          --  No checks necessary if expression statically null
978
979          if Nkind (N) = N_Null then
980             null;
981
982          --  No sliding possible on access to arrays
983
984          elsif Is_Array_Type (Desig_Typ) then
985             if Is_Constrained (Desig_Typ) then
986                Apply_Length_Check (N, Typ);
987             end if;
988
989             Apply_Range_Check (N, Typ);
990
991          elsif Has_Discriminants (Base_Type (Desig_Typ))
992             and then Is_Constrained (Desig_Typ)
993          then
994             Apply_Discriminant_Check (N, Typ);
995          end if;
996       end if;
997    end Apply_Constraint_Check;
998
999    ------------------------------
1000    -- Apply_Discriminant_Check --
1001    ------------------------------
1002
1003    procedure Apply_Discriminant_Check
1004      (N   : Node_Id;
1005       Typ : Entity_Id;
1006       Lhs : Node_Id := Empty)
1007    is
1008       Loc       : constant Source_Ptr := Sloc (N);
1009       Do_Access : constant Boolean    := Is_Access_Type (Typ);
1010       S_Typ     : Entity_Id  := Etype (N);
1011       Cond      : Node_Id;
1012       T_Typ     : Entity_Id;
1013
1014       function Is_Aliased_Unconstrained_Component return Boolean;
1015       --  It is possible for an aliased component to have a nominal
1016       --  unconstrained subtype (through instantiation). If this is a
1017       --  discriminated component assigned in the expansion of an aggregate
1018       --  in an initialization, the check must be suppressed. This unusual
1019       --  situation requires a predicate of its own (see 7503-008).
1020
1021       ----------------------------------------
1022       -- Is_Aliased_Unconstrained_Component --
1023       ----------------------------------------
1024
1025       function Is_Aliased_Unconstrained_Component return Boolean is
1026          Comp : Entity_Id;
1027          Pref : Node_Id;
1028
1029       begin
1030          if Nkind (Lhs) /= N_Selected_Component then
1031             return False;
1032          else
1033             Comp := Entity (Selector_Name (Lhs));
1034             Pref := Prefix (Lhs);
1035          end if;
1036
1037          if Ekind (Comp) /= E_Component
1038            or else not Is_Aliased (Comp)
1039          then
1040             return False;
1041          end if;
1042
1043          return not Comes_From_Source (Pref)
1044            and then In_Instance
1045            and then not Is_Constrained (Etype (Comp));
1046       end Is_Aliased_Unconstrained_Component;
1047
1048    --  Start of processing for Apply_Discriminant_Check
1049
1050    begin
1051       if Do_Access then
1052          T_Typ := Designated_Type (Typ);
1053       else
1054          T_Typ := Typ;
1055       end if;
1056
1057       --  Nothing to do if discriminant checks are suppressed or else no code
1058       --  is to be generated
1059
1060       if not Expander_Active
1061         or else Discriminant_Checks_Suppressed (T_Typ)
1062       then
1063          return;
1064       end if;
1065
1066       --  No discriminant checks necessary for access when expression
1067       --  is statically Null. This is not only an optimization, this is
1068       --  fundamental because otherwise discriminant checks may be generated
1069       --  in init procs for types containing an access to a non-frozen yet
1070       --  record, causing a deadly forward reference.
1071
1072       --  Also, if the expression is of an access type whose designated
1073       --  type is incomplete, then the access value must be null and
1074       --  we suppress the check.
1075
1076       if Nkind (N) = N_Null then
1077          return;
1078
1079       elsif Is_Access_Type (S_Typ) then
1080          S_Typ := Designated_Type (S_Typ);
1081
1082          if Ekind (S_Typ) = E_Incomplete_Type then
1083             return;
1084          end if;
1085       end if;
1086
1087       --  If an assignment target is present, then we need to generate
1088       --  the actual subtype if the target is a parameter or aliased
1089       --  object with an unconstrained nominal subtype.
1090
1091       if Present (Lhs)
1092         and then (Present (Param_Entity (Lhs))
1093                    or else (not Is_Constrained (T_Typ)
1094                              and then Is_Aliased_View (Lhs)
1095                              and then not Is_Aliased_Unconstrained_Component))
1096       then
1097          T_Typ := Get_Actual_Subtype (Lhs);
1098       end if;
1099
1100       --  Nothing to do if the type is unconstrained (this is the case
1101       --  where the actual subtype in the RM sense of N is unconstrained
1102       --  and no check is required).
1103
1104       if not Is_Constrained (T_Typ) then
1105          return;
1106       end if;
1107
1108       --  Suppress checks if the subtypes are the same.
1109       --  the check must be preserved in an assignment to a formal, because
1110       --  the constraint is given by the actual.
1111
1112       if Nkind (Original_Node (N)) /= N_Allocator
1113         and then (No (Lhs)
1114           or else not Is_Entity_Name (Lhs)
1115           or else No (Param_Entity (Lhs)))
1116       then
1117          if (Etype (N) = Typ
1118               or else (Do_Access and then Designated_Type (Typ) = S_Typ))
1119            and then not Is_Aliased_View (Lhs)
1120          then
1121             return;
1122          end if;
1123
1124       --  We can also eliminate checks on allocators with a subtype mark
1125       --  that coincides with the context type. The context type may be a
1126       --  subtype without a constraint (common case, a generic actual).
1127
1128       elsif Nkind (Original_Node (N)) = N_Allocator
1129         and then Is_Entity_Name (Expression (Original_Node (N)))
1130       then
1131          declare
1132             Alloc_Typ : constant Entity_Id :=
1133                           Entity (Expression (Original_Node (N)));
1134
1135          begin
1136             if Alloc_Typ = T_Typ
1137               or else (Nkind (Parent (T_Typ)) = N_Subtype_Declaration
1138                         and then Is_Entity_Name (
1139                           Subtype_Indication (Parent (T_Typ)))
1140                         and then Alloc_Typ = Base_Type (T_Typ))
1141
1142             then
1143                return;
1144             end if;
1145          end;
1146       end if;
1147
1148       --  See if we have a case where the types are both constrained, and
1149       --  all the constraints are constants. In this case, we can do the
1150       --  check successfully at compile time.
1151
1152       --  We skip this check for the case where the node is a rewritten`
1153       --  allocator, because it already carries the context subtype, and
1154       --  extracting the discriminants from the aggregate is messy.
1155
1156       if Is_Constrained (S_Typ)
1157         and then Nkind (Original_Node (N)) /= N_Allocator
1158       then
1159          declare
1160             DconT : Elmt_Id;
1161             Discr : Entity_Id;
1162             DconS : Elmt_Id;
1163             ItemS : Node_Id;
1164             ItemT : Node_Id;
1165
1166          begin
1167             --  S_Typ may not have discriminants in the case where it is a
1168             --  private type completed by a default discriminated type. In
1169             --  that case, we need to get the constraints from the
1170             --  underlying_type. If the underlying type is unconstrained (i.e.
1171             --  has no default discriminants) no check is needed.
1172
1173             if Has_Discriminants (S_Typ) then
1174                Discr := First_Discriminant (S_Typ);
1175                DconS := First_Elmt (Discriminant_Constraint (S_Typ));
1176
1177             else
1178                Discr := First_Discriminant (Underlying_Type (S_Typ));
1179                DconS :=
1180                  First_Elmt
1181                    (Discriminant_Constraint (Underlying_Type (S_Typ)));
1182
1183                if No (DconS) then
1184                   return;
1185                end if;
1186             end if;
1187
1188             DconT  := First_Elmt (Discriminant_Constraint (T_Typ));
1189
1190             while Present (Discr) loop
1191                ItemS := Node (DconS);
1192                ItemT := Node (DconT);
1193
1194                exit when
1195                  not Is_OK_Static_Expression (ItemS)
1196                    or else
1197                  not Is_OK_Static_Expression (ItemT);
1198
1199                if Expr_Value (ItemS) /= Expr_Value (ItemT) then
1200                   if Do_Access then   --  needs run-time check.
1201                      exit;
1202                   else
1203                      Apply_Compile_Time_Constraint_Error
1204                        (N, "incorrect value for discriminant&?",
1205                         CE_Discriminant_Check_Failed, Ent => Discr);
1206                      return;
1207                   end if;
1208                end if;
1209
1210                Next_Elmt (DconS);
1211                Next_Elmt (DconT);
1212                Next_Discriminant (Discr);
1213             end loop;
1214
1215             if No (Discr) then
1216                return;
1217             end if;
1218          end;
1219       end if;
1220
1221       --  Here we need a discriminant check. First build the expression
1222       --  for the comparisons of the discriminants:
1223
1224       --    (n.disc1 /= typ.disc1) or else
1225       --    (n.disc2 /= typ.disc2) or else
1226       --     ...
1227       --    (n.discn /= typ.discn)
1228
1229       Cond := Build_Discriminant_Checks (N, T_Typ);
1230
1231       --  If Lhs is set and is a parameter, then the condition is
1232       --  guarded by: lhs'constrained and then (condition built above)
1233
1234       if Present (Param_Entity (Lhs)) then
1235          Cond :=
1236            Make_And_Then (Loc,
1237              Left_Opnd =>
1238                Make_Attribute_Reference (Loc,
1239                  Prefix => New_Occurrence_Of (Param_Entity (Lhs), Loc),
1240                  Attribute_Name => Name_Constrained),
1241              Right_Opnd => Cond);
1242       end if;
1243
1244       if Do_Access then
1245          Cond := Guard_Access (Cond, Loc, N);
1246       end if;
1247
1248       Insert_Action (N,
1249         Make_Raise_Constraint_Error (Loc,
1250           Condition => Cond,
1251           Reason    => CE_Discriminant_Check_Failed));
1252    end Apply_Discriminant_Check;
1253
1254    ------------------------
1255    -- Apply_Divide_Check --
1256    ------------------------
1257
1258    procedure Apply_Divide_Check (N : Node_Id) is
1259       Loc   : constant Source_Ptr := Sloc (N);
1260       Typ   : constant Entity_Id  := Etype (N);
1261       Left  : constant Node_Id    := Left_Opnd (N);
1262       Right : constant Node_Id    := Right_Opnd (N);
1263
1264       LLB : Uint;
1265       Llo : Uint;
1266       Lhi : Uint;
1267       LOK : Boolean;
1268       Rlo : Uint;
1269       Rhi : Uint;
1270       ROK : Boolean;
1271
1272    begin
1273       if Expander_Active
1274         and not Backend_Divide_Checks_On_Target
1275       then
1276          Determine_Range (Right, ROK, Rlo, Rhi);
1277
1278          --  See if division by zero possible, and if so generate test. This
1279          --  part of the test is not controlled by the -gnato switch.
1280
1281          if Do_Division_Check (N) then
1282
1283             if (not ROK) or else (Rlo <= 0 and then 0 <= Rhi) then
1284                Insert_Action (N,
1285                  Make_Raise_Constraint_Error (Loc,
1286                    Condition =>
1287                      Make_Op_Eq (Loc,
1288                        Left_Opnd => Duplicate_Subexpr_Move_Checks (Right),
1289                        Right_Opnd => Make_Integer_Literal (Loc, 0)),
1290                    Reason => CE_Divide_By_Zero));
1291             end if;
1292          end if;
1293
1294          --  Test for extremely annoying case of xxx'First divided by -1
1295
1296          if Do_Overflow_Check (N) then
1297
1298             if Nkind (N) = N_Op_Divide
1299               and then Is_Signed_Integer_Type (Typ)
1300             then
1301                Determine_Range (Left, LOK, Llo, Lhi);
1302                LLB := Expr_Value (Type_Low_Bound (Base_Type (Typ)));
1303
1304                if ((not ROK) or else (Rlo <= (-1) and then (-1) <= Rhi))
1305                  and then
1306                  ((not LOK) or else (Llo = LLB))
1307                then
1308                   Insert_Action (N,
1309                     Make_Raise_Constraint_Error (Loc,
1310                       Condition =>
1311                         Make_And_Then (Loc,
1312
1313                            Make_Op_Eq (Loc,
1314                              Left_Opnd  =>
1315                                Duplicate_Subexpr_Move_Checks (Left),
1316                              Right_Opnd => Make_Integer_Literal (Loc, LLB)),
1317
1318                            Make_Op_Eq (Loc,
1319                              Left_Opnd =>
1320                                Duplicate_Subexpr (Right),
1321                              Right_Opnd =>
1322                                Make_Integer_Literal (Loc, -1))),
1323                       Reason => CE_Overflow_Check_Failed));
1324                end if;
1325             end if;
1326          end if;
1327       end if;
1328    end Apply_Divide_Check;
1329
1330    ------------------------
1331    -- Apply_Length_Check --
1332    ------------------------
1333
1334    procedure Apply_Length_Check
1335      (Ck_Node    : Node_Id;
1336       Target_Typ : Entity_Id;
1337       Source_Typ : Entity_Id := Empty)
1338    is
1339    begin
1340       Apply_Selected_Length_Checks
1341         (Ck_Node, Target_Typ, Source_Typ, Do_Static => False);
1342    end Apply_Length_Check;
1343
1344    -----------------------
1345    -- Apply_Range_Check --
1346    -----------------------
1347
1348    procedure Apply_Range_Check
1349      (Ck_Node    : Node_Id;
1350       Target_Typ : Entity_Id;
1351       Source_Typ : Entity_Id := Empty)
1352    is
1353    begin
1354       Apply_Selected_Range_Checks
1355         (Ck_Node, Target_Typ, Source_Typ, Do_Static => False);
1356    end Apply_Range_Check;
1357
1358    ------------------------------
1359    -- Apply_Scalar_Range_Check --
1360    ------------------------------
1361
1362    --  Note that Apply_Scalar_Range_Check never turns the Do_Range_Check
1363    --  flag off if it is already set on.
1364
1365    procedure Apply_Scalar_Range_Check
1366      (Expr       : Node_Id;
1367       Target_Typ : Entity_Id;
1368       Source_Typ : Entity_Id := Empty;
1369       Fixed_Int  : Boolean   := False)
1370    is
1371       Parnt   : constant Node_Id := Parent (Expr);
1372       S_Typ   : Entity_Id;
1373       Arr     : Node_Id   := Empty;  -- initialize to prevent warning
1374       Arr_Typ : Entity_Id := Empty;  -- initialize to prevent warning
1375       OK      : Boolean;
1376
1377       Is_Subscr_Ref : Boolean;
1378       --  Set true if Expr is a subscript
1379
1380       Is_Unconstrained_Subscr_Ref : Boolean;
1381       --  Set true if Expr is a subscript of an unconstrained array. In this
1382       --  case we do not attempt to do an analysis of the value against the
1383       --  range of the subscript, since we don't know the actual subtype.
1384
1385       Int_Real : Boolean;
1386       --  Set to True if Expr should be regarded as a real value
1387       --  even though the type of Expr might be discrete.
1388
1389       procedure Bad_Value;
1390       --  Procedure called if value is determined to be out of range
1391
1392       ---------------
1393       -- Bad_Value --
1394       ---------------
1395
1396       procedure Bad_Value is
1397       begin
1398          Apply_Compile_Time_Constraint_Error
1399            (Expr, "value not in range of}?", CE_Range_Check_Failed,
1400             Ent => Target_Typ,
1401             Typ => Target_Typ);
1402       end Bad_Value;
1403
1404    --  Start of processing for Apply_Scalar_Range_Check
1405
1406    begin
1407       if Inside_A_Generic then
1408          return;
1409
1410       --  Return if check obviously not needed. Note that we do not check
1411       --  for the expander being inactive, since this routine does not
1412       --  insert any code, but it does generate useful warnings sometimes,
1413       --  which we would like even if we are in semantics only mode.
1414
1415       elsif Target_Typ = Any_Type
1416         or else not Is_Scalar_Type (Target_Typ)
1417         or else Raises_Constraint_Error (Expr)
1418       then
1419          return;
1420       end if;
1421
1422       --  Now, see if checks are suppressed
1423
1424       Is_Subscr_Ref :=
1425         Is_List_Member (Expr) and then Nkind (Parnt) = N_Indexed_Component;
1426
1427       if Is_Subscr_Ref then
1428          Arr := Prefix (Parnt);
1429          Arr_Typ := Get_Actual_Subtype_If_Available (Arr);
1430       end if;
1431
1432       if not Do_Range_Check (Expr) then
1433
1434          --  Subscript reference. Check for Index_Checks suppressed
1435
1436          if Is_Subscr_Ref then
1437
1438             --  Check array type and its base type
1439
1440             if Index_Checks_Suppressed (Arr_Typ)
1441               or else Index_Checks_Suppressed (Base_Type (Arr_Typ))
1442             then
1443                return;
1444
1445             --  Check array itself if it is an entity name
1446
1447             elsif Is_Entity_Name (Arr)
1448               and then Index_Checks_Suppressed (Entity (Arr))
1449             then
1450                return;
1451
1452             --  Check expression itself if it is an entity name
1453
1454             elsif Is_Entity_Name (Expr)
1455               and then Index_Checks_Suppressed (Entity (Expr))
1456             then
1457                return;
1458             end if;
1459
1460          --  All other cases, check for Range_Checks suppressed
1461
1462          else
1463             --  Check target type and its base type
1464
1465             if Range_Checks_Suppressed (Target_Typ)
1466               or else Range_Checks_Suppressed (Base_Type (Target_Typ))
1467             then
1468                return;
1469
1470             --  Check expression itself if it is an entity name
1471
1472             elsif Is_Entity_Name (Expr)
1473               and then Range_Checks_Suppressed (Entity (Expr))
1474             then
1475                return;
1476
1477             --  If Expr is part of an assignment statement, then check
1478             --  left side of assignment if it is an entity name.
1479
1480             elsif Nkind (Parnt) = N_Assignment_Statement
1481               and then Is_Entity_Name (Name (Parnt))
1482               and then Range_Checks_Suppressed (Entity (Name (Parnt)))
1483             then
1484                return;
1485             end if;
1486          end if;
1487       end if;
1488
1489       --  Do not set range checks if they are killed
1490
1491       if Nkind (Expr) = N_Unchecked_Type_Conversion
1492         and then Kill_Range_Check (Expr)
1493       then
1494          return;
1495       end if;
1496
1497       --  Do not set range checks for any values from System.Scalar_Values
1498       --  since the whole idea of such values is to avoid checking them!
1499
1500       if Is_Entity_Name (Expr)
1501         and then Is_RTU (Scope (Entity (Expr)), System_Scalar_Values)
1502       then
1503          return;
1504       end if;
1505
1506       --  Now see if we need a check
1507
1508       if No (Source_Typ) then
1509          S_Typ := Etype (Expr);
1510       else
1511          S_Typ := Source_Typ;
1512       end if;
1513
1514       if not Is_Scalar_Type (S_Typ) or else S_Typ = Any_Type then
1515          return;
1516       end if;
1517
1518       Is_Unconstrained_Subscr_Ref :=
1519         Is_Subscr_Ref and then not Is_Constrained (Arr_Typ);
1520
1521       --  Always do a range check if the source type includes infinities
1522       --  and the target type does not include infinities. We do not do
1523       --  this if range checks are killed.
1524
1525       if Is_Floating_Point_Type (S_Typ)
1526         and then Has_Infinities (S_Typ)
1527         and then not Has_Infinities (Target_Typ)
1528       then
1529          Enable_Range_Check (Expr);
1530       end if;
1531
1532       --  Return if we know expression is definitely in the range of
1533       --  the target type as determined by Determine_Range. Right now
1534       --  we only do this for discrete types, and not fixed-point or
1535       --  floating-point types.
1536
1537       --  The additional less-precise tests below catch these cases.
1538
1539       --  Note: skip this if we are given a source_typ, since the point
1540       --  of supplying a Source_Typ is to stop us looking at the expression.
1541       --  could sharpen this test to be out parameters only ???
1542
1543       if Is_Discrete_Type (Target_Typ)
1544         and then Is_Discrete_Type (Etype (Expr))
1545         and then not Is_Unconstrained_Subscr_Ref
1546         and then No (Source_Typ)
1547       then
1548          declare
1549             Tlo : constant Node_Id := Type_Low_Bound  (Target_Typ);
1550             Thi : constant Node_Id := Type_High_Bound (Target_Typ);
1551             Lo  : Uint;
1552             Hi  : Uint;
1553
1554          begin
1555             if Compile_Time_Known_Value (Tlo)
1556               and then Compile_Time_Known_Value (Thi)
1557             then
1558                declare
1559                   Lov : constant Uint := Expr_Value (Tlo);
1560                   Hiv : constant Uint := Expr_Value (Thi);
1561
1562                begin
1563                   --  If range is null, we for sure have a constraint error
1564                   --  (we don't even need to look at the value involved,
1565                   --  since all possible values will raise CE).
1566
1567                   if Lov > Hiv then
1568                      Bad_Value;
1569                      return;
1570                   end if;
1571
1572                   --  Otherwise determine range of value
1573
1574                   Determine_Range (Expr, OK, Lo, Hi);
1575
1576                   if OK then
1577
1578                      --  If definitely in range, all OK
1579
1580                      if Lo >= Lov and then Hi <= Hiv then
1581                         return;
1582
1583                      --  If definitely not in range, warn
1584
1585                      elsif Lov > Hi or else Hiv < Lo then
1586                         Bad_Value;
1587                         return;
1588
1589                      --  Otherwise we don't know
1590
1591                      else
1592                         null;
1593                      end if;
1594                   end if;
1595                end;
1596             end if;
1597          end;
1598       end if;
1599
1600       Int_Real :=
1601         Is_Floating_Point_Type (S_Typ)
1602           or else (Is_Fixed_Point_Type (S_Typ) and then not Fixed_Int);
1603
1604       --  Check if we can determine at compile time whether Expr is in the
1605       --  range of the target type. Note that if S_Typ is within the bounds
1606       --  of Target_Typ then this must be the case. This check is meaningful
1607       --  only if this is not a conversion between integer and real types.
1608
1609       if not Is_Unconstrained_Subscr_Ref
1610         and then
1611            Is_Discrete_Type (S_Typ) = Is_Discrete_Type (Target_Typ)
1612         and then
1613           (In_Subrange_Of (S_Typ, Target_Typ, Fixed_Int)
1614              or else
1615            Is_In_Range (Expr, Target_Typ, Fixed_Int, Int_Real))
1616       then
1617          return;
1618
1619       elsif Is_Out_Of_Range (Expr, Target_Typ, Fixed_Int, Int_Real) then
1620          Bad_Value;
1621          return;
1622
1623       --  In the floating-point case, we only do range checks if the
1624       --  type is constrained. We definitely do NOT want range checks
1625       --  for unconstrained types, since we want to have infinities
1626
1627       elsif Is_Floating_Point_Type (S_Typ) then
1628          if Is_Constrained (S_Typ) then
1629             Enable_Range_Check (Expr);
1630          end if;
1631
1632       --  For all other cases we enable a range check unconditionally
1633
1634       else
1635          Enable_Range_Check (Expr);
1636          return;
1637       end if;
1638    end Apply_Scalar_Range_Check;
1639
1640    ----------------------------------
1641    -- Apply_Selected_Length_Checks --
1642    ----------------------------------
1643
1644    procedure Apply_Selected_Length_Checks
1645      (Ck_Node    : Node_Id;
1646       Target_Typ : Entity_Id;
1647       Source_Typ : Entity_Id;
1648       Do_Static  : Boolean)
1649    is
1650       Cond     : Node_Id;
1651       R_Result : Check_Result;
1652       R_Cno    : Node_Id;
1653
1654       Loc         : constant Source_Ptr := Sloc (Ck_Node);
1655       Checks_On   : constant Boolean :=
1656                       (not Index_Checks_Suppressed (Target_Typ))
1657                         or else
1658                       (not Length_Checks_Suppressed (Target_Typ));
1659
1660    begin
1661       if not Expander_Active then
1662          return;
1663       end if;
1664
1665       R_Result :=
1666         Selected_Length_Checks (Ck_Node, Target_Typ, Source_Typ, Empty);
1667
1668       for J in 1 .. 2 loop
1669          R_Cno := R_Result (J);
1670          exit when No (R_Cno);
1671
1672          --  A length check may mention an Itype which is attached to a
1673          --  subsequent node. At the top level in a package this can cause
1674          --  an order-of-elaboration problem, so we make sure that the itype
1675          --  is referenced now.
1676
1677          if Ekind (Current_Scope) = E_Package
1678            and then Is_Compilation_Unit (Current_Scope)
1679          then
1680             Ensure_Defined (Target_Typ, Ck_Node);
1681
1682             if Present (Source_Typ) then
1683                Ensure_Defined (Source_Typ, Ck_Node);
1684
1685             elsif Is_Itype (Etype (Ck_Node)) then
1686                Ensure_Defined (Etype (Ck_Node), Ck_Node);
1687             end if;
1688          end if;
1689
1690          --  If the item is a conditional raise of constraint error,
1691          --  then have a look at what check is being performed and
1692          --  ???
1693
1694          if Nkind (R_Cno) = N_Raise_Constraint_Error
1695            and then Present (Condition (R_Cno))
1696          then
1697             Cond := Condition (R_Cno);
1698
1699             if not Has_Dynamic_Length_Check (Ck_Node)
1700               and then Checks_On
1701             then
1702                Insert_Action (Ck_Node, R_Cno);
1703
1704                if not Do_Static then
1705                   Set_Has_Dynamic_Length_Check (Ck_Node);
1706                end if;
1707             end if;
1708
1709             --  Output a warning if the condition is known to be True
1710
1711             if Is_Entity_Name (Cond)
1712               and then Entity (Cond) = Standard_True
1713             then
1714                Apply_Compile_Time_Constraint_Error
1715                  (Ck_Node, "wrong length for array of}?",
1716                   CE_Length_Check_Failed,
1717                   Ent => Target_Typ,
1718                   Typ => Target_Typ);
1719
1720             --  If we were only doing a static check, or if checks are not
1721             --  on, then we want to delete the check, since it is not needed.
1722             --  We do this by replacing the if statement by a null statement
1723
1724             elsif Do_Static or else not Checks_On then
1725                Rewrite (R_Cno, Make_Null_Statement (Loc));
1726             end if;
1727
1728          else
1729             Install_Static_Check (R_Cno, Loc);
1730          end if;
1731
1732       end loop;
1733
1734    end Apply_Selected_Length_Checks;
1735
1736    ---------------------------------
1737    -- Apply_Selected_Range_Checks --
1738    ---------------------------------
1739
1740    procedure Apply_Selected_Range_Checks
1741      (Ck_Node    : Node_Id;
1742       Target_Typ : Entity_Id;
1743       Source_Typ : Entity_Id;
1744       Do_Static  : Boolean)
1745    is
1746       Cond     : Node_Id;
1747       R_Result : Check_Result;
1748       R_Cno    : Node_Id;
1749
1750       Loc       : constant Source_Ptr := Sloc (Ck_Node);
1751       Checks_On : constant Boolean :=
1752                     (not Index_Checks_Suppressed (Target_Typ))
1753                       or else
1754                     (not Range_Checks_Suppressed (Target_Typ));
1755
1756    begin
1757       if not Expander_Active or else not Checks_On then
1758          return;
1759       end if;
1760
1761       R_Result :=
1762         Selected_Range_Checks (Ck_Node, Target_Typ, Source_Typ, Empty);
1763
1764       for J in 1 .. 2 loop
1765
1766          R_Cno := R_Result (J);
1767          exit when No (R_Cno);
1768
1769          --  If the item is a conditional raise of constraint error,
1770          --  then have a look at what check is being performed and
1771          --  ???
1772
1773          if Nkind (R_Cno) = N_Raise_Constraint_Error
1774            and then Present (Condition (R_Cno))
1775          then
1776             Cond := Condition (R_Cno);
1777
1778             if not Has_Dynamic_Range_Check (Ck_Node) then
1779                Insert_Action (Ck_Node, R_Cno);
1780
1781                if not Do_Static then
1782                   Set_Has_Dynamic_Range_Check (Ck_Node);
1783                end if;
1784             end if;
1785
1786             --  Output a warning if the condition is known to be True
1787
1788             if Is_Entity_Name (Cond)
1789               and then Entity (Cond) = Standard_True
1790             then
1791                --  Since an N_Range is technically not an expression, we
1792                --  have to set one of the bounds to C_E and then just flag
1793                --  the N_Range. The warning message will point to the
1794                --  lower bound and complain about a range, which seems OK.
1795
1796                if Nkind (Ck_Node) = N_Range then
1797                   Apply_Compile_Time_Constraint_Error
1798                     (Low_Bound (Ck_Node), "static range out of bounds of}?",
1799                      CE_Range_Check_Failed,
1800                      Ent => Target_Typ,
1801                      Typ => Target_Typ);
1802
1803                   Set_Raises_Constraint_Error (Ck_Node);
1804
1805                else
1806                   Apply_Compile_Time_Constraint_Error
1807                     (Ck_Node, "static value out of range of}?",
1808                      CE_Range_Check_Failed,
1809                      Ent => Target_Typ,
1810                      Typ => Target_Typ);
1811                end if;
1812
1813             --  If we were only doing a static check, or if checks are not
1814             --  on, then we want to delete the check, since it is not needed.
1815             --  We do this by replacing the if statement by a null statement
1816
1817             elsif Do_Static or else not Checks_On then
1818                Rewrite (R_Cno, Make_Null_Statement (Loc));
1819             end if;
1820
1821          else
1822             Install_Static_Check (R_Cno, Loc);
1823          end if;
1824       end loop;
1825    end Apply_Selected_Range_Checks;
1826
1827    -------------------------------
1828    -- Apply_Static_Length_Check --
1829    -------------------------------
1830
1831    procedure Apply_Static_Length_Check
1832      (Expr       : Node_Id;
1833       Target_Typ : Entity_Id;
1834       Source_Typ : Entity_Id := Empty)
1835    is
1836    begin
1837       Apply_Selected_Length_Checks
1838         (Expr, Target_Typ, Source_Typ, Do_Static => True);
1839    end Apply_Static_Length_Check;
1840
1841    -------------------------------------
1842    -- Apply_Subscript_Validity_Checks --
1843    -------------------------------------
1844
1845    procedure Apply_Subscript_Validity_Checks (Expr : Node_Id) is
1846       Sub : Node_Id;
1847
1848    begin
1849       pragma Assert (Nkind (Expr) = N_Indexed_Component);
1850
1851       --  Loop through subscripts
1852
1853       Sub := First (Expressions (Expr));
1854       while Present (Sub) loop
1855
1856          --  Check one subscript. Note that we do not worry about
1857          --  enumeration type with holes, since we will convert the
1858          --  value to a Pos value for the subscript, and that convert
1859          --  will do the necessary validity check.
1860
1861          Ensure_Valid (Sub, Holes_OK => True);
1862
1863          --  Move to next subscript
1864
1865          Sub := Next (Sub);
1866       end loop;
1867    end Apply_Subscript_Validity_Checks;
1868
1869    ----------------------------------
1870    -- Apply_Type_Conversion_Checks --
1871    ----------------------------------
1872
1873    procedure Apply_Type_Conversion_Checks (N : Node_Id) is
1874       Target_Type : constant Entity_Id := Etype (N);
1875       Target_Base : constant Entity_Id := Base_Type (Target_Type);
1876       Expr        : constant Node_Id   := Expression (N);
1877       Expr_Type   : constant Entity_Id := Etype (Expr);
1878
1879    begin
1880       if Inside_A_Generic then
1881          return;
1882
1883       --  Skip these checks if serious errors detected, there are some nasty
1884       --  situations of incomplete trees that blow things up.
1885
1886       elsif Serious_Errors_Detected > 0 then
1887          return;
1888
1889       --  Scalar type conversions of the form Target_Type (Expr) require
1890       --  a range check if we cannot be sure that Expr is in the base type
1891       --  of Target_Typ and also that Expr is in the range of Target_Typ.
1892       --  These are not quite the same condition from an implementation
1893       --  point of view, but clearly the second includes the first.
1894
1895       elsif Is_Scalar_Type (Target_Type) then
1896          declare
1897             Conv_OK  : constant Boolean := Conversion_OK (N);
1898             --  If the Conversion_OK flag on the type conversion is set
1899             --  and no floating point type is involved in the type conversion
1900             --  then fixed point values must be read as integral values.
1901
1902          begin
1903             if not Overflow_Checks_Suppressed (Target_Base)
1904               and then not In_Subrange_Of (Expr_Type, Target_Base, Conv_OK)
1905             then
1906                Set_Do_Overflow_Check (N);
1907             end if;
1908
1909             if not Range_Checks_Suppressed (Target_Type)
1910               and then not Range_Checks_Suppressed (Expr_Type)
1911             then
1912                Apply_Scalar_Range_Check
1913                  (Expr, Target_Type, Fixed_Int => Conv_OK);
1914             end if;
1915          end;
1916
1917       elsif Comes_From_Source (N)
1918         and then Is_Record_Type (Target_Type)
1919         and then Is_Derived_Type (Target_Type)
1920         and then not Is_Tagged_Type (Target_Type)
1921         and then not Is_Constrained (Target_Type)
1922         and then Present (Stored_Constraint (Target_Type))
1923       then
1924          --  An unconstrained derived type may have inherited discriminant
1925          --  Build an actual discriminant constraint list using the stored
1926          --  constraint, to verify that the expression of the parent type
1927          --  satisfies the constraints imposed by the (unconstrained!)
1928          --  derived type. This applies to value conversions, not to view
1929          --  conversions of tagged types.
1930
1931          declare
1932             Loc         : constant Source_Ptr := Sloc (N);
1933             Cond        : Node_Id;
1934             Constraint  : Elmt_Id;
1935             Discr_Value : Node_Id;
1936             Discr       : Entity_Id;
1937
1938             New_Constraints : constant Elist_Id := New_Elmt_List;
1939             Old_Constraints : constant Elist_Id :=
1940                                 Discriminant_Constraint (Expr_Type);
1941
1942          begin
1943             Constraint := First_Elmt (Stored_Constraint (Target_Type));
1944
1945             while Present (Constraint) loop
1946                Discr_Value := Node (Constraint);
1947
1948                if Is_Entity_Name (Discr_Value)
1949                  and then Ekind (Entity (Discr_Value)) = E_Discriminant
1950                then
1951                   Discr := Corresponding_Discriminant (Entity (Discr_Value));
1952
1953                   if Present (Discr)
1954                     and then Scope (Discr) = Base_Type (Expr_Type)
1955                   then
1956                      --  Parent is constrained by new discriminant. Obtain
1957                      --  Value of original discriminant in expression. If
1958                      --  the new discriminant has been used to constrain more
1959                      --  than one of the stored discriminants, this will
1960                      --  provide the required consistency check.
1961
1962                      Append_Elmt (
1963                         Make_Selected_Component (Loc,
1964                           Prefix =>
1965                             Duplicate_Subexpr_No_Checks
1966                               (Expr, Name_Req => True),
1967                           Selector_Name =>
1968                             Make_Identifier (Loc, Chars (Discr))),
1969                                 New_Constraints);
1970
1971                   else
1972                      --  Discriminant of more remote ancestor ???
1973
1974                      return;
1975                   end if;
1976
1977                --  Derived type definition has an explicit value for
1978                --  this stored discriminant.
1979
1980                else
1981                   Append_Elmt
1982                     (Duplicate_Subexpr_No_Checks (Discr_Value),
1983                      New_Constraints);
1984                end if;
1985
1986                Next_Elmt (Constraint);
1987             end loop;
1988
1989             --  Use the unconstrained expression type to retrieve the
1990             --  discriminants of the parent, and apply momentarily the
1991             --  discriminant constraint synthesized above.
1992
1993             Set_Discriminant_Constraint (Expr_Type, New_Constraints);
1994             Cond := Build_Discriminant_Checks (Expr, Expr_Type);
1995             Set_Discriminant_Constraint (Expr_Type, Old_Constraints);
1996
1997             Insert_Action (N,
1998               Make_Raise_Constraint_Error (Loc,
1999                 Condition => Cond,
2000                 Reason    => CE_Discriminant_Check_Failed));
2001          end;
2002
2003       --  For arrays, conversions are applied during expansion, to take
2004       --  into accounts changes of representation.  The checks become range
2005       --  checks on the base type or length checks on the subtype, depending
2006       --  on whether the target type is unconstrained or constrained.
2007
2008       else
2009          null;
2010       end if;
2011    end Apply_Type_Conversion_Checks;
2012
2013    ----------------------------------------------
2014    -- Apply_Universal_Integer_Attribute_Checks --
2015    ----------------------------------------------
2016
2017    procedure Apply_Universal_Integer_Attribute_Checks (N : Node_Id) is
2018       Loc : constant Source_Ptr := Sloc (N);
2019       Typ : constant Entity_Id  := Etype (N);
2020
2021    begin
2022       if Inside_A_Generic then
2023          return;
2024
2025       --  Nothing to do if checks are suppressed
2026
2027       elsif Range_Checks_Suppressed (Typ)
2028         and then Overflow_Checks_Suppressed (Typ)
2029       then
2030          return;
2031
2032       --  Nothing to do if the attribute does not come from source. The
2033       --  internal attributes we generate of this type do not need checks,
2034       --  and furthermore the attempt to check them causes some circular
2035       --  elaboration orders when dealing with packed types.
2036
2037       elsif not Comes_From_Source (N) then
2038          return;
2039
2040       --  If the prefix is a selected component that depends on a discriminant
2041       --  the check may improperly expose a discriminant instead of using
2042       --  the bounds of the object itself. Set the type of the attribute to
2043       --  the base type of the context, so that a check will be imposed when
2044       --  needed (e.g. if the node appears as an index).
2045
2046       elsif Nkind (Prefix (N)) = N_Selected_Component
2047         and then Ekind (Typ) = E_Signed_Integer_Subtype
2048         and then Depends_On_Discriminant (Scalar_Range (Typ))
2049       then
2050          Set_Etype (N, Base_Type (Typ));
2051
2052       --  Otherwise, replace the attribute node with a type conversion
2053       --  node whose expression is the attribute, retyped to universal
2054       --  integer, and whose subtype mark is the target type. The call
2055       --  to analyze this conversion will set range and overflow checks
2056       --  as required for proper detection of an out of range value.
2057
2058       else
2059          Set_Etype    (N, Universal_Integer);
2060          Set_Analyzed (N, True);
2061
2062          Rewrite (N,
2063            Make_Type_Conversion (Loc,
2064              Subtype_Mark => New_Occurrence_Of (Typ, Loc),
2065              Expression   => Relocate_Node (N)));
2066
2067          Analyze_And_Resolve (N, Typ);
2068          return;
2069       end if;
2070
2071    end Apply_Universal_Integer_Attribute_Checks;
2072
2073    -------------------------------
2074    -- Build_Discriminant_Checks --
2075    -------------------------------
2076
2077    function Build_Discriminant_Checks
2078      (N     : Node_Id;
2079       T_Typ : Entity_Id)
2080       return Node_Id
2081    is
2082       Loc      : constant Source_Ptr := Sloc (N);
2083       Cond     : Node_Id;
2084       Disc     : Elmt_Id;
2085       Disc_Ent : Entity_Id;
2086       Dref     : Node_Id;
2087       Dval     : Node_Id;
2088
2089    begin
2090       Cond := Empty;
2091       Disc := First_Elmt (Discriminant_Constraint (T_Typ));
2092
2093       --  For a fully private type, use the discriminants of the parent type
2094
2095       if Is_Private_Type (T_Typ)
2096         and then No (Full_View (T_Typ))
2097       then
2098          Disc_Ent := First_Discriminant (Etype (Base_Type (T_Typ)));
2099       else
2100          Disc_Ent := First_Discriminant (T_Typ);
2101       end if;
2102
2103       while Present (Disc) loop
2104          Dval := Node (Disc);
2105
2106          if Nkind (Dval) = N_Identifier
2107            and then Ekind (Entity (Dval)) = E_Discriminant
2108          then
2109             Dval := New_Occurrence_Of (Discriminal (Entity (Dval)), Loc);
2110          else
2111             Dval := Duplicate_Subexpr_No_Checks (Dval);
2112          end if;
2113
2114          Dref :=
2115            Make_Selected_Component (Loc,
2116              Prefix =>
2117                Duplicate_Subexpr_No_Checks (N, Name_Req => True),
2118              Selector_Name =>
2119                Make_Identifier (Loc, Chars (Disc_Ent)));
2120
2121          Set_Is_In_Discriminant_Check (Dref);
2122
2123          Evolve_Or_Else (Cond,
2124            Make_Op_Ne (Loc,
2125              Left_Opnd => Dref,
2126              Right_Opnd => Dval));
2127
2128          Next_Elmt (Disc);
2129          Next_Discriminant (Disc_Ent);
2130       end loop;
2131
2132       return Cond;
2133    end Build_Discriminant_Checks;
2134
2135    -----------------------------------
2136    -- Check_Valid_Lvalue_Subscripts --
2137    -----------------------------------
2138
2139    procedure Check_Valid_Lvalue_Subscripts (Expr : Node_Id) is
2140    begin
2141       --  Skip this if range checks are suppressed
2142
2143       if Range_Checks_Suppressed (Etype (Expr)) then
2144          return;
2145
2146       --  Only do this check for expressions that come from source. We
2147       --  assume that expander generated assignments explicitly include
2148       --  any necessary checks. Note that this is not just an optimization,
2149       --  it avoids infinite recursions!
2150
2151       elsif not Comes_From_Source (Expr) then
2152          return;
2153
2154       --  For a selected component, check the prefix
2155
2156       elsif Nkind (Expr) = N_Selected_Component then
2157          Check_Valid_Lvalue_Subscripts (Prefix (Expr));
2158          return;
2159
2160       --  Case of indexed component
2161
2162       elsif Nkind (Expr) = N_Indexed_Component then
2163          Apply_Subscript_Validity_Checks (Expr);
2164
2165          --  Prefix may itself be or contain an indexed component, and
2166          --  these subscripts need checking as well
2167
2168          Check_Valid_Lvalue_Subscripts (Prefix (Expr));
2169       end if;
2170    end Check_Valid_Lvalue_Subscripts;
2171
2172    ----------------------------------
2173    -- Conditional_Statements_Begin --
2174    ----------------------------------
2175
2176    procedure Conditional_Statements_Begin is
2177    begin
2178       Saved_Checks_TOS := Saved_Checks_TOS + 1;
2179
2180       --  If stack overflows, kill all checks, that way we know to
2181       --  simply reset the number of saved checks to zero on return.
2182       --  This should never occur in practice.
2183
2184       if Saved_Checks_TOS > Saved_Checks_Stack'Last then
2185          Kill_All_Checks;
2186
2187       --  In the normal case, we just make a new stack entry saving
2188       --  the current number of saved checks for a later restore.
2189
2190       else
2191          Saved_Checks_Stack (Saved_Checks_TOS) := Num_Saved_Checks;
2192
2193          if Debug_Flag_CC then
2194             w ("Conditional_Statements_Begin: Num_Saved_Checks = ",
2195                Num_Saved_Checks);
2196          end if;
2197       end if;
2198    end Conditional_Statements_Begin;
2199
2200    --------------------------------
2201    -- Conditional_Statements_End --
2202    --------------------------------
2203
2204    procedure Conditional_Statements_End is
2205    begin
2206       pragma Assert (Saved_Checks_TOS > 0);
2207
2208       --  If the saved checks stack overflowed, then we killed all
2209       --  checks, so setting the number of saved checks back to
2210       --  zero is correct. This should never occur in practice.
2211
2212       if Saved_Checks_TOS > Saved_Checks_Stack'Last then
2213          Num_Saved_Checks := 0;
2214
2215       --  In the normal case, restore the number of saved checks
2216       --  from the top stack entry.
2217
2218       else
2219          Num_Saved_Checks := Saved_Checks_Stack (Saved_Checks_TOS);
2220          if Debug_Flag_CC then
2221             w ("Conditional_Statements_End: Num_Saved_Checks = ",
2222                Num_Saved_Checks);
2223          end if;
2224       end if;
2225
2226       Saved_Checks_TOS := Saved_Checks_TOS - 1;
2227    end Conditional_Statements_End;
2228
2229    ---------------------
2230    -- Determine_Range --
2231    ---------------------
2232
2233    Cache_Size : constant := 2 ** 10;
2234    type Cache_Index is range 0 .. Cache_Size - 1;
2235    --  Determine size of below cache (power of 2 is more efficient!)
2236
2237    Determine_Range_Cache_N  : array (Cache_Index) of Node_Id;
2238    Determine_Range_Cache_Lo : array (Cache_Index) of Uint;
2239    Determine_Range_Cache_Hi : array (Cache_Index) of Uint;
2240    --  The above arrays are used to implement a small direct cache
2241    --  for Determine_Range calls. Because of the way Determine_Range
2242    --  recursively traces subexpressions, and because overflow checking
2243    --  calls the routine on the way up the tree, a quadratic behavior
2244    --  can otherwise be encountered in large expressions. The cache
2245    --  entry for node N is stored in the (N mod Cache_Size) entry, and
2246    --  can be validated by checking the actual node value stored there.
2247
2248    procedure Determine_Range
2249      (N  : Node_Id;
2250       OK : out Boolean;
2251       Lo : out Uint;
2252       Hi : out Uint)
2253    is
2254       Typ : constant Entity_Id := Etype (N);
2255
2256       Lo_Left : Uint;
2257       Hi_Left : Uint;
2258       --  Lo and Hi bounds of left operand
2259
2260       Lo_Right : Uint;
2261       Hi_Right : Uint;
2262       --  Lo and Hi bounds of right (or only) operand
2263
2264       Bound : Node_Id;
2265       --  Temp variable used to hold a bound node
2266
2267       Hbound : Uint;
2268       --  High bound of base type of expression
2269
2270       Lor : Uint;
2271       Hir : Uint;
2272       --  Refined values for low and high bounds, after tightening
2273
2274       OK1 : Boolean;
2275       --  Used in lower level calls to indicate if call succeeded
2276
2277       Cindex : Cache_Index;
2278       --  Used to search cache
2279
2280       function OK_Operands return Boolean;
2281       --  Used for binary operators. Determines the ranges of the left and
2282       --  right operands, and if they are both OK, returns True, and puts
2283       --  the results in Lo_Right, Hi_Right, Lo_Left, Hi_Left
2284
2285       -----------------
2286       -- OK_Operands --
2287       -----------------
2288
2289       function OK_Operands return Boolean is
2290       begin
2291          Determine_Range (Left_Opnd  (N), OK1, Lo_Left,  Hi_Left);
2292
2293          if not OK1 then
2294             return False;
2295          end if;
2296
2297          Determine_Range (Right_Opnd (N), OK1, Lo_Right, Hi_Right);
2298          return OK1;
2299       end OK_Operands;
2300
2301    --  Start of processing for Determine_Range
2302
2303    begin
2304       --  Prevent junk warnings by initializing range variables
2305
2306       Lo  := No_Uint;
2307       Hi  := No_Uint;
2308       Lor := No_Uint;
2309       Hir := No_Uint;
2310
2311       --  If the type is not discrete, or is undefined, then we can't
2312       --  do anything about determining the range.
2313
2314       if No (Typ) or else not Is_Discrete_Type (Typ)
2315         or else Error_Posted (N)
2316       then
2317          OK := False;
2318          return;
2319       end if;
2320
2321       --  For all other cases, we can determine the range
2322
2323       OK := True;
2324
2325       --  If value is compile time known, then the possible range is the
2326       --  one value that we know this expression definitely has!
2327
2328       if Compile_Time_Known_Value (N) then
2329          Lo := Expr_Value (N);
2330          Hi := Lo;
2331          return;
2332       end if;
2333
2334       --  Return if already in the cache
2335
2336       Cindex := Cache_Index (N mod Cache_Size);
2337
2338       if Determine_Range_Cache_N (Cindex) = N then
2339          Lo := Determine_Range_Cache_Lo (Cindex);
2340          Hi := Determine_Range_Cache_Hi (Cindex);
2341          return;
2342       end if;
2343
2344       --  Otherwise, start by finding the bounds of the type of the
2345       --  expression, the value cannot be outside this range (if it
2346       --  is, then we have an overflow situation, which is a separate
2347       --  check, we are talking here only about the expression value).
2348
2349       --  We use the actual bound unless it is dynamic, in which case
2350       --  use the corresponding base type bound if possible. If we can't
2351       --  get a bound then we figure we can't determine the range (a
2352       --  peculiar case, that perhaps cannot happen, but there is no
2353       --  point in bombing in this optimization circuit.
2354
2355       --  First the low bound
2356
2357       Bound := Type_Low_Bound (Typ);
2358
2359       if Compile_Time_Known_Value (Bound) then
2360          Lo := Expr_Value (Bound);
2361
2362       elsif Compile_Time_Known_Value (Type_Low_Bound (Base_Type (Typ))) then
2363          Lo := Expr_Value (Type_Low_Bound (Base_Type (Typ)));
2364
2365       else
2366          OK := False;
2367          return;
2368       end if;
2369
2370       --  Now the high bound
2371
2372       Bound := Type_High_Bound (Typ);
2373
2374       --  We need the high bound of the base type later on, and this should
2375       --  always be compile time known. Again, it is not clear that this
2376       --  can ever be false, but no point in bombing.
2377
2378       if Compile_Time_Known_Value (Type_High_Bound (Base_Type (Typ))) then
2379          Hbound := Expr_Value (Type_High_Bound (Base_Type (Typ)));
2380          Hi := Hbound;
2381
2382       else
2383          OK := False;
2384          return;
2385       end if;
2386
2387       --  If we have a static subtype, then that may have a tighter bound
2388       --  so use the upper bound of the subtype instead in this case.
2389
2390       if Compile_Time_Known_Value (Bound) then
2391          Hi := Expr_Value (Bound);
2392       end if;
2393
2394       --  We may be able to refine this value in certain situations. If
2395       --  refinement is possible, then Lor and Hir are set to possibly
2396       --  tighter bounds, and OK1 is set to True.
2397
2398       case Nkind (N) is
2399
2400          --  For unary plus, result is limited by range of operand
2401
2402          when N_Op_Plus =>
2403             Determine_Range (Right_Opnd (N), OK1, Lor, Hir);
2404
2405          --  For unary minus, determine range of operand, and negate it
2406
2407          when N_Op_Minus =>
2408             Determine_Range (Right_Opnd (N), OK1, Lo_Right, Hi_Right);
2409
2410             if OK1 then
2411                Lor := -Hi_Right;
2412                Hir := -Lo_Right;
2413             end if;
2414
2415          --  For binary addition, get range of each operand and do the
2416          --  addition to get the result range.
2417
2418          when N_Op_Add =>
2419             if OK_Operands then
2420                Lor := Lo_Left + Lo_Right;
2421                Hir := Hi_Left + Hi_Right;
2422             end if;
2423
2424          --  Division is tricky. The only case we consider is where the
2425          --  right operand is a positive constant, and in this case we
2426          --  simply divide the bounds of the left operand
2427
2428          when N_Op_Divide =>
2429             if OK_Operands then
2430                if Lo_Right = Hi_Right
2431                  and then Lo_Right > 0
2432                then
2433                   Lor := Lo_Left / Lo_Right;
2434                   Hir := Hi_Left / Lo_Right;
2435
2436                else
2437                   OK1 := False;
2438                end if;
2439             end if;
2440
2441          --  For binary subtraction, get range of each operand and do
2442          --  the worst case subtraction to get the result range.
2443
2444          when N_Op_Subtract =>
2445             if OK_Operands then
2446                Lor := Lo_Left - Hi_Right;
2447                Hir := Hi_Left - Lo_Right;
2448             end if;
2449
2450          --  For MOD, if right operand is a positive constant, then
2451          --  result must be in the allowable range of mod results.
2452
2453          when N_Op_Mod =>
2454             if OK_Operands then
2455                if Lo_Right = Hi_Right
2456                  and then Lo_Right /= 0
2457                then
2458                   if Lo_Right > 0 then
2459                      Lor := Uint_0;
2460                      Hir := Lo_Right - 1;
2461
2462                   else -- Lo_Right < 0
2463                      Lor := Lo_Right + 1;
2464                      Hir := Uint_0;
2465                   end if;
2466
2467                else
2468                   OK1 := False;
2469                end if;
2470             end if;
2471
2472          --  For REM, if right operand is a positive constant, then
2473          --  result must be in the allowable range of mod results.
2474
2475          when N_Op_Rem =>
2476             if OK_Operands then
2477                if Lo_Right = Hi_Right
2478                  and then Lo_Right /= 0
2479                then
2480                   declare
2481                      Dval : constant Uint := (abs Lo_Right) - 1;
2482
2483                   begin
2484                      --  The sign of the result depends on the sign of the
2485                      --  dividend (but not on the sign of the divisor, hence
2486                      --  the abs operation above).
2487
2488                      if Lo_Left < 0 then
2489                         Lor := -Dval;
2490                      else
2491                         Lor := Uint_0;
2492                      end if;
2493
2494                      if Hi_Left < 0 then
2495                         Hir := Uint_0;
2496                      else
2497                         Hir := Dval;
2498                      end if;
2499                   end;
2500
2501                else
2502                   OK1 := False;
2503                end if;
2504             end if;
2505
2506          --  Attribute reference cases
2507
2508          when N_Attribute_Reference =>
2509             case Attribute_Name (N) is
2510
2511                --  For Pos/Val attributes, we can refine the range using the
2512                --  possible range of values of the attribute expression
2513
2514                when Name_Pos | Name_Val =>
2515                   Determine_Range (First (Expressions (N)), OK1, Lor, Hir);
2516
2517                --  For Length attribute, use the bounds of the corresponding
2518                --  index type to refine the range.
2519
2520                when Name_Length =>
2521                   declare
2522                      Atyp : Entity_Id := Etype (Prefix (N));
2523                      Inum : Nat;
2524                      Indx : Node_Id;
2525
2526                      LL, LU : Uint;
2527                      UL, UU : Uint;
2528
2529                   begin
2530                      if Is_Access_Type (Atyp) then
2531                         Atyp := Designated_Type (Atyp);
2532                      end if;
2533
2534                      --  For string literal, we know exact value
2535
2536                      if Ekind (Atyp) = E_String_Literal_Subtype then
2537                         OK := True;
2538                         Lo := String_Literal_Length (Atyp);
2539                         Hi := String_Literal_Length (Atyp);
2540                         return;
2541                      end if;
2542
2543                      --  Otherwise check for expression given
2544
2545                      if No (Expressions (N)) then
2546                         Inum := 1;
2547                      else
2548                         Inum :=
2549                           UI_To_Int (Expr_Value (First (Expressions (N))));
2550                      end if;
2551
2552                      Indx := First_Index (Atyp);
2553                      for J in 2 .. Inum loop
2554                         Indx := Next_Index (Indx);
2555                      end loop;
2556
2557                      Determine_Range
2558                        (Type_Low_Bound (Etype (Indx)), OK1, LL, LU);
2559
2560                      if OK1 then
2561                         Determine_Range
2562                           (Type_High_Bound (Etype (Indx)), OK1, UL, UU);
2563
2564                         if OK1 then
2565
2566                            --  The maximum value for Length is the biggest
2567                            --  possible gap between the values of the bounds.
2568                            --  But of course, this value cannot be negative.
2569
2570                            Hir := UI_Max (Uint_0, UU - LL);
2571
2572                            --  For constrained arrays, the minimum value for
2573                            --  Length is taken from the actual value of the
2574                            --  bounds, since the index will be exactly of
2575                            --  this subtype.
2576
2577                            if Is_Constrained (Atyp) then
2578                               Lor := UI_Max (Uint_0, UL - LU);
2579
2580                            --  For an unconstrained array, the minimum value
2581                            --  for length is always zero.
2582
2583                            else
2584                               Lor := Uint_0;
2585                            end if;
2586                         end if;
2587                      end if;
2588                   end;
2589
2590                --  No special handling for other attributes
2591                --  Probably more opportunities exist here ???
2592
2593                when others =>
2594                   OK1 := False;
2595
2596             end case;
2597
2598          --  For type conversion from one discrete type to another, we
2599          --  can refine the range using the converted value.
2600
2601          when N_Type_Conversion =>
2602             Determine_Range (Expression (N), OK1, Lor, Hir);
2603
2604          --  Nothing special to do for all other expression kinds
2605
2606          when others =>
2607             OK1 := False;
2608             Lor := No_Uint;
2609             Hir := No_Uint;
2610       end case;
2611
2612       --  At this stage, if OK1 is true, then we know that the actual
2613       --  result of the computed expression is in the range Lor .. Hir.
2614       --  We can use this to restrict the possible range of results.
2615
2616       if OK1 then
2617
2618          --  If the refined value of the low bound is greater than the
2619          --  type high bound, then reset it to the more restrictive
2620          --  value. However, we do NOT do this for the case of a modular
2621          --  type where the possible upper bound on the value is above the
2622          --  base type high bound, because that means the result could wrap.
2623
2624          if Lor > Lo
2625            and then not (Is_Modular_Integer_Type (Typ)
2626                            and then Hir > Hbound)
2627          then
2628             Lo := Lor;
2629          end if;
2630
2631          --  Similarly, if the refined value of the high bound is less
2632          --  than the value so far, then reset it to the more restrictive
2633          --  value. Again, we do not do this if the refined low bound is
2634          --  negative for a modular type, since this would wrap.
2635
2636          if Hir < Hi
2637            and then not (Is_Modular_Integer_Type (Typ)
2638                           and then Lor < Uint_0)
2639          then
2640             Hi := Hir;
2641          end if;
2642       end if;
2643
2644       --  Set cache entry for future call and we are all done
2645
2646       Determine_Range_Cache_N  (Cindex) := N;
2647       Determine_Range_Cache_Lo (Cindex) := Lo;
2648       Determine_Range_Cache_Hi (Cindex) := Hi;
2649       return;
2650
2651    --  If any exception occurs, it means that we have some bug in the compiler
2652    --  possibly triggered by a previous error, or by some unforseen peculiar
2653    --  occurrence. However, this is only an optimization attempt, so there is
2654    --  really no point in crashing the compiler. Instead we just decide, too
2655    --  bad, we can't figure out a range in this case after all.
2656
2657    exception
2658       when others =>
2659
2660          --  Debug flag K disables this behavior (useful for debugging)
2661
2662          if Debug_Flag_K then
2663             raise;
2664          else
2665             OK := False;
2666             Lo := No_Uint;
2667             Hi := No_Uint;
2668             return;
2669          end if;
2670    end Determine_Range;
2671
2672    ------------------------------------
2673    -- Discriminant_Checks_Suppressed --
2674    ------------------------------------
2675
2676    function Discriminant_Checks_Suppressed (E : Entity_Id) return Boolean is
2677    begin
2678       if Present (E) then
2679          if Is_Unchecked_Union (E) then
2680             return True;
2681          elsif Checks_May_Be_Suppressed (E) then
2682             return Is_Check_Suppressed (E, Discriminant_Check);
2683          end if;
2684       end if;
2685
2686       return Scope_Suppress (Discriminant_Check);
2687    end Discriminant_Checks_Suppressed;
2688
2689    --------------------------------
2690    -- Division_Checks_Suppressed --
2691    --------------------------------
2692
2693    function Division_Checks_Suppressed (E : Entity_Id) return Boolean is
2694    begin
2695       if Present (E) and then Checks_May_Be_Suppressed (E) then
2696          return Is_Check_Suppressed (E, Division_Check);
2697       else
2698          return Scope_Suppress (Division_Check);
2699       end if;
2700    end Division_Checks_Suppressed;
2701
2702    -----------------------------------
2703    -- Elaboration_Checks_Suppressed --
2704    -----------------------------------
2705
2706    function Elaboration_Checks_Suppressed (E : Entity_Id) return Boolean is
2707    begin
2708       if Present (E) then
2709          if Kill_Elaboration_Checks (E) then
2710             return True;
2711          elsif Checks_May_Be_Suppressed (E) then
2712             return Is_Check_Suppressed (E, Elaboration_Check);
2713          end if;
2714       end if;
2715
2716       return Scope_Suppress (Elaboration_Check);
2717    end Elaboration_Checks_Suppressed;
2718
2719    ---------------------------
2720    -- Enable_Overflow_Check --
2721    ---------------------------
2722
2723    procedure Enable_Overflow_Check (N : Node_Id) is
2724       Typ : constant Entity_Id  := Base_Type (Etype (N));
2725       Chk : Nat;
2726       OK  : Boolean;
2727       Ent : Entity_Id;
2728       Ofs : Uint;
2729       Lo  : Uint;
2730       Hi  : Uint;
2731
2732    begin
2733       if Debug_Flag_CC then
2734          w ("Enable_Overflow_Check for node ", Int (N));
2735          Write_Str ("  Source location = ");
2736          wl (Sloc (N));
2737          pg (N);
2738       end if;
2739
2740       --  Nothing to do if the range of the result is known OK. We skip
2741       --  this for conversions, since the caller already did the check,
2742       --  and in any case the condition for deleting the check for a
2743       --  type conversion is different in any case.
2744
2745       if Nkind (N) /= N_Type_Conversion then
2746          Determine_Range (N, OK, Lo, Hi);
2747
2748          --  Note in the test below that we assume that if a bound of the
2749          --  range is equal to that of the type. That's not quite accurate
2750          --  but we do this for the following reasons:
2751
2752          --   a) The way that Determine_Range works, it will typically report
2753          --      the bounds of the value as being equal to the bounds of the
2754          --      type, because it either can't tell anything more precise, or
2755          --      does not think it is worth the effort to be more precise.
2756
2757          --   b) It is very unusual to have a situation in which this would
2758          --      generate an unnecessary overflow check (an example would be
2759          --      a subtype with a range 0 .. Integer'Last - 1 to which the
2760          --      literal value one is added.
2761
2762          --   c) The alternative is a lot of special casing in this routine
2763          --      which would partially duplicate Determine_Range processing.
2764
2765          if OK
2766            and then Lo > Expr_Value (Type_Low_Bound  (Typ))
2767            and then Hi < Expr_Value (Type_High_Bound (Typ))
2768          then
2769             if Debug_Flag_CC then
2770                w ("No overflow check required");
2771             end if;
2772
2773             return;
2774          end if;
2775       end if;
2776
2777       --  If not in optimizing mode, set flag and we are done. We are also
2778       --  done (and just set the flag) if the type is not a discrete type,
2779       --  since it is not worth the effort to eliminate checks for other
2780       --  than discrete types. In addition, we take this same path if we
2781       --  have stored the maximum number of checks possible already (a
2782       --  very unlikely situation, but we do not want to blow up!)
2783
2784       if Optimization_Level = 0
2785         or else not Is_Discrete_Type (Etype (N))
2786         or else Num_Saved_Checks = Saved_Checks'Last
2787       then
2788          Set_Do_Overflow_Check (N, True);
2789
2790          if Debug_Flag_CC then
2791             w ("Optimization off");
2792          end if;
2793
2794          return;
2795       end if;
2796
2797       --  Otherwise evaluate and check the expression
2798
2799       Find_Check
2800         (Expr        => N,
2801          Check_Type  => 'O',
2802          Target_Type => Empty,
2803          Entry_OK    => OK,
2804          Check_Num   => Chk,
2805          Ent         => Ent,
2806          Ofs         => Ofs);
2807
2808       if Debug_Flag_CC then
2809          w ("Called Find_Check");
2810          w ("  OK = ", OK);
2811
2812          if OK then
2813             w ("  Check_Num = ", Chk);
2814             w ("  Ent       = ", Int (Ent));
2815             Write_Str ("  Ofs       = ");
2816             pid (Ofs);
2817          end if;
2818       end if;
2819
2820       --  If check is not of form to optimize, then set flag and we are done
2821
2822       if not OK then
2823          Set_Do_Overflow_Check (N, True);
2824          return;
2825       end if;
2826
2827       --  If check is already performed, then return without setting flag
2828
2829       if Chk /= 0 then
2830          if Debug_Flag_CC then
2831             w ("Check suppressed!");
2832          end if;
2833
2834          return;
2835       end if;
2836
2837       --  Here we will make a new entry for the new check
2838
2839       Set_Do_Overflow_Check (N, True);
2840       Num_Saved_Checks := Num_Saved_Checks + 1;
2841       Saved_Checks (Num_Saved_Checks) :=
2842         (Killed      => False,
2843          Entity      => Ent,
2844          Offset      => Ofs,
2845          Check_Type  => 'O',
2846          Target_Type => Empty);
2847
2848       if Debug_Flag_CC then
2849          w ("Make new entry, check number = ", Num_Saved_Checks);
2850          w ("  Entity = ", Int (Ent));
2851          Write_Str ("  Offset = ");
2852          pid (Ofs);
2853          w ("  Check_Type = O");
2854          w ("  Target_Type = Empty");
2855       end if;
2856
2857    --  If we get an exception, then something went wrong, probably because
2858    --  of an error in the structure of the tree due to an incorrect program.
2859    --  Or it may be a bug in the optimization circuit. In either case the
2860    --  safest thing is simply to set the check flag unconditionally.
2861
2862    exception
2863       when others =>
2864          Set_Do_Overflow_Check (N, True);
2865
2866          if Debug_Flag_CC then
2867             w ("  exception occurred, overflow flag set");
2868          end if;
2869
2870          return;
2871    end Enable_Overflow_Check;
2872
2873    ------------------------
2874    -- Enable_Range_Check --
2875    ------------------------
2876
2877    procedure Enable_Range_Check (N : Node_Id) is
2878       Chk  : Nat;
2879       OK   : Boolean;
2880       Ent  : Entity_Id;
2881       Ofs  : Uint;
2882       Ttyp : Entity_Id;
2883       P    : Node_Id;
2884
2885    begin
2886       --  Return if unchecked type conversion with range check killed.
2887       --  In this case we never set the flag (that's what Kill_Range_Check
2888       --  is all about!)
2889
2890       if Nkind (N) = N_Unchecked_Type_Conversion
2891         and then Kill_Range_Check (N)
2892       then
2893          return;
2894       end if;
2895
2896       --  Debug trace output
2897
2898       if Debug_Flag_CC then
2899          w ("Enable_Range_Check for node ", Int (N));
2900          Write_Str ("  Source location = ");
2901          wl (Sloc (N));
2902          pg (N);
2903       end if;
2904
2905       --  If not in optimizing mode, set flag and we are done. We are also
2906       --  done (and just set the flag) if the type is not a discrete type,
2907       --  since it is not worth the effort to eliminate checks for other
2908       --  than discrete types. In addition, we take this same path if we
2909       --  have stored the maximum number of checks possible already (a
2910       --  very unlikely situation, but we do not want to blow up!)
2911
2912       if Optimization_Level = 0
2913         or else No (Etype (N))
2914         or else not Is_Discrete_Type (Etype (N))
2915         or else Num_Saved_Checks = Saved_Checks'Last
2916       then
2917          Set_Do_Range_Check (N, True);
2918
2919          if Debug_Flag_CC then
2920             w ("Optimization off");
2921          end if;
2922
2923          return;
2924       end if;
2925
2926       --  Otherwise find out the target type
2927
2928       P := Parent (N);
2929
2930       --  For assignment, use left side subtype
2931
2932       if Nkind (P) = N_Assignment_Statement
2933         and then Expression (P) = N
2934       then
2935          Ttyp := Etype (Name (P));
2936
2937       --  For indexed component, use subscript subtype
2938
2939       elsif Nkind (P) = N_Indexed_Component then
2940          declare
2941             Atyp : Entity_Id;
2942             Indx : Node_Id;
2943             Subs : Node_Id;
2944
2945          begin
2946             Atyp := Etype (Prefix (P));
2947
2948             if Is_Access_Type (Atyp) then
2949                Atyp := Designated_Type (Atyp);
2950             end if;
2951
2952             Indx := First_Index (Atyp);
2953             Subs := First (Expressions (P));
2954             loop
2955                if Subs = N then
2956                   Ttyp := Etype (Indx);
2957                   exit;
2958                end if;
2959
2960                Next_Index (Indx);
2961                Next (Subs);
2962             end loop;
2963          end;
2964
2965       --  For now, ignore all other cases, they are not so interesting
2966
2967       else
2968          if Debug_Flag_CC then
2969             w ("  target type not found, flag set");
2970          end if;
2971
2972          Set_Do_Range_Check (N, True);
2973          return;
2974       end if;
2975
2976       --  Evaluate and check the expression
2977
2978       Find_Check
2979         (Expr        => N,
2980          Check_Type  => 'R',
2981          Target_Type => Ttyp,
2982          Entry_OK    => OK,
2983          Check_Num   => Chk,
2984          Ent         => Ent,
2985          Ofs         => Ofs);
2986
2987       if Debug_Flag_CC then
2988          w ("Called Find_Check");
2989          w ("Target_Typ = ", Int (Ttyp));
2990          w ("  OK = ", OK);
2991
2992          if OK then
2993             w ("  Check_Num = ", Chk);
2994             w ("  Ent       = ", Int (Ent));
2995             Write_Str ("  Ofs       = ");
2996             pid (Ofs);
2997          end if;
2998       end if;
2999
3000       --  If check is not of form to optimize, then set flag and we are done
3001
3002       if not OK then
3003          if Debug_Flag_CC then
3004             w ("  expression not of optimizable type, flag set");
3005          end if;
3006
3007          Set_Do_Range_Check (N, True);
3008          return;
3009       end if;
3010
3011       --  If check is already performed, then return without setting flag
3012
3013       if Chk /= 0 then
3014          if Debug_Flag_CC then
3015             w ("Check suppressed!");
3016          end if;
3017
3018          return;
3019       end if;
3020
3021       --  Here we will make a new entry for the new check
3022
3023       Set_Do_Range_Check (N, True);
3024       Num_Saved_Checks := Num_Saved_Checks + 1;
3025       Saved_Checks (Num_Saved_Checks) :=
3026         (Killed      => False,
3027          Entity      => Ent,
3028          Offset      => Ofs,
3029          Check_Type  => 'R',
3030          Target_Type => Ttyp);
3031
3032       if Debug_Flag_CC then
3033          w ("Make new entry, check number = ", Num_Saved_Checks);
3034          w ("  Entity = ", Int (Ent));
3035          Write_Str ("  Offset = ");
3036          pid (Ofs);
3037          w ("  Check_Type = R");
3038          w ("  Target_Type = ", Int (Ttyp));
3039          pg (Ttyp);
3040       end if;
3041
3042    --  If we get an exception, then something went wrong, probably because
3043    --  of an error in the structure of the tree due to an incorrect program.
3044    --  Or it may be a bug in the optimization circuit. In either case the
3045    --  safest thing is simply to set the check flag unconditionally.
3046
3047    exception
3048       when others =>
3049          Set_Do_Range_Check (N, True);
3050
3051          if Debug_Flag_CC then
3052             w ("  exception occurred, range flag set");
3053          end if;
3054
3055          return;
3056    end Enable_Range_Check;
3057
3058    ------------------
3059    -- Ensure_Valid --
3060    ------------------
3061
3062    procedure Ensure_Valid (Expr : Node_Id; Holes_OK : Boolean := False) is
3063       Typ : constant Entity_Id  := Etype (Expr);
3064
3065    begin
3066       --  Ignore call if we are not doing any validity checking
3067
3068       if not Validity_Checks_On then
3069          return;
3070
3071       --  Ignore call if range checks suppressed on entity in question
3072
3073       elsif Is_Entity_Name (Expr)
3074         and then Range_Checks_Suppressed (Entity (Expr))
3075       then
3076          return;
3077
3078       --  No check required if expression is from the expander, we assume
3079       --  the expander will generate whatever checks are needed. Note that
3080       --  this is not just an optimization, it avoids infinite recursions!
3081
3082       --  Unchecked conversions must be checked, unless they are initialized
3083       --  scalar values, as in a component assignment in an init proc.
3084
3085       --  In addition, we force a check if Force_Validity_Checks is set
3086
3087       elsif not Comes_From_Source (Expr)
3088         and then not Force_Validity_Checks
3089         and then (Nkind (Expr) /= N_Unchecked_Type_Conversion
3090                     or else Kill_Range_Check (Expr))
3091       then
3092          return;
3093
3094       --  No check required if expression is known to have valid value
3095
3096       elsif Expr_Known_Valid (Expr) then
3097          return;
3098
3099       --  No check required if checks off
3100
3101       elsif Range_Checks_Suppressed (Typ) then
3102          return;
3103
3104       --  Ignore case of enumeration with holes where the flag is set not
3105       --  to worry about holes, since no special validity check is needed
3106
3107       elsif Is_Enumeration_Type (Typ)
3108         and then Has_Non_Standard_Rep (Typ)
3109         and then Holes_OK
3110       then
3111          return;
3112
3113       --  No check required on the left-hand side of an assignment.
3114
3115       elsif Nkind (Parent (Expr)) = N_Assignment_Statement
3116         and then Expr = Name (Parent (Expr))
3117       then
3118          return;
3119
3120       --  An annoying special case. If this is an out parameter of a scalar
3121       --  type, then the value is not going to be accessed, therefore it is
3122       --  inappropriate to do any validity check at the call site.
3123
3124       else
3125          --  Only need to worry about scalar types
3126
3127          if Is_Scalar_Type (Typ) then
3128             declare
3129                P : Node_Id;
3130                N : Node_Id;
3131                E : Entity_Id;
3132                F : Entity_Id;
3133                A : Node_Id;
3134                L : List_Id;
3135
3136             begin
3137                --  Find actual argument (which may be a parameter association)
3138                --  and the parent of the actual argument (the call statement)
3139
3140                N := Expr;
3141                P := Parent (Expr);
3142
3143                if Nkind (P) = N_Parameter_Association then
3144                   N := P;
3145                   P := Parent (N);
3146                end if;
3147
3148                --  Only need to worry if we are argument of a procedure
3149                --  call since functions don't have out parameters. If this
3150                --  is an indirect or dispatching call, get signature from
3151                --  the subprogram type.
3152
3153                if Nkind (P) = N_Procedure_Call_Statement then
3154                   L := Parameter_Associations (P);
3155
3156                   if Is_Entity_Name (Name (P)) then
3157                      E := Entity (Name (P));
3158                   else
3159                      pragma Assert (Nkind (Name (P)) = N_Explicit_Dereference);
3160                      E := Etype (Name (P));
3161                   end if;
3162
3163                   --  Only need to worry if there are indeed actuals, and
3164                   --  if this could be a procedure call, otherwise we cannot
3165                   --  get a match (either we are not an argument, or the
3166                   --  mode of the formal is not OUT). This test also filters
3167                   --  out the generic case.
3168
3169                   if Is_Non_Empty_List (L)
3170                     and then Is_Subprogram (E)
3171                   then
3172                      --  This is the loop through parameters, looking to
3173                      --  see if there is an OUT parameter for which we are
3174                      --  the argument.
3175
3176                      F := First_Formal (E);
3177                      A := First (L);
3178
3179                      while Present (F) loop
3180                         if Ekind (F) = E_Out_Parameter and then A = N then
3181                            return;
3182                         end if;
3183
3184                         Next_Formal (F);
3185                         Next (A);
3186                      end loop;
3187                   end if;
3188                end if;
3189             end;
3190          end if;
3191       end if;
3192
3193       --  If we fall through, a validity check is required. Note that it would
3194       --  not be good to set Do_Range_Check, even in contexts where this is
3195       --  permissible, since this flag causes checking against the target type,
3196       --  not the source type in contexts such as assignments
3197
3198       Insert_Valid_Check (Expr);
3199    end Ensure_Valid;
3200
3201    ----------------------
3202    -- Expr_Known_Valid --
3203    ----------------------
3204
3205    function Expr_Known_Valid (Expr : Node_Id) return Boolean is
3206       Typ : constant Entity_Id := Etype (Expr);
3207
3208    begin
3209       --  Non-scalar types are always consdered valid, since they never
3210       --  give rise to the issues of erroneous or bounded error behavior
3211       --  that are the concern. In formal reference manual terms the
3212       --  notion of validity only applies to scalar types.
3213
3214       if not Is_Scalar_Type (Typ) then
3215          return True;
3216
3217       --  If no validity checking, then everything is considered valid
3218
3219       elsif not Validity_Checks_On then
3220          return True;
3221
3222       --  Floating-point types are considered valid unless floating-point
3223       --  validity checks have been specifically turned on.
3224
3225       elsif Is_Floating_Point_Type (Typ)
3226         and then not Validity_Check_Floating_Point
3227       then
3228          return True;
3229
3230       --  If the expression is the value of an object that is known to
3231       --  be valid, then clearly the expression value itself is valid.
3232
3233       elsif Is_Entity_Name (Expr)
3234         and then Is_Known_Valid (Entity (Expr))
3235       then
3236          return True;
3237
3238       --  If the type is one for which all values are known valid, then
3239       --  we are sure that the value is valid except in the slightly odd
3240       --  case where the expression is a reference to a variable whose size
3241       --  has been explicitly set to a value greater than the object size.
3242
3243       elsif Is_Known_Valid (Typ) then
3244          if Is_Entity_Name (Expr)
3245            and then Ekind (Entity (Expr)) = E_Variable
3246            and then Esize (Entity (Expr)) > Esize (Typ)
3247          then
3248             return False;
3249          else
3250             return True;
3251          end if;
3252
3253       --  Integer and character literals always have valid values, where
3254       --  appropriate these will be range checked in any case.
3255
3256       elsif Nkind (Expr) = N_Integer_Literal
3257               or else
3258             Nkind (Expr) = N_Character_Literal
3259       then
3260          return True;
3261
3262       --  If we have a type conversion or a qualification of a known valid
3263       --  value, then the result will always be valid.
3264
3265       elsif Nkind (Expr) = N_Type_Conversion
3266               or else
3267             Nkind (Expr) = N_Qualified_Expression
3268       then
3269          return Expr_Known_Valid (Expression (Expr));
3270
3271       --  The result of any function call or operator is always considered
3272       --  valid, since we assume the necessary checks are done by the call.
3273
3274       elsif Nkind (Expr) in N_Binary_Op
3275               or else
3276             Nkind (Expr) in N_Unary_Op
3277               or else
3278             Nkind (Expr) = N_Function_Call
3279       then
3280          return True;
3281
3282       --  For all other cases, we do not know the expression is valid
3283
3284       else
3285          return False;
3286       end if;
3287    end Expr_Known_Valid;
3288
3289    ----------------
3290    -- Find_Check --
3291    ----------------
3292
3293    procedure Find_Check
3294      (Expr        : Node_Id;
3295       Check_Type  : Character;
3296       Target_Type : Entity_Id;
3297       Entry_OK    : out Boolean;
3298       Check_Num   : out Nat;
3299       Ent         : out Entity_Id;
3300       Ofs         : out Uint)
3301    is
3302       function Within_Range_Of
3303         (Target_Type : Entity_Id;
3304          Check_Type  : Entity_Id)
3305          return        Boolean;
3306       --  Given a requirement for checking a range against Target_Type, and
3307       --  and a range Check_Type against which a check has already been made,
3308       --  determines if the check against check type is sufficient to ensure
3309       --  that no check against Target_Type is required.
3310
3311       ---------------------
3312       -- Within_Range_Of --
3313       ---------------------
3314
3315       function Within_Range_Of
3316         (Target_Type : Entity_Id;
3317          Check_Type  : Entity_Id)
3318          return        Boolean
3319       is
3320       begin
3321          if Target_Type = Check_Type then
3322             return True;
3323
3324          else
3325             declare
3326                Tlo : constant Node_Id := Type_Low_Bound  (Target_Type);
3327                Thi : constant Node_Id := Type_High_Bound (Target_Type);
3328                Clo : constant Node_Id := Type_Low_Bound  (Check_Type);
3329                Chi : constant Node_Id := Type_High_Bound (Check_Type);
3330
3331             begin
3332                if (Tlo = Clo
3333                      or else (Compile_Time_Known_Value (Tlo)
3334                                 and then
3335                               Compile_Time_Known_Value (Clo)
3336                                 and then
3337                               Expr_Value (Clo) >= Expr_Value (Tlo)))
3338                  and then
3339                   (Thi = Chi
3340                      or else (Compile_Time_Known_Value (Thi)
3341                                 and then
3342                               Compile_Time_Known_Value (Chi)
3343                                 and then
3344                               Expr_Value (Chi) <= Expr_Value (Clo)))
3345                then
3346                   return True;
3347                else
3348                   return False;
3349                end if;
3350             end;
3351          end if;
3352       end Within_Range_Of;
3353
3354    --  Start of processing for Find_Check
3355
3356    begin
3357       --  Establish default, to avoid warnings from GCC.
3358
3359       Check_Num := 0;
3360
3361       --  Case of expression is simple entity reference
3362
3363       if Is_Entity_Name (Expr) then
3364          Ent := Entity (Expr);
3365          Ofs := Uint_0;
3366
3367       --  Case of expression is entity + known constant
3368
3369       elsif Nkind (Expr) = N_Op_Add
3370         and then Compile_Time_Known_Value (Right_Opnd (Expr))
3371         and then Is_Entity_Name (Left_Opnd (Expr))
3372       then
3373          Ent := Entity (Left_Opnd (Expr));
3374          Ofs := Expr_Value (Right_Opnd (Expr));
3375
3376       --  Case of expression is entity - known constant
3377
3378       elsif Nkind (Expr) = N_Op_Subtract
3379         and then Compile_Time_Known_Value (Right_Opnd (Expr))
3380         and then Is_Entity_Name (Left_Opnd (Expr))
3381       then
3382          Ent := Entity (Left_Opnd (Expr));
3383          Ofs := UI_Negate (Expr_Value (Right_Opnd (Expr)));
3384
3385       --  Any other expression is not of the right form
3386
3387       else
3388          Ent := Empty;
3389          Ofs := Uint_0;
3390          Entry_OK := False;
3391          return;
3392       end if;
3393
3394       --  Come here with expression of appropriate form, check if
3395       --  entity is an appropriate one for our purposes.
3396
3397       if (Ekind (Ent) = E_Variable
3398             or else
3399           Ekind (Ent) = E_Constant
3400             or else
3401           Ekind (Ent) = E_Loop_Parameter
3402             or else
3403           Ekind (Ent) = E_In_Parameter)
3404         and then not Is_Library_Level_Entity (Ent)
3405       then
3406          Entry_OK := True;
3407       else
3408          Entry_OK := False;
3409          return;
3410       end if;
3411
3412       --  See if there is matching check already
3413
3414       for J in reverse 1 .. Num_Saved_Checks loop
3415          declare
3416             SC : Saved_Check renames Saved_Checks (J);
3417
3418          begin
3419             if SC.Killed = False
3420               and then SC.Entity = Ent
3421               and then SC.Offset = Ofs
3422               and then SC.Check_Type = Check_Type
3423               and then Within_Range_Of (Target_Type, SC.Target_Type)
3424             then
3425                Check_Num := J;
3426                return;
3427             end if;
3428          end;
3429       end loop;
3430
3431       --  If we fall through entry was not found
3432
3433       Check_Num := 0;
3434       return;
3435    end Find_Check;
3436
3437    ---------------------------------
3438    -- Generate_Discriminant_Check --
3439    ---------------------------------
3440
3441    --  Note: the code for this procedure is derived from the
3442    --  emit_discriminant_check routine a-trans.c v1.659.
3443
3444    procedure Generate_Discriminant_Check (N : Node_Id) is
3445       Loc  : constant Source_Ptr := Sloc (N);
3446       Pref : constant Node_Id    := Prefix (N);
3447       Sel  : constant Node_Id    := Selector_Name (N);
3448
3449       Orig_Comp : constant Entity_Id :=
3450                     Original_Record_Component (Entity (Sel));
3451       --  The original component to be checked
3452
3453       Discr_Fct : constant Entity_Id :=
3454                     Discriminant_Checking_Func (Orig_Comp);
3455       --  The discriminant checking function
3456
3457       Discr : Entity_Id;
3458       --  One discriminant to be checked in the type
3459
3460       Real_Discr : Entity_Id;
3461       --  Actual discriminant in the call
3462
3463       Pref_Type : Entity_Id;
3464       --  Type of relevant prefix (ignoring private/access stuff)
3465
3466       Args : List_Id;
3467       --  List of arguments for function call
3468
3469       Formal : Entity_Id;
3470       --  Keep track of the formal corresponding to the actual we build
3471       --  for each discriminant, in order to be able to perform the
3472       --  necessary type conversions.
3473
3474       Scomp : Node_Id;
3475       --  Selected component reference for checking function argument
3476
3477    begin
3478       Pref_Type := Etype (Pref);
3479
3480       --  Force evaluation of the prefix, so that it does not get evaluated
3481       --  twice (once for the check, once for the actual reference). Such a
3482       --  double evaluation is always a potential source of inefficiency,
3483       --  and is functionally incorrect in the volatile case, or when the
3484       --  prefix may have side-effects. An entity or a component of an
3485       --  entity requires no evaluation.
3486
3487       if Is_Entity_Name (Pref) then
3488          if Treat_As_Volatile (Entity (Pref)) then
3489             Force_Evaluation (Pref, Name_Req => True);
3490          end if;
3491
3492       elsif Treat_As_Volatile (Etype (Pref)) then
3493             Force_Evaluation (Pref, Name_Req => True);
3494
3495       elsif Nkind (Pref) = N_Selected_Component
3496         and then Is_Entity_Name (Prefix (Pref))
3497       then
3498          null;
3499
3500       else
3501          Force_Evaluation (Pref, Name_Req => True);
3502       end if;
3503
3504       --  For a tagged type, use the scope of the original component to
3505       --  obtain the type, because ???
3506
3507       if Is_Tagged_Type (Scope (Orig_Comp)) then
3508          Pref_Type := Scope (Orig_Comp);
3509
3510       --  For an untagged derived type, use the discriminants of the
3511       --  parent which have been renamed in the derivation, possibly
3512       --  by a one-to-many discriminant constraint.
3513       --  For non-tagged type, initially get the Etype of the prefix
3514
3515       else
3516          if Is_Derived_Type (Pref_Type)
3517            and then Number_Discriminants (Pref_Type) /=
3518                     Number_Discriminants (Etype (Base_Type (Pref_Type)))
3519          then
3520             Pref_Type := Etype (Base_Type (Pref_Type));
3521          end if;
3522       end if;
3523
3524       --  We definitely should have a checking function, This routine should
3525       --  not be called if no discriminant checking function is present.
3526
3527       pragma Assert (Present (Discr_Fct));
3528
3529       --  Create the list of the actual parameters for the call. This list
3530       --  is the list of the discriminant fields of the record expression to
3531       --  be discriminant checked.
3532
3533       Args   := New_List;
3534       Formal := First_Formal (Discr_Fct);
3535       Discr  := First_Discriminant (Pref_Type);
3536       while Present (Discr) loop
3537
3538          --  If we have a corresponding discriminant field, and a parent
3539          --  subtype is present, then we want to use the corresponding
3540          --  discriminant since this is the one with the useful value.
3541
3542          if Present (Corresponding_Discriminant (Discr))
3543            and then Ekind (Pref_Type) = E_Record_Type
3544            and then Present (Parent_Subtype (Pref_Type))
3545          then
3546             Real_Discr := Corresponding_Discriminant (Discr);
3547          else
3548             Real_Discr := Discr;
3549          end if;
3550
3551          --  Construct the reference to the discriminant
3552
3553          Scomp :=
3554            Make_Selected_Component (Loc,
3555              Prefix =>
3556                Unchecked_Convert_To (Pref_Type,
3557                  Duplicate_Subexpr (Pref)),
3558              Selector_Name => New_Occurrence_Of (Real_Discr, Loc));
3559
3560          --  Manually analyze and resolve this selected component. We really
3561          --  want it just as it appears above, and do not want the expander
3562          --  playing discriminal games etc with this reference. Then we
3563          --  append the argument to the list we are gathering.
3564
3565          Set_Etype (Scomp, Etype (Real_Discr));
3566          Set_Analyzed (Scomp, True);
3567          Append_To (Args, Convert_To (Etype (Formal), Scomp));
3568
3569          Next_Formal_With_Extras (Formal);
3570          Next_Discriminant (Discr);
3571       end loop;
3572
3573       --  Now build and insert the call
3574
3575       Insert_Action (N,
3576         Make_Raise_Constraint_Error (Loc,
3577           Condition =>
3578             Make_Function_Call (Loc,
3579               Name => New_Occurrence_Of (Discr_Fct, Loc),
3580               Parameter_Associations => Args),
3581           Reason => CE_Discriminant_Check_Failed));
3582    end Generate_Discriminant_Check;
3583
3584    ----------------------------
3585    --  Generate_Index_Checks --
3586    ----------------------------
3587
3588    procedure Generate_Index_Checks (N : Node_Id) is
3589       Loc : constant Source_Ptr := Sloc (N);
3590       A   : constant Node_Id    := Prefix (N);
3591       Sub : Node_Id;
3592       Ind : Nat;
3593       Num : List_Id;
3594
3595    begin
3596       Sub := First (Expressions (N));
3597       Ind := 1;
3598       while Present (Sub) loop
3599          if Do_Range_Check (Sub) then
3600             Set_Do_Range_Check (Sub, False);
3601
3602             --  Force evaluation except for the case of a simple name of
3603             --  a non-volatile entity.
3604
3605             if not Is_Entity_Name (Sub)
3606               or else Treat_As_Volatile (Entity (Sub))
3607             then
3608                Force_Evaluation (Sub);
3609             end if;
3610
3611             --  Generate a raise of constraint error with the appropriate
3612             --  reason and a condition of the form:
3613
3614             --    Base_Type(Sub) not in array'range (subscript)
3615
3616             --  Note that the reason we generate the conversion to the
3617             --  base type here is that we definitely want the range check
3618             --  to take place, even if it looks like the subtype is OK.
3619             --  Optimization considerations that allow us to omit the
3620             --  check have already been taken into account in the setting
3621             --  of the Do_Range_Check flag earlier on.
3622
3623             if Ind = 1 then
3624                Num := No_List;
3625             else
3626                Num :=  New_List (Make_Integer_Literal (Loc, Ind));
3627             end if;
3628
3629             Insert_Action (N,
3630               Make_Raise_Constraint_Error (Loc,
3631                 Condition =>
3632                   Make_Not_In (Loc,
3633                     Left_Opnd  =>
3634                       Convert_To (Base_Type (Etype (Sub)),
3635                         Duplicate_Subexpr_Move_Checks (Sub)),
3636                     Right_Opnd =>
3637                       Make_Attribute_Reference (Loc,
3638                         Prefix         => Duplicate_Subexpr_Move_Checks (A),
3639                         Attribute_Name => Name_Range,
3640                         Expressions    => Num)),
3641                 Reason => CE_Index_Check_Failed));
3642          end if;
3643
3644          Ind := Ind + 1;
3645          Next (Sub);
3646       end loop;
3647    end Generate_Index_Checks;
3648
3649    --------------------------
3650    -- Generate_Range_Check --
3651    --------------------------
3652
3653    procedure Generate_Range_Check
3654      (N           : Node_Id;
3655       Target_Type : Entity_Id;
3656       Reason      : RT_Exception_Code)
3657    is
3658       Loc              : constant Source_Ptr := Sloc (N);
3659       Source_Type      : constant Entity_Id  := Etype (N);
3660       Source_Base_Type : constant Entity_Id  := Base_Type (Source_Type);
3661       Target_Base_Type : constant Entity_Id  := Base_Type (Target_Type);
3662
3663    begin
3664       --  First special case, if the source type is already within the
3665       --  range of the target type, then no check is needed (probably we
3666       --  should have stopped Do_Range_Check from being set in the first
3667       --  place, but better late than later in preventing junk code!
3668
3669       --  We do NOT apply this if the source node is a literal, since in
3670       --  this case the literal has already been labeled as having the
3671       --  subtype of the target.
3672
3673       if In_Subrange_Of (Source_Type, Target_Type)
3674         and then not
3675           (Nkind (N) = N_Integer_Literal
3676              or else
3677            Nkind (N) = N_Real_Literal
3678              or else
3679            Nkind (N) = N_Character_Literal
3680              or else
3681            (Is_Entity_Name (N)
3682               and then Ekind (Entity (N)) = E_Enumeration_Literal))
3683       then
3684          return;
3685       end if;
3686
3687       --  We need a check, so force evaluation of the node, so that it does
3688       --  not get evaluated twice (once for the check, once for the actual
3689       --  reference). Such a double evaluation is always a potential source
3690       --  of inefficiency, and is functionally incorrect in the volatile case.
3691
3692       if not Is_Entity_Name (N)
3693         or else Treat_As_Volatile (Entity (N))
3694       then
3695          Force_Evaluation (N);
3696       end if;
3697
3698       --  The easiest case is when Source_Base_Type and Target_Base_Type
3699       --  are the same since in this case we can simply do a direct
3700       --  check of the value of N against the bounds of Target_Type.
3701
3702       --    [constraint_error when N not in Target_Type]
3703
3704       --  Note: this is by far the most common case, for example all cases of
3705       --  checks on the RHS of assignments are in this category, but not all
3706       --  cases are like this. Notably conversions can involve two types.
3707
3708       if Source_Base_Type = Target_Base_Type then
3709          Insert_Action (N,
3710            Make_Raise_Constraint_Error (Loc,
3711              Condition =>
3712                Make_Not_In (Loc,
3713                  Left_Opnd  => Duplicate_Subexpr (N),
3714                  Right_Opnd => New_Occurrence_Of (Target_Type, Loc)),
3715              Reason => Reason));
3716
3717       --  Next test for the case where the target type is within the bounds
3718       --  of the base type of the source type, since in this case we can
3719       --  simply convert these bounds to the base type of T to do the test.
3720
3721       --    [constraint_error when N not in
3722       --       Source_Base_Type (Target_Type'First)
3723       --         ..
3724       --       Source_Base_Type(Target_Type'Last))]
3725
3726       --  The conversions will always work and need no check.
3727
3728       elsif In_Subrange_Of (Target_Type, Source_Base_Type) then
3729          Insert_Action (N,
3730            Make_Raise_Constraint_Error (Loc,
3731              Condition =>
3732                Make_Not_In (Loc,
3733                  Left_Opnd  => Duplicate_Subexpr (N),
3734
3735                  Right_Opnd =>
3736                    Make_Range (Loc,
3737                      Low_Bound =>
3738                        Convert_To (Source_Base_Type,
3739                          Make_Attribute_Reference (Loc,
3740                            Prefix =>
3741                              New_Occurrence_Of (Target_Type, Loc),
3742                            Attribute_Name => Name_First)),
3743
3744                      High_Bound =>
3745                        Convert_To (Source_Base_Type,
3746                          Make_Attribute_Reference (Loc,
3747                            Prefix =>
3748                              New_Occurrence_Of (Target_Type, Loc),
3749                            Attribute_Name => Name_Last)))),
3750              Reason => Reason));
3751
3752       --  Note that at this stage we now that the Target_Base_Type is
3753       --  not in the range of the Source_Base_Type (since even the
3754       --  Target_Type itself is not in this range). It could still be
3755       --  the case that the Source_Type is in range of the target base
3756       --  type, since we have not checked that case.
3757
3758       --  If that is the case, we can freely convert the source to the
3759       --  target, and then test the target result against the bounds.
3760
3761       elsif In_Subrange_Of (Source_Type, Target_Base_Type) then
3762
3763          --  We make a temporary to hold the value of the converted
3764          --  value (converted to the base type), and then we will
3765          --  do the test against this temporary.
3766
3767          --     Tnn : constant Target_Base_Type := Target_Base_Type (N);
3768          --     [constraint_error when Tnn not in Target_Type]
3769
3770          --  Then the conversion itself is replaced by an occurrence of Tnn
3771
3772          declare
3773             Tnn : constant Entity_Id :=
3774                     Make_Defining_Identifier (Loc,
3775                       Chars => New_Internal_Name ('T'));
3776
3777          begin
3778             Insert_Actions (N, New_List (
3779               Make_Object_Declaration (Loc,
3780                 Defining_Identifier => Tnn,
3781                 Object_Definition   =>
3782                   New_Occurrence_Of (Target_Base_Type, Loc),
3783                 Constant_Present    => True,
3784                 Expression          =>
3785                   Make_Type_Conversion (Loc,
3786                     Subtype_Mark => New_Occurrence_Of (Target_Base_Type, Loc),
3787                     Expression   => Duplicate_Subexpr (N))),
3788
3789               Make_Raise_Constraint_Error (Loc,
3790                 Condition =>
3791                   Make_Not_In (Loc,
3792                     Left_Opnd  => New_Occurrence_Of (Tnn, Loc),
3793                     Right_Opnd => New_Occurrence_Of (Target_Type, Loc)),
3794
3795                 Reason => Reason)));
3796
3797             Rewrite (N, New_Occurrence_Of (Tnn, Loc));
3798          end;
3799
3800       --  At this stage, we know that we have two scalar types, which are
3801       --  directly convertible, and where neither scalar type has a base
3802       --  range that is in the range of the other scalar type.
3803
3804       --  The only way this can happen is with a signed and unsigned type.
3805       --  So test for these two cases:
3806
3807       else
3808          --  Case of the source is unsigned and the target is signed
3809
3810          if Is_Unsigned_Type (Source_Base_Type)
3811            and then not Is_Unsigned_Type (Target_Base_Type)
3812          then
3813             --  If the source is unsigned and the target is signed, then we
3814             --  know that the source is not shorter than the target (otherwise
3815             --  the source base type would be in the target base type range).
3816
3817             --  In other words, the unsigned type is either the same size
3818             --  as the target, or it is larger. It cannot be smaller.
3819
3820             pragma Assert
3821               (Esize (Source_Base_Type) >= Esize (Target_Base_Type));
3822
3823             --  We only need to check the low bound if the low bound of the
3824             --  target type is non-negative. If the low bound of the target
3825             --  type is negative, then we know that we will fit fine.
3826
3827             --  If the high bound of the target type is negative, then we
3828             --  know we have a constraint error, since we can't possibly
3829             --  have a negative source.
3830
3831             --  With these two checks out of the way, we can do the check
3832             --  using the source type safely
3833
3834             --  This is definitely the most annoying case!
3835
3836             --    [constraint_error
3837             --       when (Target_Type'First >= 0
3838             --               and then
3839             --                 N < Source_Base_Type (Target_Type'First))
3840             --         or else Target_Type'Last < 0
3841             --         or else N > Source_Base_Type (Target_Type'Last)];
3842
3843             --  We turn off all checks since we know that the conversions
3844             --  will work fine, given the guards for negative values.
3845
3846             Insert_Action (N,
3847               Make_Raise_Constraint_Error (Loc,
3848                 Condition =>
3849                   Make_Or_Else (Loc,
3850                     Make_Or_Else (Loc,
3851                       Left_Opnd =>
3852                         Make_And_Then (Loc,
3853                           Left_Opnd => Make_Op_Ge (Loc,
3854                             Left_Opnd =>
3855                               Make_Attribute_Reference (Loc,
3856                                 Prefix =>
3857                                   New_Occurrence_Of (Target_Type, Loc),
3858                                 Attribute_Name => Name_First),
3859                             Right_Opnd => Make_Integer_Literal (Loc, Uint_0)),
3860
3861                           Right_Opnd =>
3862                             Make_Op_Lt (Loc,
3863                               Left_Opnd => Duplicate_Subexpr (N),
3864                               Right_Opnd =>
3865                                 Convert_To (Source_Base_Type,
3866                                   Make_Attribute_Reference (Loc,
3867                                     Prefix =>
3868                                       New_Occurrence_Of (Target_Type, Loc),
3869                                     Attribute_Name => Name_First)))),
3870
3871                       Right_Opnd =>
3872                         Make_Op_Lt (Loc,
3873                           Left_Opnd =>
3874                             Make_Attribute_Reference (Loc,
3875                               Prefix => New_Occurrence_Of (Target_Type, Loc),
3876                               Attribute_Name => Name_Last),
3877                             Right_Opnd => Make_Integer_Literal (Loc, Uint_0))),
3878
3879                     Right_Opnd =>
3880                       Make_Op_Gt (Loc,
3881                         Left_Opnd => Duplicate_Subexpr (N),
3882                         Right_Opnd =>
3883                           Convert_To (Source_Base_Type,
3884                             Make_Attribute_Reference (Loc,
3885                               Prefix => New_Occurrence_Of (Target_Type, Loc),
3886                               Attribute_Name => Name_Last)))),
3887
3888                 Reason => Reason),
3889               Suppress  => All_Checks);
3890
3891          --  Only remaining possibility is that the source is signed and
3892          --  the target is unsigned
3893
3894          else
3895             pragma Assert (not Is_Unsigned_Type (Source_Base_Type)
3896                              and then Is_Unsigned_Type (Target_Base_Type));
3897
3898             --  If the source is signed and the target is unsigned, then
3899             --  we know that the target is not shorter than the source
3900             --  (otherwise the target base type would be in the source
3901             --  base type range).
3902
3903             --  In other words, the unsigned type is either the same size
3904             --  as the target, or it is larger. It cannot be smaller.
3905
3906             --  Clearly we have an error if the source value is negative
3907             --  since no unsigned type can have negative values. If the
3908             --  source type is non-negative, then the check can be done
3909             --  using the target type.
3910
3911             --    Tnn : constant Target_Base_Type (N) := Target_Type;
3912
3913             --    [constraint_error
3914             --       when N < 0 or else Tnn not in Target_Type];
3915
3916             --  We turn off all checks for the conversion of N to the
3917             --  target base type, since we generate the explicit check
3918             --  to ensure that the value is non-negative
3919
3920             declare
3921                Tnn : constant Entity_Id :=
3922                        Make_Defining_Identifier (Loc,
3923                          Chars => New_Internal_Name ('T'));
3924
3925             begin
3926                Insert_Actions (N, New_List (
3927                  Make_Object_Declaration (Loc,
3928                    Defining_Identifier => Tnn,
3929                    Object_Definition   =>
3930                      New_Occurrence_Of (Target_Base_Type, Loc),
3931                    Constant_Present    => True,
3932                    Expression          =>
3933                      Make_Type_Conversion (Loc,
3934                        Subtype_Mark =>
3935                          New_Occurrence_Of (Target_Base_Type, Loc),
3936                        Expression   => Duplicate_Subexpr (N))),
3937
3938                  Make_Raise_Constraint_Error (Loc,
3939                    Condition =>
3940                      Make_Or_Else (Loc,
3941                        Left_Opnd =>
3942                          Make_Op_Lt (Loc,
3943                            Left_Opnd  => Duplicate_Subexpr (N),
3944                            Right_Opnd => Make_Integer_Literal (Loc, Uint_0)),
3945
3946                        Right_Opnd =>
3947                          Make_Not_In (Loc,
3948                            Left_Opnd  => New_Occurrence_Of (Tnn, Loc),
3949                            Right_Opnd =>
3950                              New_Occurrence_Of (Target_Type, Loc))),
3951
3952                    Reason => Reason)),
3953                  Suppress => All_Checks);
3954
3955                --  Set the Etype explicitly, because Insert_Actions may
3956                --  have placed the declaration in the freeze list for an
3957                --  enclosing construct, and thus it is not analyzed yet.
3958
3959                Set_Etype (Tnn, Target_Base_Type);
3960                Rewrite (N, New_Occurrence_Of (Tnn, Loc));
3961             end;
3962          end if;
3963       end if;
3964    end Generate_Range_Check;
3965
3966    ---------------------
3967    -- Get_Discriminal --
3968    ---------------------
3969
3970    function Get_Discriminal (E : Entity_Id; Bound : Node_Id) return Node_Id is
3971       Loc : constant Source_Ptr := Sloc (E);
3972       D   : Entity_Id;
3973       Sc  : Entity_Id;
3974
3975    begin
3976       --  The entity E is the type of a private component of the protected
3977       --  type, or the type of a renaming of that component within a protected
3978       --  operation of that type.
3979
3980       Sc := Scope (E);
3981
3982       if Ekind (Sc) /= E_Protected_Type then
3983          Sc := Scope (Sc);
3984
3985          if Ekind (Sc) /= E_Protected_Type then
3986             return Bound;
3987          end if;
3988       end if;
3989
3990       D := First_Discriminant (Sc);
3991
3992       while Present (D)
3993         and then Chars (D) /= Chars (Bound)
3994       loop
3995          Next_Discriminant (D);
3996       end loop;
3997
3998       return New_Occurrence_Of (Discriminal (D), Loc);
3999    end Get_Discriminal;
4000
4001    ------------------
4002    -- Guard_Access --
4003    ------------------
4004
4005    function Guard_Access
4006      (Cond    : Node_Id;
4007       Loc     : Source_Ptr;
4008       Ck_Node : Node_Id)
4009       return    Node_Id
4010    is
4011    begin
4012       if Nkind (Cond) = N_Or_Else then
4013          Set_Paren_Count (Cond, 1);
4014       end if;
4015
4016       if Nkind (Ck_Node) = N_Allocator then
4017          return Cond;
4018       else
4019          return
4020            Make_And_Then (Loc,
4021              Left_Opnd =>
4022                Make_Op_Ne (Loc,
4023                  Left_Opnd  => Duplicate_Subexpr_No_Checks (Ck_Node),
4024                  Right_Opnd => Make_Null (Loc)),
4025              Right_Opnd => Cond);
4026       end if;
4027    end Guard_Access;
4028
4029    -----------------------------
4030    -- Index_Checks_Suppressed --
4031    -----------------------------
4032
4033    function Index_Checks_Suppressed (E : Entity_Id) return Boolean is
4034    begin
4035       if Present (E) and then Checks_May_Be_Suppressed (E) then
4036          return Is_Check_Suppressed (E, Index_Check);
4037       else
4038          return Scope_Suppress (Index_Check);
4039       end if;
4040    end Index_Checks_Suppressed;
4041
4042    ----------------
4043    -- Initialize --
4044    ----------------
4045
4046    procedure Initialize is
4047    begin
4048       for J in Determine_Range_Cache_N'Range loop
4049          Determine_Range_Cache_N (J) := Empty;
4050       end loop;
4051    end Initialize;
4052
4053    -------------------------
4054    -- Insert_Range_Checks --
4055    -------------------------
4056
4057    procedure Insert_Range_Checks
4058      (Checks       : Check_Result;
4059       Node         : Node_Id;
4060       Suppress_Typ : Entity_Id;
4061       Static_Sloc  : Source_Ptr := No_Location;
4062       Flag_Node    : Node_Id    := Empty;
4063       Do_Before    : Boolean    := False)
4064    is
4065       Internal_Flag_Node   : Node_Id    := Flag_Node;
4066       Internal_Static_Sloc : Source_Ptr := Static_Sloc;
4067
4068       Check_Node : Node_Id;
4069       Checks_On  : constant Boolean :=
4070                      (not Index_Checks_Suppressed (Suppress_Typ))
4071                        or else
4072                      (not Range_Checks_Suppressed (Suppress_Typ));
4073
4074    begin
4075       --  For now we just return if Checks_On is false, however this should
4076       --  be enhanced to check for an always True value in the condition
4077       --  and to generate a compilation warning???
4078
4079       if not Expander_Active or else not Checks_On then
4080          return;
4081       end if;
4082
4083       if Static_Sloc = No_Location then
4084          Internal_Static_Sloc := Sloc (Node);
4085       end if;
4086
4087       if No (Flag_Node) then
4088          Internal_Flag_Node := Node;
4089       end if;
4090
4091       for J in 1 .. 2 loop
4092          exit when No (Checks (J));
4093
4094          if Nkind (Checks (J)) = N_Raise_Constraint_Error
4095            and then Present (Condition (Checks (J)))
4096          then
4097             if not Has_Dynamic_Range_Check (Internal_Flag_Node) then
4098                Check_Node := Checks (J);
4099                Mark_Rewrite_Insertion (Check_Node);
4100
4101                if Do_Before then
4102                   Insert_Before_And_Analyze (Node, Check_Node);
4103                else
4104                   Insert_After_And_Analyze (Node, Check_Node);
4105                end if;
4106
4107                Set_Has_Dynamic_Range_Check (Internal_Flag_Node);
4108             end if;
4109
4110          else
4111             Check_Node :=
4112               Make_Raise_Constraint_Error (Internal_Static_Sloc,
4113                 Reason => CE_Range_Check_Failed);
4114             Mark_Rewrite_Insertion (Check_Node);
4115
4116             if Do_Before then
4117                Insert_Before_And_Analyze (Node, Check_Node);
4118             else
4119                Insert_After_And_Analyze (Node, Check_Node);
4120             end if;
4121          end if;
4122       end loop;
4123    end Insert_Range_Checks;
4124
4125    ------------------------
4126    -- Insert_Valid_Check --
4127    ------------------------
4128
4129    procedure Insert_Valid_Check (Expr : Node_Id) is
4130       Loc : constant Source_Ptr := Sloc (Expr);
4131       Exp : Node_Id;
4132
4133    begin
4134       --  Do not insert if checks off, or if not checking validity
4135
4136       if Range_Checks_Suppressed (Etype (Expr))
4137         or else (not Validity_Checks_On)
4138       then
4139          return;
4140       end if;
4141
4142       --  If we have a checked conversion, then validity check applies to
4143       --  the expression inside the conversion, not the result, since if
4144       --  the expression inside is valid, then so is the conversion result.
4145
4146       Exp := Expr;
4147       while Nkind (Exp) = N_Type_Conversion loop
4148          Exp := Expression (Exp);
4149       end loop;
4150
4151       --  Insert the validity check. Note that we do this with validity
4152       --  checks turned off, to avoid recursion, we do not want validity
4153       --  checks on the validity checking code itself!
4154
4155       Validity_Checks_On := False;
4156       Insert_Action
4157         (Expr,
4158          Make_Raise_Constraint_Error (Loc,
4159            Condition =>
4160              Make_Op_Not (Loc,
4161                Right_Opnd =>
4162                  Make_Attribute_Reference (Loc,
4163                    Prefix =>
4164                      Duplicate_Subexpr_No_Checks (Exp, Name_Req => True),
4165                    Attribute_Name => Name_Valid)),
4166            Reason => CE_Invalid_Data),
4167          Suppress => All_Checks);
4168       Validity_Checks_On := True;
4169    end Insert_Valid_Check;
4170
4171    --------------------------
4172    -- Install_Static_Check --
4173    --------------------------
4174
4175    procedure Install_Static_Check (R_Cno : Node_Id; Loc : Source_Ptr) is
4176       Stat : constant Boolean   := Is_Static_Expression (R_Cno);
4177       Typ  : constant Entity_Id := Etype (R_Cno);
4178
4179    begin
4180       Rewrite (R_Cno,
4181         Make_Raise_Constraint_Error (Loc,
4182           Reason => CE_Range_Check_Failed));
4183       Set_Analyzed (R_Cno);
4184       Set_Etype (R_Cno, Typ);
4185       Set_Raises_Constraint_Error (R_Cno);
4186       Set_Is_Static_Expression (R_Cno, Stat);
4187    end Install_Static_Check;
4188
4189    ---------------------
4190    -- Kill_All_Checks --
4191    ---------------------
4192
4193    procedure Kill_All_Checks is
4194    begin
4195       if Debug_Flag_CC then
4196          w ("Kill_All_Checks");
4197       end if;
4198
4199       --  We reset the number of saved checks to zero, and also modify
4200       --  all stack entries for statement ranges to indicate that the
4201       --  number of checks at each level is now zero.
4202
4203       Num_Saved_Checks := 0;
4204
4205       for J in 1 .. Saved_Checks_TOS loop
4206          Saved_Checks_Stack (J) := 0;
4207       end loop;
4208    end Kill_All_Checks;
4209
4210    -----------------
4211    -- Kill_Checks --
4212    -----------------
4213
4214    procedure Kill_Checks (V : Entity_Id) is
4215    begin
4216       if Debug_Flag_CC then
4217          w ("Kill_Checks for entity", Int (V));
4218       end if;
4219
4220       for J in 1 .. Num_Saved_Checks loop
4221          if Saved_Checks (J).Entity = V then
4222             if Debug_Flag_CC then
4223                w ("   Checks killed for saved check ", J);
4224             end if;
4225
4226             Saved_Checks (J).Killed := True;
4227          end if;
4228       end loop;
4229    end Kill_Checks;
4230
4231    ------------------------------
4232    -- Length_Checks_Suppressed --
4233    ------------------------------
4234
4235    function Length_Checks_Suppressed (E : Entity_Id) return Boolean is
4236    begin
4237       if Present (E) and then Checks_May_Be_Suppressed (E) then
4238          return Is_Check_Suppressed (E, Length_Check);
4239       else
4240          return Scope_Suppress (Length_Check);
4241       end if;
4242    end Length_Checks_Suppressed;
4243
4244    --------------------------------
4245    -- Overflow_Checks_Suppressed --
4246    --------------------------------
4247
4248    function Overflow_Checks_Suppressed (E : Entity_Id) return Boolean is
4249    begin
4250       if Present (E) and then Checks_May_Be_Suppressed (E) then
4251          return Is_Check_Suppressed (E, Overflow_Check);
4252       else
4253          return Scope_Suppress (Overflow_Check);
4254       end if;
4255    end Overflow_Checks_Suppressed;
4256
4257    -----------------
4258    -- Range_Check --
4259    -----------------
4260
4261    function Range_Check
4262      (Ck_Node    : Node_Id;
4263       Target_Typ : Entity_Id;
4264       Source_Typ : Entity_Id := Empty;
4265       Warn_Node  : Node_Id   := Empty)
4266       return       Check_Result
4267    is
4268    begin
4269       return Selected_Range_Checks
4270         (Ck_Node, Target_Typ, Source_Typ, Warn_Node);
4271    end Range_Check;
4272
4273    -----------------------------
4274    -- Range_Checks_Suppressed --
4275    -----------------------------
4276
4277    function Range_Checks_Suppressed (E : Entity_Id) return Boolean is
4278    begin
4279       if Present (E) then
4280
4281          --  Note: for now we always suppress range checks on Vax float types,
4282          --  since Gigi does not know how to generate these checks.
4283
4284          if Vax_Float (E) then
4285             return True;
4286          elsif Kill_Range_Checks (E) then
4287             return True;
4288          elsif Checks_May_Be_Suppressed (E) then
4289             return Is_Check_Suppressed (E, Range_Check);
4290          end if;
4291       end if;
4292
4293       return Scope_Suppress (Range_Check);
4294    end Range_Checks_Suppressed;
4295
4296    -------------------
4297    -- Remove_Checks --
4298    -------------------
4299
4300    procedure Remove_Checks (Expr : Node_Id) is
4301       Discard : Traverse_Result;
4302       pragma Warnings (Off, Discard);
4303
4304       function Process (N : Node_Id) return Traverse_Result;
4305       --  Process a single node during the traversal
4306
4307       function Traverse is new Traverse_Func (Process);
4308       --  The traversal function itself
4309
4310       -------------
4311       -- Process --
4312       -------------
4313
4314       function Process (N : Node_Id) return Traverse_Result is
4315       begin
4316          if Nkind (N) not in N_Subexpr then
4317             return Skip;
4318          end if;
4319
4320          Set_Do_Range_Check (N, False);
4321
4322          case Nkind (N) is
4323             when N_And_Then =>
4324                Discard := Traverse (Left_Opnd (N));
4325                return Skip;
4326
4327             when N_Attribute_Reference =>
4328                Set_Do_Overflow_Check (N, False);
4329
4330             when N_Function_Call =>
4331                Set_Do_Tag_Check (N, False);
4332
4333             when N_Op =>
4334                Set_Do_Overflow_Check (N, False);
4335
4336                case Nkind (N) is
4337                   when N_Op_Divide =>
4338                      Set_Do_Division_Check (N, False);
4339
4340                   when N_Op_And =>
4341                      Set_Do_Length_Check (N, False);
4342
4343                   when N_Op_Mod =>
4344                      Set_Do_Division_Check (N, False);
4345
4346                   when N_Op_Or =>
4347                      Set_Do_Length_Check (N, False);
4348
4349                   when N_Op_Rem =>
4350                      Set_Do_Division_Check (N, False);
4351
4352                   when N_Op_Xor =>
4353                      Set_Do_Length_Check (N, False);
4354
4355                   when others =>
4356                      null;
4357                end case;
4358
4359             when N_Or_Else =>
4360                Discard := Traverse (Left_Opnd (N));
4361                return Skip;
4362
4363             when N_Selected_Component =>
4364                Set_Do_Discriminant_Check (N, False);
4365
4366             when N_Type_Conversion =>
4367                Set_Do_Length_Check   (N, False);
4368                Set_Do_Tag_Check      (N, False);
4369                Set_Do_Overflow_Check (N, False);
4370
4371             when others =>
4372                null;
4373          end case;
4374
4375          return OK;
4376       end Process;
4377
4378    --  Start of processing for Remove_Checks
4379
4380    begin
4381       Discard := Traverse (Expr);
4382    end Remove_Checks;
4383
4384    ----------------------------
4385    -- Selected_Length_Checks --
4386    ----------------------------
4387
4388    function Selected_Length_Checks
4389      (Ck_Node    : Node_Id;
4390       Target_Typ : Entity_Id;
4391       Source_Typ : Entity_Id;
4392       Warn_Node  : Node_Id)
4393       return       Check_Result
4394    is
4395       Loc         : constant Source_Ptr := Sloc (Ck_Node);
4396       S_Typ       : Entity_Id;
4397       T_Typ       : Entity_Id;
4398       Expr_Actual : Node_Id;
4399       Exptyp      : Entity_Id;
4400       Cond        : Node_Id := Empty;
4401       Do_Access   : Boolean := False;
4402       Wnode       : Node_Id := Warn_Node;
4403       Ret_Result  : Check_Result := (Empty, Empty);
4404       Num_Checks  : Natural := 0;
4405
4406       procedure Add_Check (N : Node_Id);
4407       --  Adds the action given to Ret_Result if N is non-Empty
4408
4409       function Get_E_Length (E : Entity_Id; Indx : Nat) return Node_Id;
4410       function Get_N_Length (N : Node_Id; Indx : Nat) return Node_Id;
4411
4412       function Same_Bounds (L : Node_Id; R : Node_Id) return Boolean;
4413       --  True for equal literals and for nodes that denote the same constant
4414       --  entity, even if its value is not a static constant. This includes the
4415       --  case of a discriminal reference within an init proc. Removes some
4416       --  obviously superfluous checks.
4417
4418       function Length_E_Cond
4419         (Exptyp : Entity_Id;
4420          Typ    : Entity_Id;
4421          Indx   : Nat)
4422          return   Node_Id;
4423       --  Returns expression to compute:
4424       --    Typ'Length /= Exptyp'Length
4425
4426       function Length_N_Cond
4427         (Expr : Node_Id;
4428          Typ  : Entity_Id;
4429          Indx : Nat)
4430          return Node_Id;
4431       --  Returns expression to compute:
4432       --    Typ'Length /= Expr'Length
4433
4434       ---------------
4435       -- Add_Check --
4436       ---------------
4437
4438       procedure Add_Check (N : Node_Id) is
4439       begin
4440          if Present (N) then
4441
4442             --  For now, ignore attempt to place more than 2 checks ???
4443
4444             if Num_Checks = 2 then
4445                return;
4446             end if;
4447
4448             pragma Assert (Num_Checks <= 1);
4449             Num_Checks := Num_Checks + 1;
4450             Ret_Result (Num_Checks) := N;
4451          end if;
4452       end Add_Check;
4453
4454       ------------------
4455       -- Get_E_Length --
4456       ------------------
4457
4458       function Get_E_Length (E : Entity_Id; Indx : Nat) return Node_Id is
4459          Pt : constant Entity_Id := Scope (Scope (E));
4460          N  : Node_Id;
4461          E1 : Entity_Id := E;
4462
4463       begin
4464          if Ekind (Scope (E)) = E_Record_Type
4465            and then Has_Discriminants (Scope (E))
4466          then
4467             N := Build_Discriminal_Subtype_Of_Component (E);
4468
4469             if Present (N) then
4470                Insert_Action (Ck_Node, N);
4471                E1 := Defining_Identifier (N);
4472             end if;
4473          end if;
4474
4475          if Ekind (E1) = E_String_Literal_Subtype then
4476             return
4477               Make_Integer_Literal (Loc,
4478                 Intval => String_Literal_Length (E1));
4479
4480          elsif Ekind (Pt) = E_Protected_Type
4481            and then Has_Discriminants (Pt)
4482            and then Has_Completion (Pt)
4483            and then not Inside_Init_Proc
4484          then
4485
4486             --  If the type whose length is needed is a private component
4487             --  constrained by a discriminant, we must expand the 'Length
4488             --  attribute into an explicit computation, using the discriminal
4489             --  of the current protected operation. This is because the actual
4490             --  type of the prival is constructed after the protected opera-
4491             --  tion has been fully expanded.
4492
4493             declare
4494                Indx_Type : Node_Id;
4495                Lo        : Node_Id;
4496                Hi        : Node_Id;
4497                Do_Expand : Boolean := False;
4498
4499             begin
4500                Indx_Type := First_Index (E);
4501
4502                for J in 1 .. Indx - 1 loop
4503                   Next_Index (Indx_Type);
4504                end loop;
4505
4506                Get_Index_Bounds  (Indx_Type, Lo, Hi);
4507
4508                if Nkind (Lo) = N_Identifier
4509                  and then Ekind (Entity (Lo)) = E_In_Parameter
4510                then
4511                   Lo := Get_Discriminal (E, Lo);
4512                   Do_Expand := True;
4513                end if;
4514
4515                if Nkind (Hi) = N_Identifier
4516                  and then Ekind (Entity (Hi)) = E_In_Parameter
4517                then
4518                   Hi := Get_Discriminal (E, Hi);
4519                   Do_Expand := True;
4520                end if;
4521
4522                if Do_Expand then
4523                   if not Is_Entity_Name (Lo) then
4524                      Lo := Duplicate_Subexpr_No_Checks (Lo);
4525                   end if;
4526
4527                   if not Is_Entity_Name (Hi) then
4528                      Lo := Duplicate_Subexpr_No_Checks (Hi);
4529                   end if;
4530
4531                   N :=
4532                     Make_Op_Add (Loc,
4533                       Left_Opnd =>
4534                         Make_Op_Subtract (Loc,
4535                           Left_Opnd  => Hi,
4536                           Right_Opnd => Lo),
4537
4538                       Right_Opnd => Make_Integer_Literal (Loc, 1));
4539                   return N;
4540
4541                else
4542                   N :=
4543                     Make_Attribute_Reference (Loc,
4544                       Attribute_Name => Name_Length,
4545                       Prefix =>
4546                         New_Occurrence_Of (E1, Loc));
4547
4548                   if Indx > 1 then
4549                      Set_Expressions (N, New_List (
4550                        Make_Integer_Literal (Loc, Indx)));
4551                   end if;
4552
4553                   return N;
4554                end if;
4555             end;
4556
4557          else
4558             N :=
4559               Make_Attribute_Reference (Loc,
4560                 Attribute_Name => Name_Length,
4561                 Prefix =>
4562                   New_Occurrence_Of (E1, Loc));
4563
4564             if Indx > 1 then
4565                Set_Expressions (N, New_List (
4566                  Make_Integer_Literal (Loc, Indx)));
4567             end if;
4568
4569             return N;
4570
4571          end if;
4572       end Get_E_Length;
4573
4574       ------------------
4575       -- Get_N_Length --
4576       ------------------
4577
4578       function Get_N_Length (N : Node_Id; Indx : Nat) return Node_Id is
4579       begin
4580          return
4581            Make_Attribute_Reference (Loc,
4582              Attribute_Name => Name_Length,
4583              Prefix =>
4584                Duplicate_Subexpr_No_Checks (N, Name_Req => True),
4585              Expressions => New_List (
4586                Make_Integer_Literal (Loc, Indx)));
4587
4588       end Get_N_Length;
4589
4590       -------------------
4591       -- Length_E_Cond --
4592       -------------------
4593
4594       function Length_E_Cond
4595         (Exptyp : Entity_Id;
4596          Typ    : Entity_Id;
4597          Indx   : Nat)
4598          return   Node_Id
4599       is
4600       begin
4601          return
4602            Make_Op_Ne (Loc,
4603              Left_Opnd  => Get_E_Length (Typ, Indx),
4604              Right_Opnd => Get_E_Length (Exptyp, Indx));
4605
4606       end Length_E_Cond;
4607
4608       -------------------
4609       -- Length_N_Cond --
4610       -------------------
4611
4612       function Length_N_Cond
4613         (Expr : Node_Id;
4614          Typ  : Entity_Id;
4615          Indx : Nat)
4616          return Node_Id
4617       is
4618       begin
4619          return
4620            Make_Op_Ne (Loc,
4621              Left_Opnd  => Get_E_Length (Typ, Indx),
4622              Right_Opnd => Get_N_Length (Expr, Indx));
4623
4624       end Length_N_Cond;
4625
4626       function Same_Bounds (L : Node_Id; R : Node_Id) return Boolean is
4627       begin
4628          return
4629            (Nkind (L) = N_Integer_Literal
4630              and then Nkind (R) = N_Integer_Literal
4631              and then Intval (L) = Intval (R))
4632
4633           or else
4634             (Is_Entity_Name (L)
4635               and then Ekind (Entity (L)) = E_Constant
4636               and then ((Is_Entity_Name (R)
4637                          and then Entity (L) = Entity (R))
4638                         or else
4639                        (Nkind (R) = N_Type_Conversion
4640                          and then Is_Entity_Name (Expression (R))
4641                          and then Entity (L) = Entity (Expression (R)))))
4642
4643           or else
4644             (Is_Entity_Name (R)
4645               and then Ekind (Entity (R)) = E_Constant
4646               and then Nkind (L) = N_Type_Conversion
4647               and then Is_Entity_Name (Expression (L))
4648               and then Entity (R) = Entity (Expression (L)))
4649
4650          or else
4651             (Is_Entity_Name (L)
4652               and then Is_Entity_Name (R)
4653               and then Entity (L) = Entity (R)
4654               and then Ekind (Entity (L)) = E_In_Parameter
4655               and then Inside_Init_Proc);
4656       end Same_Bounds;
4657
4658    --  Start of processing for Selected_Length_Checks
4659
4660    begin
4661       if not Expander_Active then
4662          return Ret_Result;
4663       end if;
4664
4665       if Target_Typ = Any_Type
4666         or else Target_Typ = Any_Composite
4667         or else Raises_Constraint_Error (Ck_Node)
4668       then
4669          return Ret_Result;
4670       end if;
4671
4672       if No (Wnode) then
4673          Wnode := Ck_Node;
4674       end if;
4675
4676       T_Typ := Target_Typ;
4677
4678       if No (Source_Typ) then
4679          S_Typ := Etype (Ck_Node);
4680       else
4681          S_Typ := Source_Typ;
4682       end if;
4683
4684       if S_Typ = Any_Type or else S_Typ = Any_Composite then
4685          return Ret_Result;
4686       end if;
4687
4688       if Is_Access_Type (T_Typ) and then Is_Access_Type (S_Typ) then
4689          S_Typ := Designated_Type (S_Typ);
4690          T_Typ := Designated_Type (T_Typ);
4691          Do_Access := True;
4692
4693          --  A simple optimization
4694
4695          if Nkind (Ck_Node) = N_Null then
4696             return Ret_Result;
4697          end if;
4698       end if;
4699
4700       if Is_Array_Type (T_Typ) and then Is_Array_Type (S_Typ) then
4701          if Is_Constrained (T_Typ) then
4702
4703             --  The checking code to be generated will freeze the
4704             --  corresponding array type. However, we must freeze the
4705             --  type now, so that the freeze node does not appear within
4706             --  the generated condional expression, but ahead of it.
4707
4708             Freeze_Before (Ck_Node, T_Typ);
4709
4710             Expr_Actual := Get_Referenced_Object (Ck_Node);
4711             Exptyp      := Get_Actual_Subtype (Expr_Actual);
4712
4713             if Is_Access_Type (Exptyp) then
4714                Exptyp := Designated_Type (Exptyp);
4715             end if;
4716
4717             --  String_Literal case. This needs to be handled specially be-
4718             --  cause no index types are available for string literals. The
4719             --  condition is simply:
4720
4721             --    T_Typ'Length = string-literal-length
4722
4723             if Nkind (Expr_Actual) = N_String_Literal
4724               and then Ekind (Etype (Expr_Actual)) = E_String_Literal_Subtype
4725             then
4726                Cond :=
4727                  Make_Op_Ne (Loc,
4728                    Left_Opnd  => Get_E_Length (T_Typ, 1),
4729                    Right_Opnd =>
4730                      Make_Integer_Literal (Loc,
4731                        Intval =>
4732                          String_Literal_Length (Etype (Expr_Actual))));
4733
4734             --  General array case. Here we have a usable actual subtype for
4735             --  the expression, and the condition is built from the two types
4736             --  (Do_Length):
4737
4738             --     T_Typ'Length     /= Exptyp'Length     or else
4739             --     T_Typ'Length (2) /= Exptyp'Length (2) or else
4740             --     T_Typ'Length (3) /= Exptyp'Length (3) or else
4741             --     ...
4742
4743             elsif Is_Constrained (Exptyp) then
4744                declare
4745                   Ndims : constant Nat := Number_Dimensions (T_Typ);
4746
4747                   L_Index  : Node_Id;
4748                   R_Index  : Node_Id;
4749                   L_Low    : Node_Id;
4750                   L_High   : Node_Id;
4751                   R_Low    : Node_Id;
4752                   R_High   : Node_Id;
4753                   L_Length : Uint;
4754                   R_Length : Uint;
4755                   Ref_Node : Node_Id;
4756
4757                begin
4758
4759                   --  At the library level, we need to ensure that the
4760                   --  type of the object is elaborated before the check
4761                   --  itself is emitted.
4762
4763                   if Is_Itype (Exptyp)
4764                     and then
4765                       Ekind (Cunit_Entity (Current_Sem_Unit)) = E_Package
4766                     and then
4767                       not In_Package_Body (Cunit_Entity (Current_Sem_Unit))
4768                   then
4769                      Ref_Node := Make_Itype_Reference (Sloc (Ck_Node));
4770                      Set_Itype (Ref_Node, Exptyp);
4771                      Insert_Action (Ck_Node, Ref_Node);
4772                   end if;
4773
4774                   L_Index := First_Index (T_Typ);
4775                   R_Index := First_Index (Exptyp);
4776
4777                   for Indx in 1 .. Ndims loop
4778                      if not (Nkind (L_Index) = N_Raise_Constraint_Error
4779                                or else
4780                              Nkind (R_Index) = N_Raise_Constraint_Error)
4781                      then
4782                         Get_Index_Bounds (L_Index, L_Low, L_High);
4783                         Get_Index_Bounds (R_Index, R_Low, R_High);
4784
4785                         --  Deal with compile time length check. Note that we
4786                         --  skip this in the access case, because the access
4787                         --  value may be null, so we cannot know statically.
4788
4789                         if not Do_Access
4790                           and then Compile_Time_Known_Value (L_Low)
4791                           and then Compile_Time_Known_Value (L_High)
4792                           and then Compile_Time_Known_Value (R_Low)
4793                           and then Compile_Time_Known_Value (R_High)
4794                         then
4795                            if Expr_Value (L_High) >= Expr_Value (L_Low) then
4796                               L_Length := Expr_Value (L_High) -
4797                                           Expr_Value (L_Low) + 1;
4798                            else
4799                               L_Length := UI_From_Int (0);
4800                            end if;
4801
4802                            if Expr_Value (R_High) >= Expr_Value (R_Low) then
4803                               R_Length := Expr_Value (R_High) -
4804                                           Expr_Value (R_Low) + 1;
4805                            else
4806                               R_Length := UI_From_Int (0);
4807                            end if;
4808
4809                            if L_Length > R_Length then
4810                               Add_Check
4811                                 (Compile_Time_Constraint_Error
4812                                   (Wnode, "too few elements for}?", T_Typ));
4813
4814                            elsif  L_Length < R_Length then
4815                               Add_Check
4816                                 (Compile_Time_Constraint_Error
4817                                   (Wnode, "too many elements for}?", T_Typ));
4818                            end if;
4819
4820                         --  The comparison for an individual index subtype
4821                         --  is omitted if the corresponding index subtypes
4822                         --  statically match, since the result is known to
4823                         --  be true. Note that this test is worth while even
4824                         --  though we do static evaluation, because non-static
4825                         --  subtypes can statically match.
4826
4827                         elsif not
4828                           Subtypes_Statically_Match
4829                             (Etype (L_Index), Etype (R_Index))
4830
4831                           and then not
4832                             (Same_Bounds (L_Low, R_Low)
4833                               and then Same_Bounds (L_High, R_High))
4834                         then
4835                            Evolve_Or_Else
4836                              (Cond, Length_E_Cond (Exptyp, T_Typ, Indx));
4837                         end if;
4838
4839                         Next (L_Index);
4840                         Next (R_Index);
4841                      end if;
4842                   end loop;
4843                end;
4844
4845             --  Handle cases where we do not get a usable actual subtype that
4846             --  is constrained. This happens for example in the function call
4847             --  and explicit dereference cases. In these cases, we have to get
4848             --  the length or range from the expression itself, making sure we
4849             --  do not evaluate it more than once.
4850
4851             --  Here Ck_Node is the original expression, or more properly the
4852             --  result of applying Duplicate_Expr to the original tree,
4853             --  forcing the result to be a name.
4854
4855             else
4856                declare
4857                   Ndims : constant Nat := Number_Dimensions (T_Typ);
4858
4859                begin
4860                   --  Build the condition for the explicit dereference case
4861
4862                   for Indx in 1 .. Ndims loop
4863                      Evolve_Or_Else
4864                        (Cond, Length_N_Cond (Ck_Node, T_Typ, Indx));
4865                   end loop;
4866                end;
4867             end if;
4868          end if;
4869       end if;
4870
4871       --  Construct the test and insert into the tree
4872
4873       if Present (Cond) then
4874          if Do_Access then
4875             Cond := Guard_Access (Cond, Loc, Ck_Node);
4876          end if;
4877
4878          Add_Check
4879            (Make_Raise_Constraint_Error (Loc,
4880               Condition => Cond,
4881               Reason => CE_Length_Check_Failed));
4882       end if;
4883
4884       return Ret_Result;
4885    end Selected_Length_Checks;
4886
4887    ---------------------------
4888    -- Selected_Range_Checks --
4889    ---------------------------
4890
4891    function Selected_Range_Checks
4892      (Ck_Node    : Node_Id;
4893       Target_Typ : Entity_Id;
4894       Source_Typ : Entity_Id;
4895       Warn_Node  : Node_Id)
4896       return       Check_Result
4897    is
4898       Loc         : constant Source_Ptr := Sloc (Ck_Node);
4899       S_Typ       : Entity_Id;
4900       T_Typ       : Entity_Id;
4901       Expr_Actual : Node_Id;
4902       Exptyp      : Entity_Id;
4903       Cond        : Node_Id := Empty;
4904       Do_Access   : Boolean := False;
4905       Wnode       : Node_Id  := Warn_Node;
4906       Ret_Result  : Check_Result := (Empty, Empty);
4907       Num_Checks  : Integer := 0;
4908
4909       procedure Add_Check (N : Node_Id);
4910       --  Adds the action given to Ret_Result if N is non-Empty
4911
4912       function Discrete_Range_Cond
4913         (Expr : Node_Id;
4914          Typ  : Entity_Id)
4915          return Node_Id;
4916       --  Returns expression to compute:
4917       --    Low_Bound (Expr) < Typ'First
4918       --      or else
4919       --    High_Bound (Expr) > Typ'Last
4920
4921       function Discrete_Expr_Cond
4922         (Expr : Node_Id;
4923          Typ  : Entity_Id)
4924          return Node_Id;
4925       --  Returns expression to compute:
4926       --    Expr < Typ'First
4927       --      or else
4928       --    Expr > Typ'Last
4929
4930       function Get_E_First_Or_Last
4931         (E    : Entity_Id;
4932          Indx : Nat;
4933          Nam  : Name_Id)
4934          return Node_Id;
4935       --  Returns expression to compute:
4936       --    E'First or E'Last
4937
4938       function Get_N_First (N : Node_Id; Indx : Nat) return Node_Id;
4939       function Get_N_Last  (N : Node_Id; Indx : Nat) return Node_Id;
4940       --  Returns expression to compute:
4941       --    N'First or N'Last using Duplicate_Subexpr_No_Checks
4942
4943       function Range_E_Cond
4944         (Exptyp : Entity_Id;
4945          Typ    : Entity_Id;
4946          Indx   : Nat)
4947          return   Node_Id;
4948       --  Returns expression to compute:
4949       --    Exptyp'First < Typ'First or else Exptyp'Last > Typ'Last
4950
4951       function Range_Equal_E_Cond
4952         (Exptyp : Entity_Id;
4953          Typ    : Entity_Id;
4954          Indx   : Nat)
4955          return   Node_Id;
4956       --  Returns expression to compute:
4957       --    Exptyp'First /= Typ'First or else Exptyp'Last /= Typ'Last
4958
4959       function Range_N_Cond
4960         (Expr : Node_Id;
4961          Typ  : Entity_Id;
4962          Indx : Nat)
4963          return Node_Id;
4964       --  Return expression to compute:
4965       --    Expr'First < Typ'First or else Expr'Last > Typ'Last
4966
4967       ---------------
4968       -- Add_Check --
4969       ---------------
4970
4971       procedure Add_Check (N : Node_Id) is
4972       begin
4973          if Present (N) then
4974
4975             --  For now, ignore attempt to place more than 2 checks ???
4976
4977             if Num_Checks = 2 then
4978                return;
4979             end if;
4980
4981             pragma Assert (Num_Checks <= 1);
4982             Num_Checks := Num_Checks + 1;
4983             Ret_Result (Num_Checks) := N;
4984          end if;
4985       end Add_Check;
4986
4987       -------------------------
4988       -- Discrete_Expr_Cond --
4989       -------------------------
4990
4991       function Discrete_Expr_Cond
4992         (Expr : Node_Id;
4993          Typ  : Entity_Id)
4994          return Node_Id
4995       is
4996       begin
4997          return
4998            Make_Or_Else (Loc,
4999              Left_Opnd =>
5000                Make_Op_Lt (Loc,
5001                  Left_Opnd =>
5002                    Convert_To (Base_Type (Typ),
5003                      Duplicate_Subexpr_No_Checks (Expr)),
5004                  Right_Opnd =>
5005                    Convert_To (Base_Type (Typ),
5006                                Get_E_First_Or_Last (Typ, 0, Name_First))),
5007
5008              Right_Opnd =>
5009                Make_Op_Gt (Loc,
5010                  Left_Opnd =>
5011                    Convert_To (Base_Type (Typ),
5012                      Duplicate_Subexpr_No_Checks (Expr)),
5013                  Right_Opnd =>
5014                    Convert_To
5015                      (Base_Type (Typ),
5016                       Get_E_First_Or_Last (Typ, 0, Name_Last))));
5017       end Discrete_Expr_Cond;
5018
5019       -------------------------
5020       -- Discrete_Range_Cond --
5021       -------------------------
5022
5023       function Discrete_Range_Cond
5024         (Expr : Node_Id;
5025          Typ  : Entity_Id)
5026          return Node_Id
5027       is
5028          LB : Node_Id := Low_Bound (Expr);
5029          HB : Node_Id := High_Bound (Expr);
5030
5031          Left_Opnd  : Node_Id;
5032          Right_Opnd : Node_Id;
5033
5034       begin
5035          if Nkind (LB) = N_Identifier
5036            and then Ekind (Entity (LB)) = E_Discriminant then
5037             LB := New_Occurrence_Of (Discriminal (Entity (LB)), Loc);
5038          end if;
5039
5040          if Nkind (HB) = N_Identifier
5041            and then Ekind (Entity (HB)) = E_Discriminant then
5042             HB := New_Occurrence_Of (Discriminal (Entity (HB)), Loc);
5043          end if;
5044
5045          Left_Opnd :=
5046            Make_Op_Lt (Loc,
5047              Left_Opnd  =>
5048                Convert_To
5049                  (Base_Type (Typ), Duplicate_Subexpr_No_Checks (LB)),
5050
5051              Right_Opnd =>
5052                Convert_To
5053                  (Base_Type (Typ), Get_E_First_Or_Last (Typ, 0, Name_First)));
5054
5055          if Base_Type (Typ) = Typ then
5056             return Left_Opnd;
5057
5058          elsif Compile_Time_Known_Value (High_Bound (Scalar_Range (Typ)))
5059             and then
5060                Compile_Time_Known_Value (High_Bound (Scalar_Range
5061                                                      (Base_Type (Typ))))
5062          then
5063             if Is_Floating_Point_Type (Typ) then
5064                if Expr_Value_R (High_Bound (Scalar_Range (Typ))) =
5065                   Expr_Value_R (High_Bound (Scalar_Range (Base_Type (Typ))))
5066                then
5067                   return Left_Opnd;
5068                end if;
5069
5070             else
5071                if Expr_Value (High_Bound (Scalar_Range (Typ))) =
5072                   Expr_Value (High_Bound (Scalar_Range (Base_Type (Typ))))
5073                then
5074                   return Left_Opnd;
5075                end if;
5076             end if;
5077          end if;
5078
5079          Right_Opnd :=
5080            Make_Op_Gt (Loc,
5081              Left_Opnd  =>
5082                Convert_To
5083                  (Base_Type (Typ), Duplicate_Subexpr_No_Checks (HB)),
5084
5085              Right_Opnd =>
5086                Convert_To
5087                  (Base_Type (Typ),
5088                   Get_E_First_Or_Last (Typ, 0, Name_Last)));
5089
5090          return Make_Or_Else (Loc, Left_Opnd, Right_Opnd);
5091       end Discrete_Range_Cond;
5092
5093       -------------------------
5094       -- Get_E_First_Or_Last --
5095       -------------------------
5096
5097       function Get_E_First_Or_Last
5098         (E    : Entity_Id;
5099          Indx : Nat;
5100          Nam  : Name_Id)
5101          return Node_Id
5102       is
5103          N     : Node_Id;
5104          LB    : Node_Id;
5105          HB    : Node_Id;
5106          Bound : Node_Id;
5107
5108       begin
5109          if Is_Array_Type (E) then
5110             N := First_Index (E);
5111
5112             for J in 2 .. Indx loop
5113                Next_Index (N);
5114             end loop;
5115
5116          else
5117             N := Scalar_Range (E);
5118          end if;
5119
5120          if Nkind (N) = N_Subtype_Indication then
5121             LB := Low_Bound (Range_Expression (Constraint (N)));
5122             HB := High_Bound (Range_Expression (Constraint (N)));
5123
5124          elsif Is_Entity_Name (N) then
5125             LB := Type_Low_Bound  (Etype (N));
5126             HB := Type_High_Bound (Etype (N));
5127
5128          else
5129             LB := Low_Bound  (N);
5130             HB := High_Bound (N);
5131          end if;
5132
5133          if Nam = Name_First then
5134             Bound := LB;
5135          else
5136             Bound := HB;
5137          end if;
5138
5139          if Nkind (Bound) = N_Identifier
5140            and then Ekind (Entity (Bound)) = E_Discriminant
5141          then
5142             --  If this is a task discriminant, and we are the body, we must
5143             --  retrieve the corresponding body discriminal. This is another
5144             --  consequence of the early creation of discriminals, and the
5145             --  need to generate constraint checks before their declarations
5146             --  are made visible.
5147
5148             if Is_Concurrent_Record_Type (Scope (Entity (Bound)))  then
5149                declare
5150                   Tsk : constant Entity_Id :=
5151                           Corresponding_Concurrent_Type
5152                            (Scope (Entity (Bound)));
5153                   Disc : Entity_Id;
5154
5155                begin
5156                   if In_Open_Scopes (Tsk)
5157                     and then Has_Completion (Tsk)
5158                   then
5159                      --  Find discriminant of original task, and use its
5160                      --  current discriminal, which is the renaming within
5161                      --  the task body.
5162
5163                      Disc :=  First_Discriminant (Tsk);
5164                      while Present (Disc) loop
5165                         if Chars (Disc) = Chars (Entity (Bound)) then
5166                            Set_Scope (Discriminal (Disc), Tsk);
5167                            return New_Occurrence_Of (Discriminal (Disc), Loc);
5168                         end if;
5169
5170                         Next_Discriminant (Disc);
5171                      end loop;
5172
5173                      --  That loop should always succeed in finding a matching
5174                      --  entry and returning. Fatal error if not.
5175
5176                      raise Program_Error;
5177
5178                   else
5179                      return
5180                        New_Occurrence_Of (Discriminal (Entity (Bound)), Loc);
5181                   end if;
5182                end;
5183             else
5184                return New_Occurrence_Of (Discriminal (Entity (Bound)), Loc);
5185             end if;
5186
5187          elsif Nkind (Bound) = N_Identifier
5188            and then Ekind (Entity (Bound)) = E_In_Parameter
5189            and then not Inside_Init_Proc
5190          then
5191             return Get_Discriminal (E, Bound);
5192
5193          elsif Nkind (Bound) = N_Integer_Literal then
5194             return  Make_Integer_Literal (Loc, Intval (Bound));
5195
5196          else
5197             return Duplicate_Subexpr_No_Checks (Bound);
5198          end if;
5199       end Get_E_First_Or_Last;
5200
5201       -----------------
5202       -- Get_N_First --
5203       -----------------
5204
5205       function Get_N_First (N : Node_Id; Indx : Nat) return Node_Id is
5206       begin
5207          return
5208            Make_Attribute_Reference (Loc,
5209              Attribute_Name => Name_First,
5210              Prefix =>
5211                Duplicate_Subexpr_No_Checks (N, Name_Req => True),
5212              Expressions => New_List (
5213                Make_Integer_Literal (Loc, Indx)));
5214
5215       end Get_N_First;
5216
5217       ----------------
5218       -- Get_N_Last --
5219       ----------------
5220
5221       function Get_N_Last (N : Node_Id; Indx : Nat) return Node_Id is
5222       begin
5223          return
5224            Make_Attribute_Reference (Loc,
5225              Attribute_Name => Name_Last,
5226              Prefix =>
5227                Duplicate_Subexpr_No_Checks (N, Name_Req => True),
5228              Expressions => New_List (
5229               Make_Integer_Literal (Loc, Indx)));
5230
5231       end Get_N_Last;
5232
5233       ------------------
5234       -- Range_E_Cond --
5235       ------------------
5236
5237       function Range_E_Cond
5238         (Exptyp : Entity_Id;
5239          Typ    : Entity_Id;
5240          Indx   : Nat)
5241          return   Node_Id
5242       is
5243       begin
5244          return
5245            Make_Or_Else (Loc,
5246              Left_Opnd =>
5247                Make_Op_Lt (Loc,
5248                  Left_Opnd => Get_E_First_Or_Last (Exptyp, Indx, Name_First),
5249                  Right_Opnd  => Get_E_First_Or_Last (Typ, Indx, Name_First)),
5250
5251              Right_Opnd =>
5252                Make_Op_Gt (Loc,
5253                  Left_Opnd => Get_E_First_Or_Last (Exptyp, Indx, Name_Last),
5254                  Right_Opnd  => Get_E_First_Or_Last (Typ, Indx, Name_Last)));
5255
5256       end Range_E_Cond;
5257
5258       ------------------------
5259       -- Range_Equal_E_Cond --
5260       ------------------------
5261
5262       function Range_Equal_E_Cond
5263         (Exptyp : Entity_Id;
5264          Typ    : Entity_Id;
5265          Indx   : Nat)
5266          return   Node_Id
5267       is
5268       begin
5269          return
5270            Make_Or_Else (Loc,
5271              Left_Opnd =>
5272                Make_Op_Ne (Loc,
5273                  Left_Opnd => Get_E_First_Or_Last (Exptyp, Indx, Name_First),
5274                  Right_Opnd  => Get_E_First_Or_Last (Typ, Indx, Name_First)),
5275              Right_Opnd =>
5276                Make_Op_Ne (Loc,
5277                  Left_Opnd => Get_E_First_Or_Last (Exptyp, Indx, Name_Last),
5278                  Right_Opnd  => Get_E_First_Or_Last (Typ, Indx, Name_Last)));
5279       end Range_Equal_E_Cond;
5280
5281       ------------------
5282       -- Range_N_Cond --
5283       ------------------
5284
5285       function Range_N_Cond
5286         (Expr : Node_Id;
5287          Typ  : Entity_Id;
5288          Indx : Nat)
5289          return Node_Id
5290       is
5291       begin
5292          return
5293            Make_Or_Else (Loc,
5294              Left_Opnd =>
5295                Make_Op_Lt (Loc,
5296                  Left_Opnd => Get_N_First (Expr, Indx),
5297                  Right_Opnd  => Get_E_First_Or_Last (Typ, Indx, Name_First)),
5298
5299              Right_Opnd =>
5300                Make_Op_Gt (Loc,
5301                  Left_Opnd => Get_N_Last (Expr, Indx),
5302                  Right_Opnd  => Get_E_First_Or_Last (Typ, Indx, Name_Last)));
5303       end Range_N_Cond;
5304
5305    --  Start of processing for Selected_Range_Checks
5306
5307    begin
5308       if not Expander_Active then
5309          return Ret_Result;
5310       end if;
5311
5312       if Target_Typ = Any_Type
5313         or else Target_Typ = Any_Composite
5314         or else Raises_Constraint_Error (Ck_Node)
5315       then
5316          return Ret_Result;
5317       end if;
5318
5319       if No (Wnode) then
5320          Wnode := Ck_Node;
5321       end if;
5322
5323       T_Typ := Target_Typ;
5324
5325       if No (Source_Typ) then
5326          S_Typ := Etype (Ck_Node);
5327       else
5328          S_Typ := Source_Typ;
5329       end if;
5330
5331       if S_Typ = Any_Type or else S_Typ = Any_Composite then
5332          return Ret_Result;
5333       end if;
5334
5335       --  The order of evaluating T_Typ before S_Typ seems to be critical
5336       --  because S_Typ can be derived from Etype (Ck_Node), if it's not passed
5337       --  in, and since Node can be an N_Range node, it might be invalid.
5338       --  Should there be an assert check somewhere for taking the Etype of
5339       --  an N_Range node ???
5340
5341       if Is_Access_Type (T_Typ) and then Is_Access_Type (S_Typ) then
5342          S_Typ := Designated_Type (S_Typ);
5343          T_Typ := Designated_Type (T_Typ);
5344          Do_Access := True;
5345
5346          --  A simple optimization
5347
5348          if Nkind (Ck_Node) = N_Null then
5349             return Ret_Result;
5350          end if;
5351       end if;
5352
5353       --  For an N_Range Node, check for a null range and then if not
5354       --  null generate a range check action.
5355
5356       if Nkind (Ck_Node) = N_Range then
5357
5358          --  There's no point in checking a range against itself
5359
5360          if Ck_Node = Scalar_Range (T_Typ) then
5361             return Ret_Result;
5362          end if;
5363
5364          declare
5365             T_LB       : constant Node_Id := Type_Low_Bound  (T_Typ);
5366             T_HB       : constant Node_Id := Type_High_Bound (T_Typ);
5367             LB         : constant Node_Id := Low_Bound (Ck_Node);
5368             HB         : constant Node_Id := High_Bound (Ck_Node);
5369             Null_Range : Boolean;
5370
5371             Out_Of_Range_L : Boolean;
5372             Out_Of_Range_H : Boolean;
5373
5374          begin
5375             --  Check for case where everything is static and we can
5376             --  do the check at compile time. This is skipped if we
5377             --  have an access type, since the access value may be null.
5378
5379             --  ??? This code can be improved since you only need to know
5380             --  that the two respective bounds (LB & T_LB or HB & T_HB)
5381             --  are known at compile time to emit pertinent messages.
5382
5383             if Compile_Time_Known_Value (LB)
5384               and then Compile_Time_Known_Value (HB)
5385               and then Compile_Time_Known_Value (T_LB)
5386               and then Compile_Time_Known_Value (T_HB)
5387               and then not Do_Access
5388             then
5389                --  Floating-point case
5390
5391                if Is_Floating_Point_Type (S_Typ) then
5392                   Null_Range := Expr_Value_R (HB) < Expr_Value_R (LB);
5393                   Out_Of_Range_L :=
5394                     (Expr_Value_R (LB) < Expr_Value_R (T_LB))
5395                        or else
5396                     (Expr_Value_R (LB) > Expr_Value_R (T_HB));
5397
5398                   Out_Of_Range_H :=
5399                     (Expr_Value_R (HB) > Expr_Value_R (T_HB))
5400                        or else
5401                     (Expr_Value_R (HB) < Expr_Value_R (T_LB));
5402
5403                --  Fixed or discrete type case
5404
5405                else
5406                   Null_Range := Expr_Value (HB) < Expr_Value (LB);
5407                   Out_Of_Range_L :=
5408                     (Expr_Value (LB) < Expr_Value (T_LB))
5409                     or else
5410                     (Expr_Value (LB) > Expr_Value (T_HB));
5411
5412                   Out_Of_Range_H :=
5413                     (Expr_Value (HB) > Expr_Value (T_HB))
5414                     or else
5415                     (Expr_Value (HB) < Expr_Value (T_LB));
5416                end if;
5417
5418                if not Null_Range then
5419                   if Out_Of_Range_L then
5420                      if No (Warn_Node) then
5421                         Add_Check
5422                           (Compile_Time_Constraint_Error
5423                              (Low_Bound (Ck_Node),
5424                               "static value out of range of}?", T_Typ));
5425
5426                      else
5427                         Add_Check
5428                           (Compile_Time_Constraint_Error
5429                             (Wnode,
5430                              "static range out of bounds of}?", T_Typ));
5431                      end if;
5432                   end if;
5433
5434                   if Out_Of_Range_H then
5435                      if No (Warn_Node) then
5436                         Add_Check
5437                           (Compile_Time_Constraint_Error
5438                              (High_Bound (Ck_Node),
5439                               "static value out of range of}?", T_Typ));
5440
5441                      else
5442                         Add_Check
5443                           (Compile_Time_Constraint_Error
5444                              (Wnode,
5445                               "static range out of bounds of}?", T_Typ));
5446                      end if;
5447                   end if;
5448
5449                end if;
5450
5451             else
5452                declare
5453                   LB : Node_Id := Low_Bound (Ck_Node);
5454                   HB : Node_Id := High_Bound (Ck_Node);
5455
5456                begin
5457
5458                   --  If either bound is a discriminant and we are within
5459                   --  the record declaration, it is a use of the discriminant
5460                   --  in a constraint of a component, and nothing can be
5461                   --  checked here. The check will be emitted within the
5462                   --  init proc. Before then, the discriminal has no real
5463                   --  meaning.
5464
5465                   if Nkind (LB) = N_Identifier
5466                     and then Ekind (Entity (LB)) = E_Discriminant
5467                   then
5468                      if Current_Scope = Scope (Entity (LB)) then
5469                         return Ret_Result;
5470                      else
5471                         LB :=
5472                           New_Occurrence_Of (Discriminal (Entity (LB)), Loc);
5473                      end if;
5474                   end if;
5475
5476                   if Nkind (HB) = N_Identifier
5477                     and then Ekind (Entity (HB)) = E_Discriminant
5478                   then
5479                      if Current_Scope = Scope (Entity (HB)) then
5480                         return Ret_Result;
5481                      else
5482                         HB :=
5483                           New_Occurrence_Of (Discriminal (Entity (HB)), Loc);
5484                      end if;
5485                   end if;
5486
5487                   Cond := Discrete_Range_Cond (Ck_Node, T_Typ);
5488                   Set_Paren_Count (Cond, 1);
5489
5490                   Cond :=
5491                     Make_And_Then (Loc,
5492                       Left_Opnd =>
5493                         Make_Op_Ge (Loc,
5494                           Left_Opnd  => Duplicate_Subexpr_No_Checks (HB),
5495                           Right_Opnd => Duplicate_Subexpr_No_Checks (LB)),
5496                       Right_Opnd => Cond);
5497                end;
5498
5499             end if;
5500          end;
5501
5502       elsif Is_Scalar_Type (S_Typ) then
5503
5504          --  This somewhat duplicates what Apply_Scalar_Range_Check does,
5505          --  except the above simply sets a flag in the node and lets
5506          --  gigi generate the check base on the Etype of the expression.
5507          --  Sometimes, however we want to do a dynamic check against an
5508          --  arbitrary target type, so we do that here.
5509
5510          if Ekind (Base_Type (S_Typ)) /= Ekind (Base_Type (T_Typ)) then
5511             Cond := Discrete_Expr_Cond (Ck_Node, T_Typ);
5512
5513          --  For literals, we can tell if the constraint error will be
5514          --  raised at compile time, so we never need a dynamic check, but
5515          --  if the exception will be raised, then post the usual warning,
5516          --  and replace the literal with a raise constraint error
5517          --  expression. As usual, skip this for access types
5518
5519          elsif Compile_Time_Known_Value (Ck_Node)
5520            and then not Do_Access
5521          then
5522             declare
5523                LB : constant Node_Id := Type_Low_Bound (T_Typ);
5524                UB : constant Node_Id := Type_High_Bound (T_Typ);
5525
5526                Out_Of_Range  : Boolean;
5527                Static_Bounds : constant Boolean :=
5528                                  Compile_Time_Known_Value (LB)
5529                                    and Compile_Time_Known_Value (UB);
5530
5531             begin
5532                --  Following range tests should use Sem_Eval routine ???
5533
5534                if Static_Bounds then
5535                   if Is_Floating_Point_Type (S_Typ) then
5536                      Out_Of_Range :=
5537                        (Expr_Value_R (Ck_Node) < Expr_Value_R (LB))
5538                          or else
5539                        (Expr_Value_R (Ck_Node) > Expr_Value_R (UB));
5540
5541                   else -- fixed or discrete type
5542                      Out_Of_Range :=
5543                        Expr_Value (Ck_Node) < Expr_Value (LB)
5544                          or else
5545                        Expr_Value (Ck_Node) > Expr_Value (UB);
5546                   end if;
5547
5548                   --  Bounds of the type are static and the literal is
5549                   --  out of range so make a warning message.
5550
5551                   if Out_Of_Range then
5552                      if No (Warn_Node) then
5553                         Add_Check
5554                           (Compile_Time_Constraint_Error
5555                              (Ck_Node,
5556                               "static value out of range of}?", T_Typ));
5557
5558                      else
5559                         Add_Check
5560                           (Compile_Time_Constraint_Error
5561                              (Wnode,
5562                               "static value out of range of}?", T_Typ));
5563                      end if;
5564                   end if;
5565
5566                else
5567                   Cond := Discrete_Expr_Cond (Ck_Node, T_Typ);
5568                end if;
5569             end;
5570
5571          --  Here for the case of a non-static expression, we need a runtime
5572          --  check unless the source type range is guaranteed to be in the
5573          --  range of the target type.
5574
5575          else
5576             if not In_Subrange_Of (S_Typ, T_Typ) then
5577                Cond := Discrete_Expr_Cond (Ck_Node, T_Typ);
5578             end if;
5579          end if;
5580       end if;
5581
5582       if Is_Array_Type (T_Typ) and then Is_Array_Type (S_Typ) then
5583          if Is_Constrained (T_Typ) then
5584
5585             Expr_Actual := Get_Referenced_Object (Ck_Node);
5586             Exptyp      := Get_Actual_Subtype (Expr_Actual);
5587
5588             if Is_Access_Type (Exptyp) then
5589                Exptyp := Designated_Type (Exptyp);
5590             end if;
5591
5592             --  String_Literal case. This needs to be handled specially be-
5593             --  cause no index types are available for string literals. The
5594             --  condition is simply:
5595
5596             --    T_Typ'Length = string-literal-length
5597
5598             if Nkind (Expr_Actual) = N_String_Literal then
5599                null;
5600
5601             --  General array case. Here we have a usable actual subtype for
5602             --  the expression, and the condition is built from the two types
5603
5604             --     T_Typ'First     < Exptyp'First     or else
5605             --     T_Typ'Last      > Exptyp'Last      or else
5606             --     T_Typ'First(1)  < Exptyp'First(1)  or else
5607             --     T_Typ'Last(1)   > Exptyp'Last(1)   or else
5608             --     ...
5609
5610             elsif Is_Constrained (Exptyp) then
5611                declare
5612                   Ndims : constant Nat := Number_Dimensions (T_Typ);
5613
5614                   L_Index : Node_Id;
5615                   R_Index : Node_Id;
5616                   L_Low   : Node_Id;
5617                   L_High  : Node_Id;
5618                   R_Low   : Node_Id;
5619                   R_High  : Node_Id;
5620
5621                begin
5622                   L_Index := First_Index (T_Typ);
5623                   R_Index := First_Index (Exptyp);
5624
5625                   for Indx in 1 .. Ndims loop
5626                      if not (Nkind (L_Index) = N_Raise_Constraint_Error
5627                                or else
5628                              Nkind (R_Index) = N_Raise_Constraint_Error)
5629                      then
5630                         Get_Index_Bounds (L_Index, L_Low, L_High);
5631                         Get_Index_Bounds (R_Index, R_Low, R_High);
5632
5633                         --  Deal with compile time length check. Note that we
5634                         --  skip this in the access case, because the access
5635                         --  value may be null, so we cannot know statically.
5636
5637                         if not
5638                           Subtypes_Statically_Match
5639                             (Etype (L_Index), Etype (R_Index))
5640                         then
5641                            --  If the target type is constrained then we
5642                            --  have to check for exact equality of bounds
5643                            --  (required for qualified expressions).
5644
5645                            if Is_Constrained (T_Typ) then
5646                               Evolve_Or_Else
5647                                 (Cond,
5648                                  Range_Equal_E_Cond (Exptyp, T_Typ, Indx));
5649
5650                            else
5651                               Evolve_Or_Else
5652                                 (Cond, Range_E_Cond (Exptyp, T_Typ, Indx));
5653                            end if;
5654                         end if;
5655
5656                         Next (L_Index);
5657                         Next (R_Index);
5658
5659                      end if;
5660                   end loop;
5661                end;
5662
5663             --  Handle cases where we do not get a usable actual subtype that
5664             --  is constrained. This happens for example in the function call
5665             --  and explicit dereference cases. In these cases, we have to get
5666             --  the length or range from the expression itself, making sure we
5667             --  do not evaluate it more than once.
5668
5669             --  Here Ck_Node is the original expression, or more properly the
5670             --  result of applying Duplicate_Expr to the original tree,
5671             --  forcing the result to be a name.
5672
5673             else
5674                declare
5675                   Ndims : constant Nat := Number_Dimensions (T_Typ);
5676
5677                begin
5678                   --  Build the condition for the explicit dereference case
5679
5680                   for Indx in 1 .. Ndims loop
5681                      Evolve_Or_Else
5682                        (Cond, Range_N_Cond (Ck_Node, T_Typ, Indx));
5683                   end loop;
5684                end;
5685
5686             end if;
5687
5688          else
5689             --  Generate an Action to check that the bounds of the
5690             --  source value are within the constraints imposed by the
5691             --  target type for a conversion to an unconstrained type.
5692             --  Rule is 4.6(38).
5693
5694             if Nkind (Parent (Ck_Node)) = N_Type_Conversion then
5695                declare
5696                   Opnd_Index : Node_Id;
5697                   Targ_Index : Node_Id;
5698
5699                begin
5700                   Opnd_Index
5701                     := First_Index (Get_Actual_Subtype (Ck_Node));
5702                   Targ_Index := First_Index (T_Typ);
5703
5704                   while Opnd_Index /= Empty loop
5705                      if Nkind (Opnd_Index) = N_Range then
5706                         if Is_In_Range
5707                              (Low_Bound (Opnd_Index), Etype (Targ_Index))
5708                           and then
5709                             Is_In_Range
5710                              (High_Bound (Opnd_Index), Etype (Targ_Index))
5711                         then
5712                            null;
5713
5714                         --  If null range, no check needed.
5715                         elsif
5716                           Compile_Time_Known_Value (High_Bound (Opnd_Index))
5717                             and then
5718                           Compile_Time_Known_Value (Low_Bound (Opnd_Index))
5719                             and then
5720                              Expr_Value (High_Bound (Opnd_Index)) <
5721                                  Expr_Value (Low_Bound (Opnd_Index))
5722                         then
5723                            null;
5724
5725                         elsif Is_Out_Of_Range
5726                                 (Low_Bound (Opnd_Index), Etype (Targ_Index))
5727                           or else
5728                               Is_Out_Of_Range
5729                                 (High_Bound (Opnd_Index), Etype (Targ_Index))
5730                         then
5731                            Add_Check
5732                              (Compile_Time_Constraint_Error
5733                                (Wnode, "value out of range of}?", T_Typ));
5734
5735                         else
5736                            Evolve_Or_Else
5737                              (Cond,
5738                               Discrete_Range_Cond
5739                                 (Opnd_Index, Etype (Targ_Index)));
5740                         end if;
5741                      end if;
5742
5743                      Next_Index (Opnd_Index);
5744                      Next_Index (Targ_Index);
5745                   end loop;
5746                end;
5747             end if;
5748          end if;
5749       end if;
5750
5751       --  Construct the test and insert into the tree
5752
5753       if Present (Cond) then
5754          if Do_Access then
5755             Cond := Guard_Access (Cond, Loc, Ck_Node);
5756          end if;
5757
5758          Add_Check
5759            (Make_Raise_Constraint_Error (Loc,
5760               Condition => Cond,
5761               Reason    => CE_Range_Check_Failed));
5762       end if;
5763
5764       return Ret_Result;
5765    end Selected_Range_Checks;
5766
5767    -------------------------------
5768    -- Storage_Checks_Suppressed --
5769    -------------------------------
5770
5771    function Storage_Checks_Suppressed (E : Entity_Id) return Boolean is
5772    begin
5773       if Present (E) and then Checks_May_Be_Suppressed (E) then
5774          return Is_Check_Suppressed (E, Storage_Check);
5775       else
5776          return Scope_Suppress (Storage_Check);
5777       end if;
5778    end Storage_Checks_Suppressed;
5779
5780    ---------------------------
5781    -- Tag_Checks_Suppressed --
5782    ---------------------------
5783
5784    function Tag_Checks_Suppressed (E : Entity_Id) return Boolean is
5785    begin
5786       if Present (E) then
5787          if Kill_Tag_Checks (E) then
5788             return True;
5789          elsif Checks_May_Be_Suppressed (E) then
5790             return Is_Check_Suppressed (E, Tag_Check);
5791          end if;
5792       end if;
5793
5794       return Scope_Suppress (Tag_Check);
5795    end Tag_Checks_Suppressed;
5796
5797 end Checks;