OSDN Git Service

* 1aexcept.adb, 1aexcept.ads, 1ic.ads, 1ssecsta.adb,
[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-2002 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 Nlists;   use Nlists;
36 with Nmake;    use Nmake;
37 with Opt;      use Opt;
38 with Restrict; use Restrict;
39 with Rtsfind;  use Rtsfind;
40 with Sem;      use Sem;
41 with Sem_Eval; use Sem_Eval;
42 with Sem_Res;  use Sem_Res;
43 with Sem_Util; use Sem_Util;
44 with Sem_Warn; use Sem_Warn;
45 with Sinfo;    use Sinfo;
46 with Snames;   use Snames;
47 with Stand;    use Stand;
48 with Targparm; use Targparm;
49 with Tbuild;   use Tbuild;
50 with Ttypes;   use Ttypes;
51 with Urealp;   use Urealp;
52 with Validsw;  use Validsw;
53
54 package body Checks is
55
56    --  General note: many of these routines are concerned with generating
57    --  checking code to make sure that constraint error is raised at runtime.
58    --  Clearly this code is only needed if the expander is active, since
59    --  otherwise we will not be generating code or going into the runtime
60    --  execution anyway.
61
62    --  We therefore disconnect most of these checks if the expander is
63    --  inactive. This has the additional benefit that we do not need to
64    --  worry about the tree being messed up by previous errors (since errors
65    --  turn off expansion anyway).
66
67    --  There are a few exceptions to the above rule. For instance routines
68    --  such as Apply_Scalar_Range_Check that do not insert any code can be
69    --  safely called even when the Expander is inactive (but Errors_Detected
70    --  is 0). The benefit of executing this code when expansion is off, is
71    --  the ability to emit constraint error warning for static expressions
72    --  even when we are not generating code.
73
74    ----------------------------
75    -- Local Subprogram Specs --
76    ----------------------------
77
78    procedure Apply_Selected_Length_Checks
79      (Ck_Node    : Node_Id;
80       Target_Typ : Entity_Id;
81       Source_Typ : Entity_Id;
82       Do_Static  : Boolean);
83    --  This is the subprogram that does all the work for Apply_Length_Check
84    --  and Apply_Static_Length_Check. Expr, Target_Typ and Source_Typ are as
85    --  described for the above routines. The Do_Static flag indicates that
86    --  only a static check is to be done.
87
88    procedure Apply_Selected_Range_Checks
89      (Ck_Node    : Node_Id;
90       Target_Typ : Entity_Id;
91       Source_Typ : Entity_Id;
92       Do_Static  : Boolean);
93    --  This is the subprogram that does all the work for Apply_Range_Check.
94    --  Expr, Target_Typ and Source_Typ are as described for the above
95    --  routine. The Do_Static flag indicates that only a static check is
96    --  to be done.
97
98    function Get_Discriminal (E : Entity_Id; Bound : Node_Id) return Node_Id;
99    --  If a discriminal is used in constraining a prival, Return reference
100    --  to the discriminal of the protected body (which renames the parameter
101    --  of the enclosing protected operation). This clumsy transformation is
102    --  needed because privals are created too late and their actual subtypes
103    --  are not available when analysing the bodies of the protected operations.
104    --  To be cleaned up???
105
106    function Guard_Access
107      (Cond    : Node_Id;
108       Loc     : Source_Ptr;
109       Ck_Node : Node_Id)
110       return    Node_Id;
111    --  In the access type case, guard the test with a test to ensure
112    --  that the access value is non-null, since the checks do not
113    --  not apply to null access values.
114
115    procedure Install_Static_Check (R_Cno : Node_Id; Loc : Source_Ptr);
116    --  Called by Apply_{Length,Range}_Checks to rewrite the tree with the
117    --  Constraint_Error node.
118
119    function Selected_Length_Checks
120      (Ck_Node    : Node_Id;
121       Target_Typ : Entity_Id;
122       Source_Typ : Entity_Id;
123       Warn_Node  : Node_Id)
124       return       Check_Result;
125    --  Like Apply_Selected_Length_Checks, except it doesn't modify
126    --  anything, just returns a list of nodes as described in the spec of
127    --  this package for the Range_Check function.
128
129    function Selected_Range_Checks
130      (Ck_Node    : Node_Id;
131       Target_Typ : Entity_Id;
132       Source_Typ : Entity_Id;
133       Warn_Node  : Node_Id)
134       return       Check_Result;
135    --  Like Apply_Selected_Range_Checks, except it doesn't modify anything,
136    --  just returns a list of nodes as described in the spec of this package
137    --  for the Range_Check function.
138
139    ------------------------------
140    -- Access_Checks_Suppressed --
141    ------------------------------
142
143    function Access_Checks_Suppressed (E : Entity_Id) return Boolean is
144    begin
145       return Scope_Suppress.Access_Checks
146         or else (Present (E) and then Suppress_Access_Checks (E));
147    end Access_Checks_Suppressed;
148
149    -------------------------------------
150    -- Accessibility_Checks_Suppressed --
151    -------------------------------------
152
153    function Accessibility_Checks_Suppressed (E : Entity_Id) return Boolean is
154    begin
155       return Scope_Suppress.Accessibility_Checks
156         or else (Present (E) and then Suppress_Accessibility_Checks (E));
157    end Accessibility_Checks_Suppressed;
158
159    -------------------------
160    -- Append_Range_Checks --
161    -------------------------
162
163    procedure Append_Range_Checks
164      (Checks       : Check_Result;
165       Stmts        : List_Id;
166       Suppress_Typ : Entity_Id;
167       Static_Sloc  : Source_Ptr;
168       Flag_Node    : Node_Id)
169    is
170       Internal_Flag_Node   : Node_Id    := Flag_Node;
171       Internal_Static_Sloc : Source_Ptr := Static_Sloc;
172       Checks_On : constant Boolean :=
173                     (not Index_Checks_Suppressed (Suppress_Typ))
174                        or else
175                     (not Range_Checks_Suppressed (Suppress_Typ));
176
177    begin
178       --  For now we just return if Checks_On is false, however this should
179       --  be enhanced to check for an always True value in the condition
180       --  and to generate a compilation warning???
181
182       if not Checks_On then
183          return;
184       end if;
185
186       for J in 1 .. 2 loop
187          exit when No (Checks (J));
188
189          if Nkind (Checks (J)) = N_Raise_Constraint_Error
190            and then Present (Condition (Checks (J)))
191          then
192             if not Has_Dynamic_Range_Check (Internal_Flag_Node) then
193                Append_To (Stmts, Checks (J));
194                Set_Has_Dynamic_Range_Check (Internal_Flag_Node);
195             end if;
196
197          else
198             Append_To
199               (Stmts,
200                 Make_Raise_Constraint_Error (Internal_Static_Sloc,
201                   Reason => CE_Range_Check_Failed));
202          end if;
203       end loop;
204    end Append_Range_Checks;
205
206    ------------------------
207    -- Apply_Access_Check --
208    ------------------------
209
210    procedure Apply_Access_Check (N : Node_Id) is
211       P : constant Node_Id := Prefix (N);
212
213    begin
214       if Inside_A_Generic then
215          return;
216       end if;
217
218       if Is_Entity_Name (P) then
219          Check_Unset_Reference (P);
220       end if;
221
222       if Is_Entity_Name (P)
223         and then Access_Checks_Suppressed (Entity (P))
224       then
225          return;
226
227       elsif Access_Checks_Suppressed (Etype (P)) then
228          return;
229
230       else
231          Set_Do_Access_Check (N, True);
232       end if;
233    end Apply_Access_Check;
234
235    -------------------------------
236    -- Apply_Accessibility_Check --
237    -------------------------------
238
239    procedure Apply_Accessibility_Check (N : Node_Id; Typ : Entity_Id) is
240       Loc         : constant Source_Ptr := Sloc (N);
241       Param_Ent   : constant Entity_Id  := Param_Entity (N);
242       Param_Level : Node_Id;
243       Type_Level  : Node_Id;
244
245    begin
246       if Inside_A_Generic then
247          return;
248
249       --  Only apply the run-time check if the access parameter
250       --  has an associated extra access level parameter and
251       --  when the level of the type is less deep than the level
252       --  of the access parameter.
253
254       elsif Present (Param_Ent)
255          and then Present (Extra_Accessibility (Param_Ent))
256          and then UI_Gt (Object_Access_Level (N),
257                          Type_Access_Level (Typ))
258          and then not Accessibility_Checks_Suppressed (Param_Ent)
259          and then not Accessibility_Checks_Suppressed (Typ)
260       then
261          Param_Level :=
262            New_Occurrence_Of (Extra_Accessibility (Param_Ent), Loc);
263
264          Type_Level :=
265            Make_Integer_Literal (Loc, Type_Access_Level (Typ));
266
267          --  Raise Program_Error if the accessibility level of the
268          --  the access parameter is deeper than the level of the
269          --  target access type.
270
271          Insert_Action (N,
272            Make_Raise_Program_Error (Loc,
273              Condition =>
274                Make_Op_Gt (Loc,
275                  Left_Opnd  => Param_Level,
276                  Right_Opnd => Type_Level),
277              Reason => PE_Accessibility_Check_Failed));
278
279          Analyze_And_Resolve (N);
280       end if;
281    end Apply_Accessibility_Check;
282
283    ---------------------------
284    -- Apply_Alignment_Check --
285    ---------------------------
286
287    procedure Apply_Alignment_Check (E : Entity_Id; N : Node_Id) is
288       AC   : constant Node_Id := Address_Clause (E);
289       Expr : Node_Id;
290       Loc  : Source_Ptr;
291
292    begin
293       if No (AC) or else Range_Checks_Suppressed (E) then
294          return;
295       end if;
296
297       Loc  := Sloc (AC);
298       Expr := Expression (AC);
299
300       if Nkind (Expr) = N_Unchecked_Type_Conversion then
301          Expr := Expression (Expr);
302
303       elsif Nkind (Expr) = N_Function_Call
304         and then Is_RTE (Entity (Name (Expr)), RE_To_Address)
305       then
306          Expr := First (Parameter_Associations (Expr));
307
308          if Nkind (Expr) = N_Parameter_Association then
309             Expr := Explicit_Actual_Parameter (Expr);
310          end if;
311       end if;
312
313       --  Here Expr is the address value. See if we know that the
314       --  value is unacceptable at compile time.
315
316       if Compile_Time_Known_Value (Expr)
317         and then Known_Alignment (E)
318       then
319          if Expr_Value (Expr) mod Alignment (E) /= 0 then
320             Insert_Action (N,
321                Make_Raise_Program_Error (Loc,
322                  Reason => PE_Misaligned_Address_Value));
323             Error_Msg_NE
324               ("?specified address for& not " &
325                "consistent with alignment", Expr, E);
326          end if;
327
328       --  Here we do not know if the value is acceptable, generate
329       --  code to raise PE if alignment is inappropriate.
330
331       else
332          --  Skip generation of this code if we don't want elab code
333
334          if not Restrictions (No_Elaboration_Code) then
335             Insert_After_And_Analyze (N,
336               Make_Raise_Program_Error (Loc,
337                 Condition =>
338                   Make_Op_Ne (Loc,
339                     Left_Opnd =>
340                       Make_Op_Mod (Loc,
341                         Left_Opnd =>
342                           Unchecked_Convert_To
343                            (RTE (RE_Integer_Address),
344                             Duplicate_Subexpr (Expr)),
345                         Right_Opnd =>
346                           Make_Attribute_Reference (Loc,
347                             Prefix => New_Occurrence_Of (E, Loc),
348                             Attribute_Name => Name_Alignment)),
349                     Right_Opnd => Make_Integer_Literal (Loc, Uint_0)),
350                 Reason => PE_Misaligned_Address_Value),
351               Suppress => All_Checks);
352          end if;
353       end if;
354
355       return;
356    end Apply_Alignment_Check;
357
358    -------------------------------------
359    -- Apply_Arithmetic_Overflow_Check --
360    -------------------------------------
361
362    --  This routine is called only if the type is an integer type, and
363    --  a software arithmetic overflow check must be performed for op
364    --  (add, subtract, multiply). The check is performed only if
365    --  Software_Overflow_Checking is enabled and Do_Overflow_Check
366    --  is set. In this case we expand the operation into a more complex
367    --  sequence of tests that ensures that overflow is properly caught.
368
369    procedure Apply_Arithmetic_Overflow_Check (N : Node_Id) is
370       Loc   : constant Source_Ptr := Sloc (N);
371       Typ   : constant Entity_Id  := Etype (N);
372       Rtyp  : constant Entity_Id  := Root_Type (Typ);
373       Siz   : constant Int        := UI_To_Int (Esize (Rtyp));
374       Dsiz  : constant Int        := Siz * 2;
375       Opnod : Node_Id;
376       Ctyp  : Entity_Id;
377       Opnd  : Node_Id;
378       Cent  : RE_Id;
379       Lo    : Uint;
380       Hi    : Uint;
381       OK    : Boolean;
382
383    begin
384       if Backend_Overflow_Checks_On_Target
385         or not Do_Overflow_Check (N)
386         or not Expander_Active
387       then
388          return;
389       end if;
390
391       --  Nothing to do if the range of the result is known OK
392
393       Determine_Range (N, OK, Lo, Hi);
394
395       --  Note in the test below that we assume that if a bound of the
396       --  range is equal to that of the type. That's not quite accurate
397       --  but we do this for the following reasons:
398
399       --   a) The way that Determine_Range works, it will typically report
400       --      the bounds of the value are the bounds of the type, because
401       --      it either can't tell anything more precise, or does not think
402       --      it is worth the effort to be more precise.
403
404       --   b) It is very unusual to have a situation in which this would
405       --      generate an unnecessary overflow check (an example would be
406       --      a subtype with a range 0 .. Integer'Last - 1 to which the
407       --      literal value one is added.
408
409       --   c) The alternative is a lot of special casing in this routine
410       --      which would partially duplicate the Determine_Range processing.
411
412       if OK
413         and then Lo > Expr_Value (Type_Low_Bound  (Typ))
414         and then Hi < Expr_Value (Type_High_Bound (Typ))
415       then
416          return;
417       end if;
418
419       --  None of the special case optimizations worked, so there is nothing
420       --  for it but to generate the full general case code:
421
422       --    x op y
423
424       --  is expanded into
425
426       --    Typ (Checktyp (x) op Checktyp (y));
427
428       --  where Typ is the type of the original expression, and Checktyp is
429       --  an integer type of sufficient length to hold the largest possible
430       --  result.
431
432       --  In the case where check type exceeds the size of Long_Long_Integer,
433       --  we use a different approach, expanding to:
434
435       --    typ (xxx_With_Ovflo_Check (Integer_64 (x), Integer (y)))
436
437       --  where xxx is Add, Multiply or Subtract as appropriate
438
439       --  Find check type if one exists
440
441       if Dsiz <= Standard_Integer_Size then
442          Ctyp := Standard_Integer;
443
444       elsif Dsiz <= Standard_Long_Long_Integer_Size then
445          Ctyp := Standard_Long_Long_Integer;
446
447       --  No check type exists, use runtime call
448
449       else
450          if Nkind (N) = N_Op_Add then
451             Cent := RE_Add_With_Ovflo_Check;
452
453          elsif Nkind (N) = N_Op_Multiply then
454             Cent := RE_Multiply_With_Ovflo_Check;
455
456          else
457             pragma Assert (Nkind (N) = N_Op_Subtract);
458             Cent := RE_Subtract_With_Ovflo_Check;
459          end if;
460
461          Rewrite (N,
462            OK_Convert_To (Typ,
463              Make_Function_Call (Loc,
464                Name => New_Reference_To (RTE (Cent), Loc),
465                Parameter_Associations => New_List (
466                  OK_Convert_To (RTE (RE_Integer_64), Left_Opnd  (N)),
467                  OK_Convert_To (RTE (RE_Integer_64), Right_Opnd (N))))));
468
469          Analyze_And_Resolve (N, Typ);
470          return;
471       end if;
472
473       --  If we fall through, we have the case where we do the arithmetic in
474       --  the next higher type and get the check by conversion. In these cases
475       --  Ctyp is set to the type to be used as the check type.
476
477       Opnod := Relocate_Node (N);
478
479       Opnd := OK_Convert_To (Ctyp, Left_Opnd (Opnod));
480
481       Analyze (Opnd);
482       Set_Etype (Opnd, Ctyp);
483       Set_Analyzed (Opnd, True);
484       Set_Left_Opnd (Opnod, Opnd);
485
486       Opnd := OK_Convert_To (Ctyp, Right_Opnd (Opnod));
487
488       Analyze (Opnd);
489       Set_Etype (Opnd, Ctyp);
490       Set_Analyzed (Opnd, True);
491       Set_Right_Opnd (Opnod, Opnd);
492
493       --  The type of the operation changes to the base type of the check
494       --  type, and we reset the overflow check indication, since clearly
495       --  no overflow is possible now that we are using a double length
496       --  type. We also set the Analyzed flag to avoid a recursive attempt
497       --  to expand the node.
498
499       Set_Etype             (Opnod, Base_Type (Ctyp));
500       Set_Do_Overflow_Check (Opnod, False);
501       Set_Analyzed          (Opnod, True);
502
503       --  Now build the outer conversion
504
505       Opnd := OK_Convert_To (Typ, Opnod);
506
507       Analyze (Opnd);
508       Set_Etype (Opnd, Typ);
509       Set_Analyzed (Opnd, True);
510       Set_Do_Overflow_Check (Opnd, True);
511
512       Rewrite (N, Opnd);
513    end Apply_Arithmetic_Overflow_Check;
514
515    ----------------------------
516    -- Apply_Array_Size_Check --
517    ----------------------------
518
519    --  Note: Really of course this entre check should be in the backend,
520    --  and perhaps this is not quite the right value, but it is good
521    --  enough to catch the normal cases (and the relevant ACVC tests!)
522
523    procedure Apply_Array_Size_Check (N : Node_Id; Typ : Entity_Id) is
524       Loc  : constant Source_Ptr := Sloc (N);
525       Ctyp : constant Entity_Id  := Component_Type (Typ);
526       Ent  : constant Entity_Id  := Defining_Identifier (N);
527       Decl : Node_Id;
528       Lo   : Node_Id;
529       Hi   : Node_Id;
530       Lob  : Uint;
531       Hib  : Uint;
532       Siz  : Uint;
533       Xtyp : Entity_Id;
534       Indx : Node_Id;
535       Sizx : Node_Id;
536       Code : Node_Id;
537
538       Static : Boolean := True;
539       --  Set false if any index subtye bound is non-static
540
541       Umark : constant Uintp.Save_Mark := Uintp.Mark;
542       --  We can throw away all the Uint computations here, since they are
543       --  done only to generate boolean test results.
544
545       Check_Siz : Uint;
546       --  Size to check against
547
548       function Is_Address_Or_Import (Decl : Node_Id) return Boolean;
549       --  Determines if Decl is an address clause or Import/Interface pragma
550       --  that references the defining identifier of the current declaration.
551
552       --------------------------
553       -- Is_Address_Or_Import --
554       --------------------------
555
556       function Is_Address_Or_Import (Decl : Node_Id) return Boolean is
557       begin
558          if Nkind (Decl) = N_At_Clause then
559             return Chars (Identifier (Decl)) = Chars (Ent);
560
561          elsif Nkind (Decl) = N_Attribute_Definition_Clause then
562             return
563               Chars (Decl) = Name_Address
564                 and then
565               Nkind (Name (Decl)) = N_Identifier
566                 and then
567               Chars (Name (Decl)) = Chars (Ent);
568
569          elsif Nkind (Decl) = N_Pragma then
570             if (Chars (Decl) = Name_Import
571                  or else
572                 Chars (Decl) = Name_Interface)
573               and then Present (Pragma_Argument_Associations (Decl))
574             then
575                declare
576                   F : constant Node_Id :=
577                         First (Pragma_Argument_Associations (Decl));
578
579                begin
580                   return
581                     Present (F)
582                       and then
583                     Present (Next (F))
584                       and then
585                     Nkind (Expression (Next (F))) = N_Identifier
586                       and then
587                     Chars (Expression (Next (F))) = Chars (Ent);
588                end;
589
590             else
591                return False;
592             end if;
593
594          else
595             return False;
596          end if;
597       end Is_Address_Or_Import;
598
599    --  Start of processing for Apply_Array_Size_Check
600
601    begin
602       if not Expander_Active
603         or else Storage_Checks_Suppressed (Typ)
604       then
605          return;
606       end if;
607
608       --  It is pointless to insert this check inside an _init_proc, because
609       --  that's too late, we have already built the object to be the right
610       --  size, and if it's too large, too bad!
611
612       if Inside_Init_Proc then
613          return;
614       end if;
615
616       --  Look head for pragma interface/import or address clause applying
617       --  to this entity. If found, we suppress the check entirely. For now
618       --  we only look ahead 20 declarations to stop this becoming too slow
619       --  Note that eventually this whole routine gets moved to gigi.
620
621       Decl := N;
622       for Ctr in 1 .. 20 loop
623          Next (Decl);
624          exit when No (Decl);
625
626          if Is_Address_Or_Import (Decl) then
627             return;
628          end if;
629       end loop;
630
631       --  First step is to calculate the maximum number of elements. For this
632       --  calculation, we use the actual size of the subtype if it is static,
633       --  and if a bound of a subtype is non-static, we go to the bound of the
634       --  base type.
635
636       Siz := Uint_1;
637       Indx := First_Index (Typ);
638       while Present (Indx) loop
639          Xtyp := Etype (Indx);
640          Lo := Type_Low_Bound (Xtyp);
641          Hi := Type_High_Bound (Xtyp);
642
643          --  If any bound raises constraint error, we will never get this
644          --  far, so there is no need to generate any kind of check.
645
646          if Raises_Constraint_Error (Lo)
647               or else
648             Raises_Constraint_Error (Hi)
649          then
650             Uintp.Release (Umark);
651             return;
652          end if;
653
654          --  Otherwise get bounds values
655
656          if Is_Static_Expression (Lo) then
657             Lob := Expr_Value (Lo);
658          else
659             Lob := Expr_Value (Type_Low_Bound (Base_Type (Xtyp)));
660             Static := False;
661          end if;
662
663          if Is_Static_Expression (Hi) then
664             Hib := Expr_Value (Hi);
665          else
666             Hib := Expr_Value (Type_High_Bound (Base_Type (Xtyp)));
667             Static := False;
668          end if;
669
670          Siz := Siz *  UI_Max (Hib - Lob + 1, Uint_0);
671          Next_Index (Indx);
672       end loop;
673
674       --  Compute the limit against which we want to check. For subprograms,
675       --  where the array will go on the stack, we use 8*2**24, which (in
676       --  bits) is the size of a 16 megabyte array.
677
678       if Is_Subprogram (Scope (Ent)) then
679          Check_Siz := Uint_2 ** 27;
680       else
681          Check_Siz := Uint_2 ** 31;
682       end if;
683
684       --  If we have all static bounds and Siz is too large, then we know we
685       --  know we have a storage error right now, so generate message
686
687       if Static and then Siz >= Check_Siz then
688          Insert_Action (N,
689            Make_Raise_Storage_Error (Loc,
690              Reason => SE_Object_Too_Large));
691          Warn_On_Instance := True;
692          Error_Msg_N ("?Storage_Error will be raised at run-time", N);
693          Warn_On_Instance := False;
694          Uintp.Release (Umark);
695          return;
696       end if;
697
698       --  Case of component size known at compile time. If the array
699       --  size is definitely in range, then we do not need a check.
700
701       if Known_Esize (Ctyp)
702         and then Siz * Esize (Ctyp) < Check_Siz
703       then
704          Uintp.Release (Umark);
705          return;
706       end if;
707
708       --  Here if a dynamic check is required
709
710       --  What we do is to build an expression for the size of the array,
711       --  which is computed as the 'Size of the array component, times
712       --  the size of each dimension.
713
714       Uintp.Release (Umark);
715
716       Sizx :=
717         Make_Attribute_Reference (Loc,
718           Prefix => New_Occurrence_Of (Ctyp, Loc),
719           Attribute_Name => Name_Size);
720
721       Indx := First_Index (Typ);
722
723       for J in 1 .. Number_Dimensions (Typ) loop
724
725          if Sloc (Etype (Indx)) = Sloc (N) then
726             Ensure_Defined (Etype (Indx), N);
727          end if;
728
729          Sizx :=
730            Make_Op_Multiply (Loc,
731              Left_Opnd  => Sizx,
732              Right_Opnd =>
733                Make_Attribute_Reference (Loc,
734                  Prefix => New_Occurrence_Of (Typ, Loc),
735                  Attribute_Name => Name_Length,
736                  Expressions => New_List (
737                    Make_Integer_Literal (Loc, J))));
738          Next_Index (Indx);
739       end loop;
740
741       Code :=
742         Make_Raise_Storage_Error (Loc,
743           Condition =>
744             Make_Op_Ge (Loc,
745               Left_Opnd  => Sizx,
746               Right_Opnd =>
747                 Make_Integer_Literal (Loc, Check_Siz)),
748             Reason => SE_Object_Too_Large);
749
750       Set_Size_Check_Code (Defining_Identifier (N), Code);
751       Insert_Action (N, Code);
752    end Apply_Array_Size_Check;
753
754    ----------------------------
755    -- Apply_Constraint_Check --
756    ----------------------------
757
758    procedure Apply_Constraint_Check
759      (N          : Node_Id;
760       Typ        : Entity_Id;
761       No_Sliding : Boolean := False)
762    is
763       Desig_Typ : Entity_Id;
764
765    begin
766       if Inside_A_Generic then
767          return;
768
769       elsif Is_Scalar_Type (Typ) then
770          Apply_Scalar_Range_Check (N, Typ);
771
772       elsif Is_Array_Type (Typ) then
773
774          --  A useful optimization: an aggregate with only an Others clause
775          --  always has the right bounds.
776
777          if Nkind (N) = N_Aggregate
778            and then No (Expressions (N))
779            and then Nkind
780             (First (Choices (First (Component_Associations (N)))))
781               = N_Others_Choice
782          then
783             return;
784          end if;
785
786          if Is_Constrained (Typ) then
787             Apply_Length_Check (N, Typ);
788
789             if No_Sliding then
790                Apply_Range_Check (N, Typ);
791             end if;
792          else
793             Apply_Range_Check (N, Typ);
794          end if;
795
796       elsif (Is_Record_Type (Typ)
797                or else Is_Private_Type (Typ))
798         and then Has_Discriminants (Base_Type (Typ))
799         and then Is_Constrained (Typ)
800       then
801          Apply_Discriminant_Check (N, Typ);
802
803       elsif Is_Access_Type (Typ) then
804
805          Desig_Typ := Designated_Type (Typ);
806
807          --  No checks necessary if expression statically null
808
809          if Nkind (N) = N_Null then
810             null;
811
812          --  No sliding possible on access to arrays
813
814          elsif Is_Array_Type (Desig_Typ) then
815             if Is_Constrained (Desig_Typ) then
816                Apply_Length_Check (N, Typ);
817             end if;
818
819             Apply_Range_Check (N, Typ);
820
821          elsif Has_Discriminants (Base_Type (Desig_Typ))
822             and then Is_Constrained (Desig_Typ)
823          then
824             Apply_Discriminant_Check (N, Typ);
825          end if;
826       end if;
827    end Apply_Constraint_Check;
828
829    ------------------------------
830    -- Apply_Discriminant_Check --
831    ------------------------------
832
833    procedure Apply_Discriminant_Check
834      (N   : Node_Id;
835       Typ : Entity_Id;
836       Lhs : Node_Id := Empty)
837    is
838       Loc       : constant Source_Ptr := Sloc (N);
839       Do_Access : constant Boolean    := Is_Access_Type (Typ);
840       S_Typ     : Entity_Id  := Etype (N);
841       Cond      : Node_Id;
842       T_Typ     : Entity_Id;
843
844       function Is_Aliased_Unconstrained_Component return Boolean;
845       --  It is possible for an aliased component to have a nominal
846       --  unconstrained subtype (through instantiation). If this is a
847       --  discriminated component assigned in the expansion of an aggregate
848       --  in an initialization, the check must be suppressed. This unusual
849       --  situation requires a predicate of its own (see 7503-008).
850
851       ----------------------------------------
852       -- Is_Aliased_Unconstrained_Component --
853       ----------------------------------------
854
855       function Is_Aliased_Unconstrained_Component return Boolean is
856          Comp : Entity_Id;
857          Pref : Node_Id;
858
859       begin
860          if Nkind (Lhs) /= N_Selected_Component then
861             return False;
862          else
863             Comp := Entity (Selector_Name (Lhs));
864             Pref := Prefix (Lhs);
865          end if;
866
867          if Ekind (Comp) /= E_Component
868            or else not Is_Aliased (Comp)
869          then
870             return False;
871          end if;
872
873          return not Comes_From_Source (Pref)
874            and then In_Instance
875            and then not Is_Constrained (Etype (Comp));
876       end Is_Aliased_Unconstrained_Component;
877
878    --  Start of processing for Apply_Discriminant_Check
879
880    begin
881       if Do_Access then
882          T_Typ := Designated_Type (Typ);
883       else
884          T_Typ := Typ;
885       end if;
886
887       --  Nothing to do if discriminant checks are suppressed or else no code
888       --  is to be generated
889
890       if not Expander_Active
891         or else Discriminant_Checks_Suppressed (T_Typ)
892       then
893          return;
894       end if;
895
896       --  No discriminant checks necessary for access when expression
897       --  is statically Null. This is not only an optimization, this is
898       --  fundamental because otherwise discriminant checks may be generated
899       --  in init procs for types containing an access to a non-frozen yet
900       --  record, causing a deadly forward reference.
901
902       --  Also, if the expression is of an access type whose designated
903       --  type is incomplete, then the access value must be null and
904       --  we suppress the check.
905
906       if Nkind (N) = N_Null then
907          return;
908
909       elsif Is_Access_Type (S_Typ) then
910          S_Typ := Designated_Type (S_Typ);
911
912          if Ekind (S_Typ) = E_Incomplete_Type then
913             return;
914          end if;
915       end if;
916
917       --  If an assignment target is present, then we need to generate
918       --  the actual subtype if the target is a parameter or aliased
919       --  object with an unconstrained nominal subtype.
920
921       if Present (Lhs)
922         and then (Present (Param_Entity (Lhs))
923                    or else (not Is_Constrained (T_Typ)
924                              and then Is_Aliased_View (Lhs)
925                              and then not Is_Aliased_Unconstrained_Component))
926       then
927          T_Typ := Get_Actual_Subtype (Lhs);
928       end if;
929
930       --  Nothing to do if the type is unconstrained (this is the case
931       --  where the actual subtype in the RM sense of N is unconstrained
932       --  and no check is required).
933
934       if not Is_Constrained (T_Typ) then
935          return;
936       end if;
937
938       --  Suppress checks if the subtypes are the same.
939       --  the check must be preserved in an assignment to a formal, because
940       --  the constraint is given by the actual.
941
942       if Nkind (Original_Node (N)) /= N_Allocator
943         and then (No (Lhs)
944           or else not Is_Entity_Name (Lhs)
945           or else (Ekind (Entity (Lhs)) /=  E_In_Out_Parameter
946                     and then Ekind (Entity (Lhs)) /=  E_Out_Parameter))
947       then
948          if (Etype (N) = Typ
949               or else (Do_Access and then Designated_Type (Typ) = S_Typ))
950            and then not Is_Aliased_View (Lhs)
951          then
952             return;
953          end if;
954
955       --  We can also eliminate checks on allocators with a subtype mark
956       --  that coincides with the context type. The context type may be a
957       --  subtype without a constraint (common case, a generic actual).
958
959       elsif Nkind (Original_Node (N)) = N_Allocator
960         and then Is_Entity_Name (Expression (Original_Node (N)))
961       then
962          declare
963             Alloc_Typ : Entity_Id := Entity (Expression (Original_Node (N)));
964
965          begin
966             if Alloc_Typ = T_Typ
967               or else (Nkind (Parent (T_Typ)) = N_Subtype_Declaration
968                         and then Is_Entity_Name (
969                           Subtype_Indication (Parent (T_Typ)))
970                         and then Alloc_Typ = Base_Type (T_Typ))
971
972             then
973                return;
974             end if;
975          end;
976       end if;
977
978       --  See if we have a case where the types are both constrained, and
979       --  all the constraints are constants. In this case, we can do the
980       --  check successfully at compile time.
981
982       --  we skip this check for the case where the node is a rewritten`
983       --  allocator, because it already carries the context subtype, and
984       --  extracting the discriminants from the aggregate is messy.
985
986       if Is_Constrained (S_Typ)
987         and then Nkind (Original_Node (N)) /= N_Allocator
988       then
989          declare
990             DconT : Elmt_Id;
991             Discr : Entity_Id;
992             DconS : Elmt_Id;
993             ItemS : Node_Id;
994             ItemT : Node_Id;
995
996          begin
997             --  S_Typ may not have discriminants in the case where it is a
998             --  private type completed by a default discriminated type. In
999             --  that case, we need to get the constraints from the
1000             --  underlying_type. If the underlying type is unconstrained (i.e.
1001             --  has no default discriminants) no check is needed.
1002
1003             if Has_Discriminants (S_Typ) then
1004                Discr := First_Discriminant (S_Typ);
1005                DconS := First_Elmt (Discriminant_Constraint (S_Typ));
1006
1007             else
1008                Discr := First_Discriminant (Underlying_Type (S_Typ));
1009                DconS :=
1010                  First_Elmt
1011                    (Discriminant_Constraint (Underlying_Type (S_Typ)));
1012
1013                if No (DconS) then
1014                   return;
1015                end if;
1016             end if;
1017
1018             DconT  := First_Elmt (Discriminant_Constraint (T_Typ));
1019
1020             while Present (Discr) loop
1021                ItemS := Node (DconS);
1022                ItemT := Node (DconT);
1023
1024                exit when
1025                  not Is_OK_Static_Expression (ItemS)
1026                    or else
1027                  not Is_OK_Static_Expression (ItemT);
1028
1029                if Expr_Value (ItemS) /= Expr_Value (ItemT) then
1030                   if Do_Access then   --  needs run-time check.
1031                      exit;
1032                   else
1033                      Apply_Compile_Time_Constraint_Error
1034                        (N, "incorrect value for discriminant&?",
1035                         CE_Discriminant_Check_Failed, Ent => Discr);
1036                      return;
1037                   end if;
1038                end if;
1039
1040                Next_Elmt (DconS);
1041                Next_Elmt (DconT);
1042                Next_Discriminant (Discr);
1043             end loop;
1044
1045             if No (Discr) then
1046                return;
1047             end if;
1048          end;
1049       end if;
1050
1051       --  Here we need a discriminant check. First build the expression
1052       --  for the comparisons of the discriminants:
1053
1054       --    (n.disc1 /= typ.disc1) or else
1055       --    (n.disc2 /= typ.disc2) or else
1056       --     ...
1057       --    (n.discn /= typ.discn)
1058
1059       Cond := Build_Discriminant_Checks (N, T_Typ);
1060
1061       --  If Lhs is set and is a parameter, then the condition is
1062       --  guarded by: lhs'constrained and then (condition built above)
1063
1064       if Present (Param_Entity (Lhs)) then
1065          Cond :=
1066            Make_And_Then (Loc,
1067              Left_Opnd =>
1068                Make_Attribute_Reference (Loc,
1069                  Prefix => New_Occurrence_Of (Param_Entity (Lhs), Loc),
1070                  Attribute_Name => Name_Constrained),
1071              Right_Opnd => Cond);
1072       end if;
1073
1074       if Do_Access then
1075          Cond := Guard_Access (Cond, Loc, N);
1076       end if;
1077
1078       Insert_Action (N,
1079         Make_Raise_Constraint_Error (Loc,
1080           Condition => Cond,
1081           Reason    => CE_Discriminant_Check_Failed));
1082
1083    end Apply_Discriminant_Check;
1084
1085    ------------------------
1086    -- Apply_Divide_Check --
1087    ------------------------
1088
1089    procedure Apply_Divide_Check (N : Node_Id) is
1090       Loc   : constant Source_Ptr := Sloc (N);
1091       Typ   : constant Entity_Id  := Etype (N);
1092       Left  : constant Node_Id    := Left_Opnd (N);
1093       Right : constant Node_Id    := Right_Opnd (N);
1094
1095       LLB : Uint;
1096       Llo : Uint;
1097       Lhi : Uint;
1098       LOK : Boolean;
1099       Rlo : Uint;
1100       Rhi : Uint;
1101       ROK : Boolean;
1102
1103    begin
1104       if Expander_Active
1105         and not Backend_Divide_Checks_On_Target
1106       then
1107          Determine_Range (Right, ROK, Rlo, Rhi);
1108
1109          --  See if division by zero possible, and if so generate test. This
1110          --  part of the test is not controlled by the -gnato switch.
1111
1112          if Do_Division_Check (N) then
1113
1114             if (not ROK) or else (Rlo <= 0 and then 0 <= Rhi) then
1115                Insert_Action (N,
1116                  Make_Raise_Constraint_Error (Loc,
1117                    Condition =>
1118                      Make_Op_Eq (Loc,
1119                        Left_Opnd => Duplicate_Subexpr (Right),
1120                        Right_Opnd => Make_Integer_Literal (Loc, 0)),
1121                    Reason => CE_Divide_By_Zero));
1122             end if;
1123          end if;
1124
1125          --  Test for extremely annoying case of xxx'First divided by -1
1126
1127          if Do_Overflow_Check (N) then
1128
1129             if Nkind (N) = N_Op_Divide
1130               and then Is_Signed_Integer_Type (Typ)
1131             then
1132                Determine_Range (Left, LOK, Llo, Lhi);
1133                LLB := Expr_Value (Type_Low_Bound (Base_Type (Typ)));
1134
1135                if ((not ROK) or else (Rlo <= (-1) and then (-1) <= Rhi))
1136                  and then
1137                  ((not LOK) or else (Llo = LLB))
1138                then
1139                   Insert_Action (N,
1140                     Make_Raise_Constraint_Error (Loc,
1141                       Condition =>
1142                         Make_And_Then (Loc,
1143
1144                            Make_Op_Eq (Loc,
1145                              Left_Opnd  => Duplicate_Subexpr (Left),
1146                              Right_Opnd => Make_Integer_Literal (Loc, LLB)),
1147
1148                            Make_Op_Eq (Loc,
1149                              Left_Opnd => Duplicate_Subexpr (Right),
1150                              Right_Opnd =>
1151                                Make_Integer_Literal (Loc, -1))),
1152                       Reason => CE_Overflow_Check_Failed));
1153                end if;
1154             end if;
1155          end if;
1156       end if;
1157    end Apply_Divide_Check;
1158
1159    ------------------------
1160    -- Apply_Length_Check --
1161    ------------------------
1162
1163    procedure Apply_Length_Check
1164      (Ck_Node    : Node_Id;
1165       Target_Typ : Entity_Id;
1166       Source_Typ : Entity_Id := Empty)
1167    is
1168    begin
1169       Apply_Selected_Length_Checks
1170         (Ck_Node, Target_Typ, Source_Typ, Do_Static => False);
1171    end Apply_Length_Check;
1172
1173    -----------------------
1174    -- Apply_Range_Check --
1175    -----------------------
1176
1177    procedure Apply_Range_Check
1178      (Ck_Node    : Node_Id;
1179       Target_Typ : Entity_Id;
1180       Source_Typ : Entity_Id := Empty)
1181    is
1182    begin
1183       Apply_Selected_Range_Checks
1184         (Ck_Node, Target_Typ, Source_Typ, Do_Static => False);
1185    end Apply_Range_Check;
1186
1187    ------------------------------
1188    -- Apply_Scalar_Range_Check --
1189    ------------------------------
1190
1191    --  Note that Apply_Scalar_Range_Check never turns the Do_Range_Check
1192    --  flag off if it is already set on.
1193
1194    procedure Apply_Scalar_Range_Check
1195      (Expr       : Node_Id;
1196       Target_Typ : Entity_Id;
1197       Source_Typ : Entity_Id := Empty;
1198       Fixed_Int  : Boolean   := False)
1199    is
1200       Parnt   : constant Node_Id := Parent (Expr);
1201       S_Typ   : Entity_Id;
1202       Arr     : Node_Id   := Empty;  -- initialize to prevent warning
1203       Arr_Typ : Entity_Id := Empty;  -- initialize to prevent warning
1204       OK      : Boolean;
1205
1206       Is_Subscr_Ref : Boolean;
1207       --  Set true if Expr is a subscript
1208
1209       Is_Unconstrained_Subscr_Ref : Boolean;
1210       --  Set true if Expr is a subscript of an unconstrained array. In this
1211       --  case we do not attempt to do an analysis of the value against the
1212       --  range of the subscript, since we don't know the actual subtype.
1213
1214       Int_Real : Boolean;
1215       --  Set to True if Expr should be regarded as a real value
1216       --  even though the type of Expr might be discrete.
1217
1218       procedure Bad_Value;
1219       --  Procedure called if value is determined to be out of range
1220
1221       procedure Bad_Value is
1222       begin
1223          Apply_Compile_Time_Constraint_Error
1224            (Expr, "value not in range of}?", CE_Range_Check_Failed,
1225             Ent => Target_Typ,
1226             Typ => Target_Typ);
1227       end Bad_Value;
1228
1229    begin
1230       if Inside_A_Generic then
1231          return;
1232
1233       --  Return if check obviously not needed. Note that we do not check
1234       --  for the expander being inactive, since this routine does not
1235       --  insert any code, but it does generate useful warnings sometimes,
1236       --  which we would like even if we are in semantics only mode.
1237
1238       elsif Target_Typ = Any_Type
1239         or else not Is_Scalar_Type (Target_Typ)
1240         or else Raises_Constraint_Error (Expr)
1241       then
1242          return;
1243       end if;
1244
1245       --  Now, see if checks are suppressed
1246
1247       Is_Subscr_Ref :=
1248         Is_List_Member (Expr) and then Nkind (Parnt) = N_Indexed_Component;
1249
1250       if Is_Subscr_Ref then
1251          Arr := Prefix (Parnt);
1252          Arr_Typ := Get_Actual_Subtype_If_Available (Arr);
1253       end if;
1254
1255       if not Do_Range_Check (Expr) then
1256
1257          --  Subscript reference. Check for Index_Checks suppressed
1258
1259          if Is_Subscr_Ref then
1260
1261             --  Check array type and its base type
1262
1263             if Index_Checks_Suppressed (Arr_Typ)
1264               or else Suppress_Index_Checks (Base_Type (Arr_Typ))
1265             then
1266                return;
1267
1268             --  Check array itself if it is an entity name
1269
1270             elsif Is_Entity_Name (Arr)
1271               and then Suppress_Index_Checks (Entity (Arr))
1272             then
1273                return;
1274
1275             --  Check expression itself if it is an entity name
1276
1277             elsif Is_Entity_Name (Expr)
1278               and then Suppress_Index_Checks (Entity (Expr))
1279             then
1280                return;
1281             end if;
1282
1283          --  All other cases, check for Range_Checks suppressed
1284
1285          else
1286             --  Check target type and its base type
1287
1288             if Range_Checks_Suppressed (Target_Typ)
1289               or else Suppress_Range_Checks (Base_Type (Target_Typ))
1290             then
1291                return;
1292
1293             --  Check expression itself if it is an entity name
1294
1295             elsif Is_Entity_Name (Expr)
1296               and then Suppress_Range_Checks (Entity (Expr))
1297             then
1298                return;
1299
1300             --  If Expr is part of an assignment statement, then check
1301             --  left side of assignment if it is an entity name.
1302
1303             elsif Nkind (Parnt) = N_Assignment_Statement
1304               and then Is_Entity_Name (Name (Parnt))
1305               and then Suppress_Range_Checks (Entity (Name (Parnt)))
1306             then
1307                return;
1308             end if;
1309          end if;
1310       end if;
1311
1312       --  Now see if we need a check
1313
1314       if No (Source_Typ) then
1315          S_Typ := Etype (Expr);
1316       else
1317          S_Typ := Source_Typ;
1318       end if;
1319
1320       if not Is_Scalar_Type (S_Typ) or else S_Typ = Any_Type then
1321          return;
1322       end if;
1323
1324       Is_Unconstrained_Subscr_Ref :=
1325         Is_Subscr_Ref and then not Is_Constrained (Arr_Typ);
1326
1327       --  Always do a range check if the source type includes infinities
1328       --  and the target type does not include infinities.
1329
1330       if Is_Floating_Point_Type (S_Typ)
1331         and then Has_Infinities (S_Typ)
1332         and then not Has_Infinities (Target_Typ)
1333       then
1334          Enable_Range_Check (Expr);
1335       end if;
1336
1337       --  Return if we know expression is definitely in the range of
1338       --  the target type as determined by Determine_Range. Right now
1339       --  we only do this for discrete types, and not fixed-point or
1340       --  floating-point types.
1341
1342       --  The additional less-precise tests below catch these cases.
1343
1344       --  Note: skip this if we are given a source_typ, since the point
1345       --  of supplying a Source_Typ is to stop us looking at the expression.
1346       --  could sharpen this test to be out parameters only ???
1347
1348       if Is_Discrete_Type (Target_Typ)
1349         and then Is_Discrete_Type (Etype (Expr))
1350         and then not Is_Unconstrained_Subscr_Ref
1351         and then No (Source_Typ)
1352       then
1353          declare
1354             Tlo : constant Node_Id := Type_Low_Bound  (Target_Typ);
1355             Thi : constant Node_Id := Type_High_Bound (Target_Typ);
1356             Lo  : Uint;
1357             Hi  : Uint;
1358
1359          begin
1360             if Compile_Time_Known_Value (Tlo)
1361               and then Compile_Time_Known_Value (Thi)
1362             then
1363                Determine_Range (Expr, OK, Lo, Hi);
1364
1365                if OK then
1366                   declare
1367                      Lov : constant Uint := Expr_Value (Tlo);
1368                      Hiv : constant Uint := Expr_Value (Thi);
1369
1370                   begin
1371                      if Lo >= Lov and then Hi <= Hiv then
1372                         return;
1373
1374                      elsif Lov > Hi or else Hiv < Lo then
1375                         Bad_Value;
1376                         return;
1377                      end if;
1378                   end;
1379                end if;
1380             end if;
1381          end;
1382       end if;
1383
1384       Int_Real :=
1385         Is_Floating_Point_Type (S_Typ)
1386           or else (Is_Fixed_Point_Type (S_Typ) and then not Fixed_Int);
1387
1388       --  Check if we can determine at compile time whether Expr is in the
1389       --  range of the target type. Note that if S_Typ is within the
1390       --  bounds of Target_Typ then this must be the case. This checks is
1391       --  only meaningful if this is not a conversion between integer and
1392       --  real types.
1393
1394       if not Is_Unconstrained_Subscr_Ref
1395         and then
1396            Is_Discrete_Type (S_Typ) = Is_Discrete_Type (Target_Typ)
1397         and then
1398           (In_Subrange_Of (S_Typ, Target_Typ, Fixed_Int)
1399              or else
1400            Is_In_Range (Expr, Target_Typ, Fixed_Int, Int_Real))
1401       then
1402          return;
1403
1404       elsif Is_Out_Of_Range (Expr, Target_Typ, Fixed_Int, Int_Real) then
1405          Bad_Value;
1406          return;
1407
1408       --  Do not set range checks if they are killed
1409
1410       elsif Nkind (Expr) = N_Unchecked_Type_Conversion
1411         and then Kill_Range_Check (Expr)
1412       then
1413          return;
1414
1415       --  ??? We only need a runtime check if the target type is constrained
1416       --  (the predefined type Float is not for instance).
1417       --  so the following should really be
1418       --
1419       --    elsif Is_Constrained (Target_Typ) then
1420       --
1421       --  but it isn't because certain types do not have the Is_Constrained
1422       --  flag properly set (see 1503-003).
1423
1424       else
1425          Enable_Range_Check (Expr);
1426          return;
1427       end if;
1428
1429    end Apply_Scalar_Range_Check;
1430
1431    ----------------------------------
1432    -- Apply_Selected_Length_Checks --
1433    ----------------------------------
1434
1435    procedure Apply_Selected_Length_Checks
1436      (Ck_Node    : Node_Id;
1437       Target_Typ : Entity_Id;
1438       Source_Typ : Entity_Id;
1439       Do_Static  : Boolean)
1440    is
1441       Cond     : Node_Id;
1442       R_Result : Check_Result;
1443       R_Cno    : Node_Id;
1444
1445       Loc         : constant Source_Ptr := Sloc (Ck_Node);
1446       Checks_On   : constant Boolean :=
1447                       (not Index_Checks_Suppressed (Target_Typ))
1448                         or else
1449                       (not Length_Checks_Suppressed (Target_Typ));
1450
1451    begin
1452       if not Expander_Active then
1453          return;
1454       end if;
1455
1456       R_Result :=
1457         Selected_Length_Checks (Ck_Node, Target_Typ, Source_Typ, Empty);
1458
1459       for J in 1 .. 2 loop
1460
1461          R_Cno := R_Result (J);
1462          exit when No (R_Cno);
1463
1464          --  A length check may mention an Itype which is attached to a
1465          --  subsequent node. At the top level in a package this can cause
1466          --  an order-of-elaboration problem, so we make sure that the itype
1467          --  is referenced now.
1468
1469          if Ekind (Current_Scope) = E_Package
1470            and then Is_Compilation_Unit (Current_Scope)
1471          then
1472             Ensure_Defined (Target_Typ, Ck_Node);
1473
1474             if Present (Source_Typ) then
1475                Ensure_Defined (Source_Typ, Ck_Node);
1476
1477             elsif Is_Itype (Etype (Ck_Node)) then
1478                Ensure_Defined (Etype (Ck_Node), Ck_Node);
1479             end if;
1480          end if;
1481
1482          --  If the item is a conditional raise of constraint error,
1483          --  then have a look at what check is being performed and
1484          --  ???
1485
1486          if Nkind (R_Cno) = N_Raise_Constraint_Error
1487            and then Present (Condition (R_Cno))
1488          then
1489             Cond := Condition (R_Cno);
1490
1491             if not Has_Dynamic_Length_Check (Ck_Node)
1492               and then Checks_On
1493             then
1494                Insert_Action (Ck_Node, R_Cno);
1495
1496                if not Do_Static then
1497                   Set_Has_Dynamic_Length_Check (Ck_Node);
1498                end if;
1499             end if;
1500
1501             --  Output a warning if the condition is known to be True
1502
1503             if Is_Entity_Name (Cond)
1504               and then Entity (Cond) = Standard_True
1505             then
1506                Apply_Compile_Time_Constraint_Error
1507                  (Ck_Node, "wrong length for array of}?",
1508                   CE_Length_Check_Failed,
1509                   Ent => Target_Typ,
1510                   Typ => Target_Typ);
1511
1512             --  If we were only doing a static check, or if checks are not
1513             --  on, then we want to delete the check, since it is not needed.
1514             --  We do this by replacing the if statement by a null statement
1515
1516             elsif Do_Static or else not Checks_On then
1517                Rewrite (R_Cno, Make_Null_Statement (Loc));
1518             end if;
1519
1520          else
1521             Install_Static_Check (R_Cno, Loc);
1522          end if;
1523
1524       end loop;
1525
1526    end Apply_Selected_Length_Checks;
1527
1528    ---------------------------------
1529    -- Apply_Selected_Range_Checks --
1530    ---------------------------------
1531
1532    procedure Apply_Selected_Range_Checks
1533      (Ck_Node    : Node_Id;
1534       Target_Typ : Entity_Id;
1535       Source_Typ : Entity_Id;
1536       Do_Static  : Boolean)
1537    is
1538       Cond     : Node_Id;
1539       R_Result : Check_Result;
1540       R_Cno    : Node_Id;
1541
1542       Loc       : constant Source_Ptr := Sloc (Ck_Node);
1543       Checks_On : constant Boolean :=
1544                     (not Index_Checks_Suppressed (Target_Typ))
1545                       or else
1546                     (not Range_Checks_Suppressed (Target_Typ));
1547
1548    begin
1549       if not Expander_Active or else not Checks_On then
1550          return;
1551       end if;
1552
1553       R_Result :=
1554         Selected_Range_Checks (Ck_Node, Target_Typ, Source_Typ, Empty);
1555
1556       for J in 1 .. 2 loop
1557
1558          R_Cno := R_Result (J);
1559          exit when No (R_Cno);
1560
1561          --  If the item is a conditional raise of constraint error,
1562          --  then have a look at what check is being performed and
1563          --  ???
1564
1565          if Nkind (R_Cno) = N_Raise_Constraint_Error
1566            and then Present (Condition (R_Cno))
1567          then
1568             Cond := Condition (R_Cno);
1569
1570             if not Has_Dynamic_Range_Check (Ck_Node) then
1571                Insert_Action (Ck_Node, R_Cno);
1572
1573                if not Do_Static then
1574                   Set_Has_Dynamic_Range_Check (Ck_Node);
1575                end if;
1576             end if;
1577
1578             --  Output a warning if the condition is known to be True
1579
1580             if Is_Entity_Name (Cond)
1581               and then Entity (Cond) = Standard_True
1582             then
1583                --  Since an N_Range is technically not an expression, we
1584                --  have to set one of the bounds to C_E and then just flag
1585                --  the N_Range. The warning message will point to the
1586                --  lower bound and complain about a range, which seems OK.
1587
1588                if Nkind (Ck_Node) = N_Range then
1589                   Apply_Compile_Time_Constraint_Error
1590                     (Low_Bound (Ck_Node), "static range out of bounds of}?",
1591                      CE_Range_Check_Failed,
1592                      Ent => Target_Typ,
1593                      Typ => Target_Typ);
1594
1595                   Set_Raises_Constraint_Error (Ck_Node);
1596
1597                else
1598                   Apply_Compile_Time_Constraint_Error
1599                     (Ck_Node, "static value out of range of}?",
1600                      CE_Range_Check_Failed,
1601                      Ent => Target_Typ,
1602                      Typ => Target_Typ);
1603                end if;
1604
1605             --  If we were only doing a static check, or if checks are not
1606             --  on, then we want to delete the check, since it is not needed.
1607             --  We do this by replacing the if statement by a null statement
1608
1609             elsif Do_Static or else not Checks_On then
1610                Rewrite (R_Cno, Make_Null_Statement (Loc));
1611             end if;
1612
1613          else
1614             Install_Static_Check (R_Cno, Loc);
1615          end if;
1616
1617       end loop;
1618
1619    end Apply_Selected_Range_Checks;
1620
1621    -------------------------------
1622    -- Apply_Static_Length_Check --
1623    -------------------------------
1624
1625    procedure Apply_Static_Length_Check
1626      (Expr       : Node_Id;
1627       Target_Typ : Entity_Id;
1628       Source_Typ : Entity_Id := Empty)
1629    is
1630    begin
1631       Apply_Selected_Length_Checks
1632         (Expr, Target_Typ, Source_Typ, Do_Static => True);
1633    end Apply_Static_Length_Check;
1634
1635    -------------------------------------
1636    -- Apply_Subscript_Validity_Checks --
1637    -------------------------------------
1638
1639    procedure Apply_Subscript_Validity_Checks (Expr : Node_Id) is
1640       Sub : Node_Id;
1641
1642    begin
1643       pragma Assert (Nkind (Expr) = N_Indexed_Component);
1644
1645       --  Loop through subscripts
1646
1647       Sub := First (Expressions (Expr));
1648       while Present (Sub) loop
1649
1650          --  Check one subscript. Note that we do not worry about
1651          --  enumeration type with holes, since we will convert the
1652          --  value to a Pos value for the subscript, and that convert
1653          --  will do the necessary validity check.
1654
1655          Ensure_Valid (Sub, Holes_OK => True);
1656
1657          --  Move to next subscript
1658
1659          Sub := Next (Sub);
1660       end loop;
1661    end Apply_Subscript_Validity_Checks;
1662
1663    ----------------------------------
1664    -- Apply_Type_Conversion_Checks --
1665    ----------------------------------
1666
1667    procedure Apply_Type_Conversion_Checks (N : Node_Id) is
1668       Target_Type : constant Entity_Id := Etype (N);
1669       Target_Base : constant Entity_Id := Base_Type (Target_Type);
1670
1671       Expr      : constant Node_Id   := Expression (N);
1672       Expr_Type : constant Entity_Id := Etype (Expr);
1673
1674    begin
1675       if Inside_A_Generic then
1676          return;
1677
1678       --  Skip these checks if serious errors detected, there are some nasty
1679       --  situations of incomplete trees that blow things up.
1680
1681       elsif Serious_Errors_Detected > 0 then
1682          return;
1683
1684       --  Scalar type conversions of the form Target_Type (Expr) require
1685       --  two checks:
1686       --
1687       --    - First there is an overflow check to insure that Expr is
1688       --      in the base type of Target_Typ (4.6 (28)),
1689       --
1690       --    - After we know Expr fits into the base type, we must perform a
1691       --      range check to ensure that Expr meets the constraints of the
1692       --      Target_Type.
1693
1694       elsif Is_Scalar_Type (Target_Type) then
1695          declare
1696             Conv_OK  : constant Boolean := Conversion_OK (N);
1697             --  If the Conversion_OK flag on the type conversion is set
1698             --  and no floating point type is involved in the type conversion
1699             --  then fixed point values must be read as integral values.
1700
1701          begin
1702             --  Overflow check.
1703
1704             if not Overflow_Checks_Suppressed (Target_Base)
1705               and then not In_Subrange_Of (Expr_Type, Target_Base, Conv_OK)
1706             then
1707                Set_Do_Overflow_Check (N);
1708             end if;
1709
1710             if not Range_Checks_Suppressed (Target_Type)
1711               and then not Range_Checks_Suppressed (Expr_Type)
1712             then
1713                Apply_Scalar_Range_Check
1714                  (Expr, Target_Type, Fixed_Int => Conv_OK);
1715             end if;
1716          end;
1717
1718       elsif Comes_From_Source (N)
1719         and then Is_Record_Type (Target_Type)
1720         and then Is_Derived_Type (Target_Type)
1721         and then not Is_Tagged_Type (Target_Type)
1722         and then not Is_Constrained (Target_Type)
1723         and then Present (Girder_Constraint (Target_Type))
1724       then
1725          --  A unconstrained derived type may have inherited discriminants.
1726          --  Build an actual discriminant constraint list using the girder
1727          --  constraint, to verify that the expression of the parent type
1728          --  satisfies the constraints imposed by the (unconstrained!)
1729          --  derived type. This applies to value conversions, not to view
1730          --  conversions of tagged types.
1731
1732          declare
1733             Loc             : constant Source_Ptr := Sloc (N);
1734             Cond            : Node_Id;
1735             Constraint      : Elmt_Id;
1736             Discr_Value     : Node_Id;
1737             Discr           : Entity_Id;
1738             New_Constraints : Elist_Id := New_Elmt_List;
1739             Old_Constraints : Elist_Id := Discriminant_Constraint (Expr_Type);
1740
1741          begin
1742             Constraint := First_Elmt (Girder_Constraint (Target_Type));
1743
1744             while Present (Constraint) loop
1745                Discr_Value := Node (Constraint);
1746
1747                if Is_Entity_Name (Discr_Value)
1748                  and then Ekind (Entity (Discr_Value)) = E_Discriminant
1749                then
1750                   Discr := Corresponding_Discriminant (Entity (Discr_Value));
1751
1752                   if Present (Discr)
1753                     and then Scope (Discr) = Base_Type (Expr_Type)
1754                   then
1755                      --  Parent is constrained by new discriminant. Obtain
1756                      --  Value of original discriminant in expression. If
1757                      --  the new discriminant has been used to constrain more
1758                      --  than one of the girder ones, this will provide the
1759                      --  required consistency check.
1760
1761                      Append_Elmt (
1762                         Make_Selected_Component (Loc,
1763                           Prefix =>
1764                             Duplicate_Subexpr (Expr, Name_Req => True),
1765                           Selector_Name =>
1766                             Make_Identifier (Loc, Chars (Discr))),
1767                                 New_Constraints);
1768
1769                   else
1770                      --  Discriminant of more remote ancestor ???
1771
1772                      return;
1773                   end if;
1774
1775                --  Derived type definition has an explicit value for
1776                --  this girder discriminant.
1777
1778                else
1779                   Append_Elmt
1780                     (Duplicate_Subexpr (Discr_Value), New_Constraints);
1781                end if;
1782
1783                Next_Elmt (Constraint);
1784             end loop;
1785
1786             --  Use the unconstrained expression type to retrieve the
1787             --  discriminants of the parent, and apply momentarily the
1788             --  discriminant constraint synthesized above.
1789
1790             Set_Discriminant_Constraint (Expr_Type, New_Constraints);
1791             Cond := Build_Discriminant_Checks (Expr, Expr_Type);
1792             Set_Discriminant_Constraint (Expr_Type, Old_Constraints);
1793
1794             Insert_Action (N,
1795               Make_Raise_Constraint_Error (Loc,
1796                 Condition => Cond,
1797                 Reason    => CE_Discriminant_Check_Failed));
1798          end;
1799
1800       --  should there be other checks here for array types ???
1801
1802       else
1803          null;
1804       end if;
1805
1806    end Apply_Type_Conversion_Checks;
1807
1808    ----------------------------------------------
1809    -- Apply_Universal_Integer_Attribute_Checks --
1810    ----------------------------------------------
1811
1812    procedure Apply_Universal_Integer_Attribute_Checks (N : Node_Id) is
1813       Loc : constant Source_Ptr := Sloc (N);
1814       Typ : constant Entity_Id  := Etype (N);
1815
1816    begin
1817       if Inside_A_Generic then
1818          return;
1819
1820       --  Nothing to do if checks are suppressed
1821
1822       elsif Range_Checks_Suppressed (Typ)
1823         and then Overflow_Checks_Suppressed (Typ)
1824       then
1825          return;
1826
1827       --  Nothing to do if the attribute does not come from source. The
1828       --  internal attributes we generate of this type do not need checks,
1829       --  and furthermore the attempt to check them causes some circular
1830       --  elaboration orders when dealing with packed types.
1831
1832       elsif not Comes_From_Source (N) then
1833          return;
1834
1835       --  Otherwise, replace the attribute node with a type conversion
1836       --  node whose expression is the attribute, retyped to universal
1837       --  integer, and whose subtype mark is the target type. The call
1838       --  to analyze this conversion will set range and overflow checks
1839       --  as required for proper detection of an out of range value.
1840
1841       else
1842          Set_Etype    (N, Universal_Integer);
1843          Set_Analyzed (N, True);
1844
1845          Rewrite (N,
1846            Make_Type_Conversion (Loc,
1847              Subtype_Mark => New_Occurrence_Of (Typ, Loc),
1848              Expression   => Relocate_Node (N)));
1849
1850          Analyze_And_Resolve (N, Typ);
1851          return;
1852       end if;
1853
1854    end Apply_Universal_Integer_Attribute_Checks;
1855
1856    -------------------------------
1857    -- Build_Discriminant_Checks --
1858    -------------------------------
1859
1860    function Build_Discriminant_Checks
1861      (N     : Node_Id;
1862       T_Typ : Entity_Id)
1863       return Node_Id
1864    is
1865       Loc      : constant Source_Ptr := Sloc (N);
1866       Cond     : Node_Id;
1867       Disc     : Elmt_Id;
1868       Disc_Ent : Entity_Id;
1869       Dval     : Node_Id;
1870
1871    begin
1872       Cond := Empty;
1873       Disc := First_Elmt (Discriminant_Constraint (T_Typ));
1874
1875       --  For a fully private type, use the discriminants of the parent
1876       --  type.
1877
1878       if Is_Private_Type (T_Typ)
1879         and then No (Full_View (T_Typ))
1880       then
1881          Disc_Ent := First_Discriminant (Etype (Base_Type (T_Typ)));
1882       else
1883          Disc_Ent := First_Discriminant (T_Typ);
1884       end if;
1885
1886       while Present (Disc) loop
1887
1888          Dval := Node (Disc);
1889
1890          if Nkind (Dval) = N_Identifier
1891            and then Ekind (Entity (Dval)) = E_Discriminant
1892          then
1893             Dval := New_Occurrence_Of (Discriminal (Entity (Dval)), Loc);
1894          else
1895             Dval := Duplicate_Subexpr (Dval);
1896          end if;
1897
1898          Evolve_Or_Else (Cond,
1899            Make_Op_Ne (Loc,
1900              Left_Opnd =>
1901                Make_Selected_Component (Loc,
1902                  Prefix =>
1903                    Duplicate_Subexpr (N, Name_Req => True),
1904                  Selector_Name =>
1905                    Make_Identifier (Loc, Chars (Disc_Ent))),
1906              Right_Opnd => Dval));
1907
1908          Next_Elmt (Disc);
1909          Next_Discriminant (Disc_Ent);
1910       end loop;
1911
1912       return Cond;
1913    end Build_Discriminant_Checks;
1914
1915    -----------------------------------
1916    -- Check_Valid_Lvalue_Subscripts --
1917    -----------------------------------
1918
1919    procedure Check_Valid_Lvalue_Subscripts (Expr : Node_Id) is
1920    begin
1921       --  Skip this if range checks are suppressed
1922
1923       if Range_Checks_Suppressed (Etype (Expr)) then
1924          return;
1925
1926       --  Only do this check for expressions that come from source. We
1927       --  assume that expander generated assignments explicitly include
1928       --  any necessary checks. Note that this is not just an optimization,
1929       --  it avoids infinite recursions!
1930
1931       elsif not Comes_From_Source (Expr) then
1932          return;
1933
1934       --  For a selected component, check the prefix
1935
1936       elsif Nkind (Expr) = N_Selected_Component then
1937          Check_Valid_Lvalue_Subscripts (Prefix (Expr));
1938          return;
1939
1940       --  Case of indexed component
1941
1942       elsif Nkind (Expr) = N_Indexed_Component then
1943          Apply_Subscript_Validity_Checks (Expr);
1944
1945          --  Prefix may itself be or contain an indexed component, and
1946          --  these subscripts need checking as well
1947
1948          Check_Valid_Lvalue_Subscripts (Prefix (Expr));
1949       end if;
1950    end Check_Valid_Lvalue_Subscripts;
1951
1952    ---------------------
1953    -- Determine_Range --
1954    ---------------------
1955
1956    Cache_Size : constant := 2 ** 10;
1957    type Cache_Index is range 0 .. Cache_Size - 1;
1958    --  Determine size of below cache (power of 2 is more efficient!)
1959
1960    Determine_Range_Cache_N  : array (Cache_Index) of Node_Id;
1961    Determine_Range_Cache_Lo : array (Cache_Index) of Uint;
1962    Determine_Range_Cache_Hi : array (Cache_Index) of Uint;
1963    --  The above arrays are used to implement a small direct cache
1964    --  for Determine_Range calls. Because of the way Determine_Range
1965    --  recursively traces subexpressions, and because overflow checking
1966    --  calls the routine on the way up the tree, a quadratic behavior
1967    --  can otherwise be encountered in large expressions. The cache
1968    --  entry for node N is stored in the (N mod Cache_Size) entry, and
1969    --  can be validated by checking the actual node value stored there.
1970
1971    procedure Determine_Range
1972      (N  : Node_Id;
1973       OK : out Boolean;
1974       Lo : out Uint;
1975       Hi : out Uint)
1976    is
1977       Typ : constant Entity_Id := Etype (N);
1978
1979       Lo_Left : Uint;
1980       Hi_Left : Uint;
1981       --  Lo and Hi bounds of left operand
1982
1983       Lo_Right : Uint;
1984       Hi_Right : Uint;
1985       --  Lo and Hi bounds of right (or only) operand
1986
1987       Bound : Node_Id;
1988       --  Temp variable used to hold a bound node
1989
1990       Hbound : Uint;
1991       --  High bound of base type of expression
1992
1993       Lor : Uint;
1994       Hir : Uint;
1995       --  Refined values for low and high bounds, after tightening
1996
1997       OK1 : Boolean;
1998       --  Used in lower level calls to indicate if call succeeded
1999
2000       Cindex : Cache_Index;
2001       --  Used to search cache
2002
2003       function OK_Operands return Boolean;
2004       --  Used for binary operators. Determines the ranges of the left and
2005       --  right operands, and if they are both OK, returns True, and puts
2006       --  the results in Lo_Right, Hi_Right, Lo_Left, Hi_Left
2007
2008       -----------------
2009       -- OK_Operands --
2010       -----------------
2011
2012       function OK_Operands return Boolean is
2013       begin
2014          Determine_Range (Left_Opnd  (N), OK1, Lo_Left,  Hi_Left);
2015
2016          if not OK1 then
2017             return False;
2018          end if;
2019
2020          Determine_Range (Right_Opnd (N), OK1, Lo_Right, Hi_Right);
2021          return OK1;
2022       end OK_Operands;
2023
2024    --  Start of processing for Determine_Range
2025
2026    begin
2027       --  Prevent junk warnings by initializing range variables
2028
2029       Lo  := No_Uint;
2030       Hi  := No_Uint;
2031       Lor := No_Uint;
2032       Hir := No_Uint;
2033
2034       --  If the type is not discrete, or is undefined, then we can't
2035       --  do anything about determining the range.
2036
2037       if No (Typ) or else not Is_Discrete_Type (Typ)
2038         or else Error_Posted (N)
2039       then
2040          OK := False;
2041          return;
2042       end if;
2043
2044       --  For all other cases, we can determine the range
2045
2046       OK := True;
2047
2048       --  If value is compile time known, then the possible range is the
2049       --  one value that we know this expression definitely has!
2050
2051       if Compile_Time_Known_Value (N) then
2052          Lo := Expr_Value (N);
2053          Hi := Lo;
2054          return;
2055       end if;
2056
2057       --  Return if already in the cache
2058
2059       Cindex := Cache_Index (N mod Cache_Size);
2060
2061       if Determine_Range_Cache_N (Cindex) = N then
2062          Lo := Determine_Range_Cache_Lo (Cindex);
2063          Hi := Determine_Range_Cache_Hi (Cindex);
2064          return;
2065       end if;
2066
2067       --  Otherwise, start by finding the bounds of the type of the
2068       --  expression, the value cannot be outside this range (if it
2069       --  is, then we have an overflow situation, which is a separate
2070       --  check, we are talking here only about the expression value).
2071
2072       --  We use the actual bound unless it is dynamic, in which case
2073       --  use the corresponding base type bound if possible. If we can't
2074       --  get a bound then we figure we can't determine the range (a
2075       --  peculiar case, that perhaps cannot happen, but there is no
2076       --  point in bombing in this optimization circuit.
2077
2078       --  First the low bound
2079
2080       Bound := Type_Low_Bound (Typ);
2081
2082       if Compile_Time_Known_Value (Bound) then
2083          Lo := Expr_Value (Bound);
2084
2085       elsif Compile_Time_Known_Value (Type_Low_Bound (Base_Type (Typ))) then
2086          Lo := Expr_Value (Type_Low_Bound (Base_Type (Typ)));
2087
2088       else
2089          OK := False;
2090          return;
2091       end if;
2092
2093       --  Now the high bound
2094
2095       Bound := Type_High_Bound (Typ);
2096
2097       --  We need the high bound of the base type later on, and this should
2098       --  always be compile time known. Again, it is not clear that this
2099       --  can ever be false, but no point in bombing.
2100
2101       if Compile_Time_Known_Value (Type_High_Bound (Base_Type (Typ))) then
2102          Hbound := Expr_Value (Type_High_Bound (Base_Type (Typ)));
2103          Hi := Hbound;
2104
2105       else
2106          OK := False;
2107          return;
2108       end if;
2109
2110       --  If we have a static subtype, then that may have a tighter bound
2111       --  so use the upper bound of the subtype instead in this case.
2112
2113       if Compile_Time_Known_Value (Bound) then
2114          Hi := Expr_Value (Bound);
2115       end if;
2116
2117       --  We may be able to refine this value in certain situations. If
2118       --  refinement is possible, then Lor and Hir are set to possibly
2119       --  tighter bounds, and OK1 is set to True.
2120
2121       case Nkind (N) is
2122
2123          --  For unary plus, result is limited by range of operand
2124
2125          when N_Op_Plus =>
2126             Determine_Range (Right_Opnd (N), OK1, Lor, Hir);
2127
2128          --  For unary minus, determine range of operand, and negate it
2129
2130          when N_Op_Minus =>
2131             Determine_Range (Right_Opnd (N), OK1, Lo_Right, Hi_Right);
2132
2133             if OK1 then
2134                Lor := -Hi_Right;
2135                Hir := -Lo_Right;
2136             end if;
2137
2138          --  For binary addition, get range of each operand and do the
2139          --  addition to get the result range.
2140
2141          when N_Op_Add =>
2142             if OK_Operands then
2143                Lor := Lo_Left + Lo_Right;
2144                Hir := Hi_Left + Hi_Right;
2145             end if;
2146
2147          --  Division is tricky. The only case we consider is where the
2148          --  right operand is a positive constant, and in this case we
2149          --  simply divide the bounds of the left operand
2150
2151          when N_Op_Divide =>
2152             if OK_Operands then
2153                if Lo_Right = Hi_Right
2154                  and then Lo_Right > 0
2155                then
2156                   Lor := Lo_Left / Lo_Right;
2157                   Hir := Hi_Left / Lo_Right;
2158
2159                else
2160                   OK1 := False;
2161                end if;
2162             end if;
2163
2164          --  For binary subtraction, get range of each operand and do
2165          --  the worst case subtraction to get the result range.
2166
2167          when N_Op_Subtract =>
2168             if OK_Operands then
2169                Lor := Lo_Left - Hi_Right;
2170                Hir := Hi_Left - Lo_Right;
2171             end if;
2172
2173          --  For MOD, if right operand is a positive constant, then
2174          --  result must be in the allowable range of mod results.
2175
2176          when N_Op_Mod =>
2177             if OK_Operands then
2178                if Lo_Right = Hi_Right then
2179                   if Lo_Right > 0 then
2180                      Lor := Uint_0;
2181                      Hir := Lo_Right - 1;
2182
2183                   elsif Lo_Right < 0 then
2184                      Lor := Lo_Right + 1;
2185                      Hir := Uint_0;
2186                   end if;
2187
2188                else
2189                   OK1 := False;
2190                end if;
2191             end if;
2192
2193          --  For REM, if right operand is a positive constant, then
2194          --  result must be in the allowable range of mod results.
2195
2196          when N_Op_Rem =>
2197             if OK_Operands then
2198                if Lo_Right = Hi_Right then
2199                   declare
2200                      Dval : constant Uint := (abs Lo_Right) - 1;
2201
2202                   begin
2203                      --  The sign of the result depends on the sign of the
2204                      --  dividend (but not on the sign of the divisor, hence
2205                      --  the abs operation above).
2206
2207                      if Lo_Left < 0 then
2208                         Lor := -Dval;
2209                      else
2210                         Lor := Uint_0;
2211                      end if;
2212
2213                      if Hi_Left < 0 then
2214                         Hir := Uint_0;
2215                      else
2216                         Hir := Dval;
2217                      end if;
2218                   end;
2219
2220                else
2221                   OK1 := False;
2222                end if;
2223             end if;
2224
2225          --  Attribute reference cases
2226
2227          when N_Attribute_Reference =>
2228             case Attribute_Name (N) is
2229
2230                --  For Pos/Val attributes, we can refine the range using the
2231                --  possible range of values of the attribute expression
2232
2233                when Name_Pos | Name_Val =>
2234                   Determine_Range (First (Expressions (N)), OK1, Lor, Hir);
2235
2236                --  For Length attribute, use the bounds of the corresponding
2237                --  index type to refine the range.
2238
2239                when Name_Length =>
2240                   declare
2241                      Atyp : Entity_Id := Etype (Prefix (N));
2242                      Inum : Nat;
2243                      Indx : Node_Id;
2244
2245                      LL, LU : Uint;
2246                      UL, UU : Uint;
2247
2248                   begin
2249                      if Is_Access_Type (Atyp) then
2250                         Atyp := Designated_Type (Atyp);
2251                      end if;
2252
2253                      --  For string literal, we know exact value
2254
2255                      if Ekind (Atyp) = E_String_Literal_Subtype then
2256                         OK := True;
2257                         Lo := String_Literal_Length (Atyp);
2258                         Hi := String_Literal_Length (Atyp);
2259                         return;
2260                      end if;
2261
2262                      --  Otherwise check for expression given
2263
2264                      if No (Expressions (N)) then
2265                         Inum := 1;
2266                      else
2267                         Inum :=
2268                           UI_To_Int (Expr_Value (First (Expressions (N))));
2269                      end if;
2270
2271                      Indx := First_Index (Atyp);
2272                      for J in 2 .. Inum loop
2273                         Indx := Next_Index (Indx);
2274                      end loop;
2275
2276                      Determine_Range
2277                        (Type_Low_Bound (Etype (Indx)), OK1, LL, LU);
2278
2279                      if OK1 then
2280                         Determine_Range
2281                           (Type_High_Bound (Etype (Indx)), OK1, UL, UU);
2282
2283                         if OK1 then
2284
2285                            --  The maximum value for Length is the biggest
2286                            --  possible gap between the values of the bounds.
2287                            --  But of course, this value cannot be negative.
2288
2289                            Hir := UI_Max (Uint_0, UU - LL);
2290
2291                            --  For constrained arrays, the minimum value for
2292                            --  Length is taken from the actual value of the
2293                            --  bounds, since the index will be exactly of
2294                            --  this subtype.
2295
2296                            if Is_Constrained (Atyp) then
2297                               Lor := UI_Max (Uint_0, UL - LU);
2298
2299                            --  For an unconstrained array, the minimum value
2300                            --  for length is always zero.
2301
2302                            else
2303                               Lor := Uint_0;
2304                            end if;
2305                         end if;
2306                      end if;
2307                   end;
2308
2309                --  No special handling for other attributes
2310                --  Probably more opportunities exist here ???
2311
2312                when others =>
2313                   OK1 := False;
2314
2315             end case;
2316
2317          --  For type conversion from one discrete type to another, we
2318          --  can refine the range using the converted value.
2319
2320          when N_Type_Conversion =>
2321             Determine_Range (Expression (N), OK1, Lor, Hir);
2322
2323          --  Nothing special to do for all other expression kinds
2324
2325          when others =>
2326             OK1 := False;
2327             Lor := No_Uint;
2328             Hir := No_Uint;
2329       end case;
2330
2331       --  At this stage, if OK1 is true, then we know that the actual
2332       --  result of the computed expression is in the range Lor .. Hir.
2333       --  We can use this to restrict the possible range of results.
2334
2335       if OK1 then
2336
2337          --  If the refined value of the low bound is greater than the
2338          --  type high bound, then reset it to the more restrictive
2339          --  value. However, we do NOT do this for the case of a modular
2340          --  type where the possible upper bound on the value is above the
2341          --  base type high bound, because that means the result could wrap.
2342
2343          if Lor > Lo
2344            and then not (Is_Modular_Integer_Type (Typ)
2345                            and then Hir > Hbound)
2346          then
2347             Lo := Lor;
2348          end if;
2349
2350          --  Similarly, if the refined value of the high bound is less
2351          --  than the value so far, then reset it to the more restrictive
2352          --  value. Again, we do not do this if the refined low bound is
2353          --  negative for a modular type, since this would wrap.
2354
2355          if Hir < Hi
2356            and then not (Is_Modular_Integer_Type (Typ)
2357                           and then Lor < Uint_0)
2358          then
2359             Hi := Hir;
2360          end if;
2361       end if;
2362
2363       --  Set cache entry for future call and we are all done
2364
2365       Determine_Range_Cache_N  (Cindex) := N;
2366       Determine_Range_Cache_Lo (Cindex) := Lo;
2367       Determine_Range_Cache_Hi (Cindex) := Hi;
2368       return;
2369
2370    --  If any exception occurs, it means that we have some bug in the compiler
2371    --  possibly triggered by a previous error, or by some unforseen peculiar
2372    --  occurrence. However, this is only an optimization attempt, so there is
2373    --  really no point in crashing the compiler. Instead we just decide, too
2374    --  bad, we can't figure out a range in this case after all.
2375
2376    exception
2377       when others =>
2378
2379          --  Debug flag K disables this behavior (useful for debugging)
2380
2381          if Debug_Flag_K then
2382             raise;
2383          else
2384             OK := False;
2385             Lo := No_Uint;
2386             Hi := No_Uint;
2387             return;
2388          end if;
2389
2390    end Determine_Range;
2391
2392    ------------------------------------
2393    -- Discriminant_Checks_Suppressed --
2394    ------------------------------------
2395
2396    function Discriminant_Checks_Suppressed (E : Entity_Id) return Boolean is
2397    begin
2398       return Scope_Suppress.Discriminant_Checks
2399         or else (Present (E) and then Suppress_Discriminant_Checks (E));
2400    end Discriminant_Checks_Suppressed;
2401
2402    --------------------------------
2403    -- Division_Checks_Suppressed --
2404    --------------------------------
2405
2406    function Division_Checks_Suppressed (E : Entity_Id) return Boolean is
2407    begin
2408       return Scope_Suppress.Division_Checks
2409         or else (Present (E) and then Suppress_Division_Checks (E));
2410    end Division_Checks_Suppressed;
2411
2412    -----------------------------------
2413    -- Elaboration_Checks_Suppressed --
2414    -----------------------------------
2415
2416    function Elaboration_Checks_Suppressed (E : Entity_Id) return Boolean is
2417    begin
2418       return Scope_Suppress.Elaboration_Checks
2419         or else (Present (E) and then Suppress_Elaboration_Checks (E));
2420    end Elaboration_Checks_Suppressed;
2421
2422    ------------------------
2423    -- Enable_Range_Check --
2424    ------------------------
2425
2426    procedure Enable_Range_Check (N : Node_Id) is
2427    begin
2428       if Nkind (N) = N_Unchecked_Type_Conversion
2429         and then Kill_Range_Check (N)
2430       then
2431          return;
2432       else
2433          Set_Do_Range_Check (N, True);
2434       end if;
2435    end Enable_Range_Check;
2436
2437    ------------------
2438    -- Ensure_Valid --
2439    ------------------
2440
2441    procedure Ensure_Valid (Expr : Node_Id; Holes_OK : Boolean := False) is
2442       Typ : constant Entity_Id  := Etype (Expr);
2443
2444    begin
2445       --  Ignore call if we are not doing any validity checking
2446
2447       if not Validity_Checks_On then
2448          return;
2449
2450       --  No check required if expression is from the expander, we assume
2451       --  the expander will generate whatever checks are needed. Note that
2452       --  this is not just an optimization, it avoids infinite recursions!
2453
2454       --  Unchecked conversions must be checked, unless they are initialized
2455       --  scalar values, as in a component assignment in an init_proc.
2456
2457       elsif not Comes_From_Source (Expr)
2458         and then (Nkind (Expr) /= N_Unchecked_Type_Conversion
2459                     or else Kill_Range_Check (Expr))
2460       then
2461          return;
2462
2463       --  No check required if expression is known to have valid value
2464
2465       elsif Expr_Known_Valid (Expr) then
2466          return;
2467
2468       --  No check required if checks off
2469
2470       elsif Range_Checks_Suppressed (Typ) then
2471          return;
2472
2473       --  Ignore case of enumeration with holes where the flag is set not
2474       --  to worry about holes, since no special validity check is needed
2475
2476       elsif Is_Enumeration_Type (Typ)
2477         and then Has_Non_Standard_Rep (Typ)
2478         and then Holes_OK
2479       then
2480          return;
2481
2482       --  No check required on the left-hand side of an assignment.
2483
2484       elsif Nkind (Parent (Expr)) = N_Assignment_Statement
2485         and then Expr = Name (Parent (Expr))
2486       then
2487          return;
2488
2489       --  An annoying special case. If this is an out parameter of a scalar
2490       --  type, then the value is not going to be accessed, therefore it is
2491       --  inappropriate to do any validity check at the call site.
2492
2493       else
2494          --  Only need to worry about scalar types
2495
2496          if Is_Scalar_Type (Typ) then
2497             declare
2498                P : Node_Id;
2499                N : Node_Id;
2500                E : Entity_Id;
2501                F : Entity_Id;
2502                A : Node_Id;
2503                L : List_Id;
2504
2505             begin
2506                --  Find actual argument (which may be a parameter association)
2507                --  and the parent of the actual argument (the call statement)
2508
2509                N := Expr;
2510                P := Parent (Expr);
2511
2512                if Nkind (P) = N_Parameter_Association then
2513                   N := P;
2514                   P := Parent (N);
2515                end if;
2516
2517                --  Only need to worry if we are argument of a procedure
2518                --  call since functions don't have out parameters.
2519
2520                if Nkind (P) = N_Procedure_Call_Statement then
2521                   L := Parameter_Associations (P);
2522                   E := Entity (Name (P));
2523
2524                   --  Only need to worry if there are indeed actuals, and
2525                   --  if this could be a procedure call, otherwise we cannot
2526                   --  get a match (either we are not an argument, or the
2527                   --  mode of the formal is not OUT). This test also filters
2528                   --  out the generic case.
2529
2530                   if Is_Non_Empty_List (L)
2531                     and then Is_Subprogram (E)
2532                   then
2533                      --  This is the loop through parameters, looking to
2534                      --  see if there is an OUT parameter for which we are
2535                      --  the argument.
2536
2537                      F := First_Formal (E);
2538                      A := First (L);
2539
2540                      while Present (F) loop
2541                         if Ekind (F) = E_Out_Parameter and then A = N then
2542                            return;
2543                         end if;
2544
2545                         Next_Formal (F);
2546                         Next (A);
2547                      end loop;
2548                   end if;
2549                end if;
2550             end;
2551          end if;
2552       end if;
2553
2554       --  If we fall through, a validity check is required. Note that it would
2555       --  not be good to set Do_Range_Check, even in contexts where this is
2556       --  permissible, since this flag causes checking against the target type,
2557       --  not the source type in contexts such as assignments
2558
2559       Insert_Valid_Check (Expr);
2560    end Ensure_Valid;
2561
2562    ----------------------
2563    -- Expr_Known_Valid --
2564    ----------------------
2565
2566    function Expr_Known_Valid (Expr : Node_Id) return Boolean is
2567       Typ : constant Entity_Id := Etype (Expr);
2568
2569    begin
2570       --  Non-scalar types are always consdered valid, since they never
2571       --  give rise to the issues of erroneous or bounded error behavior
2572       --  that are the concern. In formal reference manual terms the
2573       --  notion of validity only applies to scalar types.
2574
2575       if not Is_Scalar_Type (Typ) then
2576          return True;
2577
2578       --  If no validity checking, then everything is considered valid
2579
2580       elsif not Validity_Checks_On then
2581          return True;
2582
2583       --  Floating-point types are considered valid unless floating-point
2584       --  validity checks have been specifically turned on.
2585
2586       elsif Is_Floating_Point_Type (Typ)
2587         and then not Validity_Check_Floating_Point
2588       then
2589          return True;
2590
2591       --  If the expression is the value of an object that is known to
2592       --  be valid, then clearly the expression value itself is valid.
2593
2594       elsif Is_Entity_Name (Expr)
2595         and then Is_Known_Valid (Entity (Expr))
2596       then
2597          return True;
2598
2599       --  If the type is one for which all values are known valid, then
2600       --  we are sure that the value is valid except in the slightly odd
2601       --  case where the expression is a reference to a variable whose size
2602       --  has been explicitly set to a value greater than the object size.
2603
2604       elsif Is_Known_Valid (Typ) then
2605          if Is_Entity_Name (Expr)
2606            and then Ekind (Entity (Expr)) = E_Variable
2607            and then Esize (Entity (Expr)) > Esize (Typ)
2608          then
2609             return False;
2610          else
2611             return True;
2612          end if;
2613
2614       --  Integer and character literals always have valid values, where
2615       --  appropriate these will be range checked in any case.
2616
2617       elsif Nkind (Expr) = N_Integer_Literal
2618               or else
2619             Nkind (Expr) = N_Character_Literal
2620       then
2621          return True;
2622
2623       --  If we have a type conversion or a qualification of a known valid
2624       --  value, then the result will always be valid.
2625
2626       elsif Nkind (Expr) = N_Type_Conversion
2627               or else
2628             Nkind (Expr) = N_Qualified_Expression
2629       then
2630          return Expr_Known_Valid (Expression (Expr));
2631
2632       --  The result of any function call or operator is always considered
2633       --  valid, since we assume the necessary checks are done by the call.
2634
2635       elsif Nkind (Expr) in N_Binary_Op
2636               or else
2637             Nkind (Expr) in N_Unary_Op
2638               or else
2639             Nkind (Expr) = N_Function_Call
2640       then
2641          return True;
2642
2643       --  For all other cases, we do not know the expression is valid
2644
2645       else
2646          return False;
2647       end if;
2648    end Expr_Known_Valid;
2649
2650    ---------------------
2651    -- Get_Discriminal --
2652    ---------------------
2653
2654    function Get_Discriminal (E : Entity_Id; Bound : Node_Id) return Node_Id is
2655       Loc : constant Source_Ptr := Sloc (E);
2656       D   : Entity_Id;
2657       Sc  : Entity_Id;
2658
2659    begin
2660       --  The entity E is the type of a private component of the protected
2661       --  type, or the type of a renaming of that component within a protected
2662       --  operation of that type.
2663
2664       Sc := Scope (E);
2665
2666       if Ekind (Sc) /= E_Protected_Type then
2667          Sc := Scope (Sc);
2668
2669          if Ekind (Sc) /= E_Protected_Type then
2670             return Bound;
2671          end if;
2672       end if;
2673
2674       D := First_Discriminant (Sc);
2675
2676       while Present (D)
2677         and then Chars (D) /= Chars (Bound)
2678       loop
2679          Next_Discriminant (D);
2680       end loop;
2681
2682       return New_Occurrence_Of (Discriminal (D), Loc);
2683    end Get_Discriminal;
2684
2685    ------------------
2686    -- Guard_Access --
2687    ------------------
2688
2689    function Guard_Access
2690      (Cond    : Node_Id;
2691       Loc     : Source_Ptr;
2692       Ck_Node : Node_Id)
2693       return    Node_Id
2694    is
2695    begin
2696       if Nkind (Cond) = N_Or_Else then
2697          Set_Paren_Count (Cond, 1);
2698       end if;
2699
2700       if Nkind (Ck_Node) = N_Allocator then
2701          return Cond;
2702       else
2703          return
2704            Make_And_Then (Loc,
2705              Left_Opnd =>
2706                Make_Op_Ne (Loc,
2707                  Left_Opnd  => Duplicate_Subexpr (Ck_Node),
2708                  Right_Opnd => Make_Null (Loc)),
2709              Right_Opnd => Cond);
2710       end if;
2711    end Guard_Access;
2712
2713    -----------------------------
2714    -- Index_Checks_Suppressed --
2715    -----------------------------
2716
2717    function Index_Checks_Suppressed (E : Entity_Id) return Boolean is
2718    begin
2719       return Scope_Suppress.Index_Checks
2720         or else (Present (E) and then Suppress_Index_Checks (E));
2721    end Index_Checks_Suppressed;
2722
2723    ----------------
2724    -- Initialize --
2725    ----------------
2726
2727    procedure Initialize is
2728    begin
2729       for J in Determine_Range_Cache_N'Range loop
2730          Determine_Range_Cache_N (J) := Empty;
2731       end loop;
2732    end Initialize;
2733
2734    -------------------------
2735    -- Insert_Range_Checks --
2736    -------------------------
2737
2738    procedure Insert_Range_Checks
2739      (Checks       : Check_Result;
2740       Node         : Node_Id;
2741       Suppress_Typ : Entity_Id;
2742       Static_Sloc  : Source_Ptr := No_Location;
2743       Flag_Node    : Node_Id    := Empty;
2744       Do_Before    : Boolean    := False)
2745    is
2746       Internal_Flag_Node   : Node_Id    := Flag_Node;
2747       Internal_Static_Sloc : Source_Ptr := Static_Sloc;
2748
2749       Check_Node : Node_Id;
2750       Checks_On  : constant Boolean :=
2751                      (not Index_Checks_Suppressed (Suppress_Typ))
2752                        or else
2753                      (not Range_Checks_Suppressed (Suppress_Typ));
2754
2755    begin
2756       --  For now we just return if Checks_On is false, however this should
2757       --  be enhanced to check for an always True value in the condition
2758       --  and to generate a compilation warning???
2759
2760       if not Expander_Active or else not Checks_On then
2761          return;
2762       end if;
2763
2764       if Static_Sloc = No_Location then
2765          Internal_Static_Sloc := Sloc (Node);
2766       end if;
2767
2768       if No (Flag_Node) then
2769          Internal_Flag_Node := Node;
2770       end if;
2771
2772       for J in 1 .. 2 loop
2773          exit when No (Checks (J));
2774
2775          if Nkind (Checks (J)) = N_Raise_Constraint_Error
2776            and then Present (Condition (Checks (J)))
2777          then
2778             if not Has_Dynamic_Range_Check (Internal_Flag_Node) then
2779                Check_Node := Checks (J);
2780                Mark_Rewrite_Insertion (Check_Node);
2781
2782                if Do_Before then
2783                   Insert_Before_And_Analyze (Node, Check_Node);
2784                else
2785                   Insert_After_And_Analyze (Node, Check_Node);
2786                end if;
2787
2788                Set_Has_Dynamic_Range_Check (Internal_Flag_Node);
2789             end if;
2790
2791          else
2792             Check_Node :=
2793               Make_Raise_Constraint_Error (Internal_Static_Sloc,
2794                 Reason => CE_Range_Check_Failed);
2795             Mark_Rewrite_Insertion (Check_Node);
2796
2797             if Do_Before then
2798                Insert_Before_And_Analyze (Node, Check_Node);
2799             else
2800                Insert_After_And_Analyze (Node, Check_Node);
2801             end if;
2802          end if;
2803       end loop;
2804    end Insert_Range_Checks;
2805
2806    ------------------------
2807    -- Insert_Valid_Check --
2808    ------------------------
2809
2810    procedure Insert_Valid_Check (Expr : Node_Id) is
2811       Loc : constant Source_Ptr := Sloc (Expr);
2812       Exp : Node_Id;
2813
2814    begin
2815       --  Do not insert if checks off, or if not checking validity
2816
2817       if Range_Checks_Suppressed (Etype (Expr))
2818         or else (not Validity_Checks_On)
2819       then
2820          return;
2821       end if;
2822
2823       --  If we have a checked conversion, then validity check applies to
2824       --  the expression inside the conversion, not the result, since if
2825       --  the expression inside is valid, then so is the conversion result.
2826
2827       Exp := Expr;
2828       while Nkind (Exp) = N_Type_Conversion loop
2829          Exp := Expression (Exp);
2830       end loop;
2831
2832       --  Insert the validity check. Note that we do this with validity
2833       --  checks turned off, to avoid recursion, we do not want validity
2834       --  checks on the validity checking code itself!
2835
2836       Validity_Checks_On := False;
2837       Insert_Action
2838         (Expr,
2839          Make_Raise_Constraint_Error (Loc,
2840            Condition =>
2841              Make_Op_Not (Loc,
2842                Right_Opnd =>
2843                  Make_Attribute_Reference (Loc,
2844                    Prefix =>
2845                      Duplicate_Subexpr (Exp, Name_Req => True),
2846                    Attribute_Name => Name_Valid)),
2847            Reason => CE_Invalid_Data),
2848          Suppress => All_Checks);
2849       Validity_Checks_On := True;
2850    end Insert_Valid_Check;
2851
2852    --------------------------
2853    -- Install_Static_Check --
2854    --------------------------
2855
2856    procedure Install_Static_Check (R_Cno : Node_Id; Loc : Source_Ptr) is
2857       Stat : constant Boolean   := Is_Static_Expression (R_Cno);
2858       Typ  : constant Entity_Id := Etype (R_Cno);
2859
2860    begin
2861       Rewrite (R_Cno,
2862         Make_Raise_Constraint_Error (Loc,
2863           Reason => CE_Range_Check_Failed));
2864       Set_Analyzed (R_Cno);
2865       Set_Etype (R_Cno, Typ);
2866       Set_Raises_Constraint_Error (R_Cno);
2867       Set_Is_Static_Expression (R_Cno, Stat);
2868    end Install_Static_Check;
2869
2870    ------------------------------
2871    -- Length_Checks_Suppressed --
2872    ------------------------------
2873
2874    function Length_Checks_Suppressed (E : Entity_Id) return Boolean is
2875    begin
2876       return Scope_Suppress.Length_Checks
2877         or else (Present (E) and then Suppress_Length_Checks (E));
2878    end Length_Checks_Suppressed;
2879
2880    --------------------------------
2881    -- Overflow_Checks_Suppressed --
2882    --------------------------------
2883
2884    function Overflow_Checks_Suppressed (E : Entity_Id) return Boolean is
2885    begin
2886       return Scope_Suppress.Overflow_Checks
2887         or else (Present (E) and then Suppress_Overflow_Checks (E));
2888    end Overflow_Checks_Suppressed;
2889
2890    -----------------
2891    -- Range_Check --
2892    -----------------
2893
2894    function Range_Check
2895      (Ck_Node    : Node_Id;
2896       Target_Typ : Entity_Id;
2897       Source_Typ : Entity_Id := Empty;
2898       Warn_Node  : Node_Id   := Empty)
2899       return       Check_Result
2900    is
2901    begin
2902       return Selected_Range_Checks
2903         (Ck_Node, Target_Typ, Source_Typ, Warn_Node);
2904    end Range_Check;
2905
2906    -----------------------------
2907    -- Range_Checks_Suppressed --
2908    -----------------------------
2909
2910    function Range_Checks_Suppressed (E : Entity_Id) return Boolean is
2911    begin
2912       --  Note: for now we always suppress range checks on Vax float types,
2913       --  since Gigi does not know how to generate these checks.
2914
2915       return Scope_Suppress.Range_Checks
2916         or else (Present (E) and then Suppress_Range_Checks (E))
2917         or else Vax_Float (E);
2918    end Range_Checks_Suppressed;
2919
2920    -------------------
2921    -- Remove_Checks --
2922    -------------------
2923
2924    procedure Remove_Checks (Expr : Node_Id) is
2925       Discard : Traverse_Result;
2926
2927       function Process (N : Node_Id) return Traverse_Result;
2928       --  Process a single node during the traversal
2929
2930       function Traverse is new Traverse_Func (Process);
2931       --  The traversal function itself
2932
2933       -------------
2934       -- Process --
2935       -------------
2936
2937       function Process (N : Node_Id) return Traverse_Result is
2938       begin
2939          if Nkind (N) not in N_Subexpr then
2940             return Skip;
2941          end if;
2942
2943          Set_Do_Range_Check (N, False);
2944
2945          case Nkind (N) is
2946             when N_And_Then =>
2947                Discard := Traverse (Left_Opnd (N));
2948                return Skip;
2949
2950             when N_Attribute_Reference =>
2951                Set_Do_Access_Check (N, False);
2952                Set_Do_Overflow_Check (N, False);
2953
2954             when N_Explicit_Dereference =>
2955                Set_Do_Access_Check (N, False);
2956
2957             when N_Function_Call =>
2958                Set_Do_Tag_Check (N, False);
2959
2960             when N_Indexed_Component =>
2961                Set_Do_Access_Check (N, False);
2962
2963             when N_Op =>
2964                Set_Do_Overflow_Check (N, False);
2965
2966                case Nkind (N) is
2967                   when N_Op_Divide =>
2968                      Set_Do_Division_Check (N, False);
2969
2970                   when N_Op_And =>
2971                      Set_Do_Length_Check (N, False);
2972
2973                   when N_Op_Mod =>
2974                      Set_Do_Division_Check (N, False);
2975
2976                   when N_Op_Or =>
2977                      Set_Do_Length_Check (N, False);
2978
2979                   when N_Op_Rem =>
2980                      Set_Do_Division_Check (N, False);
2981
2982                   when N_Op_Xor =>
2983                      Set_Do_Length_Check (N, False);
2984
2985                   when others =>
2986                      null;
2987                end case;
2988
2989             when N_Or_Else =>
2990                Discard := Traverse (Left_Opnd (N));
2991                return Skip;
2992
2993             when N_Selected_Component =>
2994                Set_Do_Access_Check (N, False);
2995                Set_Do_Discriminant_Check (N, False);
2996
2997             when N_Slice =>
2998                Set_Do_Access_Check (N, False);
2999
3000             when N_Type_Conversion =>
3001                Set_Do_Length_Check (N, False);
3002                Set_Do_Overflow_Check (N, False);
3003                Set_Do_Tag_Check (N, False);
3004
3005             when others =>
3006                null;
3007          end case;
3008
3009          return OK;
3010       end Process;
3011
3012    --  Start of processing for Remove_Checks
3013
3014    begin
3015       Discard := Traverse (Expr);
3016    end Remove_Checks;
3017
3018    ----------------------------
3019    -- Selected_Length_Checks --
3020    ----------------------------
3021
3022    function Selected_Length_Checks
3023      (Ck_Node    : Node_Id;
3024       Target_Typ : Entity_Id;
3025       Source_Typ : Entity_Id;
3026       Warn_Node  : Node_Id)
3027       return       Check_Result
3028    is
3029       Loc         : constant Source_Ptr := Sloc (Ck_Node);
3030       S_Typ       : Entity_Id;
3031       T_Typ       : Entity_Id;
3032       Expr_Actual : Node_Id;
3033       Exptyp      : Entity_Id;
3034       Cond        : Node_Id := Empty;
3035       Do_Access   : Boolean := False;
3036       Wnode       : Node_Id := Warn_Node;
3037       Ret_Result  : Check_Result := (Empty, Empty);
3038       Num_Checks  : Natural := 0;
3039
3040       procedure Add_Check (N : Node_Id);
3041       --  Adds the action given to Ret_Result if N is non-Empty
3042
3043       function Get_E_Length (E : Entity_Id; Indx : Nat) return Node_Id;
3044       function Get_N_Length (N : Node_Id; Indx : Nat) return Node_Id;
3045
3046       function Same_Bounds (L : Node_Id; R : Node_Id) return Boolean;
3047       --  True for equal literals and for nodes that denote the same constant
3048       --  entity, even if its value is not a static constant. This includes the
3049       --  case of a discriminal reference within an init_proc. Removes some
3050       --  obviously superfluous checks.
3051
3052       function Length_E_Cond
3053         (Exptyp : Entity_Id;
3054          Typ    : Entity_Id;
3055          Indx   : Nat)
3056          return   Node_Id;
3057       --  Returns expression to compute:
3058       --    Typ'Length /= Exptyp'Length
3059
3060       function Length_N_Cond
3061         (Expr : Node_Id;
3062          Typ  : Entity_Id;
3063          Indx : Nat)
3064          return Node_Id;
3065       --  Returns expression to compute:
3066       --    Typ'Length /= Expr'Length
3067
3068       ---------------
3069       -- Add_Check --
3070       ---------------
3071
3072       procedure Add_Check (N : Node_Id) is
3073       begin
3074          if Present (N) then
3075
3076             --  For now, ignore attempt to place more than 2 checks ???
3077
3078             if Num_Checks = 2 then
3079                return;
3080             end if;
3081
3082             pragma Assert (Num_Checks <= 1);
3083             Num_Checks := Num_Checks + 1;
3084             Ret_Result (Num_Checks) := N;
3085          end if;
3086       end Add_Check;
3087
3088       ------------------
3089       -- Get_E_Length --
3090       ------------------
3091
3092       function Get_E_Length (E : Entity_Id; Indx : Nat) return Node_Id is
3093          N  : Node_Id;
3094          E1 : Entity_Id := E;
3095          Pt : Entity_Id := Scope (Scope (E));
3096
3097       begin
3098          if Ekind (Scope (E)) = E_Record_Type
3099            and then Has_Discriminants (Scope (E))
3100          then
3101             N := Build_Discriminal_Subtype_Of_Component (E);
3102
3103             if Present (N) then
3104                Insert_Action (Ck_Node, N);
3105                E1 := Defining_Identifier (N);
3106             end if;
3107          end if;
3108
3109          if Ekind (E1) = E_String_Literal_Subtype then
3110             return
3111               Make_Integer_Literal (Loc,
3112                 Intval => String_Literal_Length (E1));
3113
3114          elsif Ekind (Pt) = E_Protected_Type
3115            and then Has_Discriminants (Pt)
3116            and then Has_Completion (Pt)
3117            and then not Inside_Init_Proc
3118          then
3119
3120             --  If the type whose length is needed is a private component
3121             --  constrained by a discriminant, we must expand the 'Length
3122             --  attribute into an explicit computation, using the discriminal
3123             --  of the current protected operation. This is because the actual
3124             --  type of the prival is constructed after the protected opera-
3125             --  tion has been fully expanded.
3126
3127             declare
3128                Indx_Type : Node_Id;
3129                Lo        : Node_Id;
3130                Hi        : Node_Id;
3131                Do_Expand : Boolean := False;
3132
3133             begin
3134                Indx_Type := First_Index (E);
3135
3136                for J in 1 .. Indx - 1 loop
3137                   Next_Index (Indx_Type);
3138                end loop;
3139
3140                Get_Index_Bounds  (Indx_Type, Lo, Hi);
3141
3142                if Nkind (Lo) = N_Identifier
3143                  and then Ekind (Entity (Lo)) = E_In_Parameter
3144                then
3145                   Lo := Get_Discriminal (E, Lo);
3146                   Do_Expand := True;
3147                end if;
3148
3149                if Nkind (Hi) = N_Identifier
3150                  and then Ekind (Entity (Hi)) = E_In_Parameter
3151                then
3152                   Hi := Get_Discriminal (E, Hi);
3153                   Do_Expand := True;
3154                end if;
3155
3156                if Do_Expand then
3157                   if not Is_Entity_Name (Lo) then
3158                      Lo := Duplicate_Subexpr (Lo);
3159                   end if;
3160
3161                   if not Is_Entity_Name (Hi) then
3162                      Lo := Duplicate_Subexpr (Hi);
3163                   end if;
3164
3165                   N :=
3166                     Make_Op_Add (Loc,
3167                       Left_Opnd =>
3168                         Make_Op_Subtract (Loc,
3169                           Left_Opnd  => Hi,
3170                           Right_Opnd => Lo),
3171
3172                       Right_Opnd => Make_Integer_Literal (Loc, 1));
3173                   return N;
3174
3175                else
3176                   N :=
3177                     Make_Attribute_Reference (Loc,
3178                       Attribute_Name => Name_Length,
3179                       Prefix =>
3180                         New_Occurrence_Of (E1, Loc));
3181
3182                   if Indx > 1 then
3183                      Set_Expressions (N, New_List (
3184                        Make_Integer_Literal (Loc, Indx)));
3185                   end if;
3186
3187                   return N;
3188                end if;
3189             end;
3190
3191          else
3192             N :=
3193               Make_Attribute_Reference (Loc,
3194                 Attribute_Name => Name_Length,
3195                 Prefix =>
3196                   New_Occurrence_Of (E1, Loc));
3197
3198             if Indx > 1 then
3199                Set_Expressions (N, New_List (
3200                  Make_Integer_Literal (Loc, Indx)));
3201             end if;
3202
3203             return N;
3204
3205          end if;
3206       end Get_E_Length;
3207
3208       ------------------
3209       -- Get_N_Length --
3210       ------------------
3211
3212       function Get_N_Length (N : Node_Id; Indx : Nat) return Node_Id is
3213       begin
3214          return
3215            Make_Attribute_Reference (Loc,
3216              Attribute_Name => Name_Length,
3217              Prefix =>
3218                Duplicate_Subexpr (N, Name_Req => True),
3219              Expressions => New_List (
3220                Make_Integer_Literal (Loc, Indx)));
3221
3222       end Get_N_Length;
3223
3224       -------------------
3225       -- Length_E_Cond --
3226       -------------------
3227
3228       function Length_E_Cond
3229         (Exptyp : Entity_Id;
3230          Typ    : Entity_Id;
3231          Indx   : Nat)
3232          return   Node_Id
3233       is
3234       begin
3235          return
3236            Make_Op_Ne (Loc,
3237              Left_Opnd  => Get_E_Length (Typ, Indx),
3238              Right_Opnd => Get_E_Length (Exptyp, Indx));
3239
3240       end Length_E_Cond;
3241
3242       -------------------
3243       -- Length_N_Cond --
3244       -------------------
3245
3246       function Length_N_Cond
3247         (Expr : Node_Id;
3248          Typ  : Entity_Id;
3249          Indx : Nat)
3250          return Node_Id
3251       is
3252       begin
3253          return
3254            Make_Op_Ne (Loc,
3255              Left_Opnd  => Get_E_Length (Typ, Indx),
3256              Right_Opnd => Get_N_Length (Expr, Indx));
3257
3258       end Length_N_Cond;
3259
3260       function Same_Bounds (L : Node_Id; R : Node_Id) return Boolean is
3261       begin
3262          return
3263            (Nkind (L) = N_Integer_Literal
3264              and then Nkind (R) = N_Integer_Literal
3265              and then Intval (L) = Intval (R))
3266
3267           or else
3268             (Is_Entity_Name (L)
3269               and then Ekind (Entity (L)) = E_Constant
3270               and then ((Is_Entity_Name (R)
3271                          and then Entity (L) = Entity (R))
3272                         or else
3273                        (Nkind (R) = N_Type_Conversion
3274                          and then Is_Entity_Name (Expression (R))
3275                          and then Entity (L) = Entity (Expression (R)))))
3276
3277           or else
3278             (Is_Entity_Name (R)
3279               and then Ekind (Entity (R)) = E_Constant
3280               and then Nkind (L) = N_Type_Conversion
3281               and then Is_Entity_Name (Expression (L))
3282               and then Entity (R) = Entity (Expression (L)))
3283
3284          or else
3285             (Is_Entity_Name (L)
3286               and then Is_Entity_Name (R)
3287               and then Entity (L) = Entity (R)
3288               and then Ekind (Entity (L)) = E_In_Parameter
3289               and then Inside_Init_Proc);
3290       end Same_Bounds;
3291
3292    --  Start of processing for Selected_Length_Checks
3293
3294    begin
3295       if not Expander_Active then
3296          return Ret_Result;
3297       end if;
3298
3299       if Target_Typ = Any_Type
3300         or else Target_Typ = Any_Composite
3301         or else Raises_Constraint_Error (Ck_Node)
3302       then
3303          return Ret_Result;
3304       end if;
3305
3306       if No (Wnode) then
3307          Wnode := Ck_Node;
3308       end if;
3309
3310       T_Typ := Target_Typ;
3311
3312       if No (Source_Typ) then
3313          S_Typ := Etype (Ck_Node);
3314       else
3315          S_Typ := Source_Typ;
3316       end if;
3317
3318       if S_Typ = Any_Type or else S_Typ = Any_Composite then
3319          return Ret_Result;
3320       end if;
3321
3322       if Is_Access_Type (T_Typ) and then Is_Access_Type (S_Typ) then
3323          S_Typ := Designated_Type (S_Typ);
3324          T_Typ := Designated_Type (T_Typ);
3325          Do_Access := True;
3326
3327          --  A simple optimization
3328
3329          if Nkind (Ck_Node) = N_Null then
3330             return Ret_Result;
3331          end if;
3332       end if;
3333
3334       if Is_Array_Type (T_Typ) and then Is_Array_Type (S_Typ) then
3335          if Is_Constrained (T_Typ) then
3336
3337             --  The checking code to be generated will freeze the
3338             --  corresponding array type. However, we must freeze the
3339             --  type now, so that the freeze node does not appear within
3340             --  the generated condional expression, but ahead of it.
3341
3342             Freeze_Before (Ck_Node, T_Typ);
3343
3344             Expr_Actual := Get_Referenced_Object (Ck_Node);
3345             Exptyp      := Get_Actual_Subtype (Expr_Actual);
3346
3347             if Is_Access_Type (Exptyp) then
3348                Exptyp := Designated_Type (Exptyp);
3349             end if;
3350
3351             --  String_Literal case. This needs to be handled specially be-
3352             --  cause no index types are available for string literals. The
3353             --  condition is simply:
3354
3355             --    T_Typ'Length = string-literal-length
3356
3357             if Nkind (Expr_Actual) = N_String_Literal then
3358                Cond :=
3359                  Make_Op_Ne (Loc,
3360                    Left_Opnd  => Get_E_Length (T_Typ, 1),
3361                    Right_Opnd =>
3362                      Make_Integer_Literal (Loc,
3363                        Intval =>
3364                          String_Literal_Length (Etype (Expr_Actual))));
3365
3366             --  General array case. Here we have a usable actual subtype for
3367             --  the expression, and the condition is built from the two types
3368             --  (Do_Length):
3369
3370             --     T_Typ'Length     /= Exptyp'Length     or else
3371             --     T_Typ'Length (2) /= Exptyp'Length (2) or else
3372             --     T_Typ'Length (3) /= Exptyp'Length (3) or else
3373             --     ...
3374
3375             elsif Is_Constrained (Exptyp) then
3376                declare
3377                   L_Index : Node_Id;
3378                   R_Index : Node_Id;
3379                   Ndims   : Nat := Number_Dimensions (T_Typ);
3380
3381                   L_Low  : Node_Id;
3382                   L_High : Node_Id;
3383                   R_Low  : Node_Id;
3384                   R_High : Node_Id;
3385
3386                   L_Length : Uint;
3387                   R_Length : Uint;
3388
3389                begin
3390                   L_Index := First_Index (T_Typ);
3391                   R_Index := First_Index (Exptyp);
3392
3393                   for Indx in 1 .. Ndims loop
3394                      if not (Nkind (L_Index) = N_Raise_Constraint_Error
3395                                or else
3396                              Nkind (R_Index) = N_Raise_Constraint_Error)
3397                      then
3398                         Get_Index_Bounds (L_Index, L_Low, L_High);
3399                         Get_Index_Bounds (R_Index, R_Low, R_High);
3400
3401                         --  Deal with compile time length check. Note that we
3402                         --  skip this in the access case, because the access
3403                         --  value may be null, so we cannot know statically.
3404
3405                         if not Do_Access
3406                           and then Compile_Time_Known_Value (L_Low)
3407                           and then Compile_Time_Known_Value (L_High)
3408                           and then Compile_Time_Known_Value (R_Low)
3409                           and then Compile_Time_Known_Value (R_High)
3410                         then
3411                            if Expr_Value (L_High) >= Expr_Value (L_Low) then
3412                               L_Length := Expr_Value (L_High) -
3413                                           Expr_Value (L_Low) + 1;
3414                            else
3415                               L_Length := UI_From_Int (0);
3416                            end if;
3417
3418                            if Expr_Value (R_High) >= Expr_Value (R_Low) then
3419                               R_Length := Expr_Value (R_High) -
3420                                           Expr_Value (R_Low) + 1;
3421                            else
3422                               R_Length := UI_From_Int (0);
3423                            end if;
3424
3425                            if L_Length > R_Length then
3426                               Add_Check
3427                                 (Compile_Time_Constraint_Error
3428                                   (Wnode, "too few elements for}?", T_Typ));
3429
3430                            elsif  L_Length < R_Length then
3431                               Add_Check
3432                                 (Compile_Time_Constraint_Error
3433                                   (Wnode, "too many elements for}?", T_Typ));
3434                            end if;
3435
3436                         --  The comparison for an individual index subtype
3437                         --  is omitted if the corresponding index subtypes
3438                         --  statically match, since the result is known to
3439                         --  be true. Note that this test is worth while even
3440                         --  though we do static evaluation, because non-static
3441                         --  subtypes can statically match.
3442
3443                         elsif not
3444                           Subtypes_Statically_Match
3445                             (Etype (L_Index), Etype (R_Index))
3446
3447                           and then not
3448                             (Same_Bounds (L_Low, R_Low)
3449                               and then Same_Bounds (L_High, R_High))
3450                         then
3451                            Evolve_Or_Else
3452                              (Cond, Length_E_Cond (Exptyp, T_Typ, Indx));
3453                         end if;
3454
3455                         Next (L_Index);
3456                         Next (R_Index);
3457                      end if;
3458                   end loop;
3459                end;
3460
3461             --  Handle cases where we do not get a usable actual subtype that
3462             --  is constrained. This happens for example in the function call
3463             --  and explicit dereference cases. In these cases, we have to get
3464             --  the length or range from the expression itself, making sure we
3465             --  do not evaluate it more than once.
3466
3467             --  Here Ck_Node is the original expression, or more properly the
3468             --  result of applying Duplicate_Expr to the original tree,
3469             --  forcing the result to be a name.
3470
3471             else
3472                declare
3473                   Ndims : Nat := Number_Dimensions (T_Typ);
3474
3475                begin
3476                   --  Build the condition for the explicit dereference case
3477
3478                   for Indx in 1 .. Ndims loop
3479                      Evolve_Or_Else
3480                        (Cond, Length_N_Cond (Ck_Node, T_Typ, Indx));
3481                   end loop;
3482                end;
3483             end if;
3484          end if;
3485       end if;
3486
3487       --  Construct the test and insert into the tree
3488
3489       if Present (Cond) then
3490          if Do_Access then
3491             Cond := Guard_Access (Cond, Loc, Ck_Node);
3492          end if;
3493
3494          Add_Check
3495            (Make_Raise_Constraint_Error (Loc,
3496               Condition => Cond,
3497               Reason => CE_Length_Check_Failed));
3498       end if;
3499
3500       return Ret_Result;
3501    end Selected_Length_Checks;
3502
3503    ---------------------------
3504    -- Selected_Range_Checks --
3505    ---------------------------
3506
3507    function Selected_Range_Checks
3508      (Ck_Node    : Node_Id;
3509       Target_Typ : Entity_Id;
3510       Source_Typ : Entity_Id;
3511       Warn_Node  : Node_Id)
3512       return       Check_Result
3513    is
3514       Loc         : constant Source_Ptr := Sloc (Ck_Node);
3515       S_Typ       : Entity_Id;
3516       T_Typ       : Entity_Id;
3517       Expr_Actual : Node_Id;
3518       Exptyp      : Entity_Id;
3519       Cond        : Node_Id := Empty;
3520       Do_Access   : Boolean := False;
3521       Wnode       : Node_Id  := Warn_Node;
3522       Ret_Result  : Check_Result := (Empty, Empty);
3523       Num_Checks  : Integer := 0;
3524
3525       procedure Add_Check (N : Node_Id);
3526       --  Adds the action given to Ret_Result if N is non-Empty
3527
3528       function Discrete_Range_Cond
3529         (Expr : Node_Id;
3530          Typ  : Entity_Id)
3531          return Node_Id;
3532       --  Returns expression to compute:
3533       --    Low_Bound (Expr) < Typ'First
3534       --      or else
3535       --    High_Bound (Expr) > Typ'Last
3536
3537       function Discrete_Expr_Cond
3538         (Expr : Node_Id;
3539          Typ  : Entity_Id)
3540          return Node_Id;
3541       --  Returns expression to compute:
3542       --    Expr < Typ'First
3543       --      or else
3544       --    Expr > Typ'Last
3545
3546       function Get_E_First_Or_Last
3547         (E    : Entity_Id;
3548          Indx : Nat;
3549          Nam  : Name_Id)
3550          return Node_Id;
3551       --  Returns expression to compute:
3552       --    E'First or E'Last
3553
3554       function Get_N_First (N : Node_Id; Indx : Nat) return Node_Id;
3555       function Get_N_Last  (N : Node_Id; Indx : Nat) return Node_Id;
3556       --  Returns expression to compute:
3557       --    N'First or N'Last using Duplicate_Subexpr
3558
3559       function Range_E_Cond
3560         (Exptyp : Entity_Id;
3561          Typ    : Entity_Id;
3562          Indx   : Nat)
3563          return   Node_Id;
3564       --  Returns expression to compute:
3565       --    Exptyp'First < Typ'First or else Exptyp'Last > Typ'Last
3566
3567       function Range_Equal_E_Cond
3568         (Exptyp : Entity_Id;
3569          Typ    : Entity_Id;
3570          Indx   : Nat)
3571          return   Node_Id;
3572       --  Returns expression to compute:
3573       --    Exptyp'First /= Typ'First or else Exptyp'Last /= Typ'Last
3574
3575       function Range_N_Cond
3576         (Expr : Node_Id;
3577          Typ  : Entity_Id;
3578          Indx : Nat)
3579          return Node_Id;
3580       --  Return expression to compute:
3581       --    Expr'First < Typ'First or else Expr'Last > Typ'Last
3582
3583       ---------------
3584       -- Add_Check --
3585       ---------------
3586
3587       procedure Add_Check (N : Node_Id) is
3588       begin
3589          if Present (N) then
3590
3591             --  For now, ignore attempt to place more than 2 checks ???
3592
3593             if Num_Checks = 2 then
3594                return;
3595             end if;
3596
3597             pragma Assert (Num_Checks <= 1);
3598             Num_Checks := Num_Checks + 1;
3599             Ret_Result (Num_Checks) := N;
3600          end if;
3601       end Add_Check;
3602
3603       -------------------------
3604       -- Discrete_Expr_Cond --
3605       -------------------------
3606
3607       function Discrete_Expr_Cond
3608         (Expr : Node_Id;
3609          Typ  : Entity_Id)
3610          return Node_Id
3611       is
3612       begin
3613          return
3614            Make_Or_Else (Loc,
3615              Left_Opnd =>
3616                Make_Op_Lt (Loc,
3617                  Left_Opnd =>
3618                    Convert_To (Base_Type (Typ), Duplicate_Subexpr (Expr)),
3619                  Right_Opnd =>
3620                    Convert_To (Base_Type (Typ),
3621                                Get_E_First_Or_Last (Typ, 0, Name_First))),
3622
3623              Right_Opnd =>
3624                Make_Op_Gt (Loc,
3625                  Left_Opnd =>
3626                    Convert_To (Base_Type (Typ), Duplicate_Subexpr (Expr)),
3627                  Right_Opnd =>
3628                    Convert_To
3629                      (Base_Type (Typ),
3630                       Get_E_First_Or_Last (Typ, 0, Name_Last))));
3631       end Discrete_Expr_Cond;
3632
3633       -------------------------
3634       -- Discrete_Range_Cond --
3635       -------------------------
3636
3637       function Discrete_Range_Cond
3638         (Expr : Node_Id;
3639          Typ  : Entity_Id)
3640          return Node_Id
3641       is
3642          LB : Node_Id := Low_Bound (Expr);
3643          HB : Node_Id := High_Bound (Expr);
3644
3645          Left_Opnd  : Node_Id;
3646          Right_Opnd : Node_Id;
3647
3648       begin
3649          if Nkind (LB) = N_Identifier
3650            and then Ekind (Entity (LB)) = E_Discriminant then
3651             LB := New_Occurrence_Of (Discriminal (Entity (LB)), Loc);
3652          end if;
3653
3654          if Nkind (HB) = N_Identifier
3655            and then Ekind (Entity (HB)) = E_Discriminant then
3656             HB := New_Occurrence_Of (Discriminal (Entity (HB)), Loc);
3657          end if;
3658
3659          Left_Opnd :=
3660            Make_Op_Lt (Loc,
3661              Left_Opnd  =>
3662                Convert_To
3663                  (Base_Type (Typ), Duplicate_Subexpr (LB)),
3664
3665              Right_Opnd =>
3666                Convert_To
3667                  (Base_Type (Typ), Get_E_First_Or_Last (Typ, 0, Name_First)));
3668
3669          if Base_Type (Typ) = Typ then
3670             return Left_Opnd;
3671
3672          elsif Compile_Time_Known_Value (High_Bound (Scalar_Range (Typ)))
3673             and then
3674                Compile_Time_Known_Value (High_Bound (Scalar_Range
3675                                                      (Base_Type (Typ))))
3676          then
3677             if Is_Floating_Point_Type (Typ) then
3678                if Expr_Value_R (High_Bound (Scalar_Range (Typ))) =
3679                   Expr_Value_R (High_Bound (Scalar_Range (Base_Type (Typ))))
3680                then
3681                   return Left_Opnd;
3682                end if;
3683
3684             else
3685                if Expr_Value (High_Bound (Scalar_Range (Typ))) =
3686                   Expr_Value (High_Bound (Scalar_Range (Base_Type (Typ))))
3687                then
3688                   return Left_Opnd;
3689                end if;
3690             end if;
3691          end if;
3692
3693          Right_Opnd :=
3694            Make_Op_Gt (Loc,
3695              Left_Opnd  =>
3696                Convert_To
3697                  (Base_Type (Typ), Duplicate_Subexpr (HB)),
3698
3699              Right_Opnd =>
3700                Convert_To
3701                  (Base_Type (Typ),
3702                   Get_E_First_Or_Last (Typ, 0, Name_Last)));
3703
3704          return Make_Or_Else (Loc, Left_Opnd, Right_Opnd);
3705       end Discrete_Range_Cond;
3706
3707       -------------------------
3708       -- Get_E_First_Or_Last --
3709       -------------------------
3710
3711       function Get_E_First_Or_Last
3712         (E    : Entity_Id;
3713          Indx : Nat;
3714          Nam  : Name_Id)
3715          return Node_Id
3716       is
3717          N     : Node_Id;
3718          LB    : Node_Id;
3719          HB    : Node_Id;
3720          Bound : Node_Id;
3721
3722       begin
3723          if Is_Array_Type (E) then
3724             N := First_Index (E);
3725
3726             for J in 2 .. Indx loop
3727                Next_Index (N);
3728             end loop;
3729
3730          else
3731             N := Scalar_Range (E);
3732          end if;
3733
3734          if Nkind (N) = N_Subtype_Indication then
3735             LB := Low_Bound (Range_Expression (Constraint (N)));
3736             HB := High_Bound (Range_Expression (Constraint (N)));
3737
3738          elsif Is_Entity_Name (N) then
3739             LB := Type_Low_Bound  (Etype (N));
3740             HB := Type_High_Bound (Etype (N));
3741
3742          else
3743             LB := Low_Bound  (N);
3744             HB := High_Bound (N);
3745          end if;
3746
3747          if Nam = Name_First then
3748             Bound := LB;
3749          else
3750             Bound := HB;
3751          end if;
3752
3753          if Nkind (Bound) = N_Identifier
3754            and then Ekind (Entity (Bound)) = E_Discriminant
3755          then
3756             return New_Occurrence_Of (Discriminal (Entity (Bound)), Loc);
3757
3758          elsif Nkind (Bound) = N_Identifier
3759            and then Ekind (Entity (Bound)) = E_In_Parameter
3760            and then not Inside_Init_Proc
3761          then
3762             return Get_Discriminal (E, Bound);
3763
3764          elsif Nkind (Bound) = N_Integer_Literal then
3765             return  Make_Integer_Literal (Loc, Intval (Bound));
3766
3767          else
3768             return Duplicate_Subexpr (Bound);
3769          end if;
3770       end Get_E_First_Or_Last;
3771
3772       -----------------
3773       -- Get_N_First --
3774       -----------------
3775
3776       function Get_N_First (N : Node_Id; Indx : Nat) return Node_Id is
3777       begin
3778          return
3779            Make_Attribute_Reference (Loc,
3780              Attribute_Name => Name_First,
3781              Prefix =>
3782                Duplicate_Subexpr (N, Name_Req => True),
3783              Expressions => New_List (
3784                Make_Integer_Literal (Loc, Indx)));
3785
3786       end Get_N_First;
3787
3788       ----------------
3789       -- Get_N_Last --
3790       ----------------
3791
3792       function Get_N_Last (N : Node_Id; Indx : Nat) return Node_Id is
3793       begin
3794          return
3795            Make_Attribute_Reference (Loc,
3796              Attribute_Name => Name_Last,
3797              Prefix =>
3798                Duplicate_Subexpr (N, Name_Req => True),
3799              Expressions => New_List (
3800               Make_Integer_Literal (Loc, Indx)));
3801
3802       end Get_N_Last;
3803
3804       ------------------
3805       -- Range_E_Cond --
3806       ------------------
3807
3808       function Range_E_Cond
3809         (Exptyp : Entity_Id;
3810          Typ    : Entity_Id;
3811          Indx   : Nat)
3812          return   Node_Id
3813       is
3814       begin
3815          return
3816            Make_Or_Else (Loc,
3817              Left_Opnd =>
3818                Make_Op_Lt (Loc,
3819                  Left_Opnd => Get_E_First_Or_Last (Exptyp, Indx, Name_First),
3820                  Right_Opnd  => Get_E_First_Or_Last (Typ, Indx, Name_First)),
3821
3822              Right_Opnd =>
3823                Make_Op_Gt (Loc,
3824                  Left_Opnd => Get_E_First_Or_Last (Exptyp, Indx, Name_Last),
3825                  Right_Opnd  => Get_E_First_Or_Last (Typ, Indx, Name_Last)));
3826
3827       end Range_E_Cond;
3828
3829       ------------------------
3830       -- Range_Equal_E_Cond --
3831       ------------------------
3832
3833       function Range_Equal_E_Cond
3834         (Exptyp : Entity_Id;
3835          Typ    : Entity_Id;
3836          Indx   : Nat)
3837          return   Node_Id
3838       is
3839       begin
3840          return
3841            Make_Or_Else (Loc,
3842              Left_Opnd =>
3843                Make_Op_Ne (Loc,
3844                  Left_Opnd => Get_E_First_Or_Last (Exptyp, Indx, Name_First),
3845                  Right_Opnd  => Get_E_First_Or_Last (Typ, Indx, Name_First)),
3846              Right_Opnd =>
3847                Make_Op_Ne (Loc,
3848                  Left_Opnd => Get_E_First_Or_Last (Exptyp, Indx, Name_Last),
3849                  Right_Opnd  => Get_E_First_Or_Last (Typ, Indx, Name_Last)));
3850       end Range_Equal_E_Cond;
3851
3852       ------------------
3853       -- Range_N_Cond --
3854       ------------------
3855
3856       function Range_N_Cond
3857         (Expr : Node_Id;
3858          Typ  : Entity_Id;
3859          Indx : Nat)
3860          return Node_Id
3861       is
3862       begin
3863          return
3864            Make_Or_Else (Loc,
3865              Left_Opnd =>
3866                Make_Op_Lt (Loc,
3867                  Left_Opnd => Get_N_First (Expr, Indx),
3868                  Right_Opnd  => Get_E_First_Or_Last (Typ, Indx, Name_First)),
3869
3870              Right_Opnd =>
3871                Make_Op_Gt (Loc,
3872                  Left_Opnd => Get_N_Last (Expr, Indx),
3873                  Right_Opnd  => Get_E_First_Or_Last (Typ, Indx, Name_Last)));
3874       end Range_N_Cond;
3875
3876    --  Start of processing for Selected_Range_Checks
3877
3878    begin
3879       if not Expander_Active then
3880          return Ret_Result;
3881       end if;
3882
3883       if Target_Typ = Any_Type
3884         or else Target_Typ = Any_Composite
3885         or else Raises_Constraint_Error (Ck_Node)
3886       then
3887          return Ret_Result;
3888       end if;
3889
3890       if No (Wnode) then
3891          Wnode := Ck_Node;
3892       end if;
3893
3894       T_Typ := Target_Typ;
3895
3896       if No (Source_Typ) then
3897          S_Typ := Etype (Ck_Node);
3898       else
3899          S_Typ := Source_Typ;
3900       end if;
3901
3902       if S_Typ = Any_Type or else S_Typ = Any_Composite then
3903          return Ret_Result;
3904       end if;
3905
3906       --  The order of evaluating T_Typ before S_Typ seems to be critical
3907       --  because S_Typ can be derived from Etype (Ck_Node), if it's not passed
3908       --  in, and since Node can be an N_Range node, it might be invalid.
3909       --  Should there be an assert check somewhere for taking the Etype of
3910       --  an N_Range node ???
3911
3912       if Is_Access_Type (T_Typ) and then Is_Access_Type (S_Typ) then
3913          S_Typ := Designated_Type (S_Typ);
3914          T_Typ := Designated_Type (T_Typ);
3915          Do_Access := True;
3916
3917          --  A simple optimization
3918
3919          if Nkind (Ck_Node) = N_Null then
3920             return Ret_Result;
3921          end if;
3922       end if;
3923
3924       --  For an N_Range Node, check for a null range and then if not
3925       --  null generate a range check action.
3926
3927       if Nkind (Ck_Node) = N_Range then
3928
3929          --  There's no point in checking a range against itself
3930
3931          if Ck_Node = Scalar_Range (T_Typ) then
3932             return Ret_Result;
3933          end if;
3934
3935          declare
3936             T_LB       : constant Node_Id := Type_Low_Bound  (T_Typ);
3937             T_HB       : constant Node_Id := Type_High_Bound (T_Typ);
3938             LB         : constant Node_Id := Low_Bound (Ck_Node);
3939             HB         : constant Node_Id := High_Bound (Ck_Node);
3940             Null_Range : Boolean;
3941
3942             Out_Of_Range_L : Boolean;
3943             Out_Of_Range_H : Boolean;
3944
3945          begin
3946             --  Check for case where everything is static and we can
3947             --  do the check at compile time. This is skipped if we
3948             --  have an access type, since the access value may be null.
3949
3950             --  ??? This code can be improved since you only need to know
3951             --  that the two respective bounds (LB & T_LB or HB & T_HB)
3952             --  are known at compile time to emit pertinent messages.
3953
3954             if Compile_Time_Known_Value (LB)
3955               and then Compile_Time_Known_Value (HB)
3956               and then Compile_Time_Known_Value (T_LB)
3957               and then Compile_Time_Known_Value (T_HB)
3958               and then not Do_Access
3959             then
3960                --  Floating-point case
3961
3962                if Is_Floating_Point_Type (S_Typ) then
3963                   Null_Range := Expr_Value_R (HB) < Expr_Value_R (LB);
3964                   Out_Of_Range_L :=
3965                     (Expr_Value_R (LB) < Expr_Value_R (T_LB))
3966                        or else
3967                     (Expr_Value_R (LB) > Expr_Value_R (T_HB));
3968
3969                   Out_Of_Range_H :=
3970                     (Expr_Value_R (HB) > Expr_Value_R (T_HB))
3971                        or else
3972                     (Expr_Value_R (HB) < Expr_Value_R (T_LB));
3973
3974                --  Fixed or discrete type case
3975
3976                else
3977                   Null_Range := Expr_Value (HB) < Expr_Value (LB);
3978                   Out_Of_Range_L :=
3979                     (Expr_Value (LB) < Expr_Value (T_LB))
3980                     or else
3981                     (Expr_Value (LB) > Expr_Value (T_HB));
3982
3983                   Out_Of_Range_H :=
3984                     (Expr_Value (HB) > Expr_Value (T_HB))
3985                     or else
3986                     (Expr_Value (HB) < Expr_Value (T_LB));
3987                end if;
3988
3989                if not Null_Range then
3990                   if Out_Of_Range_L then
3991                      if No (Warn_Node) then
3992                         Add_Check
3993                           (Compile_Time_Constraint_Error
3994                              (Low_Bound (Ck_Node),
3995                               "static value out of range of}?", T_Typ));
3996
3997                      else
3998                         Add_Check
3999                           (Compile_Time_Constraint_Error
4000                             (Wnode,
4001                              "static range out of bounds of}?", T_Typ));
4002                      end if;
4003                   end if;
4004
4005                   if Out_Of_Range_H then
4006                      if No (Warn_Node) then
4007                         Add_Check
4008                           (Compile_Time_Constraint_Error
4009                              (High_Bound (Ck_Node),
4010                               "static value out of range of}?", T_Typ));
4011
4012                      else
4013                         Add_Check
4014                           (Compile_Time_Constraint_Error
4015                              (Wnode,
4016                               "static range out of bounds of}?", T_Typ));
4017                      end if;
4018                   end if;
4019
4020                end if;
4021
4022             else
4023                declare
4024                   LB : Node_Id := Low_Bound (Ck_Node);
4025                   HB : Node_Id := High_Bound (Ck_Node);
4026
4027                begin
4028
4029                   --  If either bound is a discriminant and we are within
4030                   --  the record declaration, it is a use of the discriminant
4031                   --  in a constraint of a component, and nothing can be
4032                   --  checked here. The check will be emitted within the
4033                   --  init_proc. Before then, the discriminal has no real
4034                   --  meaning.
4035
4036                   if Nkind (LB) = N_Identifier
4037                     and then Ekind (Entity (LB)) = E_Discriminant
4038                   then
4039                      if Current_Scope = Scope (Entity (LB)) then
4040                         return Ret_Result;
4041                      else
4042                         LB :=
4043                           New_Occurrence_Of (Discriminal (Entity (LB)), Loc);
4044                      end if;
4045                   end if;
4046
4047                   if Nkind (HB) = N_Identifier
4048                     and then Ekind (Entity (HB)) = E_Discriminant
4049                   then
4050                      if Current_Scope = Scope (Entity (HB)) then
4051                         return Ret_Result;
4052                      else
4053                         HB :=
4054                           New_Occurrence_Of (Discriminal (Entity (HB)), Loc);
4055                      end if;
4056                   end if;
4057
4058                   Cond := Discrete_Range_Cond (Ck_Node, T_Typ);
4059                   Set_Paren_Count (Cond, 1);
4060
4061                   Cond :=
4062                     Make_And_Then (Loc,
4063                       Left_Opnd =>
4064                         Make_Op_Ge (Loc,
4065                           Left_Opnd  => Duplicate_Subexpr (HB),
4066                           Right_Opnd => Duplicate_Subexpr (LB)),
4067                       Right_Opnd => Cond);
4068                end;
4069
4070             end if;
4071          end;
4072
4073       elsif Is_Scalar_Type (S_Typ) then
4074
4075          --  This somewhat duplicates what Apply_Scalar_Range_Check does,
4076          --  except the above simply sets a flag in the node and lets
4077          --  gigi generate the check base on the Etype of the expression.
4078          --  Sometimes, however we want to do a dynamic check against an
4079          --  arbitrary target type, so we do that here.
4080
4081          if Ekind (Base_Type (S_Typ)) /= Ekind (Base_Type (T_Typ)) then
4082             Cond := Discrete_Expr_Cond (Ck_Node, T_Typ);
4083
4084          --  For literals, we can tell if the constraint error will be
4085          --  raised at compile time, so we never need a dynamic check, but
4086          --  if the exception will be raised, then post the usual warning,
4087          --  and replace the literal with a raise constraint error
4088          --  expression. As usual, skip this for access types
4089
4090          elsif Compile_Time_Known_Value (Ck_Node)
4091            and then not Do_Access
4092          then
4093             declare
4094                LB : constant Node_Id := Type_Low_Bound (T_Typ);
4095                UB : constant Node_Id := Type_High_Bound (T_Typ);
4096
4097                Out_Of_Range  : Boolean;
4098                Static_Bounds : constant Boolean :=
4099                                  Compile_Time_Known_Value (LB)
4100                                    and Compile_Time_Known_Value (UB);
4101
4102             begin
4103                --  Following range tests should use Sem_Eval routine ???
4104
4105                if Static_Bounds then
4106                   if Is_Floating_Point_Type (S_Typ) then
4107                      Out_Of_Range :=
4108                        (Expr_Value_R (Ck_Node) < Expr_Value_R (LB))
4109                          or else
4110                        (Expr_Value_R (Ck_Node) > Expr_Value_R (UB));
4111
4112                   else -- fixed or discrete type
4113                      Out_Of_Range :=
4114                        Expr_Value (Ck_Node) < Expr_Value (LB)
4115                          or else
4116                        Expr_Value (Ck_Node) > Expr_Value (UB);
4117                   end if;
4118
4119                   --  Bounds of the type are static and the literal is
4120                   --  out of range so make a warning message.
4121
4122                   if Out_Of_Range then
4123                      if No (Warn_Node) then
4124                         Add_Check
4125                           (Compile_Time_Constraint_Error
4126                              (Ck_Node,
4127                               "static value out of range of}?", T_Typ));
4128
4129                      else
4130                         Add_Check
4131                           (Compile_Time_Constraint_Error
4132                              (Wnode,
4133                               "static value out of range of}?", T_Typ));
4134                      end if;
4135                   end if;
4136
4137                else
4138                   Cond := Discrete_Expr_Cond (Ck_Node, T_Typ);
4139                end if;
4140             end;
4141
4142          --  Here for the case of a non-static expression, we need a runtime
4143          --  check unless the source type range is guaranteed to be in the
4144          --  range of the target type.
4145
4146          else
4147             if not In_Subrange_Of (S_Typ, T_Typ) then
4148                Cond := Discrete_Expr_Cond (Ck_Node, T_Typ);
4149             end if;
4150          end if;
4151       end if;
4152
4153       if Is_Array_Type (T_Typ) and then Is_Array_Type (S_Typ) then
4154          if Is_Constrained (T_Typ) then
4155
4156             Expr_Actual := Get_Referenced_Object (Ck_Node);
4157             Exptyp      := Get_Actual_Subtype (Expr_Actual);
4158
4159             if Is_Access_Type (Exptyp) then
4160                Exptyp := Designated_Type (Exptyp);
4161             end if;
4162
4163             --  String_Literal case. This needs to be handled specially be-
4164             --  cause no index types are available for string literals. The
4165             --  condition is simply:
4166
4167             --    T_Typ'Length = string-literal-length
4168
4169             if Nkind (Expr_Actual) = N_String_Literal then
4170                null;
4171
4172             --  General array case. Here we have a usable actual subtype for
4173             --  the expression, and the condition is built from the two types
4174
4175             --     T_Typ'First     < Exptyp'First     or else
4176             --     T_Typ'Last      > Exptyp'Last      or else
4177             --     T_Typ'First(1)  < Exptyp'First(1)  or else
4178             --     T_Typ'Last(1)   > Exptyp'Last(1)   or else
4179             --     ...
4180
4181             elsif Is_Constrained (Exptyp) then
4182                declare
4183                   L_Index : Node_Id;
4184                   R_Index : Node_Id;
4185                   Ndims   : Nat := Number_Dimensions (T_Typ);
4186
4187                   L_Low  : Node_Id;
4188                   L_High : Node_Id;
4189                   R_Low  : Node_Id;
4190                   R_High : Node_Id;
4191
4192                begin
4193                   L_Index := First_Index (T_Typ);
4194                   R_Index := First_Index (Exptyp);
4195
4196                   for Indx in 1 .. Ndims loop
4197                      if not (Nkind (L_Index) = N_Raise_Constraint_Error
4198                                or else
4199                              Nkind (R_Index) = N_Raise_Constraint_Error)
4200                      then
4201                         Get_Index_Bounds (L_Index, L_Low, L_High);
4202                         Get_Index_Bounds (R_Index, R_Low, R_High);
4203
4204                         --  Deal with compile time length check. Note that we
4205                         --  skip this in the access case, because the access
4206                         --  value may be null, so we cannot know statically.
4207
4208                         if not
4209                           Subtypes_Statically_Match
4210                             (Etype (L_Index), Etype (R_Index))
4211                         then
4212                            --  If the target type is constrained then we
4213                            --  have to check for exact equality of bounds
4214                            --  (required for qualified expressions).
4215
4216                            if Is_Constrained (T_Typ) then
4217                               Evolve_Or_Else
4218                                 (Cond,
4219                                  Range_Equal_E_Cond (Exptyp, T_Typ, Indx));
4220
4221                            else
4222                               Evolve_Or_Else
4223                                 (Cond, Range_E_Cond (Exptyp, T_Typ, Indx));
4224                            end if;
4225                         end if;
4226
4227                         Next (L_Index);
4228                         Next (R_Index);
4229
4230                      end if;
4231                   end loop;
4232                end;
4233
4234             --  Handle cases where we do not get a usable actual subtype that
4235             --  is constrained. This happens for example in the function call
4236             --  and explicit dereference cases. In these cases, we have to get
4237             --  the length or range from the expression itself, making sure we
4238             --  do not evaluate it more than once.
4239
4240             --  Here Ck_Node is the original expression, or more properly the
4241             --  result of applying Duplicate_Expr to the original tree,
4242             --  forcing the result to be a name.
4243
4244             else
4245                declare
4246                   Ndims   : Nat := Number_Dimensions (T_Typ);
4247
4248                begin
4249                   --  Build the condition for the explicit dereference case
4250
4251                   for Indx in 1 .. Ndims loop
4252                      Evolve_Or_Else
4253                        (Cond, Range_N_Cond (Ck_Node, T_Typ, Indx));
4254                   end loop;
4255                end;
4256
4257             end if;
4258
4259          else
4260             --  Generate an Action to check that the bounds of the
4261             --  source value are within the constraints imposed by the
4262             --  target type for a conversion to an unconstrained type.
4263             --  Rule is 4.6(38).
4264
4265             if Nkind (Parent (Ck_Node)) = N_Type_Conversion then
4266                declare
4267                   Opnd_Index : Node_Id;
4268                   Targ_Index : Node_Id;
4269
4270                begin
4271                   Opnd_Index
4272                     := First_Index (Get_Actual_Subtype (Ck_Node));
4273                   Targ_Index := First_Index (T_Typ);
4274
4275                   while Opnd_Index /= Empty loop
4276                      if Nkind (Opnd_Index) = N_Range then
4277                         if Is_In_Range
4278                              (Low_Bound (Opnd_Index), Etype (Targ_Index))
4279                           and then
4280                             Is_In_Range
4281                              (High_Bound (Opnd_Index), Etype (Targ_Index))
4282                         then
4283                            null;
4284
4285                         elsif Is_Out_Of_Range
4286                                 (Low_Bound (Opnd_Index), Etype (Targ_Index))
4287                           or else
4288                               Is_Out_Of_Range
4289                                 (High_Bound (Opnd_Index), Etype (Targ_Index))
4290                         then
4291                            Add_Check
4292                              (Compile_Time_Constraint_Error
4293                                (Wnode, "value out of range of}?", T_Typ));
4294
4295                         else
4296                            Evolve_Or_Else
4297                              (Cond,
4298                               Discrete_Range_Cond
4299                                 (Opnd_Index, Etype (Targ_Index)));
4300                         end if;
4301                      end if;
4302
4303                      Next_Index (Opnd_Index);
4304                      Next_Index (Targ_Index);
4305                   end loop;
4306                end;
4307             end if;
4308          end if;
4309       end if;
4310
4311       --  Construct the test and insert into the tree
4312
4313       if Present (Cond) then
4314          if Do_Access then
4315             Cond := Guard_Access (Cond, Loc, Ck_Node);
4316          end if;
4317
4318          Add_Check
4319            (Make_Raise_Constraint_Error (Loc,
4320               Condition => Cond,
4321               Reason    => CE_Range_Check_Failed));
4322       end if;
4323
4324       return Ret_Result;
4325    end Selected_Range_Checks;
4326
4327    -------------------------------
4328    -- Storage_Checks_Suppressed --
4329    -------------------------------
4330
4331    function Storage_Checks_Suppressed (E : Entity_Id) return Boolean is
4332    begin
4333       return Scope_Suppress.Storage_Checks
4334         or else (Present (E) and then Suppress_Storage_Checks (E));
4335    end Storage_Checks_Suppressed;
4336
4337    ---------------------------
4338    -- Tag_Checks_Suppressed --
4339    ---------------------------
4340
4341    function Tag_Checks_Suppressed (E : Entity_Id) return Boolean is
4342    begin
4343       return Scope_Suppress.Tag_Checks
4344         or else (Present (E) and then Suppress_Tag_Checks (E));
4345    end Tag_Checks_Suppressed;
4346
4347 end Checks;