]> git.ipfire.org Git - thirdparty/gcc.git/blob - gcc/ada/exp_ch4.adb
638501313099329b98618f3e8afd15447839d05b
[thirdparty/gcc.git] / gcc / ada / exp_ch4.adb
1 ------------------------------------------------------------------------------
2 -- --
3 -- GNAT COMPILER COMPONENTS --
4 -- --
5 -- E X P _ C H 4 --
6 -- --
7 -- B o d y --
8 -- --
9 -- Copyright (C) 1992-2023, Free Software Foundation, Inc. --
10 -- --
11 -- GNAT is free software; you can redistribute it and/or modify it under --
12 -- terms of the GNU General Public License as published by the Free Soft- --
13 -- ware Foundation; either version 3, or (at your option) any later ver- --
14 -- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
15 -- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
16 -- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License --
17 -- for more details. You should have received a copy of the GNU General --
18 -- Public License distributed with GNAT; see file COPYING3. If not, go to --
19 -- http://www.gnu.org/licenses for a complete copy of the license. --
20 -- --
21 -- GNAT was originally developed by the GNAT team at New York University. --
22 -- Extensive contributions were provided by Ada Core Technologies Inc. --
23 -- --
24 ------------------------------------------------------------------------------
25
26 with Accessibility; use Accessibility;
27 with Aspects; use Aspects;
28 with Atree; use Atree;
29 with Checks; use Checks;
30 with Debug; use Debug;
31 with Einfo; use Einfo;
32 with Einfo.Entities; use Einfo.Entities;
33 with Einfo.Utils; use Einfo.Utils;
34 with Elists; use Elists;
35 with Errout; use Errout;
36 with Exp_Aggr; use Exp_Aggr;
37 with Exp_Ch3; use Exp_Ch3;
38 with Exp_Ch6; use Exp_Ch6;
39 with Exp_Ch7; use Exp_Ch7;
40 with Exp_Ch9; use Exp_Ch9;
41 with Exp_Disp; use Exp_Disp;
42 with Exp_Fixd; use Exp_Fixd;
43 with Exp_Intr; use Exp_Intr;
44 with Exp_Pakd; use Exp_Pakd;
45 with Exp_Tss; use Exp_Tss;
46 with Exp_Util; use Exp_Util;
47 with Freeze; use Freeze;
48 with Inline; use Inline;
49 with Lib; use Lib;
50 with Namet; use Namet;
51 with Nlists; use Nlists;
52 with Nmake; use Nmake;
53 with Opt; use Opt;
54 with Par_SCO; use Par_SCO;
55 with Restrict; use Restrict;
56 with Rident; use Rident;
57 with Rtsfind; use Rtsfind;
58 with Sem; use Sem;
59 with Sem_Aux; use Sem_Aux;
60 with Sem_Cat; use Sem_Cat;
61 with Sem_Ch3; use Sem_Ch3;
62 with Sem_Ch13; use Sem_Ch13;
63 with Sem_Eval; use Sem_Eval;
64 with Sem_Res; use Sem_Res;
65 with Sem_Type; use Sem_Type;
66 with Sem_Util; use Sem_Util;
67 with Sem_Warn; use Sem_Warn;
68 with Sinfo; use Sinfo;
69 with Sinfo.Nodes; use Sinfo.Nodes;
70 with Sinfo.Utils; use Sinfo.Utils;
71 with Snames; use Snames;
72 with Stand; use Stand;
73 with SCIL_LL; use SCIL_LL;
74 with Targparm; use Targparm;
75 with Tbuild; use Tbuild;
76 with Ttypes; use Ttypes;
77 with Uintp; use Uintp;
78 with Urealp; use Urealp;
79 with Validsw; use Validsw;
80 with Warnsw; use Warnsw;
81
82 package body Exp_Ch4 is
83
84 Too_Large_Length_For_Array : constant Unat := Uint_256;
85 -- Threshold from which we do not try to create static array temporaries in
86 -- order to eliminate dynamic stack allocations.
87
88 -----------------------
89 -- Local Subprograms --
90 -----------------------
91
92 procedure Binary_Op_Validity_Checks (N : Node_Id);
93 pragma Inline (Binary_Op_Validity_Checks);
94 -- Performs validity checks for a binary operator
95
96 procedure Build_Boolean_Array_Proc_Call
97 (N : Node_Id;
98 Op1 : Node_Id;
99 Op2 : Node_Id);
100 -- If a boolean array assignment can be done in place, build call to
101 -- corresponding library procedure.
102
103 procedure Displace_Allocator_Pointer (N : Node_Id);
104 -- Ada 2005 (AI-251): Subsidiary procedure to Expand_N_Allocator and
105 -- Expand_Allocator_Expression. Allocating class-wide interface objects
106 -- this routine displaces the pointer to the allocated object to reference
107 -- the component referencing the corresponding secondary dispatch table.
108
109 procedure Expand_Allocator_Expression (N : Node_Id);
110 -- Subsidiary to Expand_N_Allocator, for the case when the expression
111 -- is a qualified expression.
112
113 procedure Expand_Array_Comparison (N : Node_Id);
114 -- This routine handles expansion of the comparison operators (N_Op_Lt,
115 -- N_Op_Le, N_Op_Gt, N_Op_Ge) when operating on an array type. The basic
116 -- code for these operators is similar, differing only in the details of
117 -- the actual comparison call that is made. Special processing (call a
118 -- run-time routine)
119
120 function Expand_Array_Equality
121 (Nod : Node_Id;
122 Lhs : Node_Id;
123 Rhs : Node_Id;
124 Bodies : List_Id;
125 Typ : Entity_Id) return Node_Id;
126 -- Expand an array equality into a call to a function implementing this
127 -- equality, and a call to it. Loc is the location for the generated nodes.
128 -- Lhs and Rhs are the array expressions to be compared. Bodies is a list
129 -- on which to attach bodies of local functions that are created in the
130 -- process. It is the responsibility of the caller to insert those bodies
131 -- at the right place. Nod provides the Sloc value for the generated code.
132 -- Normally the types used for the generated equality routine are taken
133 -- from Lhs and Rhs. However, in some situations of generated code, the
134 -- Etype fields of Lhs and Rhs are not set yet. In such cases, Typ supplies
135 -- the type to be used for the formal parameters.
136
137 procedure Expand_Boolean_Operator (N : Node_Id);
138 -- Common expansion processing for Boolean operators (And, Or, Xor) for the
139 -- case of array type arguments.
140
141 procedure Expand_Nonbinary_Modular_Op (N : Node_Id);
142 -- When generating C code, convert nonbinary modular arithmetic operations
143 -- into code that relies on the front-end expansion of operator Mod. No
144 -- expansion is performed if N is not a nonbinary modular operand.
145
146 procedure Expand_Short_Circuit_Operator (N : Node_Id);
147 -- Common expansion processing for short-circuit boolean operators
148
149 procedure Expand_Compare_Minimize_Eliminate_Overflow (N : Node_Id);
150 -- Deal with comparison in MINIMIZED/ELIMINATED overflow mode. This is
151 -- where we allow comparison of "out of range" values.
152
153 function Expand_Composite_Equality
154 (Outer_Type : Entity_Id;
155 Nod : Node_Id;
156 Comp_Type : Entity_Id;
157 Lhs : Node_Id;
158 Rhs : Node_Id) return Node_Id;
159 -- Local recursive function used to expand equality for nested composite
160 -- types. Used by Expand_Record/Array_Equality. Nod provides the Sloc value
161 -- for generated code. Lhs and Rhs are the left and right sides for the
162 -- comparison, and Comp_Typ is the type of the objects to compare.
163 -- Outer_Type is the composite type containing a component of type
164 -- Comp_Type -- used for printing messages.
165
166 procedure Expand_Concatenate (Cnode : Node_Id; Opnds : List_Id);
167 -- Routine to expand concatenation of a sequence of two or more operands
168 -- (in the list Operands) and replace node Cnode with the result of the
169 -- concatenation. The operands can be of any appropriate type, and can
170 -- include both arrays and singleton elements.
171
172 procedure Expand_Membership_Minimize_Eliminate_Overflow (N : Node_Id);
173 -- N is an N_In membership test mode, with the overflow check mode set to
174 -- MINIMIZED or ELIMINATED, and the type of the left operand is a signed
175 -- integer type. This is a case where top level processing is required to
176 -- handle overflow checks in subtrees.
177
178 procedure Fixup_Universal_Fixed_Operation (N : Node_Id);
179 -- N is a N_Op_Divide or N_Op_Multiply node whose result is universal
180 -- fixed. We do not have such a type at runtime, so the purpose of this
181 -- routine is to find the real type by looking up the tree. We also
182 -- determine if the operation must be rounded.
183
184 procedure Get_First_Index_Bounds (T : Entity_Id; Lo, Hi : out Uint);
185 -- T is an array whose index bounds are all known at compile time. Return
186 -- the value of the low and high bounds of the first index of T.
187
188 function Get_Size_For_Range (Lo, Hi : Uint) return Uint;
189 -- Return the size of a small signed integer type covering Lo .. Hi, the
190 -- main goal being to return a size lower than that of standard types.
191
192 procedure Insert_Dereference_Action (N : Node_Id);
193 -- N is an expression whose type is an access. When the type of the
194 -- associated storage pool is derived from Checked_Pool, generate a
195 -- call to the 'Dereference' primitive operation.
196
197 function Make_Array_Comparison_Op
198 (Typ : Entity_Id;
199 Nod : Node_Id) return Node_Id;
200 -- Comparisons between arrays are expanded in line. This function produces
201 -- the body of the implementation of (a > b), where a and b are one-
202 -- dimensional arrays of some discrete type. The original node is then
203 -- expanded into the appropriate call to this function. Nod provides the
204 -- Sloc value for the generated code.
205
206 function Make_Boolean_Array_Op
207 (Typ : Entity_Id;
208 N : Node_Id) return Node_Id;
209 -- Boolean operations on boolean arrays are expanded in line. This function
210 -- produce the body for the node N, which is (a and b), (a or b), or (a xor
211 -- b). It is used only the normal case and not the packed case. The type
212 -- involved, Typ, is the Boolean array type, and the logical operations in
213 -- the body are simple boolean operations. Note that Typ is always a
214 -- constrained type (the caller has ensured this by using
215 -- Convert_To_Actual_Subtype if necessary).
216
217 function Minimized_Eliminated_Overflow_Check (N : Node_Id) return Boolean;
218 -- For signed arithmetic operations when the current overflow mode is
219 -- MINIMIZED or ELIMINATED, we must call Apply_Arithmetic_Overflow_Checks
220 -- as the first thing we do. We then return. We count on the recursive
221 -- apparatus for overflow checks to call us back with an equivalent
222 -- operation that is in CHECKED mode, avoiding a recursive entry into this
223 -- routine, and that is when we will proceed with the expansion of the
224 -- operator (e.g. converting X+0 to X, or X**2 to X*X). We cannot do
225 -- these optimizations without first making this check, since there may be
226 -- operands further down the tree that are relying on the recursive calls
227 -- triggered by the top level nodes to properly process overflow checking
228 -- and remaining expansion on these nodes. Note that this call back may be
229 -- skipped if the operation is done in Bignum mode but that's fine, since
230 -- the Bignum call takes care of everything.
231
232 procedure Narrow_Large_Operation (N : Node_Id);
233 -- Try to compute the result of a large operation in a narrower type than
234 -- its nominal type. This is mainly aimed at getting rid of operations done
235 -- in Universal_Integer that can be generated for attributes.
236
237 procedure Optimize_Length_Comparison (N : Node_Id);
238 -- Given an expression, if it is of the form X'Length op N (or the other
239 -- way round), where N is known at compile time to be 0 or 1, or something
240 -- else where the value is known to be nonnegative and in the 32-bit range,
241 -- and X is a simple entity, and op is a comparison operator, optimizes it
242 -- into a comparison of X'First and X'Last.
243
244 procedure Process_If_Case_Statements (N : Node_Id; Stmts : List_Id);
245 -- Inspect and process statement list Stmt of if or case expression N for
246 -- transient objects. If such objects are found, the routine generates code
247 -- to clean them up when the context of the expression is evaluated.
248
249 procedure Process_Transient_In_Expression
250 (Obj_Decl : Node_Id;
251 Expr : Node_Id;
252 Stmts : List_Id);
253 -- Subsidiary routine to the expansion of expression_with_actions, if and
254 -- case expressions. Generate all necessary code to finalize a transient
255 -- object when the enclosing context is elaborated or evaluated. Obj_Decl
256 -- denotes the declaration of the transient object, which is usually the
257 -- result of a controlled function call. Expr denotes the expression with
258 -- actions, if expression, or case expression node. Stmts denotes the
259 -- statement list which contains Decl, either at the top level or within a
260 -- nested construct.
261
262 procedure Rewrite_Comparison (N : Node_Id);
263 -- If N is the node for a comparison whose outcome can be determined at
264 -- compile time, then the node N can be rewritten with True or False. If
265 -- the outcome cannot be determined at compile time, the call has no
266 -- effect. If N is a type conversion, then this processing is applied to
267 -- its expression. If N is neither comparison nor a type conversion, the
268 -- call has no effect.
269
270 procedure Tagged_Membership
271 (N : Node_Id;
272 SCIL_Node : out Node_Id;
273 Result : out Node_Id);
274 -- Construct the expression corresponding to the tagged membership test.
275 -- Deals with a second operand being (or not) a class-wide type.
276
277 function Safe_In_Place_Array_Op
278 (Lhs : Node_Id;
279 Op1 : Node_Id;
280 Op2 : Node_Id) return Boolean;
281 -- In the context of an assignment, where the right-hand side is a boolean
282 -- operation on arrays, check whether operation can be performed in place.
283
284 procedure Unary_Op_Validity_Checks (N : Node_Id);
285 pragma Inline (Unary_Op_Validity_Checks);
286 -- Performs validity checks for a unary operator
287
288 -------------------------------
289 -- Binary_Op_Validity_Checks --
290 -------------------------------
291
292 procedure Binary_Op_Validity_Checks (N : Node_Id) is
293 begin
294 if Validity_Checks_On and Validity_Check_Operands then
295 Ensure_Valid (Left_Opnd (N));
296 Ensure_Valid (Right_Opnd (N));
297 end if;
298 end Binary_Op_Validity_Checks;
299
300 ------------------------------------
301 -- Build_Boolean_Array_Proc_Call --
302 ------------------------------------
303
304 procedure Build_Boolean_Array_Proc_Call
305 (N : Node_Id;
306 Op1 : Node_Id;
307 Op2 : Node_Id)
308 is
309 Loc : constant Source_Ptr := Sloc (N);
310 Kind : constant Node_Kind := Nkind (Expression (N));
311 Target : constant Node_Id :=
312 Make_Attribute_Reference (Loc,
313 Prefix => Name (N),
314 Attribute_Name => Name_Address);
315
316 Arg1 : Node_Id := Op1;
317 Arg2 : Node_Id := Op2;
318 Call_Node : Node_Id;
319 Proc_Name : Entity_Id;
320
321 begin
322 if Kind = N_Op_Not then
323 if Nkind (Op1) in N_Binary_Op then
324
325 -- Use negated version of the binary operators
326
327 if Nkind (Op1) = N_Op_And then
328 Proc_Name := RTE (RE_Vector_Nand);
329
330 elsif Nkind (Op1) = N_Op_Or then
331 Proc_Name := RTE (RE_Vector_Nor);
332
333 else pragma Assert (Nkind (Op1) = N_Op_Xor);
334 Proc_Name := RTE (RE_Vector_Xor);
335 end if;
336
337 Call_Node :=
338 Make_Procedure_Call_Statement (Loc,
339 Name => New_Occurrence_Of (Proc_Name, Loc),
340
341 Parameter_Associations => New_List (
342 Target,
343 Make_Attribute_Reference (Loc,
344 Prefix => Left_Opnd (Op1),
345 Attribute_Name => Name_Address),
346
347 Make_Attribute_Reference (Loc,
348 Prefix => Right_Opnd (Op1),
349 Attribute_Name => Name_Address),
350
351 Make_Attribute_Reference (Loc,
352 Prefix => Left_Opnd (Op1),
353 Attribute_Name => Name_Length)));
354
355 else
356 Proc_Name := RTE (RE_Vector_Not);
357
358 Call_Node :=
359 Make_Procedure_Call_Statement (Loc,
360 Name => New_Occurrence_Of (Proc_Name, Loc),
361 Parameter_Associations => New_List (
362 Target,
363
364 Make_Attribute_Reference (Loc,
365 Prefix => Op1,
366 Attribute_Name => Name_Address),
367
368 Make_Attribute_Reference (Loc,
369 Prefix => Op1,
370 Attribute_Name => Name_Length)));
371 end if;
372
373 else
374 -- We use the following equivalences:
375
376 -- (not X) or (not Y) = not (X and Y) = Nand (X, Y)
377 -- (not X) and (not Y) = not (X or Y) = Nor (X, Y)
378 -- (not X) xor (not Y) = X xor Y
379 -- X xor (not Y) = not (X xor Y) = Nxor (X, Y)
380
381 if Nkind (Op1) = N_Op_Not then
382 Arg1 := Right_Opnd (Op1);
383 Arg2 := Right_Opnd (Op2);
384
385 if Kind = N_Op_And then
386 Proc_Name := RTE (RE_Vector_Nor);
387 elsif Kind = N_Op_Or then
388 Proc_Name := RTE (RE_Vector_Nand);
389 else
390 Proc_Name := RTE (RE_Vector_Xor);
391 end if;
392
393 else
394 if Kind = N_Op_And then
395 Proc_Name := RTE (RE_Vector_And);
396 elsif Kind = N_Op_Or then
397 Proc_Name := RTE (RE_Vector_Or);
398 elsif Nkind (Op2) = N_Op_Not then
399 Proc_Name := RTE (RE_Vector_Nxor);
400 Arg2 := Right_Opnd (Op2);
401 else
402 Proc_Name := RTE (RE_Vector_Xor);
403 end if;
404 end if;
405
406 Call_Node :=
407 Make_Procedure_Call_Statement (Loc,
408 Name => New_Occurrence_Of (Proc_Name, Loc),
409 Parameter_Associations => New_List (
410 Target,
411 Make_Attribute_Reference (Loc,
412 Prefix => Arg1,
413 Attribute_Name => Name_Address),
414 Make_Attribute_Reference (Loc,
415 Prefix => Arg2,
416 Attribute_Name => Name_Address),
417 Make_Attribute_Reference (Loc,
418 Prefix => Arg1,
419 Attribute_Name => Name_Length)));
420 end if;
421
422 Rewrite (N, Call_Node);
423 Analyze (N);
424
425 exception
426 when RE_Not_Available =>
427 return;
428 end Build_Boolean_Array_Proc_Call;
429
430 -----------------------
431 -- Build_Eq_Call --
432 -----------------------
433
434 function Build_Eq_Call
435 (Typ : Entity_Id;
436 Loc : Source_Ptr;
437 Lhs : Node_Id;
438 Rhs : Node_Id) return Node_Id
439 is
440 Eq : constant Entity_Id := Get_User_Defined_Equality (Typ);
441
442 begin
443 if Present (Eq) then
444 if Is_Abstract_Subprogram (Eq) then
445 return Make_Raise_Program_Error (Loc,
446 Reason => PE_Explicit_Raise);
447
448 else
449 return
450 Make_Function_Call (Loc,
451 Name => New_Occurrence_Of (Eq, Loc),
452 Parameter_Associations => New_List (Lhs, Rhs));
453 end if;
454 end if;
455
456 -- If not found, predefined operation will be used
457
458 return Empty;
459 end Build_Eq_Call;
460
461 --------------------------------
462 -- Displace_Allocator_Pointer --
463 --------------------------------
464
465 procedure Displace_Allocator_Pointer (N : Node_Id) is
466 Loc : constant Source_Ptr := Sloc (N);
467 Orig_Node : constant Node_Id := Original_Node (N);
468 Dtyp : Entity_Id;
469 Etyp : Entity_Id;
470 PtrT : Entity_Id;
471
472 begin
473 -- Do nothing in case of VM targets: the virtual machine will handle
474 -- interfaces directly.
475
476 if not Tagged_Type_Expansion then
477 return;
478 end if;
479
480 pragma Assert (Nkind (N) = N_Identifier
481 and then Nkind (Orig_Node) = N_Allocator);
482
483 PtrT := Etype (Orig_Node);
484 Dtyp := Available_View (Designated_Type (PtrT));
485 Etyp := Etype (Expression (Orig_Node));
486
487 if Is_Class_Wide_Type (Dtyp) and then Is_Interface (Dtyp) then
488
489 -- If the type of the allocator expression is not an interface type
490 -- we can generate code to reference the record component containing
491 -- the pointer to the secondary dispatch table.
492
493 if not Is_Interface (Etyp) then
494 declare
495 Saved_Typ : constant Entity_Id := Etype (Orig_Node);
496
497 begin
498 -- 1) Get access to the allocated object
499
500 Rewrite (N,
501 Make_Explicit_Dereference (Loc, Relocate_Node (N)));
502 Set_Etype (N, Etyp);
503 Set_Analyzed (N);
504
505 -- 2) Add the conversion to displace the pointer to reference
506 -- the secondary dispatch table.
507
508 Rewrite (N, Convert_To (Dtyp, Relocate_Node (N)));
509 Analyze_And_Resolve (N, Dtyp);
510
511 -- 3) The 'access to the secondary dispatch table will be used
512 -- as the value returned by the allocator.
513
514 Rewrite (N,
515 Make_Attribute_Reference (Loc,
516 Prefix => Relocate_Node (N),
517 Attribute_Name => Name_Access));
518 Set_Etype (N, Saved_Typ);
519 Set_Analyzed (N);
520 end;
521
522 -- If the type of the allocator expression is an interface type we
523 -- generate a run-time call to displace "this" to reference the
524 -- component containing the pointer to the secondary dispatch table
525 -- or else raise Constraint_Error if the actual object does not
526 -- implement the target interface. This case corresponds to the
527 -- following example:
528
529 -- function Op (Obj : Iface_1'Class) return access Iface_2'Class is
530 -- begin
531 -- return new Iface_2'Class'(Obj);
532 -- end Op;
533
534 else
535 Rewrite (N,
536 Unchecked_Convert_To (PtrT,
537 Make_Function_Call (Loc,
538 Name => New_Occurrence_Of (RTE (RE_Displace), Loc),
539 Parameter_Associations => New_List (
540 Unchecked_Convert_To (RTE (RE_Address),
541 Relocate_Node (N)),
542
543 New_Occurrence_Of
544 (Elists.Node
545 (First_Elmt
546 (Access_Disp_Table (Etype (Base_Type (Dtyp))))),
547 Loc)))));
548 Analyze_And_Resolve (N, PtrT);
549 end if;
550 end if;
551 end Displace_Allocator_Pointer;
552
553 ---------------------------------
554 -- Expand_Allocator_Expression --
555 ---------------------------------
556
557 procedure Expand_Allocator_Expression (N : Node_Id) is
558 Loc : constant Source_Ptr := Sloc (N);
559 Exp : constant Node_Id := Expression (Expression (N));
560 PtrT : constant Entity_Id := Etype (N);
561 DesigT : constant Entity_Id := Designated_Type (PtrT);
562
563 -- Local variables
564
565 Indic : constant Node_Id := Subtype_Mark (Expression (N));
566 T : constant Entity_Id := Entity (Indic);
567 Adj_Call : Node_Id;
568 Aggr_In_Place : Boolean;
569 Node : Node_Id;
570 Temp : Entity_Id;
571 Temp_Decl : Node_Id;
572
573 TagT : Entity_Id := Empty;
574 -- Type used as source for tag assignment
575
576 TagR : Node_Id := Empty;
577 -- Target reference for tag assignment
578
579 -- Start of processing for Expand_Allocator_Expression
580
581 begin
582 -- Handle call to C++ constructor
583
584 if Is_CPP_Constructor_Call (Exp) then
585 Make_CPP_Constructor_Call_In_Allocator
586 (Allocator => N,
587 Function_Call => Exp);
588 return;
589 end if;
590
591 -- If we have:
592 -- type A is access T1;
593 -- X : A := new T2'(...);
594 -- T1 and T2 can be different subtypes, and we might need to check
595 -- both constraints. First check against the type of the qualified
596 -- expression.
597
598 Apply_Constraint_Check (Exp, T, No_Sliding => True);
599
600 Apply_Predicate_Check (Exp, T);
601
602 -- Check that any anonymous access discriminants are suitable
603 -- for use in an allocator.
604
605 -- Note: This check is performed here instead of during analysis so that
606 -- we can check against the fully resolved etype of Exp.
607
608 if Is_Entity_Name (Exp)
609 and then Has_Anonymous_Access_Discriminant (Etype (Exp))
610 and then Static_Accessibility_Level (Exp, Object_Decl_Level)
611 > Static_Accessibility_Level (N, Object_Decl_Level)
612 then
613 -- A dynamic check and a warning are generated when we are within
614 -- an instance.
615
616 if In_Instance then
617 Insert_Action (N,
618 Make_Raise_Program_Error (Loc,
619 Reason => PE_Accessibility_Check_Failed));
620
621 Error_Msg_Warn := SPARK_Mode /= On;
622 Error_Msg_N ("anonymous access discriminant is too deep for use"
623 & " in allocator<<", N);
624 Error_Msg_N ("\Program_Error [<<", N);
625
626 -- Otherwise, make the error static
627
628 else
629 Error_Msg_N ("anonymous access discriminant is too deep for use"
630 & " in allocator", N);
631 end if;
632 end if;
633
634 if Do_Range_Check (Exp) then
635 Generate_Range_Check (Exp, T, CE_Range_Check_Failed);
636 end if;
637
638 -- A check is also needed in cases where the designated subtype is
639 -- constrained and differs from the subtype given in the qualified
640 -- expression. Note that the check on the qualified expression does
641 -- not allow sliding, but this check does (a relaxation from Ada 83).
642
643 if Is_Constrained (DesigT)
644 and then not Subtypes_Statically_Match (T, DesigT)
645 then
646 Apply_Constraint_Check (Exp, DesigT, No_Sliding => False);
647
648 Apply_Predicate_Check (Exp, DesigT);
649
650 if Do_Range_Check (Exp) then
651 Generate_Range_Check (Exp, DesigT, CE_Range_Check_Failed);
652 end if;
653 end if;
654
655 if Nkind (Exp) = N_Raise_Constraint_Error then
656 Rewrite (N, New_Copy (Exp));
657 Set_Etype (N, PtrT);
658 return;
659 end if;
660
661 Aggr_In_Place := Is_Delayed_Aggregate (Exp);
662
663 -- Case of tagged type or type requiring finalization
664
665 if Is_Tagged_Type (T) or else Needs_Finalization (T) then
666
667 -- Ada 2005 (AI-318-02): If the initialization expression is a call
668 -- to a build-in-place function, then access to the allocated object
669 -- must be passed to the function.
670
671 if Is_Build_In_Place_Function_Call (Exp) then
672 Make_Build_In_Place_Call_In_Allocator (N, Exp);
673 Apply_Accessibility_Check_For_Allocator
674 (N, Exp, N, Built_In_Place => True);
675 return;
676
677 -- Ada 2005 (AI-318-02): Specialization of the previous case for
678 -- expressions containing a build-in-place function call whose
679 -- returned object covers interface types, and Expr has calls to
680 -- Ada.Tags.Displace to displace the pointer to the returned build-
681 -- in-place object to reference the secondary dispatch table of a
682 -- covered interface type.
683
684 elsif Present (Unqual_BIP_Iface_Function_Call (Exp)) then
685 Make_Build_In_Place_Iface_Call_In_Allocator (N, Exp);
686 Apply_Accessibility_Check_For_Allocator
687 (N, Exp, N, Built_In_Place => True);
688 return;
689 end if;
690
691 -- Actions inserted before:
692 -- Temp : constant ptr_T := new T'(Expression);
693 -- Temp._tag = T'tag; -- when not class-wide
694 -- [Deep_]Adjust (Temp.all);
695
696 -- We analyze by hand the new internal allocator to avoid any
697 -- recursion and inappropriate call to Initialize.
698
699 -- We don't want to remove side effects when the expression must be
700 -- built in place and we don't need it when there is no storage pool
701 -- or this is a return/secondary stack allocation.
702
703 if not Aggr_In_Place
704 and then Present (Storage_Pool (N))
705 and then not Is_RTE (Storage_Pool (N), RE_RS_Pool)
706 and then not Is_RTE (Storage_Pool (N), RE_SS_Pool)
707 then
708 Remove_Side_Effects (Exp);
709 end if;
710
711 Temp := Make_Temporary (Loc, 'P', N);
712
713 -- For a class wide allocation generate the following code:
714
715 -- type Equiv_Record is record ... end record;
716 -- implicit subtype CW is <Class_Wide_Subytpe>;
717 -- temp : PtrT := new CW'(CW!(expr));
718
719 if Is_Class_Wide_Type (T) then
720 Expand_Subtype_From_Expr (Empty, T, Indic, Exp);
721
722 -- Ada 2005 (AI-251): If the expression is a class-wide interface
723 -- object we generate code to move up "this" to reference the
724 -- base of the object before allocating the new object.
725
726 -- Note that Exp'Address is recursively expanded into a call
727 -- to Base_Address (Exp.Tag)
728
729 if Is_Class_Wide_Type (Etype (Exp))
730 and then Is_Interface (Etype (Exp))
731 and then Tagged_Type_Expansion
732 then
733 Set_Expression
734 (Expression (N),
735 Unchecked_Convert_To (Entity (Indic),
736 Make_Explicit_Dereference (Loc,
737 Unchecked_Convert_To (RTE (RE_Tag_Ptr),
738 Make_Attribute_Reference (Loc,
739 Prefix => Exp,
740 Attribute_Name => Name_Address)))));
741 else
742 Set_Expression
743 (Expression (N),
744 Unchecked_Convert_To (Entity (Indic), Exp));
745 end if;
746
747 Analyze_And_Resolve (Expression (N), Entity (Indic));
748 end if;
749
750 -- Processing for allocators returning non-interface types
751
752 if not Is_Interface (DesigT) then
753 if Aggr_In_Place then
754 Temp_Decl :=
755 Make_Object_Declaration (Loc,
756 Defining_Identifier => Temp,
757 Object_Definition => New_Occurrence_Of (PtrT, Loc),
758 Expression =>
759 Make_Allocator (Loc,
760 Expression =>
761 New_Occurrence_Of (Etype (Exp), Loc)));
762
763 -- Copy the Comes_From_Source flag for the allocator we just
764 -- built, since logically this allocator is a replacement of
765 -- the original allocator node. This is for proper handling of
766 -- restriction No_Implicit_Heap_Allocations.
767
768 Preserve_Comes_From_Source
769 (Expression (Temp_Decl), N);
770
771 Set_No_Initialization (Expression (Temp_Decl));
772 Insert_Action (N, Temp_Decl);
773
774 Build_Allocate_Deallocate_Proc (Temp_Decl, True);
775 Convert_Aggr_In_Allocator (N, Temp_Decl, Exp);
776
777 else
778 Node := Relocate_Node (N);
779 Set_Analyzed (Node);
780
781 Temp_Decl :=
782 Make_Object_Declaration (Loc,
783 Defining_Identifier => Temp,
784 Constant_Present => True,
785 Object_Definition => New_Occurrence_Of (PtrT, Loc),
786 Expression => Node);
787
788 Insert_Action (N, Temp_Decl);
789 Build_Allocate_Deallocate_Proc (Temp_Decl, True);
790 end if;
791
792 -- Ada 2005 (AI-251): Handle allocators whose designated type is an
793 -- interface type. In this case we use the type of the qualified
794 -- expression to allocate the object.
795
796 else
797 declare
798 Def_Id : constant Entity_Id := Make_Temporary (Loc, 'T');
799 New_Decl : Node_Id;
800
801 begin
802 New_Decl :=
803 Make_Full_Type_Declaration (Loc,
804 Defining_Identifier => Def_Id,
805 Type_Definition =>
806 Make_Access_To_Object_Definition (Loc,
807 All_Present => True,
808 Null_Exclusion_Present => False,
809 Constant_Present =>
810 Is_Access_Constant (Etype (N)),
811 Subtype_Indication =>
812 New_Occurrence_Of (Etype (Exp), Loc)));
813
814 Insert_Action (N, New_Decl);
815
816 -- Inherit the allocation-related attributes from the original
817 -- access type.
818
819 Set_Finalization_Master
820 (Def_Id, Finalization_Master (PtrT));
821
822 Set_Associated_Storage_Pool
823 (Def_Id, Associated_Storage_Pool (PtrT));
824
825 -- Declare the object using the previous type declaration
826
827 if Aggr_In_Place then
828 Temp_Decl :=
829 Make_Object_Declaration (Loc,
830 Defining_Identifier => Temp,
831 Object_Definition => New_Occurrence_Of (Def_Id, Loc),
832 Expression =>
833 Make_Allocator (Loc,
834 New_Occurrence_Of (Etype (Exp), Loc)));
835
836 -- Copy the Comes_From_Source flag for the allocator we just
837 -- built, since logically this allocator is a replacement of
838 -- the original allocator node. This is for proper handling
839 -- of restriction No_Implicit_Heap_Allocations.
840
841 Set_Comes_From_Source
842 (Expression (Temp_Decl), Comes_From_Source (N));
843
844 Set_No_Initialization (Expression (Temp_Decl));
845 Insert_Action (N, Temp_Decl);
846
847 Build_Allocate_Deallocate_Proc (Temp_Decl, True);
848 Convert_Aggr_In_Allocator (N, Temp_Decl, Exp);
849
850 else
851 Node := Relocate_Node (N);
852 Set_Analyzed (Node);
853
854 Temp_Decl :=
855 Make_Object_Declaration (Loc,
856 Defining_Identifier => Temp,
857 Constant_Present => True,
858 Object_Definition => New_Occurrence_Of (Def_Id, Loc),
859 Expression => Node);
860
861 Insert_Action (N, Temp_Decl);
862 Build_Allocate_Deallocate_Proc (Temp_Decl, True);
863 end if;
864
865 -- Generate an additional object containing the address of the
866 -- returned object. The type of this second object declaration
867 -- is the correct type required for the common processing that
868 -- is still performed by this subprogram. The displacement of
869 -- this pointer to reference the component associated with the
870 -- interface type will be done at the end of common processing.
871
872 New_Decl :=
873 Make_Object_Declaration (Loc,
874 Defining_Identifier => Make_Temporary (Loc, 'P'),
875 Object_Definition => New_Occurrence_Of (PtrT, Loc),
876 Expression =>
877 Unchecked_Convert_To (PtrT,
878 New_Occurrence_Of (Temp, Loc)));
879
880 Insert_Action (N, New_Decl);
881
882 Temp_Decl := New_Decl;
883 Temp := Defining_Identifier (New_Decl);
884 end;
885 end if;
886
887 -- Generate the tag assignment
888
889 -- Suppress the tag assignment for VM targets because VM tags are
890 -- represented implicitly in objects.
891
892 if not Tagged_Type_Expansion then
893 null;
894
895 -- Ada 2005 (AI-251): Suppress the tag assignment with class-wide
896 -- interface objects because in this case the tag does not change.
897
898 elsif Is_Interface (Directly_Designated_Type (Etype (N))) then
899 pragma Assert (Is_Class_Wide_Type
900 (Directly_Designated_Type (Etype (N))));
901 null;
902
903 -- Likewise if the allocator is made for a special return object
904
905 elsif For_Special_Return_Object (N) then
906 null;
907
908 elsif Is_Tagged_Type (T) and then not Is_Class_Wide_Type (T) then
909 TagT := T;
910 TagR :=
911 Make_Explicit_Dereference (Loc,
912 Prefix => New_Occurrence_Of (Temp, Loc));
913
914 elsif Is_Private_Type (T)
915 and then Is_Tagged_Type (Underlying_Type (T))
916 then
917 TagT := Underlying_Type (T);
918 TagR :=
919 Unchecked_Convert_To (Underlying_Type (T),
920 Make_Explicit_Dereference (Loc,
921 Prefix => New_Occurrence_Of (Temp, Loc)));
922 end if;
923
924 if Present (TagT) then
925 Insert_Action (N,
926 Make_Tag_Assignment_From_Type
927 (Loc, TagR, Underlying_Type (TagT)));
928 end if;
929
930 -- Generate an Adjust call if the object will be moved. In Ada 2005,
931 -- the object may be inherently limited, in which case there is no
932 -- Adjust procedure, and the object is built in place. In Ada 95, the
933 -- object can be limited but not inherently limited if this allocator
934 -- came from a return statement (we're allocating the result on the
935 -- secondary stack); in that case, the object will be moved, so we do
936 -- want to Adjust. But the call is always skipped if the allocator is
937 -- made for a special return object because it's generated elsewhere.
938
939 -- Needs_Finalization (DesigT) may differ from Needs_Finalization (T)
940 -- if one of the two types is class-wide, and the other is not.
941
942 if Needs_Finalization (DesigT)
943 and then Needs_Finalization (T)
944 and then not Is_Limited_View (T)
945 and then not Aggr_In_Place
946 and then Nkind (Exp) /= N_Function_Call
947 and then not For_Special_Return_Object (N)
948 then
949 -- An unchecked conversion is needed in the classwide case because
950 -- the designated type can be an ancestor of the subtype mark of
951 -- the allocator.
952
953 Adj_Call :=
954 Make_Adjust_Call
955 (Obj_Ref =>
956 Unchecked_Convert_To (T,
957 Make_Explicit_Dereference (Loc,
958 Prefix => New_Occurrence_Of (Temp, Loc))),
959 Typ => T);
960
961 if Present (Adj_Call) then
962 Insert_Action (N, Adj_Call);
963 end if;
964 end if;
965
966 -- Note: the accessibility check must be inserted after the call to
967 -- [Deep_]Adjust to ensure proper completion of the assignment.
968
969 Apply_Accessibility_Check_For_Allocator (N, Exp, Temp);
970
971 Rewrite (N, New_Occurrence_Of (Temp, Loc));
972 Analyze_And_Resolve (N, PtrT);
973
974 -- Ada 2005 (AI-251): Displace the pointer to reference the record
975 -- component containing the secondary dispatch table of the interface
976 -- type.
977
978 if Is_Interface (DesigT) then
979 Displace_Allocator_Pointer (N);
980 end if;
981
982 -- Always force the generation of a temporary for aggregates when
983 -- generating C code, to simplify the work in the code generator.
984
985 elsif Aggr_In_Place
986 or else (Modify_Tree_For_C and then Nkind (Exp) = N_Aggregate)
987 then
988 Temp := Make_Temporary (Loc, 'P', N);
989 Temp_Decl :=
990 Make_Object_Declaration (Loc,
991 Defining_Identifier => Temp,
992 Object_Definition => New_Occurrence_Of (PtrT, Loc),
993 Expression =>
994 Make_Allocator (Loc,
995 Expression => New_Occurrence_Of (Etype (Exp), Loc)));
996
997 -- Copy the Comes_From_Source flag for the allocator we just built,
998 -- since logically this allocator is a replacement of the original
999 -- allocator node. This is for proper handling of restriction
1000 -- No_Implicit_Heap_Allocations.
1001
1002 Set_Comes_From_Source
1003 (Expression (Temp_Decl), Comes_From_Source (N));
1004
1005 Set_No_Initialization (Expression (Temp_Decl));
1006 Insert_Action (N, Temp_Decl);
1007
1008 Build_Allocate_Deallocate_Proc (Temp_Decl, True);
1009 Convert_Aggr_In_Allocator (N, Temp_Decl, Exp);
1010
1011 Rewrite (N, New_Occurrence_Of (Temp, Loc));
1012 Analyze_And_Resolve (N, PtrT);
1013
1014 elsif Is_Access_Type (T) and then Can_Never_Be_Null (T) then
1015 Install_Null_Excluding_Check (Exp);
1016
1017 elsif Is_Access_Type (DesigT)
1018 and then Nkind (Exp) = N_Allocator
1019 and then Nkind (Expression (Exp)) /= N_Qualified_Expression
1020 then
1021 -- Apply constraint to designated subtype indication
1022
1023 Apply_Constraint_Check
1024 (Expression (Exp), Designated_Type (DesigT), No_Sliding => True);
1025
1026 if Nkind (Expression (Exp)) = N_Raise_Constraint_Error then
1027
1028 -- Propagate constraint_error to enclosing allocator
1029
1030 Rewrite (Exp, New_Copy (Expression (Exp)));
1031 end if;
1032
1033 else
1034 Build_Allocate_Deallocate_Proc (N, True);
1035
1036 -- For an access to unconstrained packed array, GIGI needs to see an
1037 -- expression with a constrained subtype in order to compute the
1038 -- proper size for the allocator.
1039
1040 if Is_Packed_Array (T)
1041 and then not Is_Constrained (T)
1042 then
1043 declare
1044 ConstrT : constant Entity_Id := Make_Temporary (Loc, 'A');
1045 Internal_Exp : constant Node_Id := Relocate_Node (Exp);
1046 begin
1047 Insert_Action (Exp,
1048 Make_Subtype_Declaration (Loc,
1049 Defining_Identifier => ConstrT,
1050 Subtype_Indication =>
1051 Make_Subtype_From_Expr (Internal_Exp, T)));
1052 Freeze_Itype (ConstrT, Exp);
1053 Rewrite (Exp, OK_Convert_To (ConstrT, Internal_Exp));
1054 end;
1055 end if;
1056
1057 -- Ada 2005 (AI-318-02): If the initialization expression is a call
1058 -- to a build-in-place function, then access to the allocated object
1059 -- must be passed to the function.
1060
1061 if Is_Build_In_Place_Function_Call (Exp) then
1062 Make_Build_In_Place_Call_In_Allocator (N, Exp);
1063 end if;
1064 end if;
1065
1066 exception
1067 when RE_Not_Available =>
1068 return;
1069 end Expand_Allocator_Expression;
1070
1071 -----------------------------
1072 -- Expand_Array_Comparison --
1073 -----------------------------
1074
1075 -- Expansion is only required in the case of array types. For the unpacked
1076 -- case, an appropriate runtime routine is called. For packed cases, and
1077 -- also in some other cases where a runtime routine cannot be called, the
1078 -- form of the expansion is:
1079
1080 -- [body for greater_nn; boolean_expression]
1081
1082 -- The body is built by Make_Array_Comparison_Op, and the form of the
1083 -- Boolean expression depends on the operator involved.
1084
1085 procedure Expand_Array_Comparison (N : Node_Id) is
1086 Loc : constant Source_Ptr := Sloc (N);
1087 Op1 : Node_Id := Left_Opnd (N);
1088 Op2 : Node_Id := Right_Opnd (N);
1089 Typ1 : constant Entity_Id := Base_Type (Etype (Op1));
1090 Ctyp : constant Entity_Id := Component_Type (Typ1);
1091
1092 Expr : Node_Id;
1093 Func_Body : Node_Id;
1094 Func_Name : Entity_Id;
1095
1096 Comp : RE_Id;
1097
1098 Byte_Addressable : constant Boolean := System_Storage_Unit = Byte'Size;
1099 -- True for byte addressable target
1100
1101 function Length_Less_Than_4 (Opnd : Node_Id) return Boolean;
1102 -- Returns True if the length of the given operand is known to be less
1103 -- than 4. Returns False if this length is known to be four or greater
1104 -- or is not known at compile time.
1105
1106 ------------------------
1107 -- Length_Less_Than_4 --
1108 ------------------------
1109
1110 function Length_Less_Than_4 (Opnd : Node_Id) return Boolean is
1111 Otyp : constant Entity_Id := Etype (Opnd);
1112
1113 begin
1114 if Ekind (Otyp) = E_String_Literal_Subtype then
1115 return String_Literal_Length (Otyp) < 4;
1116
1117 elsif Compile_Time_Known_Bounds (Otyp) then
1118 declare
1119 Lo, Hi : Uint;
1120
1121 begin
1122 Get_First_Index_Bounds (Otyp, Lo, Hi);
1123 return Hi < Lo + 3;
1124 end;
1125
1126 else
1127 return False;
1128 end if;
1129 end Length_Less_Than_4;
1130
1131 -- Start of processing for Expand_Array_Comparison
1132
1133 begin
1134 -- Deal first with unpacked case, where we can call a runtime routine
1135 -- except that we avoid this for targets for which are not addressable
1136 -- by bytes.
1137
1138 if not Is_Bit_Packed_Array (Typ1) and then Byte_Addressable then
1139 -- The call we generate is:
1140
1141 -- Compare_Array_xn[_Unaligned]
1142 -- (left'address, right'address, left'length, right'length) <op> 0
1143
1144 -- x = U for unsigned, S for signed
1145 -- n = 8,16,32,64,128 for component size
1146 -- Add _Unaligned if length < 4 and component size is 8.
1147 -- <op> is the standard comparison operator
1148
1149 if Component_Size (Typ1) = 8 then
1150 if Length_Less_Than_4 (Op1)
1151 or else
1152 Length_Less_Than_4 (Op2)
1153 then
1154 if Is_Unsigned_Type (Ctyp) then
1155 Comp := RE_Compare_Array_U8_Unaligned;
1156 else
1157 Comp := RE_Compare_Array_S8_Unaligned;
1158 end if;
1159
1160 else
1161 if Is_Unsigned_Type (Ctyp) then
1162 Comp := RE_Compare_Array_U8;
1163 else
1164 Comp := RE_Compare_Array_S8;
1165 end if;
1166 end if;
1167
1168 elsif Component_Size (Typ1) = 16 then
1169 if Is_Unsigned_Type (Ctyp) then
1170 Comp := RE_Compare_Array_U16;
1171 else
1172 Comp := RE_Compare_Array_S16;
1173 end if;
1174
1175 elsif Component_Size (Typ1) = 32 then
1176 if Is_Unsigned_Type (Ctyp) then
1177 Comp := RE_Compare_Array_U32;
1178 else
1179 Comp := RE_Compare_Array_S32;
1180 end if;
1181
1182 elsif Component_Size (Typ1) = 64 then
1183 if Is_Unsigned_Type (Ctyp) then
1184 Comp := RE_Compare_Array_U64;
1185 else
1186 Comp := RE_Compare_Array_S64;
1187 end if;
1188
1189 else pragma Assert (Component_Size (Typ1) = 128);
1190 if Is_Unsigned_Type (Ctyp) then
1191 Comp := RE_Compare_Array_U128;
1192 else
1193 Comp := RE_Compare_Array_S128;
1194 end if;
1195 end if;
1196
1197 if RTE_Available (Comp) then
1198
1199 -- Expand to a call only if the runtime function is available,
1200 -- otherwise fall back to inline code.
1201
1202 Remove_Side_Effects (Op1, Name_Req => True);
1203 Remove_Side_Effects (Op2, Name_Req => True);
1204
1205 declare
1206 Comp_Call : constant Node_Id :=
1207 Make_Function_Call (Loc,
1208 Name => New_Occurrence_Of (RTE (Comp), Loc),
1209
1210 Parameter_Associations => New_List (
1211 Make_Attribute_Reference (Loc,
1212 Prefix => Relocate_Node (Op1),
1213 Attribute_Name => Name_Address),
1214
1215 Make_Attribute_Reference (Loc,
1216 Prefix => Relocate_Node (Op2),
1217 Attribute_Name => Name_Address),
1218
1219 Make_Attribute_Reference (Loc,
1220 Prefix => Relocate_Node (Op1),
1221 Attribute_Name => Name_Length),
1222
1223 Make_Attribute_Reference (Loc,
1224 Prefix => Relocate_Node (Op2),
1225 Attribute_Name => Name_Length)));
1226
1227 Zero : constant Node_Id :=
1228 Make_Integer_Literal (Loc,
1229 Intval => Uint_0);
1230
1231 Comp_Op : Node_Id;
1232
1233 begin
1234 case Nkind (N) is
1235 when N_Op_Lt =>
1236 Comp_Op := Make_Op_Lt (Loc, Comp_Call, Zero);
1237 when N_Op_Le =>
1238 Comp_Op := Make_Op_Le (Loc, Comp_Call, Zero);
1239 when N_Op_Gt =>
1240 Comp_Op := Make_Op_Gt (Loc, Comp_Call, Zero);
1241 when N_Op_Ge =>
1242 Comp_Op := Make_Op_Ge (Loc, Comp_Call, Zero);
1243 when others =>
1244 raise Program_Error;
1245 end case;
1246
1247 Rewrite (N, Comp_Op);
1248 end;
1249
1250 Analyze_And_Resolve (N, Standard_Boolean);
1251 return;
1252 end if;
1253 end if;
1254
1255 -- Cases where we cannot make runtime call
1256
1257 -- For (a <= b) we convert to not (a > b)
1258
1259 if Chars (N) = Name_Op_Le then
1260 Rewrite (N,
1261 Make_Op_Not (Loc,
1262 Right_Opnd =>
1263 Make_Op_Gt (Loc,
1264 Left_Opnd => Op1,
1265 Right_Opnd => Op2)));
1266 Analyze_And_Resolve (N, Standard_Boolean);
1267 return;
1268
1269 -- For < the Boolean expression is
1270 -- greater__nn (op2, op1)
1271
1272 elsif Chars (N) = Name_Op_Lt then
1273 Func_Body := Make_Array_Comparison_Op (Typ1, N);
1274
1275 -- Switch operands
1276
1277 Op1 := Right_Opnd (N);
1278 Op2 := Left_Opnd (N);
1279
1280 -- For (a >= b) we convert to not (a < b)
1281
1282 elsif Chars (N) = Name_Op_Ge then
1283 Rewrite (N,
1284 Make_Op_Not (Loc,
1285 Right_Opnd =>
1286 Make_Op_Lt (Loc,
1287 Left_Opnd => Op1,
1288 Right_Opnd => Op2)));
1289 Analyze_And_Resolve (N, Standard_Boolean);
1290 return;
1291
1292 -- For > the Boolean expression is
1293 -- greater__nn (op1, op2)
1294
1295 else
1296 pragma Assert (Chars (N) = Name_Op_Gt);
1297 Func_Body := Make_Array_Comparison_Op (Typ1, N);
1298 end if;
1299
1300 Func_Name := Defining_Unit_Name (Specification (Func_Body));
1301 Expr :=
1302 Make_Function_Call (Loc,
1303 Name => New_Occurrence_Of (Func_Name, Loc),
1304 Parameter_Associations => New_List (Op1, Op2));
1305
1306 Insert_Action (N, Func_Body);
1307 Rewrite (N, Expr);
1308 Analyze_And_Resolve (N, Standard_Boolean);
1309 end Expand_Array_Comparison;
1310
1311 ---------------------------
1312 -- Expand_Array_Equality --
1313 ---------------------------
1314
1315 -- Expand an equality function for multi-dimensional arrays. Here is an
1316 -- example of such a function for Nb_Dimension = 2
1317
1318 -- function Enn (A : atyp; B : btyp) return boolean is
1319 -- begin
1320 -- if (A'length (1) = 0 or else A'length (2) = 0)
1321 -- and then
1322 -- (B'length (1) = 0 or else B'length (2) = 0)
1323 -- then
1324 -- return true; -- RM 4.5.2(22)
1325 -- end if;
1326
1327 -- if A'length (1) /= B'length (1)
1328 -- or else
1329 -- A'length (2) /= B'length (2)
1330 -- then
1331 -- return false; -- RM 4.5.2(23)
1332 -- end if;
1333
1334 -- declare
1335 -- A1 : Index_T1 := A'first (1);
1336 -- B1 : Index_T1 := B'first (1);
1337 -- begin
1338 -- loop
1339 -- declare
1340 -- A2 : Index_T2 := A'first (2);
1341 -- B2 : Index_T2 := B'first (2);
1342 -- begin
1343 -- loop
1344 -- if A (A1, A2) /= B (B1, B2) then
1345 -- return False;
1346 -- end if;
1347
1348 -- exit when A2 = A'last (2);
1349 -- A2 := Index_T2'succ (A2);
1350 -- B2 := Index_T2'succ (B2);
1351 -- end loop;
1352 -- end;
1353
1354 -- exit when A1 = A'last (1);
1355 -- A1 := Index_T1'succ (A1);
1356 -- B1 := Index_T1'succ (B1);
1357 -- end loop;
1358 -- end;
1359
1360 -- return true;
1361 -- end Enn;
1362
1363 -- Note on the formal types used (atyp and btyp). If either of the arrays
1364 -- is of a private type, we use the underlying type, and do an unchecked
1365 -- conversion of the actual. If either of the arrays has a bound depending
1366 -- on a discriminant, then we use the base type since otherwise we have an
1367 -- escaped discriminant in the function.
1368
1369 -- If both arrays are constrained and have the same bounds, we can generate
1370 -- a loop with an explicit iteration scheme using a 'Range attribute over
1371 -- the first array.
1372
1373 function Expand_Array_Equality
1374 (Nod : Node_Id;
1375 Lhs : Node_Id;
1376 Rhs : Node_Id;
1377 Bodies : List_Id;
1378 Typ : Entity_Id) return Node_Id
1379 is
1380 Loc : constant Source_Ptr := Sloc (Nod);
1381 Decls : constant List_Id := New_List;
1382 Index_List1 : constant List_Id := New_List;
1383 Index_List2 : constant List_Id := New_List;
1384
1385 First_Idx : Node_Id;
1386 Formals : List_Id;
1387 Func_Name : Entity_Id;
1388 Func_Body : Node_Id;
1389
1390 A : constant Entity_Id := Make_Defining_Identifier (Loc, Name_uA);
1391 B : constant Entity_Id := Make_Defining_Identifier (Loc, Name_uB);
1392
1393 Ltyp : Entity_Id;
1394 Rtyp : Entity_Id;
1395 -- The parameter types to be used for the formals
1396
1397 New_Lhs : Node_Id;
1398 New_Rhs : Node_Id;
1399 -- The LHS and RHS converted to the parameter types
1400
1401 function Arr_Attr
1402 (Arr : Entity_Id;
1403 Nam : Name_Id;
1404 Dim : Pos) return Node_Id;
1405 -- This builds the attribute reference Arr'Nam (Dim)
1406
1407 function Component_Equality (Typ : Entity_Id) return Node_Id;
1408 -- Create one statement to compare corresponding components, designated
1409 -- by a full set of indexes.
1410
1411 function Get_Arg_Type (N : Node_Id) return Entity_Id;
1412 -- Given one of the arguments, computes the appropriate type to be used
1413 -- for that argument in the corresponding function formal
1414
1415 function Handle_One_Dimension
1416 (N : Pos;
1417 Index : Node_Id) return Node_Id;
1418 -- This procedure returns the following code
1419 --
1420 -- declare
1421 -- An : Index_T := A'First (N);
1422 -- Bn : Index_T := B'First (N);
1423 -- begin
1424 -- loop
1425 -- xxx
1426 -- exit when An = A'Last (N);
1427 -- An := Index_T'Succ (An)
1428 -- Bn := Index_T'Succ (Bn)
1429 -- end loop;
1430 -- end;
1431 --
1432 -- If both indexes are constrained and identical, the procedure
1433 -- returns a simpler loop:
1434 --
1435 -- for An in A'Range (N) loop
1436 -- xxx
1437 -- end loop
1438 --
1439 -- N is the dimension for which we are generating a loop. Index is the
1440 -- N'th index node, whose Etype is Index_Type_n in the above code. The
1441 -- xxx statement is either the loop or declare for the next dimension
1442 -- or if this is the last dimension the comparison of corresponding
1443 -- components of the arrays.
1444 --
1445 -- The actual way the code works is to return the comparison of
1446 -- corresponding components for the N+1 call. That's neater.
1447
1448 function Test_Empty_Arrays return Node_Id;
1449 -- This function constructs the test for both arrays being empty
1450 -- (A'length (1) = 0 or else A'length (2) = 0 or else ...)
1451 -- and then
1452 -- (B'length (1) = 0 or else B'length (2) = 0 or else ...)
1453
1454 function Test_Lengths_Correspond return Node_Id;
1455 -- This function constructs the test for arrays having different lengths
1456 -- in at least one index position, in which case the resulting code is:
1457
1458 -- A'length (1) /= B'length (1)
1459 -- or else
1460 -- A'length (2) /= B'length (2)
1461 -- or else
1462 -- ...
1463
1464 --------------
1465 -- Arr_Attr --
1466 --------------
1467
1468 function Arr_Attr
1469 (Arr : Entity_Id;
1470 Nam : Name_Id;
1471 Dim : Pos) return Node_Id
1472 is
1473 begin
1474 return
1475 Make_Attribute_Reference (Loc,
1476 Attribute_Name => Nam,
1477 Prefix => New_Occurrence_Of (Arr, Loc),
1478 Expressions => New_List (Make_Integer_Literal (Loc, Dim)));
1479 end Arr_Attr;
1480
1481 ------------------------
1482 -- Component_Equality --
1483 ------------------------
1484
1485 function Component_Equality (Typ : Entity_Id) return Node_Id is
1486 Test : Node_Id;
1487 L, R : Node_Id;
1488
1489 begin
1490 -- if a(i1...) /= b(j1...) then return false; end if;
1491
1492 L :=
1493 Make_Indexed_Component (Loc,
1494 Prefix => Make_Identifier (Loc, Chars (A)),
1495 Expressions => Index_List1);
1496
1497 R :=
1498 Make_Indexed_Component (Loc,
1499 Prefix => Make_Identifier (Loc, Chars (B)),
1500 Expressions => Index_List2);
1501
1502 Test := Expand_Composite_Equality
1503 (Outer_Type => Typ, Nod => Nod, Comp_Type => Component_Type (Typ),
1504 Lhs => L, Rhs => R);
1505
1506 -- If some (sub)component is an unchecked_union, the whole operation
1507 -- will raise program error.
1508
1509 if Nkind (Test) = N_Raise_Program_Error then
1510
1511 -- This node is going to be inserted at a location where a
1512 -- statement is expected: clear its Etype so analysis will set
1513 -- it to the expected Standard_Void_Type.
1514
1515 Set_Etype (Test, Empty);
1516 return Test;
1517
1518 else
1519 return
1520 Make_Implicit_If_Statement (Nod,
1521 Condition => Make_Op_Not (Loc, Right_Opnd => Test),
1522 Then_Statements => New_List (
1523 Make_Simple_Return_Statement (Loc,
1524 Expression => New_Occurrence_Of (Standard_False, Loc))));
1525 end if;
1526 end Component_Equality;
1527
1528 ------------------
1529 -- Get_Arg_Type --
1530 ------------------
1531
1532 function Get_Arg_Type (N : Node_Id) return Entity_Id is
1533 T : Entity_Id;
1534 X : Node_Id;
1535
1536 begin
1537 T := Etype (N);
1538
1539 if No (T) then
1540 return Typ;
1541
1542 else
1543 T := Underlying_Type (T);
1544
1545 X := First_Index (T);
1546 while Present (X) loop
1547 if Denotes_Discriminant (Type_Low_Bound (Etype (X)))
1548 or else
1549 Denotes_Discriminant (Type_High_Bound (Etype (X)))
1550 then
1551 T := Base_Type (T);
1552 exit;
1553 end if;
1554
1555 Next_Index (X);
1556 end loop;
1557
1558 return T;
1559 end if;
1560 end Get_Arg_Type;
1561
1562 --------------------------
1563 -- Handle_One_Dimension --
1564 ---------------------------
1565
1566 function Handle_One_Dimension
1567 (N : Pos;
1568 Index : Node_Id) return Node_Id
1569 is
1570 Need_Separate_Indexes : constant Boolean :=
1571 Ltyp /= Rtyp or else not Is_Constrained (Ltyp);
1572 -- If the index types are identical, and we are working with
1573 -- constrained types, then we can use the same index for both
1574 -- of the arrays.
1575
1576 An : constant Entity_Id := Make_Temporary (Loc, 'A');
1577
1578 Bn : Entity_Id;
1579 Index_T : Entity_Id;
1580 Stm_List : List_Id;
1581 Loop_Stm : Node_Id;
1582
1583 begin
1584 if N > Number_Dimensions (Ltyp) then
1585 return Component_Equality (Ltyp);
1586 end if;
1587
1588 -- Case where we generate a loop
1589
1590 Index_T := Base_Type (Etype (Index));
1591
1592 if Need_Separate_Indexes then
1593 Bn := Make_Temporary (Loc, 'B');
1594 else
1595 Bn := An;
1596 end if;
1597
1598 Append (New_Occurrence_Of (An, Loc), Index_List1);
1599 Append (New_Occurrence_Of (Bn, Loc), Index_List2);
1600
1601 Stm_List := New_List (
1602 Handle_One_Dimension (N + 1, Next_Index (Index)));
1603
1604 if Need_Separate_Indexes then
1605
1606 -- Generate guard for loop, followed by increments of indexes
1607
1608 Append_To (Stm_List,
1609 Make_Exit_Statement (Loc,
1610 Condition =>
1611 Make_Op_Eq (Loc,
1612 Left_Opnd => New_Occurrence_Of (An, Loc),
1613 Right_Opnd => Arr_Attr (A, Name_Last, N))));
1614
1615 Append_To (Stm_List,
1616 Make_Assignment_Statement (Loc,
1617 Name => New_Occurrence_Of (An, Loc),
1618 Expression =>
1619 Make_Attribute_Reference (Loc,
1620 Prefix => New_Occurrence_Of (Index_T, Loc),
1621 Attribute_Name => Name_Succ,
1622 Expressions => New_List (
1623 New_Occurrence_Of (An, Loc)))));
1624
1625 Append_To (Stm_List,
1626 Make_Assignment_Statement (Loc,
1627 Name => New_Occurrence_Of (Bn, Loc),
1628 Expression =>
1629 Make_Attribute_Reference (Loc,
1630 Prefix => New_Occurrence_Of (Index_T, Loc),
1631 Attribute_Name => Name_Succ,
1632 Expressions => New_List (
1633 New_Occurrence_Of (Bn, Loc)))));
1634 end if;
1635
1636 -- If separate indexes, we need a declare block for An and Bn, and a
1637 -- loop without an iteration scheme.
1638
1639 if Need_Separate_Indexes then
1640 Loop_Stm :=
1641 Make_Implicit_Loop_Statement (Nod, Statements => Stm_List);
1642
1643 return
1644 Make_Block_Statement (Loc,
1645 Declarations => New_List (
1646 Make_Object_Declaration (Loc,
1647 Defining_Identifier => An,
1648 Object_Definition => New_Occurrence_Of (Index_T, Loc),
1649 Expression => Arr_Attr (A, Name_First, N)),
1650
1651 Make_Object_Declaration (Loc,
1652 Defining_Identifier => Bn,
1653 Object_Definition => New_Occurrence_Of (Index_T, Loc),
1654 Expression => Arr_Attr (B, Name_First, N))),
1655
1656 Handled_Statement_Sequence =>
1657 Make_Handled_Sequence_Of_Statements (Loc,
1658 Statements => New_List (Loop_Stm)));
1659
1660 -- If no separate indexes, return loop statement with explicit
1661 -- iteration scheme on its own.
1662
1663 else
1664 Loop_Stm :=
1665 Make_Implicit_Loop_Statement (Nod,
1666 Statements => Stm_List,
1667 Iteration_Scheme =>
1668 Make_Iteration_Scheme (Loc,
1669 Loop_Parameter_Specification =>
1670 Make_Loop_Parameter_Specification (Loc,
1671 Defining_Identifier => An,
1672 Discrete_Subtype_Definition =>
1673 Arr_Attr (A, Name_Range, N))));
1674 return Loop_Stm;
1675 end if;
1676 end Handle_One_Dimension;
1677
1678 -----------------------
1679 -- Test_Empty_Arrays --
1680 -----------------------
1681
1682 function Test_Empty_Arrays return Node_Id is
1683 Alist : Node_Id := Empty;
1684 Blist : Node_Id := Empty;
1685
1686 begin
1687 for J in 1 .. Number_Dimensions (Ltyp) loop
1688 Evolve_Or_Else (Alist,
1689 Make_Op_Eq (Loc,
1690 Left_Opnd => Arr_Attr (A, Name_Length, J),
1691 Right_Opnd => Make_Integer_Literal (Loc, Uint_0)));
1692
1693 Evolve_Or_Else (Blist,
1694 Make_Op_Eq (Loc,
1695 Left_Opnd => Arr_Attr (B, Name_Length, J),
1696 Right_Opnd => Make_Integer_Literal (Loc, Uint_0)));
1697 end loop;
1698
1699 return
1700 Make_And_Then (Loc,
1701 Left_Opnd => Alist,
1702 Right_Opnd => Blist);
1703 end Test_Empty_Arrays;
1704
1705 -----------------------------
1706 -- Test_Lengths_Correspond --
1707 -----------------------------
1708
1709 function Test_Lengths_Correspond return Node_Id is
1710 Result : Node_Id := Empty;
1711
1712 begin
1713 for J in 1 .. Number_Dimensions (Ltyp) loop
1714 Evolve_Or_Else (Result,
1715 Make_Op_Ne (Loc,
1716 Left_Opnd => Arr_Attr (A, Name_Length, J),
1717 Right_Opnd => Arr_Attr (B, Name_Length, J)));
1718 end loop;
1719
1720 return Result;
1721 end Test_Lengths_Correspond;
1722
1723 -- Start of processing for Expand_Array_Equality
1724
1725 begin
1726 Ltyp := Get_Arg_Type (Lhs);
1727 Rtyp := Get_Arg_Type (Rhs);
1728
1729 -- For now, if the argument types are not the same, go to the base type,
1730 -- since the code assumes that the formals have the same type. This is
1731 -- fixable in future ???
1732
1733 if Ltyp /= Rtyp then
1734 Ltyp := Base_Type (Ltyp);
1735 Rtyp := Base_Type (Rtyp);
1736 end if;
1737
1738 -- If the array type is distinct from the type of the arguments, it
1739 -- is the full view of a private type. Apply an unchecked conversion
1740 -- to ensure that analysis of the code below succeeds.
1741
1742 if No (Etype (Lhs))
1743 or else Base_Type (Etype (Lhs)) /= Base_Type (Ltyp)
1744 then
1745 New_Lhs := OK_Convert_To (Ltyp, Lhs);
1746 else
1747 New_Lhs := Lhs;
1748 end if;
1749
1750 if No (Etype (Rhs))
1751 or else Base_Type (Etype (Rhs)) /= Base_Type (Rtyp)
1752 then
1753 New_Rhs := OK_Convert_To (Rtyp, Rhs);
1754 else
1755 New_Rhs := Rhs;
1756 end if;
1757
1758 pragma Assert (Ltyp = Rtyp);
1759 First_Idx := First_Index (Ltyp);
1760
1761 -- If optimization is enabled and the array boils down to a couple of
1762 -- consecutive elements, generate a simple conjunction of comparisons
1763 -- which should be easier to optimize by the code generator.
1764
1765 if Optimization_Level > 0
1766 and then Is_Constrained (Ltyp)
1767 and then Number_Dimensions (Ltyp) = 1
1768 and then Compile_Time_Known_Bounds (Ltyp)
1769 and then Expr_Value (Type_High_Bound (Etype (First_Idx))) =
1770 Expr_Value (Type_Low_Bound (Etype (First_Idx))) + 1
1771 then
1772 declare
1773 Ctyp : constant Entity_Id := Component_Type (Ltyp);
1774 Low_B : constant Node_Id :=
1775 Type_Low_Bound (Etype (First_Idx));
1776 High_B : constant Node_Id :=
1777 Type_High_Bound (Etype (First_Idx));
1778 L, R : Node_Id;
1779 TestL, TestH : Node_Id;
1780
1781 begin
1782 L :=
1783 Make_Indexed_Component (Loc,
1784 Prefix => New_Copy_Tree (New_Lhs),
1785 Expressions => New_List (New_Copy_Tree (Low_B)));
1786
1787 R :=
1788 Make_Indexed_Component (Loc,
1789 Prefix => New_Copy_Tree (New_Rhs),
1790 Expressions => New_List (New_Copy_Tree (Low_B)));
1791
1792 TestL := Expand_Composite_Equality
1793 (Outer_Type => Ltyp, Nod => Nod, Comp_Type => Ctyp,
1794 Lhs => L, Rhs => R);
1795
1796 L :=
1797 Make_Indexed_Component (Loc,
1798 Prefix => New_Lhs,
1799 Expressions => New_List (New_Copy_Tree (High_B)));
1800
1801 R :=
1802 Make_Indexed_Component (Loc,
1803 Prefix => New_Rhs,
1804 Expressions => New_List (New_Copy_Tree (High_B)));
1805
1806 TestH := Expand_Composite_Equality
1807 (Outer_Type => Ltyp, Nod => Nod, Comp_Type => Ctyp,
1808 Lhs => L, Rhs => R);
1809
1810 return
1811 Make_And_Then (Loc, Left_Opnd => TestL, Right_Opnd => TestH);
1812 end;
1813 end if;
1814
1815 -- Build list of formals for function
1816
1817 Formals := New_List (
1818 Make_Parameter_Specification (Loc,
1819 Defining_Identifier => A,
1820 Parameter_Type => New_Occurrence_Of (Ltyp, Loc)),
1821
1822 Make_Parameter_Specification (Loc,
1823 Defining_Identifier => B,
1824 Parameter_Type => New_Occurrence_Of (Rtyp, Loc)));
1825
1826 Func_Name := Make_Temporary (Loc, 'E');
1827
1828 -- Build statement sequence for function
1829
1830 Func_Body :=
1831 Make_Subprogram_Body (Loc,
1832 Specification =>
1833 Make_Function_Specification (Loc,
1834 Defining_Unit_Name => Func_Name,
1835 Parameter_Specifications => Formals,
1836 Result_Definition => New_Occurrence_Of (Standard_Boolean, Loc)),
1837
1838 Declarations => Decls,
1839
1840 Handled_Statement_Sequence =>
1841 Make_Handled_Sequence_Of_Statements (Loc,
1842 Statements => New_List (
1843
1844 Make_Implicit_If_Statement (Nod,
1845 Condition => Test_Empty_Arrays,
1846 Then_Statements => New_List (
1847 Make_Simple_Return_Statement (Loc,
1848 Expression =>
1849 New_Occurrence_Of (Standard_True, Loc)))),
1850
1851 Make_Implicit_If_Statement (Nod,
1852 Condition => Test_Lengths_Correspond,
1853 Then_Statements => New_List (
1854 Make_Simple_Return_Statement (Loc,
1855 Expression => New_Occurrence_Of (Standard_False, Loc)))),
1856
1857 Handle_One_Dimension (1, First_Idx),
1858
1859 Make_Simple_Return_Statement (Loc,
1860 Expression => New_Occurrence_Of (Standard_True, Loc)))));
1861
1862 Set_Has_Completion (Func_Name, True);
1863 Set_Is_Inlined (Func_Name);
1864
1865 Append_To (Bodies, Func_Body);
1866
1867 return
1868 Make_Function_Call (Loc,
1869 Name => New_Occurrence_Of (Func_Name, Loc),
1870 Parameter_Associations => New_List (New_Lhs, New_Rhs));
1871 end Expand_Array_Equality;
1872
1873 -----------------------------
1874 -- Expand_Boolean_Operator --
1875 -----------------------------
1876
1877 -- Note that we first get the actual subtypes of the operands, since we
1878 -- always want to deal with types that have bounds.
1879
1880 procedure Expand_Boolean_Operator (N : Node_Id) is
1881 Typ : constant Entity_Id := Etype (N);
1882
1883 begin
1884 -- Special case of bit packed array where both operands are known to be
1885 -- properly aligned. In this case we use an efficient run time routine
1886 -- to carry out the operation (see System.Bit_Ops).
1887
1888 if Is_Bit_Packed_Array (Typ)
1889 and then not Is_Possibly_Unaligned_Object (Left_Opnd (N))
1890 and then not Is_Possibly_Unaligned_Object (Right_Opnd (N))
1891 then
1892 Expand_Packed_Boolean_Operator (N);
1893 return;
1894 end if;
1895
1896 -- For the normal non-packed case, the general expansion is to build
1897 -- function for carrying out the comparison (use Make_Boolean_Array_Op)
1898 -- and then inserting it into the tree. The original operator node is
1899 -- then rewritten as a call to this function. We also use this in the
1900 -- packed case if either operand is a possibly unaligned object.
1901
1902 declare
1903 Loc : constant Source_Ptr := Sloc (N);
1904 L : constant Node_Id := Relocate_Node (Left_Opnd (N));
1905 R : Node_Id := Relocate_Node (Right_Opnd (N));
1906 Func_Body : Node_Id;
1907 Func_Name : Entity_Id;
1908
1909 begin
1910 Convert_To_Actual_Subtype (L);
1911 Convert_To_Actual_Subtype (R);
1912 Ensure_Defined (Etype (L), N);
1913 Ensure_Defined (Etype (R), N);
1914 Apply_Length_Check (R, Etype (L));
1915
1916 if Nkind (N) = N_Op_Xor then
1917 R := Duplicate_Subexpr (R);
1918 Silly_Boolean_Array_Xor_Test (N, R, Etype (L));
1919 end if;
1920
1921 if Nkind (Parent (N)) = N_Assignment_Statement
1922 and then Safe_In_Place_Array_Op (Name (Parent (N)), L, R)
1923 then
1924 Build_Boolean_Array_Proc_Call (Parent (N), L, R);
1925
1926 elsif Nkind (Parent (N)) = N_Op_Not
1927 and then Nkind (N) = N_Op_And
1928 and then Nkind (Parent (Parent (N))) = N_Assignment_Statement
1929 and then Safe_In_Place_Array_Op (Name (Parent (Parent (N))), L, R)
1930 then
1931 return;
1932 else
1933 Func_Body := Make_Boolean_Array_Op (Etype (L), N);
1934 Func_Name := Defining_Unit_Name (Specification (Func_Body));
1935 Insert_Action (N, Func_Body);
1936
1937 -- Now rewrite the expression with a call
1938
1939 if Transform_Function_Array then
1940 declare
1941 Temp_Id : constant Entity_Id := Make_Temporary (Loc, 'T');
1942 Call : Node_Id;
1943 Decl : Node_Id;
1944
1945 begin
1946 -- Generate:
1947 -- Temp : ...;
1948
1949 Decl :=
1950 Make_Object_Declaration (Loc,
1951 Defining_Identifier => Temp_Id,
1952 Object_Definition =>
1953 New_Occurrence_Of (Etype (L), Loc));
1954
1955 -- Generate:
1956 -- Proc_Call (L, R, Temp);
1957
1958 Call :=
1959 Make_Procedure_Call_Statement (Loc,
1960 Name => New_Occurrence_Of (Func_Name, Loc),
1961 Parameter_Associations =>
1962 New_List (
1963 L,
1964 Make_Type_Conversion
1965 (Loc, New_Occurrence_Of (Etype (L), Loc), R),
1966 New_Occurrence_Of (Temp_Id, Loc)));
1967
1968 Insert_Actions (Parent (N), New_List (Decl, Call));
1969 Rewrite (N, New_Occurrence_Of (Temp_Id, Loc));
1970 end;
1971 else
1972 Rewrite (N,
1973 Make_Function_Call (Loc,
1974 Name => New_Occurrence_Of (Func_Name, Loc),
1975 Parameter_Associations =>
1976 New_List (
1977 L,
1978 Make_Type_Conversion
1979 (Loc, New_Occurrence_Of (Etype (L), Loc), R))));
1980 end if;
1981
1982 Analyze_And_Resolve (N, Typ);
1983 end if;
1984 end;
1985 end Expand_Boolean_Operator;
1986
1987 ------------------------------------------------
1988 -- Expand_Compare_Minimize_Eliminate_Overflow --
1989 ------------------------------------------------
1990
1991 procedure Expand_Compare_Minimize_Eliminate_Overflow (N : Node_Id) is
1992 Loc : constant Source_Ptr := Sloc (N);
1993
1994 Result_Type : constant Entity_Id := Etype (N);
1995 -- Capture result type (could be a derived boolean type)
1996
1997 Llo, Lhi : Uint;
1998 Rlo, Rhi : Uint;
1999
2000 LLIB : constant Entity_Id := Base_Type (Standard_Long_Long_Integer);
2001 -- Entity for Long_Long_Integer'Base
2002
2003 procedure Set_True;
2004 procedure Set_False;
2005 -- These procedures rewrite N with an occurrence of Standard_True or
2006 -- Standard_False, and then makes a call to Warn_On_Known_Condition.
2007
2008 ---------------
2009 -- Set_False --
2010 ---------------
2011
2012 procedure Set_False is
2013 begin
2014 Rewrite (N, New_Occurrence_Of (Standard_False, Loc));
2015 Warn_On_Known_Condition (N);
2016 end Set_False;
2017
2018 --------------
2019 -- Set_True --
2020 --------------
2021
2022 procedure Set_True is
2023 begin
2024 Rewrite (N, New_Occurrence_Of (Standard_True, Loc));
2025 Warn_On_Known_Condition (N);
2026 end Set_True;
2027
2028 -- Start of processing for Expand_Compare_Minimize_Eliminate_Overflow
2029
2030 begin
2031 -- OK, this is the case we are interested in. First step is to process
2032 -- our operands using the Minimize_Eliminate circuitry which applies
2033 -- this processing to the two operand subtrees.
2034
2035 Minimize_Eliminate_Overflows
2036 (Left_Opnd (N), Llo, Lhi, Top_Level => False);
2037 Minimize_Eliminate_Overflows
2038 (Right_Opnd (N), Rlo, Rhi, Top_Level => False);
2039
2040 -- See if the range information decides the result of the comparison.
2041 -- We can only do this if we in fact have full range information (which
2042 -- won't be the case if either operand is bignum at this stage).
2043
2044 if Present (Llo) and then Present (Rlo) then
2045 case N_Op_Compare (Nkind (N)) is
2046 when N_Op_Eq =>
2047 if Llo = Lhi and then Rlo = Rhi and then Llo = Rlo then
2048 Set_True;
2049 elsif Llo > Rhi or else Lhi < Rlo then
2050 Set_False;
2051 end if;
2052
2053 when N_Op_Ge =>
2054 if Llo >= Rhi then
2055 Set_True;
2056 elsif Lhi < Rlo then
2057 Set_False;
2058 end if;
2059
2060 when N_Op_Gt =>
2061 if Llo > Rhi then
2062 Set_True;
2063 elsif Lhi <= Rlo then
2064 Set_False;
2065 end if;
2066
2067 when N_Op_Le =>
2068 if Llo > Rhi then
2069 Set_False;
2070 elsif Lhi <= Rlo then
2071 Set_True;
2072 end if;
2073
2074 when N_Op_Lt =>
2075 if Llo >= Rhi then
2076 Set_False;
2077 elsif Lhi < Rlo then
2078 Set_True;
2079 end if;
2080
2081 when N_Op_Ne =>
2082 if Llo = Lhi and then Rlo = Rhi and then Llo = Rlo then
2083 Set_False;
2084 elsif Llo > Rhi or else Lhi < Rlo then
2085 Set_True;
2086 end if;
2087 end case;
2088
2089 -- All done if we did the rewrite
2090
2091 if Nkind (N) not in N_Op_Compare then
2092 return;
2093 end if;
2094 end if;
2095
2096 -- Otherwise, time to do the comparison
2097
2098 declare
2099 Ltype : constant Entity_Id := Etype (Left_Opnd (N));
2100 Rtype : constant Entity_Id := Etype (Right_Opnd (N));
2101
2102 begin
2103 -- If the two operands have the same signed integer type we are
2104 -- all set, nothing more to do. This is the case where either
2105 -- both operands were unchanged, or we rewrote both of them to
2106 -- be Long_Long_Integer.
2107
2108 -- Note: Entity for the comparison may be wrong, but it's not worth
2109 -- the effort to change it, since the back end does not use it.
2110
2111 if Is_Signed_Integer_Type (Ltype)
2112 and then Base_Type (Ltype) = Base_Type (Rtype)
2113 then
2114 return;
2115
2116 -- Here if bignums are involved (can only happen in ELIMINATED mode)
2117
2118 elsif Is_RTE (Ltype, RE_Bignum) or else Is_RTE (Rtype, RE_Bignum) then
2119 declare
2120 Left : Node_Id := Left_Opnd (N);
2121 Right : Node_Id := Right_Opnd (N);
2122 -- Bignum references for left and right operands
2123
2124 begin
2125 if not Is_RTE (Ltype, RE_Bignum) then
2126 Left := Convert_To_Bignum (Left);
2127 elsif not Is_RTE (Rtype, RE_Bignum) then
2128 Right := Convert_To_Bignum (Right);
2129 end if;
2130
2131 -- We rewrite our node with:
2132
2133 -- do
2134 -- Bnn : Result_Type;
2135 -- declare
2136 -- M : Mark_Id := SS_Mark;
2137 -- begin
2138 -- Bnn := Big_xx (Left, Right); (xx = EQ, NT etc)
2139 -- SS_Release (M);
2140 -- end;
2141 -- in
2142 -- Bnn
2143 -- end
2144
2145 declare
2146 Blk : constant Node_Id := Make_Bignum_Block (Loc);
2147 Bnn : constant Entity_Id := Make_Temporary (Loc, 'B', N);
2148 Ent : RE_Id;
2149
2150 begin
2151 case N_Op_Compare (Nkind (N)) is
2152 when N_Op_Eq => Ent := RE_Big_EQ;
2153 when N_Op_Ge => Ent := RE_Big_GE;
2154 when N_Op_Gt => Ent := RE_Big_GT;
2155 when N_Op_Le => Ent := RE_Big_LE;
2156 when N_Op_Lt => Ent := RE_Big_LT;
2157 when N_Op_Ne => Ent := RE_Big_NE;
2158 end case;
2159
2160 -- Insert assignment to Bnn into the bignum block
2161
2162 Insert_Before
2163 (First (Statements (Handled_Statement_Sequence (Blk))),
2164 Make_Assignment_Statement (Loc,
2165 Name => New_Occurrence_Of (Bnn, Loc),
2166 Expression =>
2167 Make_Function_Call (Loc,
2168 Name =>
2169 New_Occurrence_Of (RTE (Ent), Loc),
2170 Parameter_Associations => New_List (Left, Right))));
2171
2172 -- Now do the rewrite with expression actions
2173
2174 Rewrite (N,
2175 Make_Expression_With_Actions (Loc,
2176 Actions => New_List (
2177 Make_Object_Declaration (Loc,
2178 Defining_Identifier => Bnn,
2179 Object_Definition =>
2180 New_Occurrence_Of (Result_Type, Loc)),
2181 Blk),
2182 Expression => New_Occurrence_Of (Bnn, Loc)));
2183 Analyze_And_Resolve (N, Result_Type);
2184 end;
2185 end;
2186
2187 -- No bignums involved, but types are different, so we must have
2188 -- rewritten one of the operands as a Long_Long_Integer but not
2189 -- the other one.
2190
2191 -- If left operand is Long_Long_Integer, convert right operand
2192 -- and we are done (with a comparison of two Long_Long_Integers).
2193
2194 elsif Ltype = LLIB then
2195 Convert_To_And_Rewrite (LLIB, Right_Opnd (N));
2196 Analyze_And_Resolve (Right_Opnd (N), LLIB, Suppress => All_Checks);
2197 return;
2198
2199 -- If right operand is Long_Long_Integer, convert left operand
2200 -- and we are done (with a comparison of two Long_Long_Integers).
2201
2202 -- This is the only remaining possibility
2203
2204 else pragma Assert (Rtype = LLIB);
2205 Convert_To_And_Rewrite (LLIB, Left_Opnd (N));
2206 Analyze_And_Resolve (Left_Opnd (N), LLIB, Suppress => All_Checks);
2207 return;
2208 end if;
2209 end;
2210 end Expand_Compare_Minimize_Eliminate_Overflow;
2211
2212 -------------------------------
2213 -- Expand_Composite_Equality --
2214 -------------------------------
2215
2216 -- This function is only called for comparing internal fields of composite
2217 -- types when these fields are themselves composites. This is a special
2218 -- case because it is not possible to respect normal Ada visibility rules.
2219
2220 function Expand_Composite_Equality
2221 (Outer_Type : Entity_Id;
2222 Nod : Node_Id;
2223 Comp_Type : Entity_Id;
2224 Lhs : Node_Id;
2225 Rhs : Node_Id) return Node_Id
2226 is
2227 Loc : constant Source_Ptr := Sloc (Nod);
2228 Full_Type : Entity_Id;
2229 Eq_Op : Entity_Id;
2230
2231 begin
2232 if Is_Private_Type (Comp_Type) then
2233 Full_Type := Underlying_Type (Comp_Type);
2234 else
2235 Full_Type := Comp_Type;
2236 end if;
2237
2238 -- If the private type has no completion the context may be the
2239 -- expansion of a composite equality for a composite type with some
2240 -- still incomplete components. The expression will not be analyzed
2241 -- until the enclosing type is completed, at which point this will be
2242 -- properly expanded, unless there is a bona fide completion error.
2243
2244 if No (Full_Type) then
2245 return Make_Op_Eq (Loc, Left_Opnd => Lhs, Right_Opnd => Rhs);
2246 end if;
2247
2248 Full_Type := Base_Type (Full_Type);
2249
2250 -- When the base type itself is private, use the full view to expand
2251 -- the composite equality.
2252
2253 if Is_Private_Type (Full_Type) then
2254 Full_Type := Underlying_Type (Full_Type);
2255 end if;
2256
2257 -- Case of tagged record types
2258
2259 if Is_Tagged_Type (Full_Type) then
2260 Eq_Op := Find_Primitive_Eq (Comp_Type);
2261 pragma Assert (Present (Eq_Op));
2262
2263 return
2264 Make_Function_Call (Loc,
2265 Name => New_Occurrence_Of (Eq_Op, Loc),
2266 Parameter_Associations =>
2267 New_List
2268 (Unchecked_Convert_To (Etype (First_Formal (Eq_Op)), Lhs),
2269 Unchecked_Convert_To (Etype (First_Formal (Eq_Op)), Rhs)));
2270
2271 -- Case of untagged record types
2272
2273 elsif Is_Record_Type (Full_Type) then
2274 Eq_Op := TSS (Full_Type, TSS_Composite_Equality);
2275
2276 if Present (Eq_Op) then
2277 declare
2278 Op_Typ : constant Entity_Id := Etype (First_Formal (Eq_Op));
2279
2280 L_Exp, R_Exp : Node_Id;
2281
2282 begin
2283 -- Adjust operands if necessary to comparison type
2284
2285 if Base_Type (Full_Type) /= Base_Type (Op_Typ) then
2286 L_Exp := OK_Convert_To (Op_Typ, Lhs);
2287 R_Exp := OK_Convert_To (Op_Typ, Rhs);
2288
2289 else
2290 L_Exp := Relocate_Node (Lhs);
2291 R_Exp := Relocate_Node (Rhs);
2292 end if;
2293
2294 return
2295 Make_Function_Call (Loc,
2296 Name => New_Occurrence_Of (Eq_Op, Loc),
2297 Parameter_Associations => New_List (L_Exp, R_Exp));
2298 end;
2299
2300 -- Equality composes in Ada 2012 for untagged record types. It also
2301 -- composes for bounded strings, because they are part of the
2302 -- predefined environment (see 4.5.2(32.1/1)). We could make it
2303 -- compose for bounded strings by making them tagged, or by making
2304 -- sure all subcomponents are set to the same value, even when not
2305 -- used. Instead, we have this special case in the compiler, because
2306 -- it's more efficient.
2307
2308 elsif Ada_Version >= Ada_2012 or else Is_Bounded_String (Comp_Type)
2309 then
2310 -- If no TSS has been created for the type, check whether there is
2311 -- a primitive equality declared for it.
2312
2313 declare
2314 Op : constant Node_Id :=
2315 Build_Eq_Call (Comp_Type, Loc, Lhs, Rhs);
2316
2317 begin
2318 -- Use user-defined primitive if it exists, otherwise use
2319 -- predefined equality.
2320
2321 if Present (Op) then
2322 return Op;
2323 else
2324 return Make_Op_Eq (Loc, Lhs, Rhs);
2325 end if;
2326 end;
2327
2328 else
2329 return Expand_Record_Equality (Nod, Full_Type, Lhs, Rhs);
2330 end if;
2331
2332 -- Case of non-record types (always use predefined equality)
2333
2334 else
2335 -- Print a warning if there is a user-defined "=", because it can be
2336 -- surprising that the predefined "=" takes precedence over it.
2337
2338 -- Suppress the warning if the "user-defined" one is in the
2339 -- predefined library, because those are defined to compose
2340 -- properly by RM-4.5.2(32.1/1). Intrinsics also compose.
2341
2342 declare
2343 Op : constant Entity_Id := Find_Primitive_Eq (Comp_Type);
2344 begin
2345 if Warn_On_Ignored_Equality
2346 and then Present (Op)
2347 and then not In_Predefined_Unit (Base_Type (Comp_Type))
2348 and then not Is_Intrinsic_Subprogram (Op)
2349 then
2350 pragma Assert
2351 (Is_First_Subtype (Outer_Type)
2352 or else Is_Generic_Actual_Type (Outer_Type));
2353 Error_Msg_Node_1 := Outer_Type;
2354 Error_Msg_Node_2 := Comp_Type;
2355 Error_Msg
2356 ("?_q?""="" for type & uses predefined ""="" for }", Loc);
2357 Error_Msg_Sloc := Sloc (Op);
2358 Error_Msg ("\?_q?""="" # is ignored here", Loc);
2359 end if;
2360 end;
2361
2362 return Make_Op_Eq (Loc, Left_Opnd => Lhs, Right_Opnd => Rhs);
2363 end if;
2364 end Expand_Composite_Equality;
2365
2366 ------------------------
2367 -- Expand_Concatenate --
2368 ------------------------
2369
2370 procedure Expand_Concatenate (Cnode : Node_Id; Opnds : List_Id) is
2371 Loc : constant Source_Ptr := Sloc (Cnode);
2372
2373 Atyp : constant Entity_Id := Base_Type (Etype (Cnode));
2374 -- Result type of concatenation
2375
2376 Ctyp : constant Entity_Id := Base_Type (Component_Type (Etype (Cnode)));
2377 -- Component type. Elements of this component type can appear as one
2378 -- of the operands of concatenation as well as arrays.
2379
2380 Istyp : constant Entity_Id := Etype (First_Index (Atyp));
2381 -- Index subtype
2382
2383 Ityp : constant Entity_Id := Base_Type (Istyp);
2384 -- Index type. This is the base type of the index subtype, and is used
2385 -- for all computed bounds (which may be out of range of Istyp in the
2386 -- case of null ranges).
2387
2388 Artyp : Entity_Id;
2389 -- This is the type we use to do arithmetic to compute the bounds and
2390 -- lengths of operands. The choice of this type is a little subtle and
2391 -- is discussed in a separate section at the start of the body code.
2392
2393 Result_May_Be_Null : Boolean := True;
2394 -- Reset to False if at least one operand is encountered which is known
2395 -- at compile time to be non-null. Used for handling the special case
2396 -- of setting the high bound to the last operand high bound for a null
2397 -- result, thus ensuring a proper high bound in the superflat case.
2398
2399 N : constant Nat := List_Length (Opnds);
2400 -- Number of concatenation operands including possibly null operands
2401
2402 NN : Nat := 0;
2403 -- Number of operands excluding any known to be null, except that the
2404 -- last operand is always retained, in case it provides the bounds for
2405 -- a null result.
2406
2407 Opnd : Node_Id := Empty;
2408 -- Current operand being processed in the loop through operands. After
2409 -- this loop is complete, always contains the last operand (which is not
2410 -- the same as Operands (NN), since null operands are skipped).
2411
2412 -- Arrays describing the operands, only the first NN entries of each
2413 -- array are set (NN < N when we exclude known null operands).
2414
2415 Is_Fixed_Length : array (1 .. N) of Boolean;
2416 -- True if length of corresponding operand known at compile time
2417
2418 Operands : array (1 .. N) of Node_Id;
2419 -- Set to the corresponding entry in the Opnds list (but note that null
2420 -- operands are excluded, so not all entries in the list are stored).
2421
2422 Fixed_Length : array (1 .. N) of Unat;
2423 -- Set to length of operand. Entries in this array are set only if the
2424 -- corresponding entry in Is_Fixed_Length is True.
2425
2426 Max_Length : array (1 .. N) of Unat;
2427 -- Set to the maximum length of operand, or Too_Large_Length_For_Array
2428 -- if it is not known. Entries in this array are set only if the
2429 -- corresponding entry in Is_Fixed_Length is False;
2430
2431 Opnd_Low_Bound : array (1 .. N) of Node_Id;
2432 -- Set to lower bound of operand. Either an integer literal in the case
2433 -- where the bound is known at compile time, else actual lower bound.
2434 -- The operand low bound is of type Ityp.
2435
2436 Var_Length : array (1 .. N) of Entity_Id;
2437 -- Set to an entity of type Natural that contains the length of an
2438 -- operand whose length is not known at compile time. Entries in this
2439 -- array are set only if the corresponding entry in Is_Fixed_Length
2440 -- is False. The entity is of type Artyp.
2441
2442 Aggr_Length : array (0 .. N) of Node_Id;
2443 -- The J'th entry is an expression node that represents the total length
2444 -- of operands 1 through J. It is either an integer literal node, or a
2445 -- reference to a constant entity with the right value, so it is fine
2446 -- to just do a Copy_Node to get an appropriate copy. The extra zeroth
2447 -- entry always is set to zero. The length is of type Artyp.
2448
2449 Max_Aggr_Length : Unat := Too_Large_Length_For_Array;
2450 -- Set to the maximum total length, or Too_Large_Length_For_Array at
2451 -- least if it is not known.
2452
2453 Low_Bound : Node_Id := Empty;
2454 -- A tree node representing the low bound of the result (of type Ityp).
2455 -- This is either an integer literal node, or an identifier reference to
2456 -- a constant entity initialized to the appropriate value.
2457
2458 High_Bound : Node_Id := Empty;
2459 -- A tree node representing the high bound of the result (of type Ityp)
2460
2461 Last_Opnd_Low_Bound : Node_Id := Empty;
2462 -- A tree node representing the low bound of the last operand. This
2463 -- need only be set if the result could be null. It is used for the
2464 -- special case of setting the right low bound for a null result.
2465 -- This is of type Ityp.
2466
2467 Last_Opnd_High_Bound : Node_Id := Empty;
2468 -- A tree node representing the high bound of the last operand. This
2469 -- need only be set if the result could be null. It is used for the
2470 -- special case of setting the right high bound for a null result.
2471 -- This is of type Ityp.
2472
2473 Result : Node_Id := Empty;
2474 -- Result of the concatenation (of type Ityp)
2475
2476 Actions : constant List_Id := New_List;
2477 -- Collect actions to be inserted
2478
2479 Known_Non_Null_Operand_Seen : Boolean;
2480 -- Set True during generation of the assignments of operands into
2481 -- result once an operand known to be non-null has been seen.
2482
2483 function Library_Level_Target return Boolean;
2484 -- Return True if the concatenation is within the expression of the
2485 -- declaration of a library-level object.
2486
2487 function Make_Artyp_Literal (Val : Uint) return Node_Id;
2488 -- This function makes an N_Integer_Literal node that is returned in
2489 -- analyzed form with the type set to Artyp. Importantly this literal
2490 -- is not flagged as static, so that if we do computations with it that
2491 -- result in statically detected out of range conditions, we will not
2492 -- generate error messages but instead warning messages.
2493
2494 function To_Artyp (X : Node_Id) return Node_Id;
2495 -- Given a node of type Ityp, returns the corresponding value of type
2496 -- Artyp. For non-enumeration types, this is a plain integer conversion.
2497 -- For enum types, the Pos of the value is returned.
2498
2499 function To_Ityp (X : Node_Id) return Node_Id;
2500 -- The inverse function (uses Val in the case of enumeration types)
2501
2502 --------------------------
2503 -- Library_Level_Target --
2504 --------------------------
2505
2506 function Library_Level_Target return Boolean is
2507 P : Node_Id := Parent (Cnode);
2508
2509 begin
2510 while Present (P) loop
2511 if Nkind (P) = N_Object_Declaration then
2512 return Is_Library_Level_Entity (Defining_Identifier (P));
2513
2514 -- Prevent the search from going too far
2515
2516 elsif Is_Body_Or_Package_Declaration (P) then
2517 return False;
2518 end if;
2519
2520 P := Parent (P);
2521 end loop;
2522
2523 return False;
2524 end Library_Level_Target;
2525
2526 ------------------------
2527 -- Make_Artyp_Literal --
2528 ------------------------
2529
2530 function Make_Artyp_Literal (Val : Uint) return Node_Id is
2531 Result : constant Node_Id := Make_Integer_Literal (Loc, Val);
2532 begin
2533 Set_Etype (Result, Artyp);
2534 Set_Analyzed (Result, True);
2535 Set_Is_Static_Expression (Result, False);
2536 return Result;
2537 end Make_Artyp_Literal;
2538
2539 --------------
2540 -- To_Artyp --
2541 --------------
2542
2543 function To_Artyp (X : Node_Id) return Node_Id is
2544 begin
2545 if Ityp = Base_Type (Artyp) then
2546 return X;
2547
2548 elsif Is_Enumeration_Type (Ityp) then
2549 return
2550 Make_Attribute_Reference (Loc,
2551 Prefix => New_Occurrence_Of (Ityp, Loc),
2552 Attribute_Name => Name_Pos,
2553 Expressions => New_List (X));
2554
2555 else
2556 return Convert_To (Artyp, X);
2557 end if;
2558 end To_Artyp;
2559
2560 -------------
2561 -- To_Ityp --
2562 -------------
2563
2564 function To_Ityp (X : Node_Id) return Node_Id is
2565 begin
2566 if Is_Enumeration_Type (Ityp) then
2567 return
2568 Make_Attribute_Reference (Loc,
2569 Prefix => New_Occurrence_Of (Ityp, Loc),
2570 Attribute_Name => Name_Val,
2571 Expressions => New_List (X));
2572
2573 -- Case where we will do a type conversion
2574
2575 else
2576 if Ityp = Base_Type (Artyp) then
2577 return X;
2578 else
2579 return Convert_To (Ityp, X);
2580 end if;
2581 end if;
2582 end To_Ityp;
2583
2584 -- Local Declarations
2585
2586 Opnd_Typ : Entity_Id;
2587 Slice_Rng : Node_Id;
2588 Subtyp_Ind : Node_Id;
2589 Subtyp_Rng : Node_Id;
2590 Ent : Entity_Id;
2591 Len : Unat;
2592 J : Nat;
2593 Clen : Node_Id;
2594 Set : Boolean;
2595
2596 -- Start of processing for Expand_Concatenate
2597
2598 begin
2599 -- Choose an appropriate computational type
2600
2601 -- We will be doing calculations of lengths and bounds in this routine
2602 -- and computing one from the other in some cases, e.g. getting the high
2603 -- bound by adding the length-1 to the low bound.
2604
2605 -- We can't just use the index type, or even its base type for this
2606 -- purpose for two reasons. First it might be an enumeration type which
2607 -- is not suitable for computations of any kind, and second it may
2608 -- simply not have enough range. For example if the index type is
2609 -- -128..+127 then lengths can be up to 256, which is out of range of
2610 -- the type.
2611
2612 -- For enumeration types, we can simply use Standard_Integer, this is
2613 -- sufficient since the actual number of enumeration literals cannot
2614 -- possibly exceed the range of integer (remember we will be doing the
2615 -- arithmetic with POS values, not representation values).
2616
2617 if Is_Enumeration_Type (Ityp) then
2618 Artyp := Standard_Integer;
2619
2620 -- For modular types, we use a 32-bit modular type for types whose size
2621 -- is in the range 1-31 bits. For 32-bit unsigned types, we use the
2622 -- identity type, and for larger unsigned types we use a 64-bit type.
2623
2624 elsif Is_Modular_Integer_Type (Ityp) then
2625 if RM_Size (Ityp) < Standard_Integer_Size then
2626 Artyp := Standard_Unsigned;
2627 elsif RM_Size (Ityp) = Standard_Integer_Size then
2628 Artyp := Ityp;
2629 else
2630 Artyp := Standard_Long_Long_Unsigned;
2631 end if;
2632
2633 -- Similar treatment for signed types
2634
2635 else
2636 if RM_Size (Ityp) < Standard_Integer_Size then
2637 Artyp := Standard_Integer;
2638 elsif RM_Size (Ityp) = Standard_Integer_Size then
2639 Artyp := Ityp;
2640 else
2641 Artyp := Standard_Long_Long_Integer;
2642 end if;
2643 end if;
2644
2645 -- Supply dummy entry at start of length array
2646
2647 Aggr_Length (0) := Make_Artyp_Literal (Uint_0);
2648
2649 -- Go through operands setting up the above arrays
2650
2651 J := 1;
2652 while J <= N loop
2653 Opnd := Remove_Head (Opnds);
2654 Opnd_Typ := Etype (Opnd);
2655
2656 -- The parent got messed up when we put the operands in a list,
2657 -- so now put back the proper parent for the saved operand, that
2658 -- is to say the concatenation node, to make sure that each operand
2659 -- is seen as a subexpression, e.g. if actions must be inserted.
2660
2661 Set_Parent (Opnd, Cnode);
2662
2663 -- Set will be True when we have setup one entry in the array
2664
2665 Set := False;
2666
2667 -- Singleton element (or character literal) case
2668
2669 if Base_Type (Opnd_Typ) = Ctyp then
2670 NN := NN + 1;
2671 Operands (NN) := Opnd;
2672 Is_Fixed_Length (NN) := True;
2673 Fixed_Length (NN) := Uint_1;
2674 Result_May_Be_Null := False;
2675
2676 -- Set low bound of operand (no need to set Last_Opnd_High_Bound
2677 -- since we know that the result cannot be null).
2678
2679 Opnd_Low_Bound (NN) :=
2680 Make_Attribute_Reference (Loc,
2681 Prefix => New_Occurrence_Of (Istyp, Loc),
2682 Attribute_Name => Name_First);
2683
2684 Set := True;
2685
2686 -- String literal case (can only occur for strings of course)
2687
2688 elsif Nkind (Opnd) = N_String_Literal then
2689 Len := String_Literal_Length (Opnd_Typ);
2690
2691 if Len > 0 then
2692 Result_May_Be_Null := False;
2693 end if;
2694
2695 -- Capture last operand low and high bound if result could be null
2696
2697 if J = N and then Result_May_Be_Null then
2698 Last_Opnd_Low_Bound :=
2699 New_Copy_Tree (String_Literal_Low_Bound (Opnd_Typ));
2700
2701 Last_Opnd_High_Bound :=
2702 Make_Op_Subtract (Loc,
2703 Left_Opnd =>
2704 New_Copy_Tree (String_Literal_Low_Bound (Opnd_Typ)),
2705 Right_Opnd => Make_Integer_Literal (Loc, 1));
2706 end if;
2707
2708 -- Skip null string literal
2709
2710 if J < N and then Len = 0 then
2711 goto Continue;
2712 end if;
2713
2714 NN := NN + 1;
2715 Operands (NN) := Opnd;
2716 Is_Fixed_Length (NN) := True;
2717
2718 -- Set length and bounds
2719
2720 Fixed_Length (NN) := Len;
2721
2722 Opnd_Low_Bound (NN) :=
2723 New_Copy_Tree (String_Literal_Low_Bound (Opnd_Typ));
2724
2725 Set := True;
2726
2727 -- All other cases
2728
2729 else
2730 -- Check constrained case with known bounds
2731
2732 if Is_Constrained (Opnd_Typ)
2733 and then Compile_Time_Known_Bounds (Opnd_Typ)
2734 then
2735 declare
2736 Lo, Hi : Uint;
2737
2738 begin
2739 -- Fixed length constrained array type with known at compile
2740 -- time bounds is last case of fixed length operand.
2741
2742 Get_First_Index_Bounds (Opnd_Typ, Lo, Hi);
2743 Len := UI_Max (Hi - Lo + 1, Uint_0);
2744
2745 if Len > 0 then
2746 Result_May_Be_Null := False;
2747 end if;
2748
2749 -- Capture last operand bounds if result could be null
2750
2751 if J = N and then Result_May_Be_Null then
2752 Last_Opnd_Low_Bound :=
2753 To_Ityp (Make_Integer_Literal (Loc, Lo));
2754
2755 Last_Opnd_High_Bound :=
2756 To_Ityp (Make_Integer_Literal (Loc, Hi));
2757 end if;
2758
2759 -- Exclude null length case unless last operand
2760
2761 if J < N and then Len = 0 then
2762 goto Continue;
2763 end if;
2764
2765 NN := NN + 1;
2766 Operands (NN) := Opnd;
2767 Is_Fixed_Length (NN) := True;
2768 Fixed_Length (NN) := Len;
2769
2770 Opnd_Low_Bound (NN) :=
2771 To_Ityp (Make_Integer_Literal (Loc, Lo));
2772 Set := True;
2773 end;
2774 end if;
2775
2776 -- All cases where the length is not known at compile time, or the
2777 -- special case of an operand which is known to be null but has a
2778 -- lower bound other than 1 or is other than a string type.
2779
2780 if not Set then
2781 NN := NN + 1;
2782
2783 -- Capture operand bounds
2784
2785 Opnd_Low_Bound (NN) :=
2786 Make_Attribute_Reference (Loc,
2787 Prefix =>
2788 Duplicate_Subexpr (Opnd, Name_Req => True),
2789 Attribute_Name => Name_First);
2790
2791 -- Capture last operand bounds if result could be null
2792
2793 if J = N and Result_May_Be_Null then
2794 Last_Opnd_Low_Bound :=
2795 Convert_To (Ityp,
2796 Make_Attribute_Reference (Loc,
2797 Prefix =>
2798 Duplicate_Subexpr (Opnd, Name_Req => True),
2799 Attribute_Name => Name_First));
2800
2801 Last_Opnd_High_Bound :=
2802 Convert_To (Ityp,
2803 Make_Attribute_Reference (Loc,
2804 Prefix =>
2805 Duplicate_Subexpr (Opnd, Name_Req => True),
2806 Attribute_Name => Name_Last));
2807 end if;
2808
2809 -- Capture length of operand in entity
2810
2811 Operands (NN) := Opnd;
2812 Is_Fixed_Length (NN) := False;
2813
2814 Var_Length (NN) := Make_Temporary (Loc, 'L');
2815
2816 -- If the operand is a slice, try to compute an upper bound for
2817 -- its length.
2818
2819 if Nkind (Opnd) = N_Slice
2820 and then Is_Constrained (Etype (Prefix (Opnd)))
2821 and then Compile_Time_Known_Bounds (Etype (Prefix (Opnd)))
2822 then
2823 declare
2824 Lo, Hi : Uint;
2825
2826 begin
2827 Get_First_Index_Bounds (Etype (Prefix (Opnd)), Lo, Hi);
2828 Max_Length (NN) := UI_Max (Hi - Lo + 1, Uint_0);
2829 end;
2830
2831 else
2832 Max_Length (NN) := Too_Large_Length_For_Array;
2833 end if;
2834
2835 Append_To (Actions,
2836 Make_Object_Declaration (Loc,
2837 Defining_Identifier => Var_Length (NN),
2838 Constant_Present => True,
2839 Object_Definition => New_Occurrence_Of (Artyp, Loc),
2840 Expression =>
2841 Make_Attribute_Reference (Loc,
2842 Prefix =>
2843 Duplicate_Subexpr (Opnd, Name_Req => True),
2844 Attribute_Name => Name_Length)));
2845 end if;
2846 end if;
2847
2848 -- Set next entry in aggregate length array
2849
2850 -- For first entry, make either integer literal for fixed length
2851 -- or a reference to the saved length for variable length.
2852
2853 if NN = 1 then
2854 if Is_Fixed_Length (1) then
2855 Aggr_Length (1) := Make_Integer_Literal (Loc, Fixed_Length (1));
2856 Max_Aggr_Length := Fixed_Length (1);
2857 else
2858 Aggr_Length (1) := New_Occurrence_Of (Var_Length (1), Loc);
2859 Max_Aggr_Length := Max_Length (1);
2860 end if;
2861
2862 -- If entry is fixed length and only fixed lengths so far, make
2863 -- appropriate new integer literal adding new length.
2864
2865 elsif Is_Fixed_Length (NN)
2866 and then Nkind (Aggr_Length (NN - 1)) = N_Integer_Literal
2867 then
2868 Aggr_Length (NN) :=
2869 Make_Integer_Literal (Loc,
2870 Intval => Fixed_Length (NN) + Intval (Aggr_Length (NN - 1)));
2871 Max_Aggr_Length := Intval (Aggr_Length (NN));
2872
2873 -- All other cases, construct an addition node for the length and
2874 -- create an entity initialized to this length.
2875
2876 else
2877 Ent := Make_Temporary (Loc, 'L');
2878
2879 if Is_Fixed_Length (NN) then
2880 Clen := Make_Integer_Literal (Loc, Fixed_Length (NN));
2881 Max_Aggr_Length := Max_Aggr_Length + Fixed_Length (NN);
2882
2883 else
2884 Clen := New_Occurrence_Of (Var_Length (NN), Loc);
2885 Max_Aggr_Length := Max_Aggr_Length + Max_Length (NN);
2886 end if;
2887
2888 Append_To (Actions,
2889 Make_Object_Declaration (Loc,
2890 Defining_Identifier => Ent,
2891 Constant_Present => True,
2892 Object_Definition => New_Occurrence_Of (Artyp, Loc),
2893 Expression =>
2894 Make_Op_Add (Loc,
2895 Left_Opnd => New_Copy_Tree (Aggr_Length (NN - 1)),
2896 Right_Opnd => Clen)));
2897
2898 Aggr_Length (NN) := Make_Identifier (Loc, Chars => Chars (Ent));
2899 end if;
2900
2901 <<Continue>>
2902 J := J + 1;
2903 end loop;
2904
2905 -- If we have only skipped null operands, return the last operand
2906
2907 if NN = 0 then
2908 Result := Opnd;
2909 goto Done;
2910 end if;
2911
2912 -- If we have only one non-null operand, return it and we are done.
2913 -- There is one case in which this cannot be done, and that is when
2914 -- the sole operand is of the element type, in which case it must be
2915 -- converted to an array, and the easiest way of doing that is to go
2916 -- through the normal general circuit.
2917
2918 if NN = 1 and then Base_Type (Etype (Operands (1))) /= Ctyp then
2919 Result := Operands (1);
2920 goto Done;
2921 end if;
2922
2923 -- Cases where we have a real concatenation
2924
2925 -- Next step is to find the low bound for the result array that we
2926 -- will allocate. The rules for this are in (RM 4.5.6(5-7)).
2927
2928 -- If the ultimate ancestor of the index subtype is a constrained array
2929 -- definition, then the lower bound is that of the index subtype as
2930 -- specified by (RM 4.5.3(6)).
2931
2932 -- The right test here is to go to the root type, and then the ultimate
2933 -- ancestor is the first subtype of this root type.
2934
2935 if Is_Constrained (First_Subtype (Root_Type (Atyp))) then
2936 Low_Bound :=
2937 Make_Attribute_Reference (Loc,
2938 Prefix =>
2939 New_Occurrence_Of (First_Subtype (Root_Type (Atyp)), Loc),
2940 Attribute_Name => Name_First);
2941
2942 -- If the first operand in the list has known length we know that
2943 -- the lower bound of the result is the lower bound of this operand.
2944
2945 elsif Is_Fixed_Length (1) then
2946 Low_Bound := Opnd_Low_Bound (1);
2947
2948 -- OK, we don't know the lower bound, we have to build a horrible
2949 -- if expression node of the form
2950
2951 -- if Cond1'Length /= 0 then
2952 -- Opnd1 low bound
2953 -- else
2954 -- if Opnd2'Length /= 0 then
2955 -- Opnd2 low bound
2956 -- else
2957 -- ...
2958
2959 -- The nesting ends either when we hit an operand whose length is known
2960 -- at compile time, or on reaching the last operand, whose low bound we
2961 -- take unconditionally whether or not it is null. It's easiest to do
2962 -- this with a recursive procedure:
2963
2964 else
2965 declare
2966 function Get_Known_Bound (J : Nat) return Node_Id;
2967 -- Returns the lower bound determined by operands J .. NN
2968
2969 ---------------------
2970 -- Get_Known_Bound --
2971 ---------------------
2972
2973 function Get_Known_Bound (J : Nat) return Node_Id is
2974 begin
2975 if Is_Fixed_Length (J) or else J = NN then
2976 return New_Copy_Tree (Opnd_Low_Bound (J));
2977
2978 else
2979 return
2980 Make_If_Expression (Loc,
2981 Expressions => New_List (
2982
2983 Make_Op_Ne (Loc,
2984 Left_Opnd =>
2985 New_Occurrence_Of (Var_Length (J), Loc),
2986 Right_Opnd =>
2987 Make_Integer_Literal (Loc, 0)),
2988
2989 New_Copy_Tree (Opnd_Low_Bound (J)),
2990 Get_Known_Bound (J + 1)));
2991 end if;
2992 end Get_Known_Bound;
2993
2994 begin
2995 Ent := Make_Temporary (Loc, 'L');
2996
2997 Append_To (Actions,
2998 Make_Object_Declaration (Loc,
2999 Defining_Identifier => Ent,
3000 Constant_Present => True,
3001 Object_Definition => New_Occurrence_Of (Ityp, Loc),
3002 Expression => Get_Known_Bound (1)));
3003
3004 Low_Bound := New_Occurrence_Of (Ent, Loc);
3005 end;
3006 end if;
3007
3008 pragma Assert (Present (Low_Bound));
3009
3010 -- Now we can compute the high bound as Low_Bound + Length - 1
3011
3012 if Compile_Time_Known_Value (Low_Bound)
3013 and then Nkind (Aggr_Length (NN)) = N_Integer_Literal
3014 then
3015 High_Bound :=
3016 To_Ityp
3017 (Make_Artyp_Literal
3018 (Expr_Value (Low_Bound) + Intval (Aggr_Length (NN)) - 1));
3019
3020 else
3021 High_Bound :=
3022 To_Ityp
3023 (Make_Op_Add (Loc,
3024 Left_Opnd => To_Artyp (New_Copy_Tree (Low_Bound)),
3025 Right_Opnd =>
3026 Make_Op_Subtract (Loc,
3027 Left_Opnd => New_Copy_Tree (Aggr_Length (NN)),
3028 Right_Opnd => Make_Artyp_Literal (Uint_1))));
3029
3030 -- Note that calculation of the high bound may cause overflow in some
3031 -- very weird cases, so in the general case we need an overflow check
3032 -- on the high bound. We can avoid this for the common case of string
3033 -- types and other types whose index is Positive, since we chose a
3034 -- wider range for the arithmetic type. If checks are suppressed, we
3035 -- do not set the flag so superfluous warnings may be omitted.
3036
3037 if Istyp /= Standard_Positive
3038 and then not Overflow_Checks_Suppressed (Istyp)
3039 then
3040 Activate_Overflow_Check (High_Bound);
3041 end if;
3042 end if;
3043
3044 -- Handle the exceptional case where the result is null, in which case
3045 -- case the bounds come from the last operand (so that we get the proper
3046 -- bounds if the last operand is superflat).
3047
3048 if Result_May_Be_Null then
3049 Low_Bound :=
3050 Make_If_Expression (Loc,
3051 Expressions => New_List (
3052 Make_Op_Eq (Loc,
3053 Left_Opnd => New_Copy_Tree (Aggr_Length (NN)),
3054 Right_Opnd => Make_Artyp_Literal (Uint_0)),
3055 Last_Opnd_Low_Bound,
3056 Low_Bound));
3057
3058 High_Bound :=
3059 Make_If_Expression (Loc,
3060 Expressions => New_List (
3061 Make_Op_Eq (Loc,
3062 Left_Opnd => New_Copy_Tree (Aggr_Length (NN)),
3063 Right_Opnd => Make_Artyp_Literal (Uint_0)),
3064 Last_Opnd_High_Bound,
3065 High_Bound));
3066 end if;
3067
3068 -- Here is where we insert the saved up actions
3069
3070 Insert_Actions (Cnode, Actions, Suppress => All_Checks);
3071
3072 -- If the low bound is known at compile time and not the high bound, but
3073 -- we have computed a sensible upper bound for the length, then adjust
3074 -- the high bound for the subtype of the array. This will change it into
3075 -- a static subtype and thus help the code generator.
3076
3077 if Compile_Time_Known_Value (Low_Bound)
3078 and then not Compile_Time_Known_Value (High_Bound)
3079 and then Max_Aggr_Length < Too_Large_Length_For_Array
3080 then
3081 declare
3082 Known_High_Bound : constant Node_Id :=
3083 To_Ityp
3084 (Make_Artyp_Literal
3085 (Expr_Value (Low_Bound) + Max_Aggr_Length - 1));
3086
3087 begin
3088 if not Is_Out_Of_Range (Known_High_Bound, Ityp) then
3089 Slice_Rng := Make_Range (Loc, Low_Bound, High_Bound);
3090 High_Bound := Known_High_Bound;
3091
3092 else
3093 Slice_Rng := Empty;
3094 end if;
3095 end;
3096
3097 else
3098 Slice_Rng := Empty;
3099 end if;
3100
3101 Subtyp_Rng := Make_Range (Loc, Low_Bound, High_Bound);
3102
3103 -- If the result cannot be null then the range cannot be superflat
3104
3105 Set_Cannot_Be_Superflat (Subtyp_Rng, not Result_May_Be_Null);
3106
3107 -- Now we construct an array object with appropriate bounds. We mark
3108 -- the target as internal to prevent useless initialization when
3109 -- Initialize_Scalars is enabled. Also since this is the actual result
3110 -- entity, we make sure we have debug information for the result.
3111
3112 Subtyp_Ind :=
3113 Make_Subtype_Indication (Loc,
3114 Subtype_Mark => New_Occurrence_Of (Atyp, Loc),
3115 Constraint =>
3116 Make_Index_Or_Discriminant_Constraint (Loc,
3117 Constraints => New_List (Subtyp_Rng)));
3118
3119 Ent := Make_Temporary (Loc, 'S');
3120 Set_Is_Internal (Ent);
3121 Set_Debug_Info_Needed (Ent);
3122
3123 -- If we are concatenating strings and the current scope already uses
3124 -- the secondary stack, allocate the result also on the secondary stack
3125 -- to avoid putting too much pressure on the primary stack.
3126
3127 -- Don't do this if -gnatd.h is set, as this will break the wrapping of
3128 -- Cnode in an Expression_With_Actions, see Expand_N_Op_Concat.
3129
3130 if Atyp = Standard_String
3131 and then Uses_Sec_Stack (Current_Scope)
3132 and then RTE_Available (RE_SS_Pool)
3133 and then not Debug_Flag_Dot_H
3134 then
3135 -- Generate:
3136 -- subtype Axx is String (<low-bound> .. <high-bound>)
3137 -- type Ayy is access Axx;
3138 -- Rxx : Ayy := new <Axx> [storage_pool = ss_pool];
3139 -- Sxx : Axx renames Rxx.all;
3140
3141 declare
3142 ConstrT : constant Entity_Id := Make_Temporary (Loc, 'A');
3143 Acc_Typ : constant Entity_Id := Make_Temporary (Loc, 'A');
3144
3145 Alloc : Node_Id;
3146 Temp : Entity_Id;
3147
3148 begin
3149 Insert_Action (Cnode,
3150 Make_Subtype_Declaration (Loc,
3151 Defining_Identifier => ConstrT,
3152 Subtype_Indication => Subtyp_Ind),
3153 Suppress => All_Checks);
3154
3155 Freeze_Itype (ConstrT, Cnode);
3156
3157 Insert_Action (Cnode,
3158 Make_Full_Type_Declaration (Loc,
3159 Defining_Identifier => Acc_Typ,
3160 Type_Definition =>
3161 Make_Access_To_Object_Definition (Loc,
3162 Subtype_Indication => New_Occurrence_Of (ConstrT, Loc))),
3163 Suppress => All_Checks);
3164
3165 Mutate_Ekind (Acc_Typ, E_Access_Type);
3166 Set_Associated_Storage_Pool (Acc_Typ, RTE (RE_SS_Pool));
3167
3168 Alloc :=
3169 Make_Allocator (Loc,
3170 Expression => New_Occurrence_Of (ConstrT, Loc));
3171
3172 -- This is currently done only for type String, which normally
3173 -- doesn't have default initialization, but we need to set the
3174 -- No_Initialization flag in case of either Initialize_Scalars
3175 -- or Normalize_Scalars.
3176
3177 Set_No_Initialization (Alloc);
3178
3179 Temp := Make_Temporary (Loc, 'R', Alloc);
3180 Insert_Action (Cnode,
3181 Make_Object_Declaration (Loc,
3182 Defining_Identifier => Temp,
3183 Object_Definition => New_Occurrence_Of (Acc_Typ, Loc),
3184 Expression => Alloc),
3185 Suppress => All_Checks);
3186
3187 Insert_Action (Cnode,
3188 Make_Object_Renaming_Declaration (Loc,
3189 Defining_Identifier => Ent,
3190 Subtype_Mark => New_Occurrence_Of (ConstrT, Loc),
3191 Name =>
3192 Make_Explicit_Dereference (Loc,
3193 Prefix => New_Occurrence_Of (Temp, Loc))),
3194 Suppress => All_Checks);
3195 end;
3196
3197 else
3198 -- If the bound is statically known to be out of range, we do not
3199 -- want to abort, we want a warning and a runtime constraint error.
3200 -- Note that we have arranged that the result will not be treated
3201 -- as a static constant, so we won't get an illegality during this
3202 -- insertion. We also enable checks (in particular range checks) in
3203 -- case the bounds of Subtyp_Ind are out of range.
3204
3205 Insert_Action (Cnode,
3206 Make_Object_Declaration (Loc,
3207 Defining_Identifier => Ent,
3208 Object_Definition => Subtyp_Ind));
3209 end if;
3210
3211 -- If the result of the concatenation appears as the initializing
3212 -- expression of an object declaration, we can just rename the
3213 -- result, rather than copying it.
3214
3215 Set_OK_To_Rename (Ent);
3216
3217 -- Catch the static out of range case now
3218
3219 if Raises_Constraint_Error (High_Bound)
3220 or else Is_Out_Of_Range (High_Bound, Ityp)
3221 then
3222 -- Kill warning generated for the declaration of the static out of
3223 -- range high bound, and instead generate a Constraint_Error with
3224 -- an appropriate specific message.
3225
3226 if Nkind (High_Bound) = N_Integer_Literal then
3227 Kill_Dead_Code (High_Bound);
3228 Rewrite (High_Bound, New_Copy_Tree (Low_Bound));
3229
3230 else
3231 Kill_Dead_Code (Declaration_Node (Entity (High_Bound)));
3232 end if;
3233
3234 Apply_Compile_Time_Constraint_Error
3235 (N => Cnode,
3236 Msg => "concatenation result upper bound out of range??",
3237 Reason => CE_Range_Check_Failed);
3238
3239 return;
3240 end if;
3241
3242 -- Now we will generate the assignments to do the actual concatenation
3243
3244 -- There is one case in which we will not do this, namely when all the
3245 -- following conditions are met:
3246
3247 -- The result type is Standard.String
3248
3249 -- There are nine or fewer retained (non-null) operands
3250
3251 -- The optimization level is -O0 or the debug flag gnatd.C is set,
3252 -- and the debug flag gnatd.c is not set.
3253
3254 -- The corresponding System.Concat_n.Str_Concat_n routine is
3255 -- available in the run time.
3256
3257 -- If all these conditions are met then we generate a call to the
3258 -- relevant concatenation routine. The purpose of this is to avoid
3259 -- undesirable code bloat at -O0.
3260
3261 -- If the concatenation is within the declaration of a library-level
3262 -- object, we call the built-in concatenation routines to prevent code
3263 -- bloat, regardless of the optimization level. This is space efficient
3264 -- and prevents linking problems when units are compiled with different
3265 -- optimization levels.
3266
3267 if Atyp = Standard_String
3268 and then NN in 2 .. 9
3269 and then (((Optimization_Level = 0 or else Debug_Flag_Dot_CC)
3270 and then not Debug_Flag_Dot_C)
3271 or else Library_Level_Target)
3272 then
3273 declare
3274 RR : constant array (Nat range 2 .. 9) of RE_Id :=
3275 (RE_Str_Concat_2,
3276 RE_Str_Concat_3,
3277 RE_Str_Concat_4,
3278 RE_Str_Concat_5,
3279 RE_Str_Concat_6,
3280 RE_Str_Concat_7,
3281 RE_Str_Concat_8,
3282 RE_Str_Concat_9);
3283
3284 begin
3285 if RTE_Available (RR (NN)) then
3286 declare
3287 Opnds : constant List_Id :=
3288 New_List (New_Occurrence_Of (Ent, Loc));
3289
3290 begin
3291 for J in 1 .. NN loop
3292 if Is_List_Member (Operands (J)) then
3293 Remove (Operands (J));
3294 end if;
3295
3296 if Base_Type (Etype (Operands (J))) = Ctyp then
3297 Append_To (Opnds,
3298 Make_Aggregate (Loc,
3299 Component_Associations => New_List (
3300 Make_Component_Association (Loc,
3301 Choices => New_List (
3302 Make_Integer_Literal (Loc, 1)),
3303 Expression => Operands (J)))));
3304
3305 else
3306 Append_To (Opnds, Operands (J));
3307 end if;
3308 end loop;
3309
3310 Insert_Action (Cnode,
3311 Make_Procedure_Call_Statement (Loc,
3312 Name => New_Occurrence_Of (RTE (RR (NN)), Loc),
3313 Parameter_Associations => Opnds));
3314
3315 -- No assignments left to do below
3316
3317 NN := 0;
3318 end;
3319 end if;
3320 end;
3321 end if;
3322
3323 -- Not special case so generate the assignments
3324
3325 Known_Non_Null_Operand_Seen := False;
3326
3327 for J in 1 .. NN loop
3328 declare
3329 Lo : constant Node_Id :=
3330 Make_Op_Add (Loc,
3331 Left_Opnd => To_Artyp (New_Copy_Tree (Low_Bound)),
3332 Right_Opnd => Aggr_Length (J - 1));
3333
3334 Hi : constant Node_Id :=
3335 Make_Op_Add (Loc,
3336 Left_Opnd => To_Artyp (New_Copy_Tree (Low_Bound)),
3337 Right_Opnd =>
3338 Make_Op_Subtract (Loc,
3339 Left_Opnd => Aggr_Length (J),
3340 Right_Opnd => Make_Artyp_Literal (Uint_1)));
3341
3342 begin
3343 -- Singleton case, simple assignment
3344
3345 if Base_Type (Etype (Operands (J))) = Ctyp then
3346 Known_Non_Null_Operand_Seen := True;
3347 Insert_Action (Cnode,
3348 Make_Assignment_Statement (Loc,
3349 Name =>
3350 Make_Indexed_Component (Loc,
3351 Prefix => New_Occurrence_Of (Ent, Loc),
3352 Expressions => New_List (To_Ityp (Lo))),
3353 Expression => Operands (J)),
3354 Suppress => All_Checks);
3355
3356 -- Array case, slice assignment, skipped when argument is fixed
3357 -- length and known to be null.
3358
3359 elsif not Is_Fixed_Length (J) or else Fixed_Length (J) > 0 then
3360 declare
3361 Assign : Node_Id :=
3362 Make_Assignment_Statement (Loc,
3363 Name =>
3364 Make_Slice (Loc,
3365 Prefix =>
3366 New_Occurrence_Of (Ent, Loc),
3367 Discrete_Range =>
3368 Make_Range (Loc,
3369 Low_Bound => To_Ityp (Lo),
3370 High_Bound => To_Ityp (Hi))),
3371 Expression => Operands (J));
3372 begin
3373 if Is_Fixed_Length (J) then
3374 Known_Non_Null_Operand_Seen := True;
3375
3376 elsif not Known_Non_Null_Operand_Seen then
3377
3378 -- Here if operand length is not statically known and no
3379 -- operand known to be non-null has been processed yet.
3380 -- If operand length is 0, we do not need to perform the
3381 -- assignment, and we must avoid the evaluation of the
3382 -- high bound of the slice, since it may underflow if the
3383 -- low bound is Ityp'First.
3384
3385 Assign :=
3386 Make_Implicit_If_Statement (Cnode,
3387 Condition =>
3388 Make_Op_Ne (Loc,
3389 Left_Opnd =>
3390 New_Occurrence_Of (Var_Length (J), Loc),
3391 Right_Opnd => Make_Integer_Literal (Loc, 0)),
3392 Then_Statements => New_List (Assign));
3393 end if;
3394
3395 Insert_Action (Cnode, Assign, Suppress => All_Checks);
3396 end;
3397 end if;
3398 end;
3399 end loop;
3400
3401 -- Finally we build the result, which is either a direct reference to
3402 -- the array object or a slice of it.
3403
3404 Result := New_Occurrence_Of (Ent, Loc);
3405
3406 if Present (Slice_Rng) then
3407 Result := Make_Slice (Loc, Result, Slice_Rng);
3408 end if;
3409
3410 <<Done>>
3411 pragma Assert (Present (Result));
3412 Rewrite (Cnode, Result);
3413 Analyze_And_Resolve (Cnode, Atyp);
3414 end Expand_Concatenate;
3415
3416 ---------------------------------------------------
3417 -- Expand_Membership_Minimize_Eliminate_Overflow --
3418 ---------------------------------------------------
3419
3420 procedure Expand_Membership_Minimize_Eliminate_Overflow (N : Node_Id) is
3421 pragma Assert (Nkind (N) = N_In);
3422 -- Despite the name, this routine applies only to N_In, not to
3423 -- N_Not_In. The latter is always rewritten as not (X in Y).
3424
3425 Result_Type : constant Entity_Id := Etype (N);
3426 -- Capture result type, may be a derived boolean type
3427
3428 Loc : constant Source_Ptr := Sloc (N);
3429 Lop : constant Node_Id := Left_Opnd (N);
3430 Rop : constant Node_Id := Right_Opnd (N);
3431
3432 -- Note: there are many referencs to Etype (Lop) and Etype (Rop). It
3433 -- is thus tempting to capture these values, but due to the rewrites
3434 -- that occur as a result of overflow checking, these values change
3435 -- as we go along, and it is safe just to always use Etype explicitly.
3436
3437 Restype : constant Entity_Id := Etype (N);
3438 -- Save result type
3439
3440 Lo, Hi : Uint;
3441 -- Bounds in Minimize calls, not used currently
3442
3443 LLIB : constant Entity_Id := Base_Type (Standard_Long_Long_Integer);
3444 -- Entity for Long_Long_Integer'Base
3445
3446 begin
3447 Minimize_Eliminate_Overflows (Lop, Lo, Hi, Top_Level => False);
3448
3449 -- If right operand is a subtype name, and the subtype name has no
3450 -- predicate, then we can just replace the right operand with an
3451 -- explicit range T'First .. T'Last, and use the explicit range code.
3452
3453 if Nkind (Rop) /= N_Range
3454 and then No (Predicate_Function (Etype (Rop)))
3455 then
3456 declare
3457 Rtyp : constant Entity_Id := Etype (Rop);
3458 begin
3459 Rewrite (Rop,
3460 Make_Range (Loc,
3461 Low_Bound =>
3462 Make_Attribute_Reference (Loc,
3463 Attribute_Name => Name_First,
3464 Prefix => New_Occurrence_Of (Rtyp, Loc)),
3465 High_Bound =>
3466 Make_Attribute_Reference (Loc,
3467 Attribute_Name => Name_Last,
3468 Prefix => New_Occurrence_Of (Rtyp, Loc))));
3469 Analyze_And_Resolve (Rop, Rtyp, Suppress => All_Checks);
3470 end;
3471 end if;
3472
3473 -- Here for the explicit range case. Note that the bounds of the range
3474 -- have not been processed for minimized or eliminated checks.
3475
3476 if Nkind (Rop) = N_Range then
3477 Minimize_Eliminate_Overflows
3478 (Low_Bound (Rop), Lo, Hi, Top_Level => False);
3479 Minimize_Eliminate_Overflows
3480 (High_Bound (Rop), Lo, Hi, Top_Level => False);
3481
3482 -- We have A in B .. C, treated as A >= B and then A <= C
3483
3484 -- Bignum case
3485
3486 if Is_RTE (Etype (Lop), RE_Bignum)
3487 or else Is_RTE (Etype (Low_Bound (Rop)), RE_Bignum)
3488 or else Is_RTE (Etype (High_Bound (Rop)), RE_Bignum)
3489 then
3490 declare
3491 Blk : constant Node_Id := Make_Bignum_Block (Loc);
3492 Bnn : constant Entity_Id := Make_Temporary (Loc, 'B', N);
3493 L : constant Entity_Id :=
3494 Make_Defining_Identifier (Loc, Name_uL);
3495 Lopnd : constant Node_Id := Convert_To_Bignum (Lop);
3496 Lbound : constant Node_Id :=
3497 Convert_To_Bignum (Low_Bound (Rop));
3498 Hbound : constant Node_Id :=
3499 Convert_To_Bignum (High_Bound (Rop));
3500
3501 -- Now we rewrite the membership test node to look like
3502
3503 -- do
3504 -- Bnn : Result_Type;
3505 -- declare
3506 -- M : Mark_Id := SS_Mark;
3507 -- L : Bignum := Lopnd;
3508 -- begin
3509 -- Bnn := Big_GE (L, Lbound) and then Big_LE (L, Hbound)
3510 -- SS_Release (M);
3511 -- end;
3512 -- in
3513 -- Bnn
3514 -- end
3515
3516 begin
3517 -- Insert declaration of L into declarations of bignum block
3518
3519 Insert_After
3520 (Last (Declarations (Blk)),
3521 Make_Object_Declaration (Loc,
3522 Defining_Identifier => L,
3523 Object_Definition =>
3524 New_Occurrence_Of (RTE (RE_Bignum), Loc),
3525 Expression => Lopnd));
3526
3527 -- Insert assignment to Bnn into expressions of bignum block
3528
3529 Insert_Before
3530 (First (Statements (Handled_Statement_Sequence (Blk))),
3531 Make_Assignment_Statement (Loc,
3532 Name => New_Occurrence_Of (Bnn, Loc),
3533 Expression =>
3534 Make_And_Then (Loc,
3535 Left_Opnd =>
3536 Make_Function_Call (Loc,
3537 Name =>
3538 New_Occurrence_Of (RTE (RE_Big_GE), Loc),
3539 Parameter_Associations => New_List (
3540 New_Occurrence_Of (L, Loc),
3541 Lbound)),
3542
3543 Right_Opnd =>
3544 Make_Function_Call (Loc,
3545 Name =>
3546 New_Occurrence_Of (RTE (RE_Big_LE), Loc),
3547 Parameter_Associations => New_List (
3548 New_Occurrence_Of (L, Loc),
3549 Hbound)))));
3550
3551 -- Now rewrite the node
3552
3553 Rewrite (N,
3554 Make_Expression_With_Actions (Loc,
3555 Actions => New_List (
3556 Make_Object_Declaration (Loc,
3557 Defining_Identifier => Bnn,
3558 Object_Definition =>
3559 New_Occurrence_Of (Result_Type, Loc)),
3560 Blk),
3561 Expression => New_Occurrence_Of (Bnn, Loc)));
3562 Analyze_And_Resolve (N, Result_Type);
3563 return;
3564 end;
3565
3566 -- Here if no bignums around
3567
3568 else
3569 -- Case where types are all the same
3570
3571 if Base_Type (Etype (Lop)) = Base_Type (Etype (Low_Bound (Rop)))
3572 and then
3573 Base_Type (Etype (Lop)) = Base_Type (Etype (High_Bound (Rop)))
3574 then
3575 null;
3576
3577 -- If types are not all the same, it means that we have rewritten
3578 -- at least one of them to be of type Long_Long_Integer, and we
3579 -- will convert the other operands to Long_Long_Integer.
3580
3581 else
3582 Convert_To_And_Rewrite (LLIB, Lop);
3583 Set_Analyzed (Lop, False);
3584 Analyze_And_Resolve (Lop, LLIB);
3585
3586 -- For the right operand, avoid unnecessary recursion into
3587 -- this routine, we know that overflow is not possible.
3588
3589 Convert_To_And_Rewrite (LLIB, Low_Bound (Rop));
3590 Convert_To_And_Rewrite (LLIB, High_Bound (Rop));
3591 Set_Analyzed (Rop, False);
3592 Analyze_And_Resolve (Rop, LLIB, Suppress => Overflow_Check);
3593 end if;
3594
3595 -- Now the three operands are of the same signed integer type,
3596 -- so we can use the normal expansion routine for membership,
3597 -- setting the flag to prevent recursion into this procedure.
3598
3599 Set_No_Minimize_Eliminate (N);
3600 Expand_N_In (N);
3601 end if;
3602
3603 -- Right operand is a subtype name and the subtype has a predicate. We
3604 -- have to make sure the predicate is checked, and for that we need to
3605 -- use the standard N_In circuitry with appropriate types.
3606
3607 else
3608 pragma Assert (Present (Predicate_Function (Etype (Rop))));
3609
3610 -- If types are "right", just call Expand_N_In preventing recursion
3611
3612 if Base_Type (Etype (Lop)) = Base_Type (Etype (Rop)) then
3613 Set_No_Minimize_Eliminate (N);
3614 Expand_N_In (N);
3615
3616 -- Bignum case
3617
3618 elsif Is_RTE (Etype (Lop), RE_Bignum) then
3619
3620 -- For X in T, we want to rewrite our node as
3621
3622 -- do
3623 -- Bnn : Result_Type;
3624
3625 -- declare
3626 -- M : Mark_Id := SS_Mark;
3627 -- Lnn : Long_Long_Integer'Base
3628 -- Nnn : Bignum;
3629
3630 -- begin
3631 -- Nnn := X;
3632
3633 -- if not Bignum_In_LLI_Range (Nnn) then
3634 -- Bnn := False;
3635 -- else
3636 -- Lnn := From_Bignum (Nnn);
3637 -- Bnn :=
3638 -- Lnn in LLIB (T'Base'First) .. LLIB (T'Base'Last)
3639 -- and then T'Base (Lnn) in T;
3640 -- end if;
3641
3642 -- SS_Release (M);
3643 -- end
3644 -- in
3645 -- Bnn
3646 -- end
3647
3648 -- A bit gruesome, but there doesn't seem to be a simpler way
3649
3650 declare
3651 Blk : constant Node_Id := Make_Bignum_Block (Loc);
3652 Bnn : constant Entity_Id := Make_Temporary (Loc, 'B', N);
3653 Lnn : constant Entity_Id := Make_Temporary (Loc, 'L', N);
3654 Nnn : constant Entity_Id := Make_Temporary (Loc, 'N', N);
3655 T : constant Entity_Id := Etype (Rop);
3656 TB : constant Entity_Id := Base_Type (T);
3657 Nin : Node_Id;
3658
3659 begin
3660 -- Mark the last membership operation to prevent recursion
3661
3662 Nin :=
3663 Make_In (Loc,
3664 Left_Opnd => Convert_To (TB, New_Occurrence_Of (Lnn, Loc)),
3665 Right_Opnd => New_Occurrence_Of (T, Loc));
3666 Set_No_Minimize_Eliminate (Nin);
3667
3668 -- Now decorate the block
3669
3670 Insert_After
3671 (Last (Declarations (Blk)),
3672 Make_Object_Declaration (Loc,
3673 Defining_Identifier => Lnn,
3674 Object_Definition => New_Occurrence_Of (LLIB, Loc)));
3675
3676 Insert_After
3677 (Last (Declarations (Blk)),
3678 Make_Object_Declaration (Loc,
3679 Defining_Identifier => Nnn,
3680 Object_Definition =>
3681 New_Occurrence_Of (RTE (RE_Bignum), Loc)));
3682
3683 Insert_List_Before
3684 (First (Statements (Handled_Statement_Sequence (Blk))),
3685 New_List (
3686 Make_Assignment_Statement (Loc,
3687 Name => New_Occurrence_Of (Nnn, Loc),
3688 Expression => Relocate_Node (Lop)),
3689
3690 Make_Implicit_If_Statement (N,
3691 Condition =>
3692 Make_Op_Not (Loc,
3693 Right_Opnd =>
3694 Make_Function_Call (Loc,
3695 Name =>
3696 New_Occurrence_Of
3697 (RTE (RE_Bignum_In_LLI_Range), Loc),
3698 Parameter_Associations => New_List (
3699 New_Occurrence_Of (Nnn, Loc)))),
3700
3701 Then_Statements => New_List (
3702 Make_Assignment_Statement (Loc,
3703 Name => New_Occurrence_Of (Bnn, Loc),
3704 Expression =>
3705 New_Occurrence_Of (Standard_False, Loc))),
3706
3707 Else_Statements => New_List (
3708 Make_Assignment_Statement (Loc,
3709 Name => New_Occurrence_Of (Lnn, Loc),
3710 Expression =>
3711 Make_Function_Call (Loc,
3712 Name =>
3713 New_Occurrence_Of (RTE (RE_From_Bignum), Loc),
3714 Parameter_Associations => New_List (
3715 New_Occurrence_Of (Nnn, Loc)))),
3716
3717 Make_Assignment_Statement (Loc,
3718 Name => New_Occurrence_Of (Bnn, Loc),
3719 Expression =>
3720 Make_And_Then (Loc,
3721 Left_Opnd =>
3722 Make_In (Loc,
3723 Left_Opnd => New_Occurrence_Of (Lnn, Loc),
3724 Right_Opnd =>
3725 Make_Range (Loc,
3726 Low_Bound =>
3727 Convert_To (LLIB,
3728 Make_Attribute_Reference (Loc,
3729 Attribute_Name => Name_First,
3730 Prefix =>
3731 New_Occurrence_Of (TB, Loc))),
3732
3733 High_Bound =>
3734 Convert_To (LLIB,
3735 Make_Attribute_Reference (Loc,
3736 Attribute_Name => Name_Last,
3737 Prefix =>
3738 New_Occurrence_Of (TB, Loc))))),
3739
3740 Right_Opnd => Nin))))));
3741
3742 -- Now we can do the rewrite
3743
3744 Rewrite (N,
3745 Make_Expression_With_Actions (Loc,
3746 Actions => New_List (
3747 Make_Object_Declaration (Loc,
3748 Defining_Identifier => Bnn,
3749 Object_Definition =>
3750 New_Occurrence_Of (Result_Type, Loc)),
3751 Blk),
3752 Expression => New_Occurrence_Of (Bnn, Loc)));
3753 Analyze_And_Resolve (N, Result_Type);
3754 return;
3755 end;
3756
3757 -- Not bignum case, but types don't match (this means we rewrote the
3758 -- left operand to be Long_Long_Integer).
3759
3760 else
3761 pragma Assert (Base_Type (Etype (Lop)) = LLIB);
3762
3763 -- We rewrite the membership test as (where T is the type with
3764 -- the predicate, i.e. the type of the right operand)
3765
3766 -- Lop in LLIB (T'Base'First) .. LLIB (T'Base'Last)
3767 -- and then T'Base (Lop) in T
3768
3769 declare
3770 T : constant Entity_Id := Etype (Rop);
3771 TB : constant Entity_Id := Base_Type (T);
3772 Nin : Node_Id;
3773
3774 begin
3775 -- The last membership test is marked to prevent recursion
3776
3777 Nin :=
3778 Make_In (Loc,
3779 Left_Opnd => Convert_To (TB, Duplicate_Subexpr (Lop)),
3780 Right_Opnd => New_Occurrence_Of (T, Loc));
3781 Set_No_Minimize_Eliminate (Nin);
3782
3783 -- Now do the rewrite
3784
3785 Rewrite (N,
3786 Make_And_Then (Loc,
3787 Left_Opnd =>
3788 Make_In (Loc,
3789 Left_Opnd => Lop,
3790 Right_Opnd =>
3791 Make_Range (Loc,
3792 Low_Bound =>
3793 Convert_To (LLIB,
3794 Make_Attribute_Reference (Loc,
3795 Attribute_Name => Name_First,
3796 Prefix =>
3797 New_Occurrence_Of (TB, Loc))),
3798 High_Bound =>
3799 Convert_To (LLIB,
3800 Make_Attribute_Reference (Loc,
3801 Attribute_Name => Name_Last,
3802 Prefix =>
3803 New_Occurrence_Of (TB, Loc))))),
3804 Right_Opnd => Nin));
3805 Set_Analyzed (N, False);
3806 Analyze_And_Resolve (N, Restype);
3807 end;
3808 end if;
3809 end if;
3810 end Expand_Membership_Minimize_Eliminate_Overflow;
3811
3812 ---------------------------------
3813 -- Expand_Nonbinary_Modular_Op --
3814 ---------------------------------
3815
3816 procedure Expand_Nonbinary_Modular_Op (N : Node_Id) is
3817 Loc : constant Source_Ptr := Sloc (N);
3818 Typ : constant Entity_Id := Etype (N);
3819
3820 procedure Expand_Modular_Addition;
3821 -- Expand the modular addition, handling the special case of adding a
3822 -- constant.
3823
3824 procedure Expand_Modular_Op;
3825 -- Compute the general rule: (lhs OP rhs) mod Modulus
3826
3827 procedure Expand_Modular_Subtraction;
3828 -- Expand the modular addition, handling the special case of subtracting
3829 -- a constant.
3830
3831 -----------------------------
3832 -- Expand_Modular_Addition --
3833 -----------------------------
3834
3835 procedure Expand_Modular_Addition is
3836 begin
3837 -- If this is not the addition of a constant then compute it using
3838 -- the general rule: (lhs + rhs) mod Modulus
3839
3840 if Nkind (Right_Opnd (N)) /= N_Integer_Literal then
3841 Expand_Modular_Op;
3842
3843 -- If this is an addition of a constant, convert it to a subtraction
3844 -- plus a conditional expression since we can compute it faster than
3845 -- computing the modulus.
3846
3847 -- modMinusRhs = Modulus - rhs
3848 -- if lhs < modMinusRhs then lhs + rhs
3849 -- else lhs - modMinusRhs
3850
3851 else
3852 declare
3853 Mod_Minus_Right : constant Uint :=
3854 Modulus (Typ) - Intval (Right_Opnd (N));
3855
3856 Cond_Expr : Node_Id;
3857 Then_Expr : Node_Id;
3858 Else_Expr : Node_Id;
3859 begin
3860 -- To prevent spurious visibility issues, convert all
3861 -- operands to Standard.Unsigned.
3862
3863 Cond_Expr :=
3864 Make_Op_Lt (Loc,
3865 Left_Opnd =>
3866 Unchecked_Convert_To (Standard_Unsigned,
3867 New_Copy_Tree (Left_Opnd (N))),
3868 Right_Opnd =>
3869 Make_Integer_Literal (Loc, Mod_Minus_Right));
3870
3871 Then_Expr :=
3872 Make_Op_Add (Loc,
3873 Left_Opnd =>
3874 Unchecked_Convert_To (Standard_Unsigned,
3875 New_Copy_Tree (Left_Opnd (N))),
3876 Right_Opnd =>
3877 Make_Integer_Literal (Loc, Intval (Right_Opnd (N))));
3878
3879 Else_Expr :=
3880 Make_Op_Subtract (Loc,
3881 Left_Opnd =>
3882 Unchecked_Convert_To (Standard_Unsigned,
3883 New_Copy_Tree (Left_Opnd (N))),
3884 Right_Opnd =>
3885 Make_Integer_Literal (Loc, Mod_Minus_Right));
3886
3887 Rewrite (N,
3888 Unchecked_Convert_To (Typ,
3889 Make_If_Expression (Loc,
3890 Expressions =>
3891 New_List (Cond_Expr, Then_Expr, Else_Expr))));
3892 end;
3893 end if;
3894 end Expand_Modular_Addition;
3895
3896 -----------------------
3897 -- Expand_Modular_Op --
3898 -----------------------
3899
3900 procedure Expand_Modular_Op is
3901 -- We will convert to another type (not a nonbinary-modulus modular
3902 -- type), evaluate the op in that representation, reduce the result,
3903 -- and convert back to the original type. This means that the
3904 -- backend does not have to deal with nonbinary-modulus ops.
3905
3906 Op_Expr : constant Node_Id := New_Op_Node (Nkind (N), Loc);
3907 Mod_Expr : Node_Id;
3908
3909 Target_Type : Entity_Id;
3910 begin
3911 -- Select a target type that is large enough to avoid spurious
3912 -- intermediate overflow on pre-reduction computation (for
3913 -- correctness) but is no larger than is needed (for performance).
3914
3915 declare
3916 Required_Size : Uint := RM_Size (Etype (N));
3917 Use_Unsigned : Boolean := True;
3918 begin
3919 case Nkind (N) is
3920 when N_Op_Add =>
3921 -- For example, if modulus is 255 then RM_Size will be 8
3922 -- and the range of possible values (before reduction) will
3923 -- be 0 .. 508; that range requires 9 bits.
3924 Required_Size := Required_Size + 1;
3925
3926 when N_Op_Subtract =>
3927 -- For example, if modulus is 255 then RM_Size will be 8
3928 -- and the range of possible values (before reduction) will
3929 -- be -254 .. 254; that range requires 9 bits, signed.
3930 Use_Unsigned := False;
3931 Required_Size := Required_Size + 1;
3932
3933 when N_Op_Multiply =>
3934 -- For example, if modulus is 255 then RM_Size will be 8
3935 -- and the range of possible values (before reduction) will
3936 -- be 0 .. 64,516; that range requires 16 bits.
3937 Required_Size := Required_Size * 2;
3938
3939 when others =>
3940 null;
3941 end case;
3942
3943 if Use_Unsigned then
3944 if Required_Size <= Standard_Short_Short_Integer_Size then
3945 Target_Type := Standard_Short_Short_Unsigned;
3946 elsif Required_Size <= Standard_Short_Integer_Size then
3947 Target_Type := Standard_Short_Unsigned;
3948 elsif Required_Size <= Standard_Integer_Size then
3949 Target_Type := Standard_Unsigned;
3950 else
3951 pragma Assert (Required_Size <= 64);
3952 Target_Type := Standard_Unsigned_64;
3953 end if;
3954 elsif Required_Size <= 8 then
3955 Target_Type := Standard_Integer_8;
3956 elsif Required_Size <= 16 then
3957 Target_Type := Standard_Integer_16;
3958 elsif Required_Size <= 32 then
3959 Target_Type := Standard_Integer_32;
3960 else
3961 pragma Assert (Required_Size <= 64);
3962 Target_Type := Standard_Integer_64;
3963 end if;
3964
3965 pragma Assert (Present (Target_Type));
3966 end;
3967
3968 Set_Left_Opnd (Op_Expr,
3969 Unchecked_Convert_To (Target_Type,
3970 New_Copy_Tree (Left_Opnd (N))));
3971 Set_Right_Opnd (Op_Expr,
3972 Unchecked_Convert_To (Target_Type,
3973 New_Copy_Tree (Right_Opnd (N))));
3974
3975 -- ??? Why do this stuff for some ops and not others?
3976 if Nkind (N) not in N_Op_And | N_Op_Or | N_Op_Xor then
3977
3978 -- Link this node to the tree to analyze it
3979
3980 -- If the parent node is an expression with actions we link it to
3981 -- N since otherwise Force_Evaluation cannot identify if this node
3982 -- comes from the Expression and rejects generating the temporary.
3983
3984 if Nkind (Parent (N)) = N_Expression_With_Actions then
3985 Set_Parent (Op_Expr, N);
3986
3987 -- Common case
3988
3989 else
3990 Set_Parent (Op_Expr, Parent (N));
3991 end if;
3992
3993 Analyze (Op_Expr);
3994
3995 -- Force generating a temporary because in the expansion of this
3996 -- expression we may generate code that performs this computation
3997 -- several times.
3998
3999 Force_Evaluation (Op_Expr, Mode => Strict);
4000 end if;
4001
4002 Mod_Expr :=
4003 Make_Op_Mod (Loc,
4004 Left_Opnd => Op_Expr,
4005 Right_Opnd => Make_Integer_Literal (Loc, Modulus (Typ)));
4006
4007 Rewrite (N,
4008 Unchecked_Convert_To (Typ, Mod_Expr));
4009 end Expand_Modular_Op;
4010
4011 --------------------------------
4012 -- Expand_Modular_Subtraction --
4013 --------------------------------
4014
4015 procedure Expand_Modular_Subtraction is
4016 begin
4017 -- If this is not the addition of a constant then compute it using
4018 -- the general rule: (lhs + rhs) mod Modulus
4019
4020 if Nkind (Right_Opnd (N)) /= N_Integer_Literal then
4021 Expand_Modular_Op;
4022
4023 -- If this is an addition of a constant, convert it to a subtraction
4024 -- plus a conditional expression since we can compute it faster than
4025 -- computing the modulus.
4026
4027 -- modMinusRhs = Modulus - rhs
4028 -- if lhs < rhs then lhs + modMinusRhs
4029 -- else lhs - rhs
4030
4031 else
4032 declare
4033 Mod_Minus_Right : constant Uint :=
4034 Modulus (Typ) - Intval (Right_Opnd (N));
4035
4036 Cond_Expr : Node_Id;
4037 Then_Expr : Node_Id;
4038 Else_Expr : Node_Id;
4039 begin
4040 Cond_Expr :=
4041 Make_Op_Lt (Loc,
4042 Left_Opnd =>
4043 Unchecked_Convert_To (Standard_Unsigned,
4044 New_Copy_Tree (Left_Opnd (N))),
4045 Right_Opnd =>
4046 Make_Integer_Literal (Loc, Intval (Right_Opnd (N))));
4047
4048 Then_Expr :=
4049 Make_Op_Add (Loc,
4050 Left_Opnd =>
4051 Unchecked_Convert_To (Standard_Unsigned,
4052 New_Copy_Tree (Left_Opnd (N))),
4053 Right_Opnd =>
4054 Make_Integer_Literal (Loc, Mod_Minus_Right));
4055
4056 Else_Expr :=
4057 Make_Op_Subtract (Loc,
4058 Left_Opnd =>
4059 Unchecked_Convert_To (Standard_Unsigned,
4060 New_Copy_Tree (Left_Opnd (N))),
4061 Right_Opnd =>
4062 Unchecked_Convert_To (Standard_Unsigned,
4063 New_Copy_Tree (Right_Opnd (N))));
4064
4065 Rewrite (N,
4066 Unchecked_Convert_To (Typ,
4067 Make_If_Expression (Loc,
4068 Expressions =>
4069 New_List (Cond_Expr, Then_Expr, Else_Expr))));
4070 end;
4071 end if;
4072 end Expand_Modular_Subtraction;
4073
4074 -- Start of processing for Expand_Nonbinary_Modular_Op
4075
4076 begin
4077 -- No action needed if front-end expansion is not required or if we
4078 -- have a binary modular operand.
4079
4080 if not Expand_Nonbinary_Modular_Ops
4081 or else not Non_Binary_Modulus (Typ)
4082 then
4083 return;
4084 end if;
4085
4086 case Nkind (N) is
4087 when N_Op_Add =>
4088 Expand_Modular_Addition;
4089
4090 when N_Op_Subtract =>
4091 Expand_Modular_Subtraction;
4092
4093 when N_Op_Minus =>
4094
4095 -- Expand -expr into (0 - expr)
4096
4097 Rewrite (N,
4098 Make_Op_Subtract (Loc,
4099 Left_Opnd => Make_Integer_Literal (Loc, 0),
4100 Right_Opnd => Right_Opnd (N)));
4101 Analyze_And_Resolve (N, Typ);
4102
4103 when others =>
4104 Expand_Modular_Op;
4105 end case;
4106
4107 Analyze_And_Resolve (N, Typ);
4108 end Expand_Nonbinary_Modular_Op;
4109
4110 ------------------------
4111 -- Expand_N_Allocator --
4112 ------------------------
4113
4114 procedure Expand_N_Allocator (N : Node_Id) is
4115 Etyp : constant Entity_Id := Etype (Expression (N));
4116 Loc : constant Source_Ptr := Sloc (N);
4117 PtrT : constant Entity_Id := Etype (N);
4118
4119 procedure Rewrite_Coextension (N : Node_Id);
4120 -- Static coextensions have the same lifetime as the entity they
4121 -- constrain. Such occurrences can be rewritten as aliased objects
4122 -- and their unrestricted access used instead of the coextension.
4123
4124 function Size_In_Storage_Elements (E : Entity_Id) return Node_Id;
4125 -- Given a constrained array type E, returns a node representing the
4126 -- code to compute a close approximation of the size in storage elements
4127 -- for the given type; for indexes that are modular types we compute
4128 -- 'Last - First (instead of 'Length) because for large arrays computing
4129 -- 'Last -'First + 1 causes overflow. This is done without using the
4130 -- attribute 'Size_In_Storage_Elements (which malfunctions for large
4131 -- sizes ???).
4132
4133 -------------------------
4134 -- Rewrite_Coextension --
4135 -------------------------
4136
4137 procedure Rewrite_Coextension (N : Node_Id) is
4138 Temp_Id : constant Node_Id := Make_Temporary (Loc, 'C');
4139 Temp_Decl : Node_Id;
4140
4141 begin
4142 -- Generate:
4143 -- Cnn : aliased Etyp;
4144
4145 Temp_Decl :=
4146 Make_Object_Declaration (Loc,
4147 Defining_Identifier => Temp_Id,
4148 Aliased_Present => True,
4149 Object_Definition => New_Occurrence_Of (Etyp, Loc));
4150
4151 if Nkind (Expression (N)) = N_Qualified_Expression then
4152 Set_Expression (Temp_Decl, Expression (Expression (N)));
4153 end if;
4154
4155 Insert_Action (N, Temp_Decl);
4156 Rewrite (N,
4157 Make_Attribute_Reference (Loc,
4158 Prefix => New_Occurrence_Of (Temp_Id, Loc),
4159 Attribute_Name => Name_Unrestricted_Access));
4160
4161 Analyze_And_Resolve (N, PtrT);
4162 end Rewrite_Coextension;
4163
4164 ------------------------------
4165 -- Size_In_Storage_Elements --
4166 ------------------------------
4167
4168 function Size_In_Storage_Elements (E : Entity_Id) return Node_Id is
4169 Idx : Node_Id := First_Index (E);
4170 Len : Node_Id;
4171 Res : Node_Id := Empty;
4172
4173 begin
4174 -- Logically this just returns E'Max_Size_In_Storage_Elements.
4175 -- However, the reason for the existence of this function is to
4176 -- construct a test for sizes too large, which means near the 32-bit
4177 -- limit on a 32-bit machine, and precisely the trouble is that we
4178 -- get overflows when sizes are greater than 2**31.
4179
4180 -- So what we end up doing for array types is to use the expression:
4181
4182 -- number-of-elements * component_type'Max_Size_In_Storage_Elements
4183
4184 -- which avoids this problem. All this is a bit bogus, but it does
4185 -- mean we catch common cases of trying to allocate arrays that are
4186 -- too large, and which in the absence of a check results in
4187 -- undetected chaos ???
4188
4189 for J in 1 .. Number_Dimensions (E) loop
4190
4191 if not Is_Modular_Integer_Type (Etype (Idx)) then
4192 Len :=
4193 Make_Attribute_Reference (Loc,
4194 Prefix => New_Occurrence_Of (E, Loc),
4195 Attribute_Name => Name_Length,
4196 Expressions => New_List (Make_Integer_Literal (Loc, J)));
4197
4198 -- For indexes that are modular types we cannot generate code to
4199 -- compute 'Length since for large arrays 'Last -'First + 1 causes
4200 -- overflow; therefore we compute 'Last - 'First (which is not the
4201 -- exact number of components but it is valid for the purpose of
4202 -- this runtime check on 32-bit targets).
4203
4204 else
4205 declare
4206 Len_Minus_1_Expr : Node_Id;
4207 Test_Gt : Node_Id;
4208
4209 begin
4210 Test_Gt :=
4211 Make_Op_Gt (Loc,
4212 Make_Attribute_Reference (Loc,
4213 Prefix => New_Occurrence_Of (E, Loc),
4214 Attribute_Name => Name_Last,
4215 Expressions =>
4216 New_List (Make_Integer_Literal (Loc, J))),
4217 Make_Attribute_Reference (Loc,
4218 Prefix => New_Occurrence_Of (E, Loc),
4219 Attribute_Name => Name_First,
4220 Expressions =>
4221 New_List (Make_Integer_Literal (Loc, J))));
4222
4223 Len_Minus_1_Expr :=
4224 Convert_To (Standard_Unsigned,
4225 Make_Op_Subtract (Loc,
4226 Make_Attribute_Reference (Loc,
4227 Prefix => New_Occurrence_Of (E, Loc),
4228 Attribute_Name => Name_Last,
4229 Expressions =>
4230 New_List (Make_Integer_Literal (Loc, J))),
4231 Make_Attribute_Reference (Loc,
4232 Prefix => New_Occurrence_Of (E, Loc),
4233 Attribute_Name => Name_First,
4234 Expressions =>
4235 New_List (Make_Integer_Literal (Loc, J)))));
4236
4237 -- Handle superflat arrays, i.e. arrays with such bounds as
4238 -- 4 .. 2, to ensure that the result is correct.
4239
4240 -- Generate:
4241 -- (if X'Last > X'First then X'Last - X'First else 0)
4242
4243 Len :=
4244 Make_If_Expression (Loc,
4245 Expressions => New_List (
4246 Test_Gt,
4247 Len_Minus_1_Expr,
4248 Make_Integer_Literal (Loc, Uint_0)));
4249 end;
4250 end if;
4251
4252 if J = 1 then
4253 Res := Len;
4254
4255 else
4256 pragma Assert (Present (Res));
4257 Res :=
4258 Make_Op_Multiply (Loc,
4259 Left_Opnd => Res,
4260 Right_Opnd => Len);
4261 end if;
4262
4263 Next_Index (Idx);
4264 end loop;
4265
4266 return
4267 Make_Op_Multiply (Loc,
4268 Left_Opnd => Len,
4269 Right_Opnd =>
4270 Make_Attribute_Reference (Loc,
4271 Prefix => New_Occurrence_Of (Component_Type (E), Loc),
4272 Attribute_Name => Name_Max_Size_In_Storage_Elements));
4273 end Size_In_Storage_Elements;
4274
4275 -- Local variables
4276
4277 Dtyp : constant Entity_Id := Available_View (Designated_Type (PtrT));
4278 Desig : Entity_Id;
4279 Nod : Node_Id;
4280 Pool : Entity_Id;
4281 Rel_Typ : Entity_Id;
4282 Temp : Entity_Id;
4283
4284 -- Start of processing for Expand_N_Allocator
4285
4286 begin
4287 -- Warn on the presence of an allocator of an anonymous access type when
4288 -- enabled, except when it's an object declaration at library level.
4289
4290 if Warn_On_Anonymous_Allocators
4291 and then Ekind (PtrT) = E_Anonymous_Access_Type
4292 and then not (Is_Library_Level_Entity (PtrT)
4293 and then Nkind (Associated_Node_For_Itype (PtrT)) =
4294 N_Object_Declaration)
4295 then
4296 Error_Msg_N ("?_a?use of an anonymous access type allocator", N);
4297 end if;
4298
4299 -- RM E.2.2(17). We enforce that the expected type of an allocator
4300 -- shall not be a remote access-to-class-wide-limited-private type.
4301 -- We probably shouldn't be doing this legality check during expansion,
4302 -- but this is only an issue for Annex E users, and is unlikely to be a
4303 -- problem in practice.
4304
4305 Validate_Remote_Access_To_Class_Wide_Type (N);
4306
4307 -- Processing for anonymous access-to-controlled types. These access
4308 -- types receive a special finalization master which appears in the
4309 -- declarations of the enclosing semantic unit. This expansion is done
4310 -- now to ensure that any additional types generated by this routine or
4311 -- Expand_Allocator_Expression inherit the proper type attributes.
4312
4313 if (Ekind (PtrT) = E_Anonymous_Access_Type
4314 or else (Is_Itype (PtrT) and then No (Finalization_Master (PtrT))))
4315 and then Needs_Finalization (Dtyp)
4316 then
4317 -- Detect the allocation of an anonymous controlled object where the
4318 -- type of the context is named. For example:
4319
4320 -- procedure Proc (Ptr : Named_Access_Typ);
4321 -- Proc (new Designated_Typ);
4322
4323 -- Regardless of the anonymous-to-named access type conversion, the
4324 -- lifetime of the object must be associated with the named access
4325 -- type. Use the finalization-related attributes of this type.
4326
4327 if Nkind (Parent (N)) in N_Type_Conversion
4328 | N_Unchecked_Type_Conversion
4329 and then Ekind (Etype (Parent (N))) in E_Access_Subtype
4330 | E_Access_Type
4331 | E_General_Access_Type
4332 then
4333 Rel_Typ := Etype (Parent (N));
4334 else
4335 Rel_Typ := Empty;
4336 end if;
4337
4338 -- Anonymous access-to-controlled types allocate on the global pool.
4339 -- Note that this is a "root type only" attribute.
4340
4341 if No (Associated_Storage_Pool (PtrT)) then
4342 if Present (Rel_Typ) then
4343 Set_Associated_Storage_Pool
4344 (Root_Type (PtrT), Associated_Storage_Pool (Rel_Typ));
4345 else
4346 Set_Associated_Storage_Pool
4347 (Root_Type (PtrT), RTE (RE_Global_Pool_Object));
4348 end if;
4349 end if;
4350
4351 -- The finalization master must be inserted and analyzed as part of
4352 -- the current semantic unit. Note that the master is updated when
4353 -- analysis changes current units. Note that this is a "root type
4354 -- only" attribute.
4355
4356 if Present (Rel_Typ) then
4357 Set_Finalization_Master
4358 (Root_Type (PtrT), Finalization_Master (Rel_Typ));
4359 else
4360 Build_Anonymous_Master (Root_Type (PtrT));
4361 end if;
4362 end if;
4363
4364 -- Set the storage pool and find the appropriate version of Allocate to
4365 -- call. Do not overwrite the storage pool if it is already set, which
4366 -- can happen for build-in-place function returns (see
4367 -- Exp_Ch4.Expand_N_Extended_Return_Statement).
4368
4369 if No (Storage_Pool (N)) then
4370 Pool := Associated_Storage_Pool (Root_Type (PtrT));
4371
4372 if Present (Pool) then
4373 Set_Storage_Pool (N, Pool);
4374
4375 if Is_RTE (Pool, RE_RS_Pool) then
4376 Set_Procedure_To_Call (N, RTE (RE_RS_Allocate));
4377
4378 elsif Is_RTE (Pool, RE_SS_Pool) then
4379 Check_Restriction (No_Secondary_Stack, N);
4380 Set_Procedure_To_Call (N, RTE (RE_SS_Allocate));
4381
4382 -- In the case of an allocator for a simple storage pool, locate
4383 -- and save a reference to the pool type's Allocate routine.
4384
4385 elsif Present (Get_Rep_Pragma
4386 (Etype (Pool), Name_Simple_Storage_Pool_Type))
4387 then
4388 declare
4389 Pool_Type : constant Entity_Id := Base_Type (Etype (Pool));
4390 Alloc_Op : Entity_Id;
4391 begin
4392 Alloc_Op := Get_Name_Entity_Id (Name_Allocate);
4393 while Present (Alloc_Op) loop
4394 if Scope (Alloc_Op) = Scope (Pool_Type)
4395 and then Present (First_Formal (Alloc_Op))
4396 and then Etype (First_Formal (Alloc_Op)) = Pool_Type
4397 then
4398 Set_Procedure_To_Call (N, Alloc_Op);
4399 exit;
4400 else
4401 Alloc_Op := Homonym (Alloc_Op);
4402 end if;
4403 end loop;
4404 end;
4405
4406 elsif Is_Class_Wide_Type (Etype (Pool)) then
4407 Set_Procedure_To_Call (N, RTE (RE_Allocate_Any));
4408
4409 else
4410 Set_Procedure_To_Call (N,
4411 Find_Storage_Op (Etype (Pool), Name_Allocate));
4412 end if;
4413 end if;
4414 end if;
4415
4416 -- Under certain circumstances we can replace an allocator by an access
4417 -- to statically allocated storage. The conditions, as noted in AARM
4418 -- 3.10 (10c) are as follows:
4419
4420 -- Size and initial value is known at compile time
4421 -- Access type is access-to-constant
4422
4423 -- The allocator is not part of a constraint on a record component,
4424 -- because in that case the inserted actions are delayed until the
4425 -- record declaration is fully analyzed, which is too late for the
4426 -- analysis of the rewritten allocator.
4427
4428 if Is_Access_Constant (PtrT)
4429 and then Nkind (Expression (N)) = N_Qualified_Expression
4430 and then Compile_Time_Known_Value (Expression (Expression (N)))
4431 and then Size_Known_At_Compile_Time
4432 (Etype (Expression (Expression (N))))
4433 and then not Is_Record_Type (Current_Scope)
4434 then
4435 -- Here we can do the optimization. For the allocator
4436
4437 -- new x'(y)
4438
4439 -- We insert an object declaration
4440
4441 -- Tnn : aliased x := y;
4442
4443 -- and replace the allocator by Tnn'Unrestricted_Access. Tnn is
4444 -- marked as requiring static allocation.
4445
4446 Temp := Make_Temporary (Loc, 'T', Expression (Expression (N)));
4447 Desig := Subtype_Mark (Expression (N));
4448
4449 -- If context is constrained, use constrained subtype directly,
4450 -- so that the constant is not labelled as having a nominally
4451 -- unconstrained subtype.
4452
4453 if Entity (Desig) = Base_Type (Dtyp) then
4454 Desig := New_Occurrence_Of (Dtyp, Loc);
4455 end if;
4456
4457 Insert_Action (N,
4458 Make_Object_Declaration (Loc,
4459 Defining_Identifier => Temp,
4460 Aliased_Present => True,
4461 Constant_Present => Is_Access_Constant (PtrT),
4462 Object_Definition => Desig,
4463 Expression => Expression (Expression (N))));
4464
4465 Rewrite (N,
4466 Make_Attribute_Reference (Loc,
4467 Prefix => New_Occurrence_Of (Temp, Loc),
4468 Attribute_Name => Name_Unrestricted_Access));
4469
4470 Analyze_And_Resolve (N, PtrT);
4471
4472 -- We set the variable as statically allocated, since we don't want
4473 -- it going on the stack of the current procedure.
4474
4475 Set_Is_Statically_Allocated (Temp);
4476 return;
4477 end if;
4478
4479 -- Same if the allocator is an access discriminant for a local object:
4480 -- instead of an allocator we create a local value and constrain the
4481 -- enclosing object with the corresponding access attribute.
4482
4483 if Is_Static_Coextension (N) then
4484 Rewrite_Coextension (N);
4485 return;
4486 end if;
4487
4488 -- Check for size too large, we do this because the back end misses
4489 -- proper checks here and can generate rubbish allocation calls when
4490 -- we are near the limit. We only do this for the 32-bit address case
4491 -- since that is from a practical point of view where we see a problem.
4492
4493 if System_Address_Size = 32
4494 and then not Storage_Checks_Suppressed (PtrT)
4495 and then not Storage_Checks_Suppressed (Dtyp)
4496 and then not Storage_Checks_Suppressed (Etyp)
4497 then
4498 -- The check we want to generate should look like
4499
4500 -- if Etyp'Max_Size_In_Storage_Elements > 3.5 gigabytes then
4501 -- raise Storage_Error;
4502 -- end if;
4503
4504 -- where 3.5 gigabytes is a constant large enough to accommodate any
4505 -- reasonable request for. But we can't do it this way because at
4506 -- least at the moment we don't compute this attribute right, and
4507 -- can silently give wrong results when the result gets large. Since
4508 -- this is all about large results, that's bad, so instead we only
4509 -- apply the check for constrained arrays, and manually compute the
4510 -- value of the attribute ???
4511
4512 -- The check on No_Initialization is used here to prevent generating
4513 -- this runtime check twice when the allocator is locally replaced by
4514 -- the expander with another one.
4515
4516 if Is_Array_Type (Etyp) and then not No_Initialization (N) then
4517 declare
4518 Cond : Node_Id;
4519 Ins_Nod : Node_Id := N;
4520 Siz_Typ : Entity_Id := Etyp;
4521 Expr : Node_Id;
4522
4523 begin
4524 -- For unconstrained array types initialized with a qualified
4525 -- expression we use its type to perform this check
4526
4527 if not Is_Constrained (Etyp)
4528 and then not No_Initialization (N)
4529 and then Nkind (Expression (N)) = N_Qualified_Expression
4530 then
4531 Expr := Expression (Expression (N));
4532 Siz_Typ := Etype (Expression (Expression (N)));
4533
4534 -- If the qualified expression has been moved to an internal
4535 -- temporary (to remove side effects) then we must insert
4536 -- the runtime check before its declaration to ensure that
4537 -- the check is performed before the execution of the code
4538 -- computing the qualified expression.
4539
4540 if Nkind (Expr) = N_Identifier
4541 and then Is_Internal_Name (Chars (Expr))
4542 and then
4543 Nkind (Parent (Entity (Expr))) = N_Object_Declaration
4544 then
4545 Ins_Nod := Parent (Entity (Expr));
4546 else
4547 Ins_Nod := Expr;
4548 end if;
4549 end if;
4550
4551 if Is_Constrained (Siz_Typ)
4552 and then Ekind (Siz_Typ) /= E_String_Literal_Subtype
4553 then
4554 -- For CCG targets, the largest array may have up to 2**31-1
4555 -- components (i.e. 2 gigabytes if each array component is
4556 -- one byte). This ensures that fat pointer fields do not
4557 -- overflow, since they are 32-bit integer types, and also
4558 -- ensures that 'Length can be computed at run time.
4559
4560 if Modify_Tree_For_C then
4561 Cond :=
4562 Make_Op_Gt (Loc,
4563 Left_Opnd => Size_In_Storage_Elements (Siz_Typ),
4564 Right_Opnd => Make_Integer_Literal (Loc,
4565 Uint_2 ** 31 - Uint_1));
4566
4567 -- For native targets the largest object is 3.5 gigabytes
4568
4569 else
4570 Cond :=
4571 Make_Op_Gt (Loc,
4572 Left_Opnd => Size_In_Storage_Elements (Siz_Typ),
4573 Right_Opnd => Make_Integer_Literal (Loc,
4574 Uint_7 * (Uint_2 ** 29)));
4575 end if;
4576
4577 Insert_Action (Ins_Nod,
4578 Make_Raise_Storage_Error (Loc,
4579 Condition => Cond,
4580 Reason => SE_Object_Too_Large));
4581
4582 if Entity (Cond) = Standard_True then
4583 Error_Msg_N
4584 ("object too large: Storage_Error will be raised at "
4585 & "run time??", N);
4586 end if;
4587 end if;
4588 end;
4589 end if;
4590 end if;
4591
4592 -- If no storage pool has been specified, or the storage pool
4593 -- is System.Pool_Global.Global_Pool_Object, and the restriction
4594 -- No_Standard_Allocators_After_Elaboration is present, then generate
4595 -- a call to Elaboration_Allocators.Check_Standard_Allocator.
4596
4597 if Nkind (N) = N_Allocator
4598 and then (No (Storage_Pool (N))
4599 or else Is_RTE (Storage_Pool (N), RE_Global_Pool_Object))
4600 and then Restriction_Active (No_Standard_Allocators_After_Elaboration)
4601 then
4602 Insert_Action (N,
4603 Make_Procedure_Call_Statement (Loc,
4604 Name =>
4605 New_Occurrence_Of (RTE (RE_Check_Standard_Allocator), Loc)));
4606 end if;
4607
4608 -- Handle case of qualified expression (other than optimization above)
4609
4610 if Nkind (Expression (N)) = N_Qualified_Expression then
4611 Expand_Allocator_Expression (N);
4612 return;
4613 end if;
4614
4615 -- If the allocator is for a type which requires initialization, and
4616 -- there is no initial value (i.e. operand is a subtype indication
4617 -- rather than a qualified expression), then we must generate a call to
4618 -- the initialization routine using an expressions action node:
4619
4620 -- [Pnnn : constant ptr_T := new (T); Init (Pnnn.all,...); Pnnn]
4621
4622 -- Here ptr_T is the pointer type for the allocator, and T is the
4623 -- subtype of the allocator. A special case arises if the designated
4624 -- type of the access type is a task or contains tasks. In this case
4625 -- the call to Init (Temp.all ...) is replaced by code that ensures
4626 -- that tasks get activated (see Exp_Ch9.Build_Task_Allocate_Block
4627 -- for details). In addition, if the type T is a task type, then the
4628 -- first argument to Init must be converted to the task record type.
4629
4630 declare
4631 T : constant Entity_Id := Etype (Expression (N));
4632 Args : List_Id;
4633 Decls : List_Id;
4634 Decl : Node_Id;
4635 Discr : Elmt_Id;
4636 Init : Entity_Id;
4637 Init_Arg1 : Node_Id;
4638 Init_Call : Node_Id;
4639 Temp_Decl : Node_Id;
4640 Temp_Type : Entity_Id;
4641
4642 begin
4643 -- Apply constraint checks against designated subtype (RM 4.8(10/2))
4644 -- but ignore the expression if the No_Initialization flag is set.
4645 -- Discriminant checks will be generated by the expansion below.
4646
4647 if Is_Array_Type (Dtyp) and then not No_Initialization (N) then
4648 Apply_Constraint_Check (Expression (N), Dtyp, No_Sliding => True);
4649
4650 Apply_Predicate_Check (Expression (N), Dtyp);
4651
4652 if Nkind (Expression (N)) = N_Raise_Constraint_Error then
4653 Rewrite (N, New_Copy (Expression (N)));
4654 Set_Etype (N, PtrT);
4655 return;
4656 end if;
4657 end if;
4658
4659 if No_Initialization (N) then
4660
4661 -- Even though this might be a simple allocation, create a custom
4662 -- Allocate if the context requires it.
4663
4664 if Present (Finalization_Master (PtrT)) then
4665 Build_Allocate_Deallocate_Proc
4666 (N => N,
4667 Is_Allocate => True);
4668 end if;
4669
4670 -- Optimize the default allocation of an array object when pragma
4671 -- Initialize_Scalars or Normalize_Scalars is in effect. Construct an
4672 -- in-place initialization aggregate which may be convert into a fast
4673 -- memset by the backend.
4674
4675 elsif Init_Or_Norm_Scalars
4676 and then Is_Array_Type (T)
4677
4678 -- The array must lack atomic components because they are treated
4679 -- as non-static, and as a result the backend will not initialize
4680 -- the memory in one go.
4681
4682 and then not Has_Atomic_Components (T)
4683
4684 -- The array must not be packed because the invalid values in
4685 -- System.Scalar_Values are multiples of Storage_Unit.
4686
4687 and then not Is_Packed (T)
4688
4689 -- The array must have static non-empty ranges, otherwise the
4690 -- backend cannot initialize the memory in one go.
4691
4692 and then Has_Static_Non_Empty_Array_Bounds (T)
4693
4694 -- The optimization is only relevant for arrays of scalar types
4695
4696 and then Is_Scalar_Type (Component_Type (T))
4697
4698 -- Similar to regular array initialization using a type init proc,
4699 -- predicate checks are not performed because the initialization
4700 -- values are intentionally invalid, and may violate the predicate.
4701
4702 and then not Has_Predicates (Component_Type (T))
4703
4704 -- The component type must have a single initialization value
4705
4706 and then Needs_Simple_Initialization
4707 (Typ => Component_Type (T),
4708 Consider_IS => True)
4709 then
4710 Set_Analyzed (N);
4711 Temp := Make_Temporary (Loc, 'P');
4712
4713 -- Generate:
4714 -- Temp : Ptr_Typ := new ...;
4715
4716 Insert_Action
4717 (Assoc_Node => N,
4718 Ins_Action =>
4719 Make_Object_Declaration (Loc,
4720 Defining_Identifier => Temp,
4721 Object_Definition => New_Occurrence_Of (PtrT, Loc),
4722 Expression => Relocate_Node (N)),
4723 Suppress => All_Checks);
4724
4725 -- Generate:
4726 -- Temp.all := (others => ...);
4727
4728 Insert_Action
4729 (Assoc_Node => N,
4730 Ins_Action =>
4731 Make_Assignment_Statement (Loc,
4732 Name =>
4733 Make_Explicit_Dereference (Loc,
4734 Prefix => New_Occurrence_Of (Temp, Loc)),
4735 Expression =>
4736 Get_Simple_Init_Val
4737 (Typ => T,
4738 N => N,
4739 Size => Esize (Component_Type (T)))),
4740 Suppress => All_Checks);
4741
4742 Rewrite (N, New_Occurrence_Of (Temp, Loc));
4743 Analyze_And_Resolve (N, PtrT);
4744
4745 -- Case of no initialization procedure present
4746
4747 elsif not Has_Non_Null_Base_Init_Proc (T) then
4748
4749 -- Case of simple initialization required
4750
4751 if Needs_Simple_Initialization (T) then
4752 Check_Restriction (No_Default_Initialization, N);
4753 Rewrite (Expression (N),
4754 Make_Qualified_Expression (Loc,
4755 Subtype_Mark => New_Occurrence_Of (T, Loc),
4756 Expression => Get_Simple_Init_Val (T, N)));
4757
4758 Analyze_And_Resolve (Expression (Expression (N)), T);
4759 Analyze_And_Resolve (Expression (N), T);
4760 Set_Paren_Count (Expression (Expression (N)), 1);
4761 Expand_N_Allocator (N);
4762
4763 -- No initialization required
4764
4765 else
4766 Build_Allocate_Deallocate_Proc
4767 (N => N,
4768 Is_Allocate => True);
4769 end if;
4770
4771 -- Case of initialization procedure present, must be called
4772
4773 -- NOTE: There is a *huge* amount of code duplication here from
4774 -- Build_Initialization_Call. We should probably refactor???
4775
4776 else
4777 Check_Restriction (No_Default_Initialization, N);
4778
4779 if not Restriction_Active (No_Default_Initialization) then
4780 Init := Base_Init_Proc (T);
4781 Nod := N;
4782 Temp := Make_Temporary (Loc, 'P');
4783
4784 -- Construct argument list for the initialization routine call
4785
4786 Init_Arg1 :=
4787 Make_Explicit_Dereference (Loc,
4788 Prefix =>
4789 New_Occurrence_Of (Temp, Loc));
4790
4791 Set_Assignment_OK (Init_Arg1);
4792 Temp_Type := PtrT;
4793
4794 -- The initialization procedure expects a specific type. if the
4795 -- context is access to class wide, indicate that the object
4796 -- being allocated has the right specific type.
4797
4798 if Is_Class_Wide_Type (Dtyp) then
4799 Init_Arg1 := Unchecked_Convert_To (T, Init_Arg1);
4800 end if;
4801
4802 -- If designated type is a concurrent type or if it is private
4803 -- type whose definition is a concurrent type, the first
4804 -- argument in the Init routine has to be unchecked conversion
4805 -- to the corresponding record type. If the designated type is
4806 -- a derived type, also convert the argument to its root type.
4807
4808 if Is_Concurrent_Type (T) then
4809 Init_Arg1 :=
4810 Unchecked_Convert_To (
4811 Corresponding_Record_Type (T), Init_Arg1);
4812
4813 elsif Is_Private_Type (T)
4814 and then Present (Full_View (T))
4815 and then Is_Concurrent_Type (Full_View (T))
4816 then
4817 Init_Arg1 :=
4818 Unchecked_Convert_To
4819 (Corresponding_Record_Type (Full_View (T)), Init_Arg1);
4820
4821 elsif Etype (First_Formal (Init)) /= Base_Type (T) then
4822 declare
4823 Ftyp : constant Entity_Id := Etype (First_Formal (Init));
4824
4825 begin
4826 Init_Arg1 := OK_Convert_To (Etype (Ftyp), Init_Arg1);
4827 Set_Etype (Init_Arg1, Ftyp);
4828 end;
4829 end if;
4830
4831 Args := New_List (Init_Arg1);
4832
4833 -- For the task case, pass the Master_Id of the access type as
4834 -- the value of the _Master parameter, and _Chain as the value
4835 -- of the _Chain parameter (_Chain will be defined as part of
4836 -- the generated code for the allocator).
4837
4838 -- In Ada 2005, the context may be a function that returns an
4839 -- anonymous access type. In that case the Master_Id has been
4840 -- created when expanding the function declaration.
4841
4842 if Has_Task (T) then
4843 if No (Master_Id (Base_Type (PtrT))) then
4844
4845 -- The designated type was an incomplete type, and the
4846 -- access type did not get expanded. Salvage it now.
4847
4848 if Present (Parent (Base_Type (PtrT))) then
4849 Expand_N_Full_Type_Declaration
4850 (Parent (Base_Type (PtrT)));
4851
4852 -- When the allocator has a subtype indication then a
4853 -- constraint is present and an itype has been added by
4854 -- Analyze_Allocator as the subtype of this allocator.
4855
4856 -- If an allocator with constraints is called in the
4857 -- return statement of a function returning a general
4858 -- access type, then propagate to the itype the master
4859 -- of the general access type (since it is the master
4860 -- associated with the returned object).
4861
4862 elsif Is_Itype (PtrT)
4863 and then Ekind (Current_Scope) = E_Function
4864 and then Ekind (Etype (Current_Scope))
4865 = E_General_Access_Type
4866 and then In_Return_Value (N)
4867 then
4868 Set_Master_Id (PtrT,
4869 Master_Id (Etype (Current_Scope)));
4870
4871 -- The only other possibility is an itype. For this
4872 -- case, the master must exist in the context. This is
4873 -- the case when the allocator initializes an access
4874 -- component in an init-proc.
4875
4876 else
4877 pragma Assert (Is_Itype (PtrT));
4878 Build_Master_Renaming (PtrT, N);
4879 end if;
4880 end if;
4881
4882 -- If the context of the allocator is a declaration or an
4883 -- assignment, we can generate a meaningful image for it,
4884 -- even though subsequent assignments might remove the
4885 -- connection between task and entity. We build this image
4886 -- when the left-hand side is a simple variable, a simple
4887 -- indexed assignment or a simple selected component.
4888
4889 if Nkind (Parent (N)) = N_Assignment_Statement then
4890 declare
4891 Nam : constant Node_Id := Name (Parent (N));
4892
4893 begin
4894 if Is_Entity_Name (Nam) then
4895 Decls :=
4896 Build_Task_Image_Decls
4897 (Loc,
4898 New_Occurrence_Of
4899 (Entity (Nam), Sloc (Nam)), T);
4900
4901 elsif Nkind (Nam) in N_Indexed_Component
4902 | N_Selected_Component
4903 and then Is_Entity_Name (Prefix (Nam))
4904 then
4905 Decls :=
4906 Build_Task_Image_Decls
4907 (Loc, Nam, Etype (Prefix (Nam)));
4908 else
4909 Decls := Build_Task_Image_Decls (Loc, T, T);
4910 end if;
4911 end;
4912
4913 elsif Nkind (Parent (N)) = N_Object_Declaration then
4914 Decls :=
4915 Build_Task_Image_Decls
4916 (Loc, Defining_Identifier (Parent (N)), T);
4917
4918 else
4919 Decls := Build_Task_Image_Decls (Loc, T, T);
4920 end if;
4921
4922 if Restriction_Active (No_Task_Hierarchy) then
4923 Append_To
4924 (Args, Make_Integer_Literal (Loc, Library_Task_Level));
4925 else
4926 Append_To (Args,
4927 New_Occurrence_Of
4928 (Master_Id (Base_Type (Root_Type (PtrT))), Loc));
4929 end if;
4930
4931 Append_To (Args, Make_Identifier (Loc, Name_uChain));
4932
4933 Decl := Last (Decls);
4934 Append_To (Args,
4935 New_Occurrence_Of (Defining_Identifier (Decl), Loc));
4936
4937 -- Has_Task is false, Decls not used
4938
4939 else
4940 Decls := No_List;
4941 end if;
4942
4943 -- Add discriminants if discriminated type
4944
4945 declare
4946 Dis : Boolean := False;
4947 Typ : Entity_Id := T;
4948
4949 begin
4950 if Has_Discriminants (T) then
4951 Dis := True;
4952
4953 -- Type may be a private type with no visible discriminants
4954 -- in which case check full view if in scope, or the
4955 -- underlying_full_view if dealing with a type whose full
4956 -- view may be derived from a private type whose own full
4957 -- view has discriminants.
4958
4959 elsif Is_Private_Type (T) then
4960 if Present (Full_View (T))
4961 and then Has_Discriminants (Full_View (T))
4962 then
4963 Dis := True;
4964 Typ := Full_View (T);
4965
4966 elsif Present (Underlying_Full_View (T))
4967 and then Has_Discriminants (Underlying_Full_View (T))
4968 then
4969 Dis := True;
4970 Typ := Underlying_Full_View (T);
4971 end if;
4972 end if;
4973
4974 if Dis then
4975
4976 -- If the allocated object will be constrained by the
4977 -- default values for discriminants, then build a subtype
4978 -- with those defaults, and change the allocated subtype
4979 -- to that. Note that this happens in fewer cases in Ada
4980 -- 2005 (AI-363).
4981
4982 if not Is_Constrained (Typ)
4983 and then Present (Discriminant_Default_Value
4984 (First_Discriminant (Typ)))
4985 and then (Ada_Version < Ada_2005
4986 or else not
4987 Object_Type_Has_Constrained_Partial_View
4988 (Typ, Current_Scope))
4989 then
4990 Typ := Build_Default_Subtype (Typ, N);
4991 Set_Expression (N, New_Occurrence_Of (Typ, Loc));
4992 end if;
4993
4994 Discr := First_Elmt (Discriminant_Constraint (Typ));
4995 while Present (Discr) loop
4996 Nod := Node (Discr);
4997 Append (New_Copy_Tree (Node (Discr)), Args);
4998
4999 -- AI-416: when the discriminant constraint is an
5000 -- anonymous access type make sure an accessibility
5001 -- check is inserted if necessary (3.10.2(22.q/2))
5002
5003 if Ada_Version >= Ada_2005
5004 and then
5005 Ekind (Etype (Nod)) = E_Anonymous_Access_Type
5006 and then not
5007 No_Dynamic_Accessibility_Checks_Enabled (Nod)
5008 then
5009 Apply_Accessibility_Check
5010 (Nod, Typ, Insert_Node => Nod);
5011 end if;
5012
5013 Next_Elmt (Discr);
5014 end loop;
5015 end if;
5016
5017 -- When the designated subtype is unconstrained and
5018 -- the allocator specifies a constrained subtype (or
5019 -- such a subtype has been created, such as above by
5020 -- Build_Default_Subtype), associate that subtype with
5021 -- the dereference of the allocator's access value.
5022 -- This is needed by the expander for cases where the
5023 -- access type has a Designated_Storage_Model in order
5024 -- to support allocation of a host object of the right
5025 -- size for passing to the initialization procedure.
5026
5027 if not Is_Constrained (Dtyp)
5028 and then Is_Constrained (Typ)
5029 then
5030 declare
5031 Deref : constant Node_Id := Unqual_Conv (Init_Arg1);
5032
5033 begin
5034 pragma Assert (Nkind (Deref) = N_Explicit_Dereference);
5035
5036 Set_Actual_Designated_Subtype (Deref, Typ);
5037 end;
5038 end if;
5039 end;
5040
5041 -- We set the allocator as analyzed so that when we analyze
5042 -- the if expression node, we do not get an unwanted recursive
5043 -- expansion of the allocator expression.
5044
5045 Set_Analyzed (N, True);
5046 Nod := Relocate_Node (N);
5047
5048 -- Here is the transformation:
5049 -- input: new Ctrl_Typ
5050 -- output: Temp : constant Ctrl_Typ_Ptr := new Ctrl_Typ;
5051 -- Ctrl_TypIP (Temp.all, ...);
5052 -- [Deep_]Initialize (Temp.all);
5053
5054 -- Here Ctrl_Typ_Ptr is the pointer type for the allocator, and
5055 -- is the subtype of the allocator.
5056
5057 Temp_Decl :=
5058 Make_Object_Declaration (Loc,
5059 Defining_Identifier => Temp,
5060 Constant_Present => True,
5061 Object_Definition => New_Occurrence_Of (Temp_Type, Loc),
5062 Expression => Nod);
5063
5064 Set_Assignment_OK (Temp_Decl);
5065 Insert_Action (N, Temp_Decl, Suppress => All_Checks);
5066
5067 Build_Allocate_Deallocate_Proc (Temp_Decl, True);
5068
5069 -- If the designated type is a task type or contains tasks,
5070 -- create block to activate created tasks, and insert
5071 -- declaration for Task_Image variable ahead of call.
5072
5073 if Has_Task (T) then
5074 declare
5075 L : constant List_Id := New_List;
5076 Blk : Node_Id;
5077 begin
5078 Build_Task_Allocate_Block (L, Nod, Args);
5079 Blk := Last (L);
5080 Insert_List_Before (First (Declarations (Blk)), Decls);
5081 Insert_Actions (N, L);
5082 end;
5083
5084 else
5085 Insert_Action (N,
5086 Make_Procedure_Call_Statement (Loc,
5087 Name => New_Occurrence_Of (Init, Loc),
5088 Parameter_Associations => Args));
5089 end if;
5090
5091 if Needs_Finalization (T) then
5092
5093 -- Generate:
5094 -- [Deep_]Initialize (Init_Arg1);
5095
5096 Init_Call :=
5097 Make_Init_Call
5098 (Obj_Ref => New_Copy_Tree (Init_Arg1),
5099 Typ => T);
5100
5101 -- Guard against a missing [Deep_]Initialize when the
5102 -- designated type was not properly frozen.
5103
5104 if Present (Init_Call) then
5105 Insert_Action (N, Init_Call);
5106 end if;
5107 end if;
5108
5109 Rewrite (N, New_Occurrence_Of (Temp, Loc));
5110 Analyze_And_Resolve (N, PtrT);
5111
5112 -- When designated type has Default_Initial_Condition aspects,
5113 -- make a call to the type's DIC procedure to perform the
5114 -- checks. Theoretically this might also be needed for cases
5115 -- where the type doesn't have an init proc, but those should
5116 -- be very uncommon, and for now we only support the init proc
5117 -- case. ???
5118
5119 if Has_DIC (Dtyp)
5120 and then Present (DIC_Procedure (Dtyp))
5121 and then not Has_Null_Body (DIC_Procedure (Dtyp))
5122 then
5123 Insert_Action (N,
5124 Build_DIC_Call (Loc,
5125 Make_Explicit_Dereference (Loc,
5126 Prefix => New_Occurrence_Of (Temp, Loc)),
5127 Dtyp));
5128 end if;
5129 end if;
5130 end if;
5131 end;
5132
5133 -- Ada 2005 (AI-251): If the allocator is for a class-wide interface
5134 -- object that has been rewritten as a reference, we displace "this"
5135 -- to reference properly its secondary dispatch table.
5136
5137 if Nkind (N) = N_Identifier and then Is_Interface (Dtyp) then
5138 Displace_Allocator_Pointer (N);
5139 end if;
5140
5141 exception
5142 when RE_Not_Available =>
5143 return;
5144 end Expand_N_Allocator;
5145
5146 -----------------------
5147 -- Expand_N_And_Then --
5148 -----------------------
5149
5150 procedure Expand_N_And_Then (N : Node_Id)
5151 renames Expand_Short_Circuit_Operator;
5152
5153 ------------------------------
5154 -- Expand_N_Case_Expression --
5155 ------------------------------
5156
5157 procedure Expand_N_Case_Expression (N : Node_Id) is
5158 function Is_Copy_Type (Typ : Entity_Id) return Boolean;
5159 -- Return True if we can copy objects of this type when expanding a case
5160 -- expression.
5161
5162 ------------------
5163 -- Is_Copy_Type --
5164 ------------------
5165
5166 function Is_Copy_Type (Typ : Entity_Id) return Boolean is
5167 begin
5168 -- If Minimize_Expression_With_Actions is True, we can afford to copy
5169 -- large objects, as long as they are constrained and not limited.
5170
5171 return
5172 Is_Elementary_Type (Underlying_Type (Typ))
5173 or else
5174 (Minimize_Expression_With_Actions
5175 and then Is_Constrained (Underlying_Type (Typ))
5176 and then not Is_Limited_Type (Underlying_Type (Typ)));
5177 end Is_Copy_Type;
5178
5179 -- Local variables
5180
5181 Loc : constant Source_Ptr := Sloc (N);
5182 Par : constant Node_Id := Parent (N);
5183 Typ : constant Entity_Id := Etype (N);
5184
5185 Acts : List_Id;
5186 Alt : Node_Id;
5187 Case_Stmt : Node_Id;
5188 Decl : Node_Id;
5189 Target : Entity_Id := Empty;
5190 Target_Typ : Entity_Id;
5191
5192 In_Predicate : Boolean := False;
5193 -- Flag set when the case expression appears within a predicate
5194
5195 Optimize_Return_Stmt : Boolean := False;
5196 -- Flag set when the case expression can be optimized in the context of
5197 -- a simple return statement.
5198
5199 -- Start of processing for Expand_N_Case_Expression
5200
5201 begin
5202 -- Check for MINIMIZED/ELIMINATED overflow mode
5203
5204 if Minimized_Eliminated_Overflow_Check (N) then
5205 Apply_Arithmetic_Overflow_Check (N);
5206 return;
5207 end if;
5208
5209 -- If the case expression is a predicate specification, and the type
5210 -- to which it applies has a static predicate aspect, do not expand,
5211 -- because it will be converted to the proper predicate form later.
5212
5213 if Ekind (Current_Scope) in E_Function | E_Procedure
5214 and then Is_Predicate_Function (Current_Scope)
5215 then
5216 In_Predicate := True;
5217
5218 if Has_Static_Predicate_Aspect (Etype (First_Entity (Current_Scope)))
5219 then
5220 return;
5221 end if;
5222 end if;
5223
5224 -- When the type of the case expression is elementary, expand
5225
5226 -- (case X is when A => AX, when B => BX ...)
5227
5228 -- into
5229
5230 -- do
5231 -- Target : Typ;
5232 -- case X is
5233 -- when A =>
5234 -- Target := AX;
5235 -- when B =>
5236 -- Target := BX;
5237 -- ...
5238 -- end case;
5239 -- in Target end;
5240
5241 -- In all other cases expand into
5242
5243 -- type Ptr_Typ is access all Typ;
5244 -- Target : Ptr_Typ;
5245 -- case X is
5246 -- when A =>
5247 -- Target := AX'Unrestricted_Access;
5248 -- when B =>
5249 -- Target := BX'Unrestricted_Access;
5250 -- ...
5251 -- end case;
5252
5253 -- and replace the case expression by a reference to Target.all.
5254
5255 -- This approach avoids extra copies of potentially large objects. It
5256 -- also allows handling of values of limited or unconstrained types.
5257 -- Note that we do the copy also for constrained, nonlimited types
5258 -- when minimizing expressions with actions (e.g. when generating C
5259 -- code) since it allows us to do the optimization below in more cases.
5260
5261 Case_Stmt :=
5262 Make_Case_Statement (Loc,
5263 Expression => Expression (N),
5264 Alternatives => New_List);
5265
5266 -- Preserve the original context for which the case statement is being
5267 -- generated. This is needed by the finalization machinery to prevent
5268 -- the premature finalization of controlled objects found within the
5269 -- case statement.
5270
5271 Set_From_Conditional_Expression (Case_Stmt);
5272 Acts := New_List;
5273
5274 -- Small optimization: when the case expression appears in the context
5275 -- of a simple return statement, expand into
5276
5277 -- case X is
5278 -- when A =>
5279 -- return AX;
5280 -- when B =>
5281 -- return BX;
5282 -- ...
5283 -- end case;
5284
5285 -- This makes the expansion much easier when expressions are calls to
5286 -- a BIP function. But do not perform it when the return statement is
5287 -- within a predicate function, as this causes spurious errors.
5288
5289 Optimize_Return_Stmt :=
5290 Nkind (Par) = N_Simple_Return_Statement and then not In_Predicate;
5291
5292 -- Scalar/Copy case
5293
5294 if Is_Copy_Type (Typ) then
5295 Target_Typ := Typ;
5296
5297 -- Otherwise create an access type to handle the general case using
5298 -- 'Unrestricted_Access.
5299
5300 -- Generate:
5301 -- type Ptr_Typ is access all Typ;
5302
5303 else
5304 if Generate_C_Code then
5305
5306 -- We cannot ensure that correct C code will be generated if any
5307 -- temporary is created down the line (to e.g. handle checks or
5308 -- capture values) since we might end up with dangling references
5309 -- to local variables, so better be safe and reject the construct.
5310
5311 Error_Msg_N
5312 ("case expression too complex, use case statement instead", N);
5313 end if;
5314
5315 Target_Typ := Make_Temporary (Loc, 'P');
5316
5317 Append_To (Acts,
5318 Make_Full_Type_Declaration (Loc,
5319 Defining_Identifier => Target_Typ,
5320 Type_Definition =>
5321 Make_Access_To_Object_Definition (Loc,
5322 All_Present => True,
5323 Subtype_Indication => New_Occurrence_Of (Typ, Loc))));
5324 end if;
5325
5326 -- Create the declaration of the target which captures the value of the
5327 -- expression.
5328
5329 -- Generate:
5330 -- Target : [Ptr_]Typ;
5331
5332 if not Optimize_Return_Stmt then
5333 Target := Make_Temporary (Loc, 'T');
5334
5335 Decl :=
5336 Make_Object_Declaration (Loc,
5337 Defining_Identifier => Target,
5338 Object_Definition => New_Occurrence_Of (Target_Typ, Loc));
5339 Set_No_Initialization (Decl);
5340
5341 Append_To (Acts, Decl);
5342 end if;
5343
5344 -- Process the alternatives
5345
5346 Alt := First (Alternatives (N));
5347 while Present (Alt) loop
5348 declare
5349 Alt_Expr : Node_Id := Expression (Alt);
5350 Alt_Loc : constant Source_Ptr := Sloc (Alt_Expr);
5351 LHS : Node_Id;
5352 Stmts : List_Id;
5353
5354 begin
5355 -- Take the unrestricted access of the expression value for non-
5356 -- scalar types. This approach avoids big copies and covers the
5357 -- limited and unconstrained cases.
5358
5359 -- Generate:
5360 -- return AX['Unrestricted_Access];
5361
5362 if Optimize_Return_Stmt then
5363 Stmts := New_List (
5364 Make_Simple_Return_Statement (Alt_Loc,
5365 Expression => Alt_Expr));
5366
5367 -- Generate:
5368 -- Target := AX['Unrestricted_Access];
5369
5370 else
5371 if not Is_Copy_Type (Typ) then
5372 Alt_Expr :=
5373 Make_Attribute_Reference (Alt_Loc,
5374 Prefix => Relocate_Node (Alt_Expr),
5375 Attribute_Name => Name_Unrestricted_Access);
5376 end if;
5377
5378 LHS := New_Occurrence_Of (Target, Loc);
5379 Set_Assignment_OK (LHS);
5380
5381 Stmts := New_List (
5382 Make_Assignment_Statement (Alt_Loc,
5383 Name => LHS,
5384 Expression => Alt_Expr));
5385 end if;
5386
5387 -- Propagate declarations inserted in the node by Insert_Actions
5388 -- (for example, temporaries generated to remove side effects).
5389 -- These actions must remain attached to the alternative, given
5390 -- that they are generated by the corresponding expression.
5391
5392 if Present (Actions (Alt)) then
5393 Prepend_List (Actions (Alt), Stmts);
5394 end if;
5395
5396 Append_To
5397 (Alternatives (Case_Stmt),
5398 Make_Case_Statement_Alternative (Sloc (Alt),
5399 Discrete_Choices => Discrete_Choices (Alt),
5400 Statements => Stmts));
5401
5402 -- Finalize any transient objects on exit from the alternative.
5403 -- This needs to be done only when the case expression is _not_
5404 -- later converted into an expression with actions, which already
5405 -- contains this form of processing, and after Stmts is attached
5406 -- to the Alternatives list above (for Safe_To_Capture_Value).
5407
5408 if Optimize_Return_Stmt or else not Is_Copy_Type (Typ) then
5409 Process_If_Case_Statements (N, Stmts);
5410 end if;
5411 end;
5412
5413 Next (Alt);
5414 end loop;
5415
5416 -- Rewrite the parent return statement as a case statement
5417
5418 if Optimize_Return_Stmt then
5419 Rewrite (Par, Case_Stmt);
5420 Analyze (Par);
5421
5422 -- Otherwise rewrite the case expression itself
5423
5424 else
5425 Append_To (Acts, Case_Stmt);
5426
5427 if Is_Copy_Type (Typ) then
5428 Rewrite (N,
5429 Make_Expression_With_Actions (Loc,
5430 Expression => New_Occurrence_Of (Target, Loc),
5431 Actions => Acts));
5432
5433 else
5434 Insert_Actions (N, Acts);
5435 Rewrite (N,
5436 Make_Explicit_Dereference (Loc,
5437 Prefix => New_Occurrence_Of (Target, Loc)));
5438 end if;
5439
5440 Analyze_And_Resolve (N, Typ);
5441 end if;
5442 end Expand_N_Case_Expression;
5443
5444 -----------------------------------
5445 -- Expand_N_Explicit_Dereference --
5446 -----------------------------------
5447
5448 procedure Expand_N_Explicit_Dereference (N : Node_Id) is
5449 begin
5450 -- Insert explicit dereference call for the checked storage pool case
5451
5452 Insert_Dereference_Action (Prefix (N));
5453
5454 -- If the type is an Atomic type for which Atomic_Sync is enabled, then
5455 -- we set the atomic sync flag.
5456
5457 if Is_Atomic (Etype (N))
5458 and then not Atomic_Synchronization_Disabled (Etype (N))
5459 then
5460 Activate_Atomic_Synchronization (N);
5461 end if;
5462 end Expand_N_Explicit_Dereference;
5463
5464 --------------------------------------
5465 -- Expand_N_Expression_With_Actions --
5466 --------------------------------------
5467
5468 procedure Expand_N_Expression_With_Actions (N : Node_Id) is
5469 Acts : constant List_Id := Actions (N);
5470
5471 procedure Force_Boolean_Evaluation (Expr : Node_Id);
5472 -- Force the evaluation of Boolean expression Expr
5473
5474 function Process_Action (Act : Node_Id) return Traverse_Result;
5475 -- Inspect and process a single action of an expression_with_actions for
5476 -- transient objects. If such objects are found, the routine generates
5477 -- code to clean them up when the context of the expression is evaluated
5478 -- or elaborated.
5479
5480 ------------------------------
5481 -- Force_Boolean_Evaluation --
5482 ------------------------------
5483
5484 procedure Force_Boolean_Evaluation (Expr : Node_Id) is
5485 Loc : constant Source_Ptr := Sloc (N);
5486 Flag_Decl : Node_Id;
5487 Flag_Id : Entity_Id;
5488
5489 begin
5490 -- Relocate the expression to the actions list by capturing its value
5491 -- in a Boolean flag. Generate:
5492 -- Flag : constant Boolean := Expr;
5493
5494 Flag_Id := Make_Temporary (Loc, 'F');
5495
5496 Flag_Decl :=
5497 Make_Object_Declaration (Loc,
5498 Defining_Identifier => Flag_Id,
5499 Constant_Present => True,
5500 Object_Definition => New_Occurrence_Of (Standard_Boolean, Loc),
5501 Expression => Relocate_Node (Expr));
5502
5503 Append (Flag_Decl, Acts);
5504 Analyze (Flag_Decl);
5505
5506 -- Replace the expression with a reference to the flag
5507
5508 Rewrite (Expression (N), New_Occurrence_Of (Flag_Id, Loc));
5509 Analyze (Expression (N));
5510 end Force_Boolean_Evaluation;
5511
5512 --------------------
5513 -- Process_Action --
5514 --------------------
5515
5516 function Process_Action (Act : Node_Id) return Traverse_Result is
5517 begin
5518 if Nkind (Act) = N_Object_Declaration
5519 and then Is_Finalizable_Transient (Act, N)
5520 then
5521 Process_Transient_In_Expression (Act, N, Acts);
5522 return Skip;
5523
5524 -- Avoid processing temporary function results multiple times when
5525 -- dealing with nested expression_with_actions or nested blocks.
5526 -- Similarly, do not process temporary function results in loops.
5527 -- This is done by Expand_N_Loop_Statement and Build_Finalizer.
5528 -- Note that we used to wrongly return Abandon instead of Skip here:
5529 -- this is wrong since it means that we were ignoring lots of
5530 -- relevant subsequent statements.
5531
5532 elsif Nkind (Act) in N_Expression_With_Actions
5533 | N_Block_Statement
5534 | N_Loop_Statement
5535 then
5536 return Skip;
5537 end if;
5538
5539 return OK;
5540 end Process_Action;
5541
5542 procedure Process_Single_Action is new Traverse_Proc (Process_Action);
5543
5544 -- Local variables
5545
5546 Act : Node_Id;
5547
5548 -- Start of processing for Expand_N_Expression_With_Actions
5549
5550 begin
5551 -- Do not evaluate the expression when it denotes an entity because the
5552 -- expression_with_actions node will be replaced by the reference.
5553
5554 if Is_Entity_Name (Expression (N)) then
5555 null;
5556
5557 -- Do not evaluate the expression when there are no actions because the
5558 -- expression_with_actions node will be replaced by the expression.
5559
5560 elsif Is_Empty_List (Acts) then
5561 null;
5562
5563 -- Force the evaluation of the expression by capturing its value in a
5564 -- temporary. This ensures that aliases of transient objects do not leak
5565 -- to the expression of the expression_with_actions node:
5566
5567 -- do
5568 -- Trans_Id : Ctrl_Typ := ...;
5569 -- Alias : ... := Trans_Id;
5570 -- in ... Alias ... end;
5571
5572 -- In the example above, Trans_Id cannot be finalized at the end of the
5573 -- actions list because this may affect the alias and the final value of
5574 -- the expression_with_actions. Forcing the evaluation encapsulates the
5575 -- reference to the Alias within the actions list:
5576
5577 -- do
5578 -- Trans_Id : Ctrl_Typ := ...;
5579 -- Alias : ... := Trans_Id;
5580 -- Val : constant Boolean := ... Alias ...;
5581 -- <finalize Trans_Id>
5582 -- in Val end;
5583
5584 -- Once this transformation is performed, it is safe to finalize the
5585 -- transient object at the end of the actions list.
5586
5587 -- Note that Force_Evaluation does not remove side effects in operators
5588 -- because it assumes that all operands are evaluated and side effect
5589 -- free. This is not the case when an operand depends implicitly on the
5590 -- transient object through the use of access types.
5591
5592 elsif Is_Boolean_Type (Etype (Expression (N))) then
5593 Force_Boolean_Evaluation (Expression (N));
5594
5595 -- The expression of an expression_with_actions node may not necessarily
5596 -- be Boolean when the node appears in an if expression. In this case do
5597 -- the usual forced evaluation to encapsulate potential aliasing.
5598
5599 else
5600 -- A check is also needed since the subtype of the EWA node and the
5601 -- subtype of the expression may differ (for example, the EWA node
5602 -- may have a null-excluding access subtype).
5603
5604 Apply_Constraint_Check (Expression (N), Etype (N));
5605 Force_Evaluation (Expression (N));
5606 end if;
5607
5608 -- Process all transient objects found within the actions of the EWA
5609 -- node.
5610
5611 Act := First (Acts);
5612 while Present (Act) loop
5613 Process_Single_Action (Act);
5614 Next (Act);
5615 end loop;
5616
5617 -- Deal with case where there are no actions. In this case we simply
5618 -- rewrite the node with its expression since we don't need the actions
5619 -- and the specification of this node does not allow a null action list.
5620
5621 -- Note: we use Rewrite instead of Replace, because Codepeer is using
5622 -- the expanded tree and relying on being able to retrieve the original
5623 -- tree in cases like this. This raises a whole lot of issues of whether
5624 -- we have problems elsewhere, which will be addressed in the future???
5625
5626 if Is_Empty_List (Acts) then
5627 Rewrite (N, Relocate_Node (Expression (N)));
5628 end if;
5629 end Expand_N_Expression_With_Actions;
5630
5631 ----------------------------
5632 -- Expand_N_If_Expression --
5633 ----------------------------
5634
5635 -- Deal with limited types and condition actions
5636
5637 procedure Expand_N_If_Expression (N : Node_Id) is
5638 Cond : constant Node_Id := First (Expressions (N));
5639 Loc : constant Source_Ptr := Sloc (N);
5640 Thenx : constant Node_Id := Next (Cond);
5641 Elsex : constant Node_Id := Next (Thenx);
5642 Par : constant Node_Id := Parent (N);
5643 Typ : constant Entity_Id := Etype (N);
5644
5645 Force_Expand : constant Boolean := Is_Anonymous_Access_Actual (N);
5646 -- Determine if we are dealing with a special case of a conditional
5647 -- expression used as an actual for an anonymous access type which
5648 -- forces us to transform the if expression into an expression with
5649 -- actions in order to create a temporary to capture the level of the
5650 -- expression in each branch.
5651
5652 function OK_For_Single_Subtype (T1, T2 : Entity_Id) return Boolean;
5653 -- Return true if it is acceptable to use a single subtype for two
5654 -- dependent expressions of subtype T1 and T2 respectively, which are
5655 -- unidimensional arrays whose index bounds are known at compile time.
5656
5657 ---------------------------
5658 -- OK_For_Single_Subtype --
5659 ---------------------------
5660
5661 function OK_For_Single_Subtype (T1, T2 : Entity_Id) return Boolean is
5662 Lo1, Hi1 : Uint;
5663 Lo2, Hi2 : Uint;
5664
5665 begin
5666 Get_First_Index_Bounds (T1, Lo1, Hi1);
5667 Get_First_Index_Bounds (T2, Lo2, Hi2);
5668
5669 -- Return true if the length of the covering subtype is not too large
5670
5671 return
5672 UI_Max (Hi1, Hi2) - UI_Min (Lo1, Lo2) < Too_Large_Length_For_Array;
5673 end OK_For_Single_Subtype;
5674
5675 Optimize_Return_Stmt : Boolean := False;
5676 -- Flag set when the if expression can be optimized in the context of
5677 -- a simple return statement.
5678
5679 -- Local variables
5680
5681 Actions : List_Id;
5682 Decl : Node_Id;
5683 Expr : Node_Id;
5684 New_If : Node_Id;
5685 New_N : Node_Id;
5686
5687 -- Start of processing for Expand_N_If_Expression
5688
5689 begin
5690 -- Deal with non-standard booleans
5691
5692 Adjust_Condition (Cond);
5693
5694 -- Check for MINIMIZED/ELIMINATED overflow mode.
5695 -- Apply_Arithmetic_Overflow_Check will not deal with Then/Else_Actions
5696 -- so skip this step if any actions are present.
5697
5698 if Minimized_Eliminated_Overflow_Check (N)
5699 and then No (Then_Actions (N))
5700 and then No (Else_Actions (N))
5701 then
5702 Apply_Arithmetic_Overflow_Check (N);
5703 return;
5704 end if;
5705
5706 -- Fold at compile time if condition known. We have already folded
5707 -- static if expressions, but it is possible to fold any case in which
5708 -- the condition is known at compile time, even though the result is
5709 -- non-static.
5710
5711 -- Note that we don't do the fold of such cases in Sem_Elab because
5712 -- it can cause infinite loops with the expander adding a conditional
5713 -- expression, and Sem_Elab circuitry removing it repeatedly.
5714
5715 if Compile_Time_Known_Value (Cond) then
5716 declare
5717 function Fold_Known_Value (Cond : Node_Id) return Boolean;
5718 -- Fold at compile time. Assumes condition known. Return True if
5719 -- folding occurred, meaning we're done.
5720
5721 ----------------------
5722 -- Fold_Known_Value --
5723 ----------------------
5724
5725 function Fold_Known_Value (Cond : Node_Id) return Boolean is
5726 begin
5727 if Is_True (Expr_Value (Cond)) then
5728 Expr := Thenx;
5729 Actions := Then_Actions (N);
5730 else
5731 Expr := Elsex;
5732 Actions := Else_Actions (N);
5733 end if;
5734
5735 Remove (Expr);
5736
5737 if Present (Actions) then
5738
5739 -- To minimize the use of Expression_With_Actions, just skip
5740 -- the optimization as it is not critical for correctness.
5741
5742 if Minimize_Expression_With_Actions then
5743 return False;
5744 end if;
5745
5746 Rewrite (N,
5747 Make_Expression_With_Actions (Loc,
5748 Expression => Relocate_Node (Expr),
5749 Actions => Actions));
5750 Analyze_And_Resolve (N, Typ);
5751
5752 else
5753 Rewrite (N, Relocate_Node (Expr));
5754 end if;
5755
5756 -- Note that the result is never static (legitimate cases of
5757 -- static if expressions were folded in Sem_Eval).
5758
5759 Set_Is_Static_Expression (N, False);
5760 return True;
5761 end Fold_Known_Value;
5762
5763 begin
5764 if Fold_Known_Value (Cond) then
5765 return;
5766 end if;
5767 end;
5768 end if;
5769
5770 -- Small optimization: when the if expression appears in the context of
5771 -- a simple return statement, expand into
5772
5773 -- if cond then
5774 -- return then-expr
5775 -- else
5776 -- return else-expr;
5777 -- end if;
5778
5779 -- This makes the expansion much easier when expressions are calls to
5780 -- a BIP function. But do not perform it when the return statement is
5781 -- within a predicate function, as this causes spurious errors.
5782
5783 Optimize_Return_Stmt :=
5784 Nkind (Par) = N_Simple_Return_Statement
5785 and then not (Ekind (Current_Scope) in E_Function | E_Procedure
5786 and then Is_Predicate_Function (Current_Scope));
5787
5788 if Optimize_Return_Stmt then
5789 -- When the "then" or "else" expressions involve controlled function
5790 -- calls, generated temporaries are chained on the corresponding list
5791 -- of actions. These temporaries need to be finalized after the if
5792 -- expression is evaluated.
5793
5794 Process_If_Case_Statements (N, Then_Actions (N));
5795 Process_If_Case_Statements (N, Else_Actions (N));
5796
5797 New_If :=
5798 Make_Implicit_If_Statement (N,
5799 Condition => Relocate_Node (Cond),
5800 Then_Statements => New_List (
5801 Make_Simple_Return_Statement (Sloc (Thenx),
5802 Expression => Relocate_Node (Thenx))),
5803 Else_Statements => New_List (
5804 Make_Simple_Return_Statement (Sloc (Elsex),
5805 Expression => Relocate_Node (Elsex))));
5806
5807 -- Preserve the original context for which the if statement is
5808 -- being generated. This is needed by the finalization machinery
5809 -- to prevent the premature finalization of controlled objects
5810 -- found within the if statement.
5811
5812 Set_From_Conditional_Expression (New_If);
5813
5814 -- If the type is by reference, then we expand as follows to avoid the
5815 -- possibility of improper copying.
5816
5817 -- type Ptr is access all Typ;
5818 -- Cnn : Ptr;
5819 -- if cond then
5820 -- <<then actions>>
5821 -- Cnn := then-expr'Unrestricted_Access;
5822 -- else
5823 -- <<else actions>>
5824 -- Cnn := else-expr'Unrestricted_Access;
5825 -- end if;
5826
5827 -- and replace the if expression by a reference to Cnn.all.
5828
5829 elsif Is_By_Reference_Type (Typ) then
5830 -- When the "then" or "else" expressions involve controlled function
5831 -- calls, generated temporaries are chained on the corresponding list
5832 -- of actions. These temporaries need to be finalized after the if
5833 -- expression is evaluated.
5834
5835 Process_If_Case_Statements (N, Then_Actions (N));
5836 Process_If_Case_Statements (N, Else_Actions (N));
5837
5838 declare
5839 Cnn : constant Entity_Id := Make_Temporary (Loc, 'C', N);
5840 Ptr_Typ : constant Entity_Id := Make_Temporary (Loc, 'A');
5841
5842 begin
5843 -- Generate:
5844 -- type Ann is access all Typ;
5845
5846 Insert_Action (N,
5847 Make_Full_Type_Declaration (Loc,
5848 Defining_Identifier => Ptr_Typ,
5849 Type_Definition =>
5850 Make_Access_To_Object_Definition (Loc,
5851 All_Present => True,
5852 Subtype_Indication => New_Occurrence_Of (Typ, Loc))));
5853
5854 -- Generate:
5855 -- Cnn : Ann;
5856
5857 Decl :=
5858 Make_Object_Declaration (Loc,
5859 Defining_Identifier => Cnn,
5860 Object_Definition => New_Occurrence_Of (Ptr_Typ, Loc));
5861
5862 -- Generate:
5863 -- if Cond then
5864 -- Cnn := <Thenx>'Unrestricted_Access;
5865 -- else
5866 -- Cnn := <Elsex>'Unrestricted_Access;
5867 -- end if;
5868
5869 New_If :=
5870 Make_Implicit_If_Statement (N,
5871 Condition => Relocate_Node (Cond),
5872 Then_Statements => New_List (
5873 Make_Assignment_Statement (Sloc (Thenx),
5874 Name => New_Occurrence_Of (Cnn, Sloc (Thenx)),
5875 Expression =>
5876 Make_Attribute_Reference (Loc,
5877 Prefix => Relocate_Node (Thenx),
5878 Attribute_Name => Name_Unrestricted_Access))),
5879
5880 Else_Statements => New_List (
5881 Make_Assignment_Statement (Sloc (Elsex),
5882 Name => New_Occurrence_Of (Cnn, Sloc (Elsex)),
5883 Expression =>
5884 Make_Attribute_Reference (Loc,
5885 Prefix => Relocate_Node (Elsex),
5886 Attribute_Name => Name_Unrestricted_Access))));
5887
5888 -- Preserve the original context for which the if statement is
5889 -- being generated. This is needed by the finalization machinery
5890 -- to prevent the premature finalization of controlled objects
5891 -- found within the if statement.
5892
5893 Set_From_Conditional_Expression (New_If);
5894
5895 New_N :=
5896 Make_Explicit_Dereference (Loc,
5897 Prefix => New_Occurrence_Of (Cnn, Loc));
5898 end;
5899
5900 -- If the result is a unidimensional unconstrained array but the two
5901 -- dependent expressions have constrained subtypes with known bounds,
5902 -- then we expand as follows:
5903
5904 -- subtype Txx is Typ (<static low-bound> .. <static high-bound>);
5905 -- Cnn : Txx;
5906 -- if cond then
5907 -- <<then actions>>
5908 -- Cnn (<then low-bound .. then high-bound>) := then-expr;
5909 -- else
5910 -- <<else actions>>
5911 -- Cnn (<else low bound .. else high-bound>) := else-expr;
5912 -- end if;
5913
5914 -- and replace the if expression by a slice of Cnn, provided that Txx
5915 -- is not too large. This will create a static temporary instead of the
5916 -- dynamic one of the next case and thus help the code generator.
5917
5918 -- Note that we need to deal with the case where the else expression is
5919 -- itself such a slice, in order to catch if expressions with more than
5920 -- two dependent expressions in the source code.
5921
5922 -- Also note that this creates variables on branches without an explicit
5923 -- scope, causing troubles with e.g. the LLVM IR, so disable this
5924 -- optimization when Unnest_Subprogram_Mode (enabled for LLVM).
5925
5926 elsif Is_Array_Type (Typ)
5927 and then Number_Dimensions (Typ) = 1
5928 and then not Is_Constrained (Typ)
5929 and then Is_Constrained (Etype (Thenx))
5930 and then Compile_Time_Known_Bounds (Etype (Thenx))
5931 and then
5932 ((Is_Constrained (Etype (Elsex))
5933 and then Compile_Time_Known_Bounds (Etype (Elsex))
5934 and then OK_For_Single_Subtype (Etype (Thenx), Etype (Elsex)))
5935 or else
5936 (Nkind (Elsex) = N_Slice
5937 and then Is_Constrained (Etype (Prefix (Elsex)))
5938 and then Compile_Time_Known_Bounds (Etype (Prefix (Elsex)))
5939 and then
5940 OK_For_Single_Subtype (Etype (Thenx), Etype (Prefix (Elsex)))))
5941 and then not Generate_C_Code
5942 and then not Unnest_Subprogram_Mode
5943 then
5944 declare
5945 Ityp : constant Entity_Id := Base_Type (Etype (First_Index (Typ)));
5946
5947 function Build_New_Bound
5948 (Then_Bnd : Uint;
5949 Else_Bnd : Uint;
5950 Slice_Bnd : Node_Id) return Node_Id;
5951 -- Build a new bound from the bounds of the if expression
5952
5953 function To_Ityp (V : Uint) return Node_Id;
5954 -- Convert V to an index value in Ityp
5955
5956 ---------------------
5957 -- Build_New_Bound --
5958 ---------------------
5959
5960 function Build_New_Bound
5961 (Then_Bnd : Uint;
5962 Else_Bnd : Uint;
5963 Slice_Bnd : Node_Id) return Node_Id is
5964
5965 begin
5966 -- We need to use the special processing for slices only if
5967 -- they do not have compile-time known bounds; if they do, they
5968 -- can be treated like any other expressions.
5969
5970 if Nkind (Elsex) = N_Slice
5971 and then not Compile_Time_Known_Bounds (Etype (Elsex))
5972 then
5973 if Compile_Time_Known_Value (Slice_Bnd)
5974 and then Expr_Value (Slice_Bnd) = Then_Bnd
5975 then
5976 return To_Ityp (Then_Bnd);
5977
5978 else
5979 return Make_If_Expression (Loc,
5980 Expressions => New_List (
5981 Duplicate_Subexpr (Cond),
5982 To_Ityp (Then_Bnd),
5983 New_Copy_Tree (Slice_Bnd)));
5984 end if;
5985
5986 elsif Then_Bnd = Else_Bnd then
5987 return To_Ityp (Then_Bnd);
5988
5989 else
5990 return Make_If_Expression (Loc,
5991 Expressions => New_List (
5992 Duplicate_Subexpr (Cond),
5993 To_Ityp (Then_Bnd),
5994 To_Ityp (Else_Bnd)));
5995 end if;
5996 end Build_New_Bound;
5997
5998 -------------
5999 -- To_Ityp --
6000 -------------
6001
6002 function To_Ityp (V : Uint) return Node_Id is
6003 Result : constant Node_Id := Make_Integer_Literal (Loc, V);
6004
6005 begin
6006 if Is_Enumeration_Type (Ityp) then
6007 return
6008 Make_Attribute_Reference (Loc,
6009 Prefix => New_Occurrence_Of (Ityp, Loc),
6010 Attribute_Name => Name_Val,
6011 Expressions => New_List (Result));
6012 else
6013 return Result;
6014 end if;
6015 end To_Ityp;
6016
6017 Ent : Node_Id;
6018 Slice_Lo, Slice_Hi : Node_Id;
6019 Subtyp_Ind : Node_Id;
6020 Else_Lo, Else_Hi : Uint;
6021 Min_Lo, Max_Hi : Uint;
6022 Then_Lo, Then_Hi : Uint;
6023 Then_List, Else_List : List_Id;
6024
6025 begin
6026 Get_First_Index_Bounds (Etype (Thenx), Then_Lo, Then_Hi);
6027
6028 -- See the rationale in Build_New_Bound
6029
6030 if Nkind (Elsex) = N_Slice
6031 and then not Compile_Time_Known_Bounds (Etype (Elsex))
6032 then
6033 Slice_Lo := Low_Bound (Discrete_Range (Elsex));
6034 Slice_Hi := High_Bound (Discrete_Range (Elsex));
6035 Get_First_Index_Bounds
6036 (Etype (Prefix (Elsex)), Else_Lo, Else_Hi);
6037
6038 else
6039 Slice_Lo := Empty;
6040 Slice_Hi := Empty;
6041 Get_First_Index_Bounds (Etype (Elsex), Else_Lo, Else_Hi);
6042 end if;
6043
6044 Min_Lo := UI_Min (Then_Lo, Else_Lo);
6045 Max_Hi := UI_Max (Then_Hi, Else_Hi);
6046
6047 -- Now we construct an array object with appropriate bounds and
6048 -- mark it as internal to prevent useless initialization when
6049 -- Initialize_Scalars is enabled. Also since this is the actual
6050 -- result entity, we make sure we have debug information for it.
6051
6052 Subtyp_Ind :=
6053 Make_Subtype_Indication (Loc,
6054 Subtype_Mark => New_Occurrence_Of (Typ, Loc),
6055 Constraint =>
6056 Make_Index_Or_Discriminant_Constraint (Loc,
6057 Constraints => New_List (
6058 Make_Range (Loc,
6059 Low_Bound => To_Ityp (Min_Lo),
6060 High_Bound => To_Ityp (Max_Hi)))));
6061
6062 Ent := Make_Temporary (Loc, 'C');
6063 Set_Is_Internal (Ent);
6064 Set_Debug_Info_Needed (Ent);
6065
6066 Decl :=
6067 Make_Object_Declaration (Loc,
6068 Defining_Identifier => Ent,
6069 Object_Definition => Subtyp_Ind);
6070
6071 -- If the result of the expression appears as the initializing
6072 -- expression of an object declaration, we can just rename the
6073 -- result, rather than copying it.
6074
6075 Mutate_Ekind (Ent, E_Variable);
6076 Set_OK_To_Rename (Ent);
6077
6078 Then_List := New_List (
6079 Make_Assignment_Statement (Loc,
6080 Name =>
6081 Make_Slice (Loc,
6082 Prefix => New_Occurrence_Of (Ent, Loc),
6083 Discrete_Range =>
6084 Make_Range (Loc,
6085 Low_Bound => To_Ityp (Then_Lo),
6086 High_Bound => To_Ityp (Then_Hi))),
6087 Expression => Relocate_Node (Thenx)));
6088
6089 Set_Suppress_Assignment_Checks (Last (Then_List));
6090
6091 -- See the rationale in Build_New_Bound
6092
6093 if Nkind (Elsex) = N_Slice
6094 and then not Compile_Time_Known_Bounds (Etype (Elsex))
6095 then
6096 Else_List := New_List (
6097 Make_Assignment_Statement (Loc,
6098 Name =>
6099 Make_Slice (Loc,
6100 Prefix => New_Occurrence_Of (Ent, Loc),
6101 Discrete_Range =>
6102 Make_Range (Loc,
6103 Low_Bound => New_Copy_Tree (Slice_Lo),
6104 High_Bound => New_Copy_Tree (Slice_Hi))),
6105 Expression => Relocate_Node (Elsex)));
6106
6107 else
6108 Else_List := New_List (
6109 Make_Assignment_Statement (Loc,
6110 Name =>
6111 Make_Slice (Loc,
6112 Prefix => New_Occurrence_Of (Ent, Loc),
6113 Discrete_Range =>
6114 Make_Range (Loc,
6115 Low_Bound => To_Ityp (Else_Lo),
6116 High_Bound => To_Ityp (Else_Hi))),
6117 Expression => Relocate_Node (Elsex)));
6118 end if;
6119
6120 Set_Suppress_Assignment_Checks (Last (Else_List));
6121
6122 New_If :=
6123 Make_Implicit_If_Statement (N,
6124 Condition => Duplicate_Subexpr (Cond),
6125 Then_Statements => Then_List,
6126 Else_Statements => Else_List);
6127
6128 New_N :=
6129 Make_Slice (Loc,
6130 Prefix => New_Occurrence_Of (Ent, Loc),
6131 Discrete_Range => Make_Range (Loc,
6132 Low_Bound => Build_New_Bound (Then_Lo, Else_Lo, Slice_Lo),
6133 High_Bound => Build_New_Bound (Then_Hi, Else_Hi, Slice_Hi)));
6134 end;
6135
6136 -- If the result is an unconstrained array and the if expression is in a
6137 -- context other than the initializing expression of the declaration of
6138 -- an object, then we pull out the if expression as follows:
6139
6140 -- Cnn : constant typ := if-expression
6141
6142 -- and then replace the if expression with an occurrence of Cnn. This
6143 -- avoids the need in the back end to create on-the-fly variable length
6144 -- temporaries (which it cannot do!)
6145
6146 -- Note that the test for being in an object declaration avoids doing an
6147 -- unnecessary expansion, and also avoids infinite recursion.
6148
6149 elsif Is_Array_Type (Typ)
6150 and then not Is_Constrained (Typ)
6151 and then not (Nkind (Par) = N_Object_Declaration
6152 and then Expression (Par) = N)
6153 then
6154 declare
6155 Cnn : constant Node_Id := Make_Temporary (Loc, 'C', N);
6156
6157 begin
6158 Insert_Action (N,
6159 Make_Object_Declaration (Loc,
6160 Defining_Identifier => Cnn,
6161 Constant_Present => True,
6162 Object_Definition => New_Occurrence_Of (Typ, Loc),
6163 Expression => Relocate_Node (N),
6164 Has_Init_Expression => True));
6165
6166 Rewrite (N, New_Occurrence_Of (Cnn, Loc));
6167 return;
6168 end;
6169
6170 -- For other types, we only need to expand if there are other actions
6171 -- associated with either branch or we need to force expansion to deal
6172 -- with if expressions used as an actual of an anonymous access type.
6173
6174 elsif Present (Then_Actions (N))
6175 or else Present (Else_Actions (N))
6176 or else Force_Expand
6177 then
6178
6179 -- We now wrap the actions into the appropriate expression
6180
6181 if Minimize_Expression_With_Actions
6182 and then (Is_Elementary_Type (Underlying_Type (Typ))
6183 or else Is_Constrained (Underlying_Type (Typ)))
6184 then
6185 -- If we can't use N_Expression_With_Actions nodes, then we insert
6186 -- the following sequence of actions (using Insert_Actions):
6187
6188 -- Cnn : typ;
6189 -- if cond then
6190 -- <<then actions>>
6191 -- Cnn := then-expr;
6192 -- else
6193 -- <<else actions>>
6194 -- Cnn := else-expr
6195 -- end if;
6196
6197 -- and replace the if expression by a reference to Cnn
6198
6199 declare
6200 Cnn : constant Node_Id := Make_Temporary (Loc, 'C', N);
6201
6202 begin
6203 Decl :=
6204 Make_Object_Declaration (Loc,
6205 Defining_Identifier => Cnn,
6206 Object_Definition => New_Occurrence_Of (Typ, Loc));
6207
6208 New_If :=
6209 Make_Implicit_If_Statement (N,
6210 Condition => Relocate_Node (Cond),
6211
6212 Then_Statements => New_List (
6213 Make_Assignment_Statement (Sloc (Thenx),
6214 Name => New_Occurrence_Of (Cnn, Sloc (Thenx)),
6215 Expression => Relocate_Node (Thenx))),
6216
6217 Else_Statements => New_List (
6218 Make_Assignment_Statement (Sloc (Elsex),
6219 Name => New_Occurrence_Of (Cnn, Sloc (Elsex)),
6220 Expression => Relocate_Node (Elsex))));
6221
6222 Set_Assignment_OK (Name (First (Then_Statements (New_If))));
6223 Set_Assignment_OK (Name (First (Else_Statements (New_If))));
6224
6225 New_N := New_Occurrence_Of (Cnn, Loc);
6226 end;
6227
6228 -- Regular path using Expression_With_Actions
6229
6230 else
6231 if Present (Then_Actions (N)) then
6232 Rewrite (Thenx,
6233 Make_Expression_With_Actions (Sloc (Thenx),
6234 Actions => Then_Actions (N),
6235 Expression => Relocate_Node (Thenx)));
6236
6237 Set_Then_Actions (N, No_List);
6238 Analyze_And_Resolve (Thenx, Typ);
6239 end if;
6240
6241 if Present (Else_Actions (N)) then
6242 Rewrite (Elsex,
6243 Make_Expression_With_Actions (Sloc (Elsex),
6244 Actions => Else_Actions (N),
6245 Expression => Relocate_Node (Elsex)));
6246
6247 Set_Else_Actions (N, No_List);
6248 Analyze_And_Resolve (Elsex, Typ);
6249 end if;
6250
6251 -- We must force expansion into an expression with actions when
6252 -- an if expression gets used directly as an actual for an
6253 -- anonymous access type.
6254
6255 if Force_Expand then
6256 declare
6257 Cnn : constant Entity_Id := Make_Temporary (Loc, 'C');
6258 Acts : List_Id;
6259 begin
6260 Acts := New_List;
6261
6262 -- Generate:
6263 -- Cnn : Ann;
6264
6265 Decl :=
6266 Make_Object_Declaration (Loc,
6267 Defining_Identifier => Cnn,
6268 Object_Definition => New_Occurrence_Of (Typ, Loc));
6269 Append_To (Acts, Decl);
6270
6271 Set_No_Initialization (Decl);
6272
6273 -- Generate:
6274 -- if Cond then
6275 -- Cnn := <Thenx>;
6276 -- else
6277 -- Cnn := <Elsex>;
6278 -- end if;
6279
6280 New_If :=
6281 Make_Implicit_If_Statement (N,
6282 Condition => Relocate_Node (Cond),
6283 Then_Statements => New_List (
6284 Make_Assignment_Statement (Sloc (Thenx),
6285 Name => New_Occurrence_Of (Cnn, Sloc (Thenx)),
6286 Expression => Relocate_Node (Thenx))),
6287
6288 Else_Statements => New_List (
6289 Make_Assignment_Statement (Sloc (Elsex),
6290 Name => New_Occurrence_Of (Cnn, Sloc (Elsex)),
6291 Expression => Relocate_Node (Elsex))));
6292 Append_To (Acts, New_If);
6293
6294 -- Generate:
6295 -- do
6296 -- ...
6297 -- in Cnn end;
6298
6299 Rewrite (N,
6300 Make_Expression_With_Actions (Loc,
6301 Expression => New_Occurrence_Of (Cnn, Loc),
6302 Actions => Acts));
6303 Analyze_And_Resolve (N, Typ);
6304 end;
6305 end if;
6306
6307 return;
6308 end if;
6309
6310 -- For the sake of GNATcoverage, generate an intermediate temporary in
6311 -- the case where the if expression is a condition in an outer decision,
6312 -- in order to make sure that no branch is shared between the decisions.
6313
6314 elsif Opt.Suppress_Control_Flow_Optimizations
6315 and then Nkind (Original_Node (Par)) in N_Case_Expression
6316 | N_Case_Statement
6317 | N_If_Expression
6318 | N_If_Statement
6319 | N_Goto_When_Statement
6320 | N_Loop_Statement
6321 | N_Return_When_Statement
6322 | N_Short_Circuit
6323 then
6324 declare
6325 Cnn : constant Entity_Id := Make_Temporary (Loc, 'C');
6326 Acts : List_Id;
6327
6328 begin
6329 -- Generate:
6330 -- do
6331 -- Cnn : constant Typ := N;
6332 -- in Cnn end
6333
6334 Acts := New_List (
6335 Make_Object_Declaration (Loc,
6336 Defining_Identifier => Cnn,
6337 Constant_Present => True,
6338 Object_Definition => New_Occurrence_Of (Typ, Loc),
6339 Expression => Relocate_Node (N)));
6340
6341 Rewrite (N,
6342 Make_Expression_With_Actions (Loc,
6343 Expression => New_Occurrence_Of (Cnn, Loc),
6344 Actions => Acts));
6345
6346 Analyze_And_Resolve (N, Typ);
6347 return;
6348 end;
6349
6350 -- If no actions then no expansion needed, gigi will handle it using the
6351 -- same approach as a C conditional expression.
6352
6353 else
6354 return;
6355 end if;
6356
6357 -- Fall through here for either the limited expansion, or the case of
6358 -- inserting actions for nonlimited types. In both these cases, we must
6359 -- move the SLOC of the parent If statement to the newly created one and
6360 -- change it to the SLOC of the expression which, after expansion, will
6361 -- correspond to what is being evaluated.
6362
6363 if Present (Par) and then Nkind (Par) = N_If_Statement then
6364 Set_Sloc (New_If, Sloc (Par));
6365 Set_Sloc (Par, Loc);
6366 end if;
6367
6368 -- Move Then_Actions and Else_Actions, if any, to the new if statement
6369
6370 if Present (Then_Actions (N)) then
6371 Prepend_List (Then_Actions (N), Then_Statements (New_If));
6372 end if;
6373
6374 if Present (Else_Actions (N)) then
6375 Prepend_List (Else_Actions (N), Else_Statements (New_If));
6376 end if;
6377
6378 -- Rewrite the parent return statement as an if statement
6379
6380 if Optimize_Return_Stmt then
6381 Rewrite (Par, New_If);
6382 Analyze (Par);
6383
6384 -- Otherwise rewrite the if expression itself
6385
6386 else
6387 Insert_Action (N, Decl);
6388 Insert_Action (N, New_If);
6389 Rewrite (N, New_N);
6390 Analyze_And_Resolve (N, Typ);
6391 end if;
6392 end Expand_N_If_Expression;
6393
6394 -----------------
6395 -- Expand_N_In --
6396 -----------------
6397
6398 procedure Expand_N_In (N : Node_Id) is
6399 Loc : constant Source_Ptr := Sloc (N);
6400 Restyp : constant Entity_Id := Etype (N);
6401 Lop : constant Node_Id := Left_Opnd (N);
6402 Rop : constant Node_Id := Right_Opnd (N);
6403 Static : constant Boolean := Is_OK_Static_Expression (N);
6404
6405 procedure Substitute_Valid_Test;
6406 -- Replaces node N by Lop'Valid. This is done when we have an explicit
6407 -- test for the left operand being in range of its subtype.
6408
6409 ---------------------------
6410 -- Substitute_Valid_Test --
6411 ---------------------------
6412
6413 procedure Substitute_Valid_Test is
6414 function Is_OK_Object_Reference (Nod : Node_Id) return Boolean;
6415 -- Determine whether arbitrary node Nod denotes a source object that
6416 -- may safely act as prefix of attribute 'Valid.
6417
6418 ----------------------------
6419 -- Is_OK_Object_Reference --
6420 ----------------------------
6421
6422 function Is_OK_Object_Reference (Nod : Node_Id) return Boolean is
6423 Obj_Ref : constant Node_Id := Original_Node (Nod);
6424 -- The original operand
6425
6426 begin
6427 -- The object reference must be a source construct, otherwise the
6428 -- codefix suggestion may refer to nonexistent code from a user
6429 -- perspective.
6430
6431 return Comes_From_Source (Obj_Ref)
6432 and then Is_Object_Reference (Unqual_Conv (Obj_Ref));
6433 end Is_OK_Object_Reference;
6434
6435 -- Start of processing for Substitute_Valid_Test
6436
6437 begin
6438 Rewrite (N,
6439 Make_Attribute_Reference (Loc,
6440 Prefix => Relocate_Node (Lop),
6441 Attribute_Name => Name_Valid));
6442
6443 Analyze_And_Resolve (N, Restyp);
6444
6445 -- Emit a warning when the left-hand operand of the membership test
6446 -- is a source object, otherwise the use of attribute 'Valid would be
6447 -- illegal. The warning is not given when overflow checking is either
6448 -- MINIMIZED or ELIMINATED, as the danger of optimization has been
6449 -- eliminated above.
6450
6451 if Is_OK_Object_Reference (Lop)
6452 and then Overflow_Check_Mode not in Minimized_Or_Eliminated
6453 then
6454 Error_Msg_N
6455 ("??explicit membership test may be optimized away", N);
6456 Error_Msg_N -- CODEFIX
6457 ("\??use ''Valid attribute instead", N);
6458 end if;
6459 end Substitute_Valid_Test;
6460
6461 -- Local variables
6462
6463 Ltyp : Entity_Id;
6464 Rtyp : Entity_Id;
6465
6466 -- Start of processing for Expand_N_In
6467
6468 begin
6469 -- If set membership case, expand with separate procedure
6470
6471 if Present (Alternatives (N)) then
6472 Expand_Set_Membership (N);
6473 return;
6474 end if;
6475
6476 -- Not set membership, proceed with expansion
6477
6478 Ltyp := Etype (Left_Opnd (N));
6479 Rtyp := Etype (Right_Opnd (N));
6480
6481 -- If MINIMIZED/ELIMINATED overflow mode and type is a signed integer
6482 -- type, then expand with a separate procedure. Note the use of the
6483 -- flag No_Minimize_Eliminate to prevent infinite recursion.
6484
6485 if Minimized_Eliminated_Overflow_Check (Left_Opnd (N))
6486 and then not No_Minimize_Eliminate (N)
6487 then
6488 Expand_Membership_Minimize_Eliminate_Overflow (N);
6489 return;
6490 end if;
6491
6492 -- Check case of explicit test for an expression in range of its
6493 -- subtype. This is suspicious usage and we replace it with a 'Valid
6494 -- test and give a warning for scalar types.
6495
6496 if Is_Scalar_Type (Ltyp)
6497
6498 -- Only relevant for source comparisons
6499
6500 and then Comes_From_Source (N)
6501
6502 -- In floating-point this is a standard way to check for finite values
6503 -- and using 'Valid would typically be a pessimization.
6504
6505 and then not Is_Floating_Point_Type (Ltyp)
6506
6507 -- Don't give the message unless right operand is a type entity and
6508 -- the type of the left operand matches this type. Note that this
6509 -- eliminates the cases where MINIMIZED/ELIMINATED mode overflow
6510 -- checks have changed the type of the left operand.
6511
6512 and then Is_Entity_Name (Rop)
6513 and then Ltyp = Entity (Rop)
6514
6515 -- Skip this for predicated types, where such expressions are a
6516 -- reasonable way of testing if something meets the predicate.
6517
6518 and then No (Predicate_Function (Ltyp))
6519 then
6520 Substitute_Valid_Test;
6521 return;
6522 end if;
6523
6524 -- Do validity check on operands
6525
6526 if Validity_Checks_On and Validity_Check_Operands then
6527 Ensure_Valid (Left_Opnd (N));
6528 Validity_Check_Range (Right_Opnd (N));
6529 end if;
6530
6531 -- Case of explicit range
6532
6533 if Nkind (Rop) = N_Range then
6534 declare
6535 Lo : constant Node_Id := Low_Bound (Rop);
6536 Hi : constant Node_Id := High_Bound (Rop);
6537
6538 Lo_Orig : constant Node_Id := Original_Node (Lo);
6539 Hi_Orig : constant Node_Id := Original_Node (Hi);
6540 Rop_Orig : constant Node_Id := Original_Node (Rop);
6541
6542 Comes_From_Simple_Range_In_Source : constant Boolean :=
6543 Comes_From_Source (N)
6544 and then not
6545 (Is_Entity_Name (Rop_Orig)
6546 and then Is_Type (Entity (Rop_Orig))
6547 and then Present (Predicate_Function (Entity (Rop_Orig))));
6548 -- This is true for a membership test present in the source with a
6549 -- range or mark for a subtype that is not predicated. As already
6550 -- explained a few lines above, we do not want to give warnings on
6551 -- a test with a mark for a subtype that is predicated.
6552
6553 Warn : constant Boolean :=
6554 Constant_Condition_Warnings
6555 and then Comes_From_Simple_Range_In_Source
6556 and then not In_Instance;
6557 -- This must be true for any of the optimization warnings, we
6558 -- clearly want to give them only for source with the flag on. We
6559 -- also skip these warnings in an instance since it may be the
6560 -- case that different instantiations have different ranges.
6561
6562 Lcheck : Compare_Result;
6563 Ucheck : Compare_Result;
6564
6565 begin
6566 -- If test is explicit x'First .. x'Last, replace by 'Valid test
6567
6568 if Is_Scalar_Type (Ltyp)
6569
6570 -- Only relevant for source comparisons
6571
6572 and then Comes_From_Simple_Range_In_Source
6573
6574 -- And left operand is X'First where X matches left operand
6575 -- type (this eliminates cases of type mismatch, including
6576 -- the cases where ELIMINATED/MINIMIZED mode has changed the
6577 -- type of the left operand.
6578
6579 and then Nkind (Lo_Orig) = N_Attribute_Reference
6580 and then Attribute_Name (Lo_Orig) = Name_First
6581 and then Is_Entity_Name (Prefix (Lo_Orig))
6582 and then Entity (Prefix (Lo_Orig)) = Ltyp
6583
6584 -- Same tests for right operand
6585
6586 and then Nkind (Hi_Orig) = N_Attribute_Reference
6587 and then Attribute_Name (Hi_Orig) = Name_Last
6588 and then Is_Entity_Name (Prefix (Hi_Orig))
6589 and then Entity (Prefix (Hi_Orig)) = Ltyp
6590 then
6591 Substitute_Valid_Test;
6592 goto Leave;
6593 end if;
6594
6595 -- If bounds of type are known at compile time, and the end points
6596 -- are known at compile time and identical, this is another case
6597 -- for substituting a valid test. We only do this for discrete
6598 -- types, since it won't arise in practice for float types.
6599
6600 if Comes_From_Simple_Range_In_Source
6601 and then Is_Discrete_Type (Ltyp)
6602 and then Compile_Time_Known_Value (Type_High_Bound (Ltyp))
6603 and then Compile_Time_Known_Value (Type_Low_Bound (Ltyp))
6604 and then Compile_Time_Known_Value (Lo)
6605 and then Compile_Time_Known_Value (Hi)
6606 and then Expr_Value (Type_High_Bound (Ltyp)) = Expr_Value (Hi)
6607 and then Expr_Value (Type_Low_Bound (Ltyp)) = Expr_Value (Lo)
6608
6609 -- Kill warnings in instances, since they may be cases where we
6610 -- have a test in the generic that makes sense with some types
6611 -- and not with other types.
6612
6613 -- Similarly, do not rewrite membership as a 'Valid test if
6614 -- within the predicate function for the type.
6615
6616 -- Finally, if the original bounds are type conversions, even
6617 -- if they have been folded into constants, there are different
6618 -- types involved and 'Valid is not appropriate.
6619
6620 then
6621 if In_Instance
6622 or else (Ekind (Current_Scope) = E_Function
6623 and then Is_Predicate_Function (Current_Scope))
6624 then
6625 null;
6626
6627 elsif Nkind (Lo_Orig) = N_Type_Conversion
6628 or else Nkind (Hi_Orig) = N_Type_Conversion
6629 then
6630 null;
6631
6632 else
6633 Substitute_Valid_Test;
6634 goto Leave;
6635 end if;
6636 end if;
6637
6638 -- If we have an explicit range, do a bit of optimization based on
6639 -- range analysis (we may be able to kill one or both checks).
6640
6641 Lcheck := Compile_Time_Compare (Lop, Lo, Assume_Valid => False);
6642 Ucheck := Compile_Time_Compare (Lop, Hi, Assume_Valid => False);
6643
6644 -- If either check is known to fail, replace result by False since
6645 -- the other check does not matter. Preserve the static flag for
6646 -- legality checks, because we are constant-folding beyond RM 4.9.
6647
6648 if Lcheck = LT or else Ucheck = GT then
6649 if Warn then
6650 Error_Msg_N ("?c?range test optimized away", N);
6651 Error_Msg_N ("\?c?value is known to be out of range", N);
6652 end if;
6653
6654 Rewrite (N, New_Occurrence_Of (Standard_False, Loc));
6655 Analyze_And_Resolve (N, Restyp);
6656 Set_Is_Static_Expression (N, Static);
6657 goto Leave;
6658
6659 -- If both checks are known to succeed, replace result by True,
6660 -- since we know we are in range.
6661
6662 elsif Lcheck in Compare_GE and then Ucheck in Compare_LE then
6663 if Warn then
6664 Error_Msg_N ("?c?range test optimized away", N);
6665 Error_Msg_N ("\?c?value is known to be in range", N);
6666 end if;
6667
6668 Rewrite (N, New_Occurrence_Of (Standard_True, Loc));
6669 Analyze_And_Resolve (N, Restyp);
6670 Set_Is_Static_Expression (N, Static);
6671 goto Leave;
6672
6673 -- If lower bound check succeeds and upper bound check is not
6674 -- known to succeed or fail, then replace the range check with
6675 -- a comparison against the upper bound.
6676
6677 elsif Lcheck in Compare_GE then
6678 Rewrite (N,
6679 Make_Op_Le (Loc,
6680 Left_Opnd => Lop,
6681 Right_Opnd => High_Bound (Rop)));
6682 Analyze_And_Resolve (N, Restyp);
6683 goto Leave;
6684
6685 -- Inverse of previous case.
6686
6687 elsif Ucheck in Compare_LE then
6688 Rewrite (N,
6689 Make_Op_Ge (Loc,
6690 Left_Opnd => Lop,
6691 Right_Opnd => Low_Bound (Rop)));
6692 Analyze_And_Resolve (N, Restyp);
6693 goto Leave;
6694 end if;
6695
6696 -- We couldn't optimize away the range check, but there is one
6697 -- more issue. If we are checking constant conditionals, then we
6698 -- see if we can determine the outcome assuming everything is
6699 -- valid, and if so give an appropriate warning.
6700
6701 if Warn and then not Assume_No_Invalid_Values then
6702 Lcheck := Compile_Time_Compare (Lop, Lo, Assume_Valid => True);
6703 Ucheck := Compile_Time_Compare (Lop, Hi, Assume_Valid => True);
6704
6705 -- Result is out of range for valid value
6706
6707 if Lcheck = LT or else Ucheck = GT then
6708 Error_Msg_N
6709 ("?c?value can only be in range if it is invalid", N);
6710
6711 -- Result is in range for valid value
6712
6713 elsif Lcheck in Compare_GE and then Ucheck in Compare_LE then
6714 Error_Msg_N
6715 ("?c?value can only be out of range if it is invalid", N);
6716 end if;
6717 end if;
6718 end;
6719
6720 -- Try to narrow the operation
6721
6722 if Ltyp = Universal_Integer and then Nkind (N) = N_In then
6723 Narrow_Large_Operation (N);
6724 end if;
6725
6726 -- For all other cases of an explicit range, nothing to be done
6727
6728 goto Leave;
6729
6730 -- Here right operand is a subtype mark
6731
6732 else
6733 declare
6734 Typ : Entity_Id := Etype (Rop);
6735 Is_Acc : constant Boolean := Is_Access_Type (Typ);
6736 Check_Null_Exclusion : Boolean;
6737 Cond : Node_Id := Empty;
6738 New_N : Node_Id;
6739 Obj : Node_Id := Lop;
6740 SCIL_Node : Node_Id;
6741
6742 begin
6743 Remove_Side_Effects (Obj);
6744
6745 -- For tagged type, do tagged membership operation
6746
6747 if Is_Tagged_Type (Typ) then
6748
6749 -- No expansion will be performed for VM targets, as the VM
6750 -- back ends will handle the membership tests directly.
6751
6752 if Tagged_Type_Expansion then
6753 Tagged_Membership (N, SCIL_Node, New_N);
6754 Rewrite (N, New_N);
6755 Analyze_And_Resolve (N, Restyp, Suppress => All_Checks);
6756
6757 -- Update decoration of relocated node referenced by the
6758 -- SCIL node.
6759
6760 if Generate_SCIL and then Present (SCIL_Node) then
6761 Set_SCIL_Node (N, SCIL_Node);
6762 end if;
6763 end if;
6764
6765 goto Leave;
6766
6767 -- If type is scalar type, rewrite as x in t'First .. t'Last.
6768 -- The reason we do this is that the bounds may have the wrong
6769 -- type if they come from the original type definition. Also this
6770 -- way we get all the processing above for an explicit range.
6771
6772 -- Don't do this for predicated types, since in this case we want
6773 -- to generate the predicate check at the end of the function.
6774
6775 elsif Is_Scalar_Type (Typ) then
6776 if No (Predicate_Function (Typ)) then
6777 Rewrite (Rop,
6778 Make_Range (Loc,
6779 Low_Bound =>
6780 Make_Attribute_Reference (Loc,
6781 Attribute_Name => Name_First,
6782 Prefix => New_Occurrence_Of (Typ, Loc)),
6783
6784 High_Bound =>
6785 Make_Attribute_Reference (Loc,
6786 Attribute_Name => Name_Last,
6787 Prefix => New_Occurrence_Of (Typ, Loc))));
6788
6789 Analyze_And_Resolve (N, Restyp);
6790 end if;
6791
6792 goto Leave;
6793
6794 -- Ada 2005 (AI95-0216 amended by AI12-0162): Program_Error is
6795 -- raised when evaluating an individual membership test if the
6796 -- subtype mark denotes a constrained Unchecked_Union subtype
6797 -- and the expression lacks inferable discriminants.
6798
6799 elsif Is_Unchecked_Union (Base_Type (Typ))
6800 and then Is_Constrained (Typ)
6801 and then not Has_Inferable_Discriminants (Lop)
6802 then
6803 Rewrite (N,
6804 Make_Expression_With_Actions (Loc,
6805 Actions =>
6806 New_List (Make_Raise_Program_Error (Loc,
6807 Reason => PE_Unchecked_Union_Restriction)),
6808 Expression =>
6809 New_Occurrence_Of (Standard_False, Loc)));
6810 Analyze_And_Resolve (N, Restyp);
6811
6812 goto Leave;
6813 end if;
6814
6815 -- Here we have a non-scalar type
6816
6817 if Is_Acc then
6818
6819 -- If the null exclusion checks are not compatible, need to
6820 -- perform further checks. In other words, we cannot have
6821 -- Ltyp including null or Lop being null, and Typ excluding
6822 -- null. All other cases are OK.
6823
6824 Check_Null_Exclusion :=
6825 Can_Never_Be_Null (Typ)
6826 and then (not Can_Never_Be_Null (Ltyp)
6827 or else Nkind (Lop) = N_Null);
6828 Typ := Designated_Type (Typ);
6829 end if;
6830
6831 if not Is_Constrained (Typ) then
6832 Cond := New_Occurrence_Of (Standard_True, Loc);
6833
6834 -- For the constrained array case, we have to check the subscripts
6835 -- for an exact match if the lengths are non-zero (the lengths
6836 -- must match in any case).
6837
6838 elsif Is_Array_Type (Typ) then
6839 Check_Subscripts : declare
6840 function Build_Attribute_Reference
6841 (E : Node_Id;
6842 Nam : Name_Id;
6843 Dim : Nat) return Node_Id;
6844 -- Build attribute reference E'Nam (Dim)
6845
6846 -------------------------------
6847 -- Build_Attribute_Reference --
6848 -------------------------------
6849
6850 function Build_Attribute_Reference
6851 (E : Node_Id;
6852 Nam : Name_Id;
6853 Dim : Nat) return Node_Id
6854 is
6855 begin
6856 return
6857 Make_Attribute_Reference (Loc,
6858 Prefix => E,
6859 Attribute_Name => Nam,
6860 Expressions => New_List (
6861 Make_Integer_Literal (Loc, Dim)));
6862 end Build_Attribute_Reference;
6863
6864 -- Start of processing for Check_Subscripts
6865
6866 begin
6867 for J in 1 .. Number_Dimensions (Typ) loop
6868 Evolve_And_Then (Cond,
6869 Make_Op_Eq (Loc,
6870 Left_Opnd =>
6871 Build_Attribute_Reference
6872 (Duplicate_Subexpr_No_Checks (Obj),
6873 Name_First, J),
6874 Right_Opnd =>
6875 Build_Attribute_Reference
6876 (New_Occurrence_Of (Typ, Loc), Name_First, J)));
6877
6878 Evolve_And_Then (Cond,
6879 Make_Op_Eq (Loc,
6880 Left_Opnd =>
6881 Build_Attribute_Reference
6882 (Duplicate_Subexpr_No_Checks (Obj),
6883 Name_Last, J),
6884 Right_Opnd =>
6885 Build_Attribute_Reference
6886 (New_Occurrence_Of (Typ, Loc), Name_Last, J)));
6887 end loop;
6888 end Check_Subscripts;
6889
6890 -- These are the cases where constraint checks may be required,
6891 -- e.g. records with possible discriminants
6892
6893 else
6894 -- Expand the test into a series of discriminant comparisons.
6895 -- The expression that is built is the negation of the one that
6896 -- is used for checking discriminant constraints.
6897
6898 Obj := Relocate_Node (Left_Opnd (N));
6899
6900 if Has_Discriminants (Typ) then
6901 Cond := Make_Op_Not (Loc,
6902 Right_Opnd => Build_Discriminant_Checks (Obj, Typ));
6903 else
6904 Cond := New_Occurrence_Of (Standard_True, Loc);
6905 end if;
6906 end if;
6907
6908 if Is_Acc then
6909 if Check_Null_Exclusion then
6910 Cond := Make_And_Then (Loc,
6911 Left_Opnd =>
6912 Make_Op_Ne (Loc,
6913 Left_Opnd => Obj,
6914 Right_Opnd => Make_Null (Loc)),
6915 Right_Opnd => Cond);
6916 else
6917 Cond := Make_Or_Else (Loc,
6918 Left_Opnd =>
6919 Make_Op_Eq (Loc,
6920 Left_Opnd => Obj,
6921 Right_Opnd => Make_Null (Loc)),
6922 Right_Opnd => Cond);
6923 end if;
6924 end if;
6925
6926 Rewrite (N, Cond);
6927 Analyze_And_Resolve (N, Restyp);
6928
6929 -- Ada 2012 (AI05-0149): Handle membership tests applied to an
6930 -- expression of an anonymous access type. This can involve an
6931 -- accessibility test and a tagged type membership test in the
6932 -- case of tagged designated types.
6933
6934 if Ada_Version >= Ada_2012
6935 and then Is_Acc
6936 and then Ekind (Ltyp) = E_Anonymous_Access_Type
6937 then
6938 declare
6939 Expr_Entity : Entity_Id := Empty;
6940 New_N : Node_Id;
6941 Param_Level : Node_Id;
6942 Type_Level : Node_Id;
6943
6944 begin
6945 if Is_Entity_Name (Lop) then
6946 Expr_Entity := Param_Entity (Lop);
6947
6948 if No (Expr_Entity) then
6949 Expr_Entity := Entity (Lop);
6950 end if;
6951 end if;
6952
6953 -- When restriction No_Dynamic_Accessibility_Checks is in
6954 -- effect, expand the membership test to a static value
6955 -- since we cannot rely on dynamic levels.
6956
6957 if No_Dynamic_Accessibility_Checks_Enabled (Lop) then
6958 if Static_Accessibility_Level
6959 (Lop, Object_Decl_Level)
6960 > Type_Access_Level (Rtyp)
6961 then
6962 Rewrite (N, New_Occurrence_Of (Standard_False, Loc));
6963 else
6964 Rewrite (N, New_Occurrence_Of (Standard_True, Loc));
6965 end if;
6966 Analyze_And_Resolve (N, Restyp);
6967
6968 -- If a conversion of the anonymous access value to the
6969 -- tested type would be illegal, then the result is False.
6970
6971 elsif not Valid_Conversion
6972 (Lop, Rtyp, Lop, Report_Errs => False)
6973 then
6974 Rewrite (N, New_Occurrence_Of (Standard_False, Loc));
6975 Analyze_And_Resolve (N, Restyp);
6976
6977 -- Apply an accessibility check if the access object has an
6978 -- associated access level and when the level of the type is
6979 -- less deep than the level of the access parameter. This
6980 -- can only occur for access parameters and stand-alone
6981 -- objects of an anonymous access type.
6982
6983 else
6984 Param_Level := Accessibility_Level
6985 (Expr_Entity, Dynamic_Level);
6986
6987 Type_Level :=
6988 Make_Integer_Literal (Loc, Type_Access_Level (Rtyp));
6989
6990 -- Return True only if the accessibility level of the
6991 -- expression entity is not deeper than the level of
6992 -- the tested access type.
6993
6994 Rewrite (N,
6995 Make_And_Then (Loc,
6996 Left_Opnd => Relocate_Node (N),
6997 Right_Opnd => Make_Op_Le (Loc,
6998 Left_Opnd => Param_Level,
6999 Right_Opnd => Type_Level)));
7000
7001 Analyze_And_Resolve (N);
7002
7003 -- If the designated type is tagged, do tagged membership
7004 -- operation.
7005
7006 if Is_Tagged_Type (Typ) then
7007
7008 -- No expansion will be performed for VM targets, as
7009 -- the VM back ends will handle the membership tests
7010 -- directly.
7011
7012 if Tagged_Type_Expansion then
7013
7014 -- Note that we have to pass Original_Node, because
7015 -- the membership test might already have been
7016 -- rewritten by earlier parts of membership test.
7017
7018 Tagged_Membership
7019 (Original_Node (N), SCIL_Node, New_N);
7020
7021 -- Update decoration of relocated node referenced
7022 -- by the SCIL node.
7023
7024 if Generate_SCIL and then Present (SCIL_Node) then
7025 Set_SCIL_Node (New_N, SCIL_Node);
7026 end if;
7027
7028 Rewrite (N,
7029 Make_And_Then (Loc,
7030 Left_Opnd => Relocate_Node (N),
7031 Right_Opnd => New_N));
7032
7033 Analyze_And_Resolve (N, Restyp);
7034 end if;
7035 end if;
7036 end if;
7037 end;
7038 end if;
7039 end;
7040 end if;
7041
7042 -- At this point, we have done the processing required for the basic
7043 -- membership test, but not yet dealt with the predicate.
7044
7045 <<Leave>>
7046
7047 -- If a predicate is present, then we do the predicate test, but we
7048 -- most certainly want to omit this if we are within the predicate
7049 -- function itself, since otherwise we have an infinite recursion.
7050 -- The check should also not be emitted when testing against a range
7051 -- (the check is only done when the right operand is a subtype; see
7052 -- RM12-4.5.2 (28.1/3-30/3)).
7053
7054 Predicate_Check : declare
7055 function In_Range_Check return Boolean;
7056 -- Within an expanded range check that may raise Constraint_Error do
7057 -- not generate a predicate check as well. It is redundant because
7058 -- the context will add an explicit predicate check, and it will
7059 -- raise the wrong exception if it fails.
7060
7061 --------------------
7062 -- In_Range_Check --
7063 --------------------
7064
7065 function In_Range_Check return Boolean is
7066 P : Node_Id;
7067 begin
7068 P := Parent (N);
7069 while Present (P) loop
7070 if Nkind (P) = N_Raise_Constraint_Error then
7071 return True;
7072
7073 elsif Nkind (P) in N_Statement_Other_Than_Procedure_Call
7074 or else Nkind (P) = N_Procedure_Call_Statement
7075 or else Nkind (P) in N_Declaration
7076 then
7077 return False;
7078 end if;
7079
7080 P := Parent (P);
7081 end loop;
7082
7083 return False;
7084 end In_Range_Check;
7085
7086 -- Local variables
7087
7088 PFunc : constant Entity_Id := Predicate_Function (Rtyp);
7089 R_Op : Node_Id;
7090
7091 -- Start of processing for Predicate_Check
7092
7093 begin
7094 if Present (PFunc)
7095 and then Current_Scope /= PFunc
7096 and then Nkind (Rop) /= N_Range
7097 then
7098 -- First apply the transformation that was skipped above
7099
7100 if Is_Scalar_Type (Rtyp) then
7101 Rewrite (Rop,
7102 Make_Range (Loc,
7103 Low_Bound =>
7104 Make_Attribute_Reference (Loc,
7105 Attribute_Name => Name_First,
7106 Prefix => New_Occurrence_Of (Rtyp, Loc)),
7107
7108 High_Bound =>
7109 Make_Attribute_Reference (Loc,
7110 Attribute_Name => Name_Last,
7111 Prefix => New_Occurrence_Of (Rtyp, Loc))));
7112
7113 Analyze_And_Resolve (N, Restyp);
7114 end if;
7115
7116 if not In_Range_Check then
7117 -- Indicate via Static_Mem parameter that this predicate
7118 -- evaluation is for a membership test.
7119 R_Op := Make_Predicate_Call (Rtyp, Lop, Static_Mem => True);
7120 else
7121 R_Op := New_Occurrence_Of (Standard_True, Loc);
7122 end if;
7123
7124 Rewrite (N,
7125 Make_And_Then (Loc,
7126 Left_Opnd => Relocate_Node (N),
7127 Right_Opnd => R_Op));
7128
7129 -- Analyze new expression, mark left operand as analyzed to
7130 -- avoid infinite recursion adding predicate calls. Similarly,
7131 -- suppress further range checks on the call.
7132
7133 Set_Analyzed (Left_Opnd (N));
7134 Analyze_And_Resolve (N, Standard_Boolean, Suppress => All_Checks);
7135 end if;
7136 end Predicate_Check;
7137 end Expand_N_In;
7138
7139 --------------------------------
7140 -- Expand_N_Indexed_Component --
7141 --------------------------------
7142
7143 procedure Expand_N_Indexed_Component (N : Node_Id) is
7144
7145 Wild_Reads_May_Have_Bad_Side_Effects : Boolean
7146 renames Validity_Check_Subscripts;
7147 -- This Boolean needs to be True if reading from a bad address can
7148 -- have a bad side effect (e.g., a segmentation fault that is not
7149 -- transformed into a Storage_Error exception, or interactions with
7150 -- memory-mapped I/O) that needs to be prevented. This refers to the
7151 -- act of reading itself, not to any damage that might be caused later
7152 -- by making use of whatever value was read. We assume here that
7153 -- Validity_Check_Subscripts meets this requirement, but introduce
7154 -- this declaration in order to document this assumption.
7155
7156 function Is_Renamed_Variable_Name (N : Node_Id) return Boolean;
7157 -- Returns True if the given name occurs as part of the renaming
7158 -- of a variable. In this case, the indexing operation should be
7159 -- treated as a write, rather than a read, with respect to validity
7160 -- checking. This is because the renamed variable can later be
7161 -- written to.
7162
7163 function Type_Requires_Subscript_Validity_Checks_For_Reads
7164 (Typ : Entity_Id) return Boolean;
7165 -- If Wild_Reads_May_Have_Bad_Side_Effects is False and we are indexing
7166 -- into an array of characters in order to read an element, it is ok
7167 -- if an invalid index value goes undetected. But if it is an array of
7168 -- pointers or an array of tasks, the consequences of such a read are
7169 -- potentially more severe and so we want to detect an invalid index
7170 -- value. This function captures that distinction; this is intended to
7171 -- be consistent with the "but does not by itself lead to erroneous
7172 -- ... execution" rule of RM 13.9.1(11).
7173
7174 ------------------------------
7175 -- Is_Renamed_Variable_Name --
7176 ------------------------------
7177
7178 function Is_Renamed_Variable_Name (N : Node_Id) return Boolean is
7179 Rover : Node_Id := N;
7180 begin
7181 if Is_Variable (N) then
7182 loop
7183 declare
7184 Rover_Parent : constant Node_Id := Parent (Rover);
7185 begin
7186 case Nkind (Rover_Parent) is
7187 when N_Object_Renaming_Declaration =>
7188 return Rover = Name (Rover_Parent);
7189
7190 when N_Indexed_Component
7191 | N_Slice
7192 | N_Selected_Component
7193 =>
7194 exit when Rover /= Prefix (Rover_Parent);
7195 Rover := Rover_Parent;
7196
7197 -- No need to check for qualified expressions or type
7198 -- conversions here, mostly because of the Is_Variable
7199 -- test. It is possible to have a view conversion for
7200 -- which Is_Variable yields True and which occurs as
7201 -- part of an object renaming, but only if the type is
7202 -- tagged; in that case this function will not be called.
7203
7204 when others =>
7205 exit;
7206 end case;
7207 end;
7208 end loop;
7209 end if;
7210 return False;
7211 end Is_Renamed_Variable_Name;
7212
7213 -------------------------------------------------------
7214 -- Type_Requires_Subscript_Validity_Checks_For_Reads --
7215 -------------------------------------------------------
7216
7217 function Type_Requires_Subscript_Validity_Checks_For_Reads
7218 (Typ : Entity_Id) return Boolean
7219 is
7220 -- a shorter name for recursive calls
7221 function Needs_Check (Typ : Entity_Id) return Boolean renames
7222 Type_Requires_Subscript_Validity_Checks_For_Reads;
7223 begin
7224 if Is_Access_Type (Typ)
7225 or else Is_Tagged_Type (Typ)
7226 or else Is_Concurrent_Type (Typ)
7227 or else (Is_Array_Type (Typ)
7228 and then Needs_Check (Component_Type (Typ)))
7229 or else (Is_Scalar_Type (Typ)
7230 and then Has_Aspect (Typ, Aspect_Default_Value))
7231 then
7232 return True;
7233 end if;
7234
7235 if Is_Record_Type (Typ) then
7236 declare
7237 Comp : Entity_Id := First_Component_Or_Discriminant (Typ);
7238 begin
7239 while Present (Comp) loop
7240 if Needs_Check (Etype (Comp)) then
7241 return True;
7242 end if;
7243
7244 Next_Component_Or_Discriminant (Comp);
7245 end loop;
7246 end;
7247 end if;
7248
7249 return False;
7250 end Type_Requires_Subscript_Validity_Checks_For_Reads;
7251
7252 -- Local constants
7253
7254 Loc : constant Source_Ptr := Sloc (N);
7255 Typ : constant Entity_Id := Etype (N);
7256 P : constant Node_Id := Prefix (N);
7257 T : constant Entity_Id := Etype (P);
7258
7259 -- Start of processing for Expand_N_Indexed_Component
7260
7261 begin
7262 -- A special optimization, if we have an indexed component that is
7263 -- selecting from a slice, then we can eliminate the slice, since, for
7264 -- example, x (i .. j)(k) is identical to x(k). The only difference is
7265 -- the range check required by the slice. The range check for the slice
7266 -- itself has already been generated. The range check for the
7267 -- subscripting operation is ensured by converting the subject to
7268 -- the subtype of the slice.
7269
7270 -- This optimization not only generates better code, avoiding slice
7271 -- messing especially in the packed case, but more importantly bypasses
7272 -- some problems in handling this peculiar case, for example, the issue
7273 -- of dealing specially with object renamings.
7274
7275 if Nkind (P) = N_Slice
7276
7277 -- This optimization is disabled for CodePeer because it can transform
7278 -- an index-check constraint_error into a range-check constraint_error
7279 -- and CodePeer cares about that distinction.
7280
7281 and then not CodePeer_Mode
7282 then
7283 Rewrite (N,
7284 Make_Indexed_Component (Loc,
7285 Prefix => Prefix (P),
7286 Expressions => New_List (
7287 Convert_To
7288 (Etype (First_Index (Etype (P))),
7289 First (Expressions (N))))));
7290 Analyze_And_Resolve (N, Typ);
7291 return;
7292 end if;
7293
7294 -- Ada 2005 (AI-318-02): If the prefix is a call to a build-in-place
7295 -- function, then additional actuals must be passed.
7296
7297 if Is_Build_In_Place_Function_Call (P) then
7298 Make_Build_In_Place_Call_In_Anonymous_Context (P);
7299
7300 -- Ada 2005 (AI-318-02): Specialization of the previous case for prefix
7301 -- containing build-in-place function calls whose returned object covers
7302 -- interface types.
7303
7304 elsif Present (Unqual_BIP_Iface_Function_Call (P)) then
7305 Make_Build_In_Place_Iface_Call_In_Anonymous_Context (P);
7306 end if;
7307
7308 -- Generate index and validity checks
7309
7310 declare
7311 Dims_Checked : Dimension_Set (Dimensions =>
7312 (if Is_Array_Type (T)
7313 then Number_Dimensions (T)
7314 else 1));
7315 -- Dims_Checked is used to avoid generating two checks (one in
7316 -- Generate_Index_Checks, one in Apply_Subscript_Validity_Checks)
7317 -- for the same index value in cases where the index check eliminates
7318 -- the need for the validity check. The Is_Array_Type test avoids
7319 -- cascading errors.
7320
7321 begin
7322 Generate_Index_Checks (N, Checks_Generated => Dims_Checked);
7323
7324 if Validity_Checks_On
7325 and then (Validity_Check_Subscripts
7326 or else Wild_Reads_May_Have_Bad_Side_Effects
7327 or else Type_Requires_Subscript_Validity_Checks_For_Reads
7328 (Typ)
7329 or else Is_Renamed_Variable_Name (N))
7330 then
7331 if Validity_Check_Subscripts then
7332 -- If we index into an array with an uninitialized variable
7333 -- and we generate an index check that passes at run time,
7334 -- passing that check does not ensure that the variable is
7335 -- valid (although it does in the common case where the
7336 -- object's subtype matches the index subtype).
7337 -- Consider an uninitialized variable with subtype 1 .. 10
7338 -- used to index into an array with bounds 1 .. 20 when the
7339 -- value of the uninitialized variable happens to be 15.
7340 -- The index check will succeed but the variable is invalid.
7341 -- If Validity_Check_Subscripts is True then we need to
7342 -- ensure validity, so we adjust Dims_Checked accordingly.
7343 Dims_Checked.Elements := (others => False);
7344
7345 elsif Is_Array_Type (T) then
7346 -- We are only adding extra validity checks here to
7347 -- deal with uninitialized variables (but this includes
7348 -- assigning one uninitialized variable to another). Other
7349 -- ways of producing invalid objects imply erroneousness, so
7350 -- the compiler can do whatever it wants for those cases.
7351 -- If an index type has the Default_Value aspect specified,
7352 -- then we don't have to worry about the possibility of an
7353 -- uninitialized variable, so no need for these extra
7354 -- validity checks.
7355
7356 declare
7357 Idx : Node_Id := First_Index (T);
7358 begin
7359 for No_Check_Needed of Dims_Checked.Elements loop
7360 No_Check_Needed := No_Check_Needed
7361 or else Has_Aspect (Etype (Idx), Aspect_Default_Value);
7362 Next_Index (Idx);
7363 end loop;
7364 end;
7365 end if;
7366
7367 Apply_Subscript_Validity_Checks
7368 (N, No_Check_Needed => Dims_Checked);
7369 end if;
7370 end;
7371
7372 -- If selecting from an array with atomic components, and atomic sync
7373 -- is not suppressed for this array type, set atomic sync flag.
7374
7375 if (Has_Atomic_Components (T)
7376 and then not Atomic_Synchronization_Disabled (T))
7377 or else (Is_Atomic (Typ)
7378 and then not Atomic_Synchronization_Disabled (Typ))
7379 or else (Is_Entity_Name (P)
7380 and then Has_Atomic_Components (Entity (P))
7381 and then not Atomic_Synchronization_Disabled (Entity (P)))
7382 then
7383 Activate_Atomic_Synchronization (N);
7384 end if;
7385
7386 -- All done if the prefix is not a packed array implemented specially
7387
7388 if not (Is_Packed (Etype (Prefix (N)))
7389 and then Present (Packed_Array_Impl_Type (Etype (Prefix (N)))))
7390 then
7391 return;
7392 end if;
7393
7394 -- For packed arrays that are not bit-packed (i.e. the case of an array
7395 -- with one or more index types with a non-contiguous enumeration type),
7396 -- we can always use the normal packed element get circuit.
7397
7398 if not Is_Bit_Packed_Array (Etype (Prefix (N))) then
7399 Expand_Packed_Element_Reference (N);
7400 return;
7401 end if;
7402
7403 -- For a reference to a component of a bit packed array, we convert it
7404 -- to a reference to the corresponding Packed_Array_Impl_Type. We only
7405 -- want to do this for simple references, and not for:
7406
7407 -- Left side of assignment, or prefix of left side of assignment, or
7408 -- prefix of the prefix, to handle packed arrays of packed arrays,
7409 -- This case is handled in Exp_Ch5.Expand_N_Assignment_Statement
7410
7411 -- Renaming objects in renaming associations
7412 -- This case is handled when a use of the renamed variable occurs
7413
7414 -- Actual parameters for a subprogram call
7415 -- This case is handled in Exp_Ch6.Expand_Actuals
7416
7417 -- The second expression in a 'Read attribute reference
7418
7419 -- The prefix of an address or bit or size attribute reference
7420
7421 -- The following circuit detects these exceptions. Note that we need to
7422 -- deal with implicit dereferences when climbing up the parent chain,
7423 -- with the additional difficulty that the type of parents may have yet
7424 -- to be resolved since prefixes are usually resolved first.
7425
7426 declare
7427 Child : Node_Id := N;
7428 Parnt : Node_Id := Parent (N);
7429
7430 begin
7431 loop
7432 if Nkind (Parnt) = N_Unchecked_Expression then
7433 null;
7434
7435 elsif Nkind (Parnt) = N_Object_Renaming_Declaration then
7436 return;
7437
7438 elsif Nkind (Parnt) in N_Subprogram_Call
7439 or else (Nkind (Parnt) = N_Parameter_Association
7440 and then Nkind (Parent (Parnt)) in N_Subprogram_Call)
7441 then
7442 return;
7443
7444 elsif Nkind (Parnt) = N_Attribute_Reference
7445 and then Attribute_Name (Parnt) in Name_Address
7446 | Name_Bit
7447 | Name_Size
7448 and then Prefix (Parnt) = Child
7449 then
7450 return;
7451
7452 elsif Nkind (Parnt) = N_Assignment_Statement
7453 and then Name (Parnt) = Child
7454 then
7455 return;
7456
7457 -- If the expression is an index of an indexed component, it must
7458 -- be expanded regardless of context.
7459
7460 elsif Nkind (Parnt) = N_Indexed_Component
7461 and then Child /= Prefix (Parnt)
7462 then
7463 Expand_Packed_Element_Reference (N);
7464 return;
7465
7466 elsif Nkind (Parent (Parnt)) = N_Assignment_Statement
7467 and then Name (Parent (Parnt)) = Parnt
7468 then
7469 return;
7470
7471 elsif Nkind (Parnt) = N_Attribute_Reference
7472 and then Attribute_Name (Parnt) = Name_Read
7473 and then Next (First (Expressions (Parnt))) = Child
7474 then
7475 return;
7476
7477 elsif Nkind (Parnt) = N_Indexed_Component
7478 and then Prefix (Parnt) = Child
7479 then
7480 null;
7481
7482 elsif Nkind (Parnt) = N_Selected_Component
7483 and then Prefix (Parnt) = Child
7484 and then not (Present (Etype (Selector_Name (Parnt)))
7485 and then
7486 Is_Access_Type (Etype (Selector_Name (Parnt))))
7487 then
7488 null;
7489
7490 -- If the parent is a dereference, either implicit or explicit,
7491 -- then the packed reference needs to be expanded.
7492
7493 else
7494 Expand_Packed_Element_Reference (N);
7495 return;
7496 end if;
7497
7498 -- Keep looking up tree for unchecked expression, or if we are the
7499 -- prefix of a possible assignment left side.
7500
7501 Child := Parnt;
7502 Parnt := Parent (Child);
7503 end loop;
7504 end;
7505 end Expand_N_Indexed_Component;
7506
7507 ---------------------
7508 -- Expand_N_Not_In --
7509 ---------------------
7510
7511 -- Replace a not in b by not (a in b) so that the expansions for (a in b)
7512 -- can be done. This avoids needing to duplicate this expansion code.
7513
7514 procedure Expand_N_Not_In (N : Node_Id) is
7515 Loc : constant Source_Ptr := Sloc (N);
7516 Typ : constant Entity_Id := Etype (N);
7517 Cfs : constant Boolean := Comes_From_Source (N);
7518
7519 begin
7520 Rewrite (N,
7521 Make_Op_Not (Loc,
7522 Right_Opnd =>
7523 Make_In (Loc,
7524 Left_Opnd => Left_Opnd (N),
7525 Right_Opnd => Right_Opnd (N))));
7526
7527 -- If this is a set membership, preserve list of alternatives
7528
7529 Set_Alternatives (Right_Opnd (N), Alternatives (Original_Node (N)));
7530
7531 -- We want this to appear as coming from source if original does (see
7532 -- transformations in Expand_N_In).
7533
7534 Set_Comes_From_Source (N, Cfs);
7535 Set_Comes_From_Source (Right_Opnd (N), Cfs);
7536
7537 -- Now analyze transformed node
7538
7539 Analyze_And_Resolve (N, Typ);
7540 end Expand_N_Not_In;
7541
7542 -------------------
7543 -- Expand_N_Null --
7544 -------------------
7545
7546 -- The only replacement required is for the case of a null of a type that
7547 -- is an access to protected subprogram, or a subtype thereof. We represent
7548 -- such access values as a record, and so we must replace the occurrence of
7549 -- null by the equivalent record (with a null address and a null pointer in
7550 -- it), so that the back end creates the proper value.
7551
7552 procedure Expand_N_Null (N : Node_Id) is
7553 Loc : constant Source_Ptr := Sloc (N);
7554 Typ : constant Entity_Id := Base_Type (Etype (N));
7555 Agg : Node_Id;
7556
7557 begin
7558 if Is_Access_Protected_Subprogram_Type (Typ) then
7559 Agg :=
7560 Make_Aggregate (Loc,
7561 Expressions => New_List (
7562 New_Occurrence_Of (RTE (RE_Null_Address), Loc),
7563 Make_Null (Loc)));
7564
7565 Rewrite (N, Agg);
7566 Analyze_And_Resolve (N, Equivalent_Type (Typ));
7567
7568 -- For subsequent semantic analysis, the node must retain its type.
7569 -- Gigi in any case replaces this type by the corresponding record
7570 -- type before processing the node.
7571
7572 Set_Etype (N, Typ);
7573 end if;
7574
7575 exception
7576 when RE_Not_Available =>
7577 return;
7578 end Expand_N_Null;
7579
7580 ---------------------
7581 -- Expand_N_Op_Abs --
7582 ---------------------
7583
7584 procedure Expand_N_Op_Abs (N : Node_Id) is
7585 Loc : constant Source_Ptr := Sloc (N);
7586 Expr : constant Node_Id := Right_Opnd (N);
7587 Typ : constant Entity_Id := Etype (N);
7588
7589 begin
7590 Unary_Op_Validity_Checks (N);
7591
7592 -- Check for MINIMIZED/ELIMINATED overflow mode
7593
7594 if Minimized_Eliminated_Overflow_Check (N) then
7595 Apply_Arithmetic_Overflow_Check (N);
7596 return;
7597 end if;
7598
7599 -- Try to narrow the operation
7600
7601 if Typ = Universal_Integer then
7602 Narrow_Large_Operation (N);
7603
7604 if Nkind (N) /= N_Op_Abs then
7605 return;
7606 end if;
7607 end if;
7608
7609 -- Deal with software overflow checking
7610
7611 if Is_Signed_Integer_Type (Typ)
7612 and then Do_Overflow_Check (N)
7613 then
7614 -- The only case to worry about is when the argument is equal to the
7615 -- largest negative number, so what we do is to insert the check:
7616
7617 -- [constraint_error when Expr = typ'Base'First]
7618
7619 -- with the usual Duplicate_Subexpr use coding for expr
7620
7621 Insert_Action (N,
7622 Make_Raise_Constraint_Error (Loc,
7623 Condition =>
7624 Make_Op_Eq (Loc,
7625 Left_Opnd => Duplicate_Subexpr (Expr),
7626 Right_Opnd =>
7627 Make_Attribute_Reference (Loc,
7628 Prefix =>
7629 New_Occurrence_Of (Base_Type (Etype (Expr)), Loc),
7630 Attribute_Name => Name_First)),
7631 Reason => CE_Overflow_Check_Failed));
7632
7633 Set_Do_Overflow_Check (N, False);
7634 end if;
7635 end Expand_N_Op_Abs;
7636
7637 ---------------------
7638 -- Expand_N_Op_Add --
7639 ---------------------
7640
7641 procedure Expand_N_Op_Add (N : Node_Id) is
7642 Typ : constant Entity_Id := Etype (N);
7643
7644 begin
7645 Binary_Op_Validity_Checks (N);
7646
7647 -- Check for MINIMIZED/ELIMINATED overflow mode
7648
7649 if Minimized_Eliminated_Overflow_Check (N) then
7650 Apply_Arithmetic_Overflow_Check (N);
7651 return;
7652 end if;
7653
7654 -- N + 0 = 0 + N = N for integer types
7655
7656 if Is_Integer_Type (Typ) then
7657 if Compile_Time_Known_Value (Right_Opnd (N))
7658 and then Expr_Value (Right_Opnd (N)) = Uint_0
7659 then
7660 Rewrite (N, Left_Opnd (N));
7661 return;
7662
7663 elsif Compile_Time_Known_Value (Left_Opnd (N))
7664 and then Expr_Value (Left_Opnd (N)) = Uint_0
7665 then
7666 Rewrite (N, Right_Opnd (N));
7667 return;
7668 end if;
7669 end if;
7670
7671 -- Try to narrow the operation
7672
7673 if Typ = Universal_Integer then
7674 Narrow_Large_Operation (N);
7675
7676 if Nkind (N) /= N_Op_Add then
7677 return;
7678 end if;
7679 end if;
7680
7681 -- Arithmetic overflow checks for signed integer/fixed point types
7682
7683 if Is_Signed_Integer_Type (Typ) or else Is_Fixed_Point_Type (Typ) then
7684 Apply_Arithmetic_Overflow_Check (N);
7685 return;
7686 end if;
7687
7688 -- Overflow checks for floating-point if -gnateF mode active
7689
7690 Check_Float_Op_Overflow (N);
7691
7692 Expand_Nonbinary_Modular_Op (N);
7693 end Expand_N_Op_Add;
7694
7695 ---------------------
7696 -- Expand_N_Op_And --
7697 ---------------------
7698
7699 procedure Expand_N_Op_And (N : Node_Id) is
7700 Typ : constant Entity_Id := Etype (N);
7701
7702 begin
7703 Binary_Op_Validity_Checks (N);
7704
7705 if Is_Array_Type (Etype (N)) then
7706 Expand_Boolean_Operator (N);
7707
7708 elsif Is_Boolean_Type (Etype (N)) then
7709 Adjust_Condition (Left_Opnd (N));
7710 Adjust_Condition (Right_Opnd (N));
7711 Set_Etype (N, Standard_Boolean);
7712 Adjust_Result_Type (N, Typ);
7713
7714 elsif Is_Intrinsic_Subprogram (Entity (N)) then
7715 Expand_Intrinsic_Call (N, Entity (N));
7716 end if;
7717
7718 Expand_Nonbinary_Modular_Op (N);
7719 end Expand_N_Op_And;
7720
7721 ------------------------
7722 -- Expand_N_Op_Concat --
7723 ------------------------
7724
7725 procedure Expand_N_Op_Concat (N : Node_Id) is
7726 Opnds : List_Id;
7727 -- List of operands to be concatenated
7728
7729 Cnode : Node_Id;
7730 -- Node which is to be replaced by the result of concatenating the nodes
7731 -- in the list Opnds.
7732
7733 begin
7734 -- Ensure validity of both operands
7735
7736 Binary_Op_Validity_Checks (N);
7737
7738 -- If we are the left operand of a concatenation higher up the tree,
7739 -- then do nothing for now, since we want to deal with a series of
7740 -- concatenations as a unit.
7741
7742 if Nkind (Parent (N)) = N_Op_Concat
7743 and then N = Left_Opnd (Parent (N))
7744 then
7745 return;
7746 end if;
7747
7748 -- We get here with a concatenation whose left operand may be a
7749 -- concatenation itself with a consistent type. We need to process
7750 -- these concatenation operands from left to right, which means
7751 -- from the deepest node in the tree to the highest node.
7752
7753 Cnode := N;
7754 while Nkind (Left_Opnd (Cnode)) = N_Op_Concat loop
7755 Cnode := Left_Opnd (Cnode);
7756 end loop;
7757
7758 -- Now Cnode is the deepest concatenation, and its parents are the
7759 -- concatenation nodes above, so now we process bottom up, doing the
7760 -- operands.
7761
7762 -- The outer loop runs more than once if more than one concatenation
7763 -- type is involved.
7764
7765 Outer : loop
7766 Opnds := New_List (Left_Opnd (Cnode), Right_Opnd (Cnode));
7767 Set_Parent (Opnds, N);
7768
7769 -- The inner loop gathers concatenation operands
7770
7771 Inner : while Cnode /= N
7772 and then Base_Type (Etype (Cnode)) =
7773 Base_Type (Etype (Parent (Cnode)))
7774 loop
7775 Cnode := Parent (Cnode);
7776 Append (Right_Opnd (Cnode), Opnds);
7777 end loop Inner;
7778
7779 -- Note: The following code is a temporary workaround for N731-034
7780 -- and N829-028 and will be kept until the general issue of internal
7781 -- symbol serialization is addressed. The workaround is kept under a
7782 -- debug switch to avoid permiating into the general case.
7783
7784 -- Wrap the node to concatenate into an expression actions node to
7785 -- keep it nicely packaged. This is useful in the case of an assert
7786 -- pragma with a concatenation where we want to be able to delete
7787 -- the concatenation and all its expansion stuff.
7788
7789 if Debug_Flag_Dot_H then
7790 declare
7791 Cnod : constant Node_Id := New_Copy_Tree (Cnode);
7792 Typ : constant Entity_Id := Base_Type (Etype (Cnode));
7793
7794 begin
7795 -- Note: use Rewrite rather than Replace here, so that for
7796 -- example Why_Not_Static can find the original concatenation
7797 -- node OK!
7798
7799 Rewrite (Cnode,
7800 Make_Expression_With_Actions (Sloc (Cnode),
7801 Actions => New_List (Make_Null_Statement (Sloc (Cnode))),
7802 Expression => Cnod));
7803
7804 Expand_Concatenate (Cnod, Opnds);
7805 Analyze_And_Resolve (Cnode, Typ);
7806 end;
7807
7808 -- Default case
7809
7810 else
7811 Expand_Concatenate (Cnode, Opnds);
7812 end if;
7813
7814 exit Outer when Cnode = N;
7815 Cnode := Parent (Cnode);
7816 end loop Outer;
7817 end Expand_N_Op_Concat;
7818
7819 ------------------------
7820 -- Expand_N_Op_Divide --
7821 ------------------------
7822
7823 procedure Expand_N_Op_Divide (N : Node_Id) is
7824 Loc : constant Source_Ptr := Sloc (N);
7825 Lopnd : constant Node_Id := Left_Opnd (N);
7826 Ropnd : constant Node_Id := Right_Opnd (N);
7827 Ltyp : constant Entity_Id := Etype (Lopnd);
7828 Rtyp : constant Entity_Id := Etype (Ropnd);
7829 Typ : Entity_Id := Etype (N);
7830 Rknow : constant Boolean := Is_Integer_Type (Typ)
7831 and then
7832 Compile_Time_Known_Value (Ropnd);
7833 Rval : Uint;
7834
7835 begin
7836 Binary_Op_Validity_Checks (N);
7837
7838 -- Check for MINIMIZED/ELIMINATED overflow mode
7839
7840 if Minimized_Eliminated_Overflow_Check (N) then
7841 Apply_Arithmetic_Overflow_Check (N);
7842 return;
7843 end if;
7844
7845 -- Otherwise proceed with expansion of division
7846
7847 if Rknow then
7848 Rval := Expr_Value (Ropnd);
7849 end if;
7850
7851 -- N / 1 = N for integer types
7852
7853 if Rknow and then Rval = Uint_1 then
7854 Rewrite (N, Lopnd);
7855 return;
7856 end if;
7857
7858 -- Try to narrow the operation
7859
7860 if Typ = Universal_Integer then
7861 Narrow_Large_Operation (N);
7862
7863 if Nkind (N) /= N_Op_Divide then
7864 return;
7865 end if;
7866 end if;
7867
7868 -- Convert x / 2 ** y to Shift_Right (x, y). Note that the fact that
7869 -- Is_Power_Of_2_For_Shift is set means that we know that our left
7870 -- operand is an unsigned integer, as required for this to work.
7871
7872 if Nkind (Ropnd) = N_Op_Expon
7873 and then Is_Power_Of_2_For_Shift (Ropnd)
7874
7875 -- We cannot do this transformation in configurable run time mode if we
7876 -- have 64-bit integers and long shifts are not available.
7877
7878 and then (Esize (Ltyp) <= 32 or else Support_Long_Shifts_On_Target)
7879 then
7880 Rewrite (N,
7881 Make_Op_Shift_Right (Loc,
7882 Left_Opnd => Lopnd,
7883 Right_Opnd =>
7884 Convert_To (Standard_Natural, Right_Opnd (Ropnd))));
7885 Analyze_And_Resolve (N, Typ);
7886 return;
7887 end if;
7888
7889 -- Do required fixup of universal fixed operation
7890
7891 if Typ = Universal_Fixed then
7892 Fixup_Universal_Fixed_Operation (N);
7893 Typ := Etype (N);
7894 end if;
7895
7896 -- Divisions with fixed-point results
7897
7898 if Is_Fixed_Point_Type (Typ) then
7899
7900 if Is_Integer_Type (Rtyp) then
7901 Expand_Divide_Fixed_By_Integer_Giving_Fixed (N);
7902 else
7903 Expand_Divide_Fixed_By_Fixed_Giving_Fixed (N);
7904 end if;
7905
7906 -- Deal with divide-by-zero check if back end cannot handle them
7907 -- and the flag is set indicating that we need such a check. Note
7908 -- that we don't need to bother here with the case of mixed-mode
7909 -- (Right operand an integer type), since these will be rewritten
7910 -- with conversions to a divide with a fixed-point right operand.
7911
7912 if Nkind (N) = N_Op_Divide
7913 and then Do_Division_Check (N)
7914 and then not Backend_Divide_Checks_On_Target
7915 and then not Is_Integer_Type (Rtyp)
7916 then
7917 Set_Do_Division_Check (N, False);
7918 Insert_Action (N,
7919 Make_Raise_Constraint_Error (Loc,
7920 Condition =>
7921 Make_Op_Eq (Loc,
7922 Left_Opnd => Duplicate_Subexpr_Move_Checks (Ropnd),
7923 Right_Opnd => Make_Real_Literal (Loc, Ureal_0)),
7924 Reason => CE_Divide_By_Zero));
7925 end if;
7926
7927 -- Other cases of division of fixed-point operands
7928
7929 elsif Is_Fixed_Point_Type (Ltyp) or else Is_Fixed_Point_Type (Rtyp) then
7930 if Is_Integer_Type (Typ) then
7931 Expand_Divide_Fixed_By_Fixed_Giving_Integer (N);
7932 else
7933 pragma Assert (Is_Floating_Point_Type (Typ));
7934 Expand_Divide_Fixed_By_Fixed_Giving_Float (N);
7935 end if;
7936
7937 -- Mixed-mode operations can appear in a non-static universal context,
7938 -- in which case the integer argument must be converted explicitly.
7939
7940 elsif Typ = Universal_Real and then Is_Integer_Type (Rtyp) then
7941 Rewrite (Ropnd,
7942 Convert_To (Universal_Real, Relocate_Node (Ropnd)));
7943
7944 Analyze_And_Resolve (Ropnd, Universal_Real);
7945
7946 elsif Typ = Universal_Real and then Is_Integer_Type (Ltyp) then
7947 Rewrite (Lopnd,
7948 Convert_To (Universal_Real, Relocate_Node (Lopnd)));
7949
7950 Analyze_And_Resolve (Lopnd, Universal_Real);
7951
7952 -- Non-fixed point cases, do integer zero divide and overflow checks
7953
7954 elsif Is_Integer_Type (Typ) then
7955 Apply_Divide_Checks (N);
7956 end if;
7957
7958 -- Overflow checks for floating-point if -gnateF mode active
7959
7960 Check_Float_Op_Overflow (N);
7961
7962 Expand_Nonbinary_Modular_Op (N);
7963 end Expand_N_Op_Divide;
7964
7965 --------------------
7966 -- Expand_N_Op_Eq --
7967 --------------------
7968
7969 procedure Expand_N_Op_Eq (N : Node_Id) is
7970 Loc : constant Source_Ptr := Sloc (N);
7971 Typ : constant Entity_Id := Etype (N);
7972 Lhs : constant Node_Id := Left_Opnd (N);
7973 Rhs : constant Node_Id := Right_Opnd (N);
7974 Bodies : constant List_Id := New_List;
7975 A_Typ : constant Entity_Id := Etype (Lhs);
7976
7977 procedure Build_Equality_Call (Eq : Entity_Id);
7978 -- If a constructed equality exists for the type or for its parent,
7979 -- build and analyze call, adding conversions if the operation is
7980 -- inherited.
7981
7982 function Find_Equality (Prims : Elist_Id) return Entity_Id;
7983 -- Find a primitive equality function within primitive operation list
7984 -- Prims.
7985
7986 function Has_Unconstrained_UU_Component (Typ : Entity_Id) return Boolean;
7987 -- Determines whether a type has a subcomponent of an unconstrained
7988 -- Unchecked_Union subtype. Typ is a record type.
7989
7990 -------------------------
7991 -- Build_Equality_Call --
7992 -------------------------
7993
7994 procedure Build_Equality_Call (Eq : Entity_Id) is
7995 Op_Typ : constant Entity_Id := Etype (First_Formal (Eq));
7996
7997 L_Exp, R_Exp : Node_Id;
7998
7999 begin
8000 -- Adjust operands if necessary to comparison type
8001
8002 if Base_Type (A_Typ) /= Base_Type (Op_Typ)
8003 and then not Is_Class_Wide_Type (A_Typ)
8004 then
8005 L_Exp := OK_Convert_To (Op_Typ, Lhs);
8006 R_Exp := OK_Convert_To (Op_Typ, Rhs);
8007
8008 else
8009 L_Exp := Relocate_Node (Lhs);
8010 R_Exp := Relocate_Node (Rhs);
8011 end if;
8012
8013 Rewrite (N,
8014 Make_Function_Call (Loc,
8015 Name => New_Occurrence_Of (Eq, Loc),
8016 Parameter_Associations => New_List (L_Exp, R_Exp)));
8017
8018 Analyze_And_Resolve (N, Standard_Boolean, Suppress => All_Checks);
8019 end Build_Equality_Call;
8020
8021 -------------------
8022 -- Find_Equality --
8023 -------------------
8024
8025 function Find_Equality (Prims : Elist_Id) return Entity_Id is
8026 function Find_Aliased_Equality (Prim : Entity_Id) return Entity_Id;
8027 -- Find an equality in a possible alias chain starting from primitive
8028 -- operation Prim.
8029
8030 ---------------------------
8031 -- Find_Aliased_Equality --
8032 ---------------------------
8033
8034 function Find_Aliased_Equality (Prim : Entity_Id) return Entity_Id is
8035 Candid : Entity_Id;
8036
8037 begin
8038 -- Inspect each candidate in the alias chain, checking whether it
8039 -- denotes an equality.
8040
8041 Candid := Prim;
8042 while Present (Candid) loop
8043 if Is_User_Defined_Equality (Candid) then
8044 return Candid;
8045 end if;
8046
8047 Candid := Alias (Candid);
8048 end loop;
8049
8050 return Empty;
8051 end Find_Aliased_Equality;
8052
8053 -- Local variables
8054
8055 Eq_Prim : Entity_Id;
8056 Prim_Elmt : Elmt_Id;
8057
8058 -- Start of processing for Find_Equality
8059
8060 begin
8061 -- Assume that the tagged type lacks an equality
8062
8063 Eq_Prim := Empty;
8064
8065 -- Inspect the list of primitives looking for a suitable equality
8066 -- within a possible chain of aliases.
8067
8068 Prim_Elmt := First_Elmt (Prims);
8069 while Present (Prim_Elmt) and then No (Eq_Prim) loop
8070 Eq_Prim := Find_Aliased_Equality (Node (Prim_Elmt));
8071
8072 Next_Elmt (Prim_Elmt);
8073 end loop;
8074
8075 -- A tagged type should always have an equality
8076
8077 pragma Assert (Present (Eq_Prim));
8078
8079 return Eq_Prim;
8080 end Find_Equality;
8081
8082 ------------------------------------
8083 -- Has_Unconstrained_UU_Component --
8084 ------------------------------------
8085
8086 function Has_Unconstrained_UU_Component
8087 (Typ : Entity_Id) return Boolean
8088 is
8089 function Unconstrained_UU_In_Component_Declaration
8090 (N : Node_Id) return Boolean;
8091
8092 function Unconstrained_UU_In_Component_Items
8093 (L : List_Id) return Boolean;
8094
8095 function Unconstrained_UU_In_Component_List
8096 (N : Node_Id) return Boolean;
8097
8098 function Unconstrained_UU_In_Variant_Part
8099 (N : Node_Id) return Boolean;
8100 -- A family of routines that determine whether a particular construct
8101 -- of a record type definition contains a subcomponent of an
8102 -- unchecked union type whose nominal subtype is unconstrained.
8103 --
8104 -- Individual routines correspond to the production rules of the Ada
8105 -- grammar, as described in the Ada RM (P).
8106
8107 -----------------------------------------------
8108 -- Unconstrained_UU_In_Component_Declaration --
8109 -----------------------------------------------
8110
8111 function Unconstrained_UU_In_Component_Declaration
8112 (N : Node_Id) return Boolean
8113 is
8114 pragma Assert (Nkind (N) = N_Component_Declaration);
8115
8116 Sindic : constant Node_Id :=
8117 Subtype_Indication (Component_Definition (N));
8118 begin
8119 -- If the component declaration includes a subtype indication
8120 -- it is not an unchecked_union. Otherwise verify that it carries
8121 -- the Unchecked_Union flag and is either a record or a private
8122 -- type. A Record_Subtype declared elsewhere does not qualify,
8123 -- even if its parent type carries the flag.
8124
8125 return Nkind (Sindic) in N_Expanded_Name | N_Identifier
8126 and then Is_Unchecked_Union (Base_Type (Etype (Sindic)))
8127 and then Ekind (Entity (Sindic)) in
8128 E_Private_Type | E_Record_Type;
8129 end Unconstrained_UU_In_Component_Declaration;
8130
8131 -----------------------------------------
8132 -- Unconstrained_UU_In_Component_Items --
8133 -----------------------------------------
8134
8135 function Unconstrained_UU_In_Component_Items
8136 (L : List_Id) return Boolean
8137 is
8138 N : Node_Id := First (L);
8139 begin
8140 while Present (N) loop
8141 if Nkind (N) = N_Component_Declaration
8142 and then Unconstrained_UU_In_Component_Declaration (N)
8143 then
8144 return True;
8145 end if;
8146
8147 Next (N);
8148 end loop;
8149
8150 return False;
8151 end Unconstrained_UU_In_Component_Items;
8152
8153 ----------------------------------------
8154 -- Unconstrained_UU_In_Component_List --
8155 ----------------------------------------
8156
8157 function Unconstrained_UU_In_Component_List
8158 (N : Node_Id) return Boolean
8159 is
8160 pragma Assert (Nkind (N) = N_Component_List);
8161
8162 Optional_Variant_Part : Node_Id;
8163 begin
8164 if Unconstrained_UU_In_Component_Items (Component_Items (N)) then
8165 return True;
8166 end if;
8167
8168 Optional_Variant_Part := Variant_Part (N);
8169
8170 return
8171 Present (Optional_Variant_Part)
8172 and then
8173 Unconstrained_UU_In_Variant_Part (Optional_Variant_Part);
8174 end Unconstrained_UU_In_Component_List;
8175
8176 --------------------------------------
8177 -- Unconstrained_UU_In_Variant_Part --
8178 --------------------------------------
8179
8180 function Unconstrained_UU_In_Variant_Part
8181 (N : Node_Id) return Boolean
8182 is
8183 pragma Assert (Nkind (N) = N_Variant_Part);
8184
8185 Variant : Node_Id := First (Variants (N));
8186 begin
8187 loop
8188 if Unconstrained_UU_In_Component_List (Component_List (Variant))
8189 then
8190 return True;
8191 end if;
8192
8193 Next (Variant);
8194 exit when No (Variant);
8195 end loop;
8196
8197 return False;
8198 end Unconstrained_UU_In_Variant_Part;
8199
8200 Typ_Def : constant Node_Id :=
8201 Type_Definition (Declaration_Node (Base_Type (Typ)));
8202
8203 Optional_Component_List : constant Node_Id :=
8204 Component_List (Typ_Def);
8205
8206 -- Start of processing for Has_Unconstrained_UU_Component
8207
8208 begin
8209 return Present (Optional_Component_List)
8210 and then
8211 Unconstrained_UU_In_Component_List (Optional_Component_List);
8212 end Has_Unconstrained_UU_Component;
8213
8214 -- Local variables
8215
8216 Typl : Entity_Id;
8217
8218 -- Start of processing for Expand_N_Op_Eq
8219
8220 begin
8221 Binary_Op_Validity_Checks (N);
8222
8223 -- Deal with private types
8224
8225 Typl := Underlying_Type (A_Typ);
8226
8227 -- It may happen in error situations that the underlying type is not
8228 -- set. The error will be detected later, here we just defend the
8229 -- expander code.
8230
8231 if No (Typl) then
8232 return;
8233 end if;
8234
8235 -- Now get the implementation base type (note that plain Base_Type here
8236 -- might lead us back to the private type, which is not what we want!)
8237
8238 Typl := Implementation_Base_Type (Typl);
8239
8240 -- Equality between variant records results in a call to a routine
8241 -- that has conditional tests of the discriminant value(s), and hence
8242 -- violates the No_Implicit_Conditionals restriction.
8243
8244 if Has_Variant_Part (Typl) then
8245 declare
8246 Msg : Boolean;
8247
8248 begin
8249 Check_Restriction (Msg, No_Implicit_Conditionals, N);
8250
8251 if Msg then
8252 Error_Msg_N
8253 ("\comparison of variant records tests discriminants", N);
8254 return;
8255 end if;
8256 end;
8257 end if;
8258
8259 -- Deal with overflow checks in MINIMIZED/ELIMINATED mode and if that
8260 -- means we no longer have a comparison operation, we are all done.
8261
8262 if Minimized_Eliminated_Overflow_Check (Left_Opnd (N)) then
8263 Expand_Compare_Minimize_Eliminate_Overflow (N);
8264 end if;
8265
8266 if Nkind (N) /= N_Op_Eq then
8267 return;
8268 end if;
8269
8270 -- Boolean types (requiring handling of non-standard case)
8271
8272 if Is_Boolean_Type (Typl) then
8273 Adjust_Condition (Left_Opnd (N));
8274 Adjust_Condition (Right_Opnd (N));
8275 Set_Etype (N, Standard_Boolean);
8276 Adjust_Result_Type (N, Typ);
8277
8278 -- Array types
8279
8280 elsif Is_Array_Type (Typl) then
8281
8282 -- If we are doing full validity checking, and it is possible for the
8283 -- array elements to be invalid then expand out array comparisons to
8284 -- make sure that we check the array elements.
8285
8286 if Validity_Check_Operands
8287 and then not Is_Known_Valid (Component_Type (Typl))
8288 then
8289 declare
8290 Save_Force_Validity_Checks : constant Boolean :=
8291 Force_Validity_Checks;
8292 begin
8293 Force_Validity_Checks := True;
8294 Rewrite (N,
8295 Expand_Array_Equality
8296 (N,
8297 Relocate_Node (Lhs),
8298 Relocate_Node (Rhs),
8299 Bodies,
8300 Typl));
8301 Insert_Actions (N, Bodies);
8302 Analyze_And_Resolve (N, Standard_Boolean);
8303 Force_Validity_Checks := Save_Force_Validity_Checks;
8304 end;
8305
8306 -- Packed case where both operands are known aligned
8307
8308 elsif Is_Bit_Packed_Array (Typl)
8309 and then not Is_Possibly_Unaligned_Object (Lhs)
8310 and then not Is_Possibly_Unaligned_Object (Rhs)
8311 then
8312 Expand_Packed_Eq (N);
8313
8314 -- Where the component type is elementary we can use a block bit
8315 -- comparison (if supported on the target) exception in the case
8316 -- of floating-point (negative zero issues require element by
8317 -- element comparison), and full access types (where we must be sure
8318 -- to load elements independently) and possibly unaligned arrays.
8319
8320 elsif Is_Elementary_Type (Component_Type (Typl))
8321 and then not Is_Floating_Point_Type (Component_Type (Typl))
8322 and then not Is_Full_Access (Component_Type (Typl))
8323 and then not Is_Possibly_Unaligned_Object (Lhs)
8324 and then not Is_Possibly_Unaligned_Slice (Lhs)
8325 and then not Is_Possibly_Unaligned_Object (Rhs)
8326 and then not Is_Possibly_Unaligned_Slice (Rhs)
8327 and then Support_Composite_Compare_On_Target
8328 then
8329 null;
8330
8331 -- For composite and floating-point cases, expand equality loop to
8332 -- make sure of using proper comparisons for tagged types, and
8333 -- correctly handling the floating-point case.
8334
8335 else
8336 Rewrite (N,
8337 Expand_Array_Equality
8338 (N,
8339 Relocate_Node (Lhs),
8340 Relocate_Node (Rhs),
8341 Bodies,
8342 Typl));
8343 Insert_Actions (N, Bodies, Suppress => All_Checks);
8344 Analyze_And_Resolve (N, Standard_Boolean, Suppress => All_Checks);
8345 end if;
8346
8347 -- Record Types
8348
8349 elsif Is_Record_Type (Typl) then
8350
8351 -- For tagged types, use the primitive "="
8352
8353 if Is_Tagged_Type (Typl) then
8354
8355 -- No need to do anything else compiling under restriction
8356 -- No_Dispatching_Calls. During the semantic analysis we
8357 -- already notified such violation.
8358
8359 if Restriction_Active (No_Dispatching_Calls) then
8360 return;
8361 end if;
8362
8363 -- If this is an untagged private type completed with a derivation
8364 -- of an untagged private type whose full view is a tagged type,
8365 -- we use the primitive operations of the private type (since it
8366 -- does not have a full view, and also because its equality
8367 -- primitive may have been overridden in its untagged full view).
8368
8369 if Inherits_From_Tagged_Full_View (A_Typ) then
8370 Build_Equality_Call
8371 (Find_Equality (Collect_Primitive_Operations (A_Typ)));
8372
8373 -- Find the type's predefined equality or an overriding
8374 -- user-defined equality. The reason for not simply calling
8375 -- Find_Prim_Op here is that there may be a user-defined
8376 -- overloaded equality op that precedes the equality that we
8377 -- want, so we have to explicitly search (e.g., there could be
8378 -- an equality with two different parameter types).
8379
8380 else
8381 if Is_Class_Wide_Type (Typl) then
8382 Typl := Find_Specific_Type (Typl);
8383 end if;
8384
8385 Build_Equality_Call
8386 (Find_Equality (Primitive_Operations (Typl)));
8387 end if;
8388
8389 -- Ada 2005 (AI-216): Program_Error is raised when evaluating the
8390 -- predefined equality operator for a type which has a subcomponent
8391 -- of an unchecked union type whose nominal subtype is unconstrained.
8392
8393 elsif Has_Unconstrained_UU_Component (Typl) then
8394 Insert_Action (N,
8395 Make_Raise_Program_Error (Loc,
8396 Reason => PE_Unchecked_Union_Restriction));
8397
8398 Rewrite (N,
8399 New_Occurrence_Of (Standard_False, Loc));
8400
8401 -- If a type support function is present, e.g. if there is a variant
8402 -- part, including an unchecked union type, use it.
8403
8404 elsif Present (TSS (Root_Type (Typl), TSS_Composite_Equality)) then
8405 Build_Equality_Call
8406 (TSS (Root_Type (Typl), TSS_Composite_Equality));
8407
8408 -- When comparing two Bounded_Strings, use the primitive equality of
8409 -- the root Super_String type.
8410
8411 elsif Is_Bounded_String (Typl) then
8412 Build_Equality_Call
8413 (Find_Equality
8414 (Collect_Primitive_Operations (Root_Type (Typl))));
8415
8416 -- Otherwise expand the component by component equality. Note that
8417 -- we never use block-bit comparisons for records, because of the
8418 -- problems with gaps. The back end will often be able to recombine
8419 -- the separate comparisons that we generate here.
8420
8421 else
8422 Remove_Side_Effects (Lhs);
8423 Remove_Side_Effects (Rhs);
8424 Rewrite (N, Expand_Record_Equality (N, Typl, Lhs, Rhs));
8425
8426 Analyze_And_Resolve (N, Standard_Boolean, Suppress => All_Checks);
8427 end if;
8428
8429 -- If unnesting, handle elementary types whose Equivalent_Types are
8430 -- records because there may be padding or undefined fields.
8431
8432 elsif Unnest_Subprogram_Mode
8433 and then Ekind (Typl) in E_Class_Wide_Type
8434 | E_Class_Wide_Subtype
8435 | E_Access_Subprogram_Type
8436 | E_Access_Protected_Subprogram_Type
8437 | E_Anonymous_Access_Protected_Subprogram_Type
8438 | E_Exception_Type
8439 and then Present (Equivalent_Type (Typl))
8440 and then Is_Record_Type (Equivalent_Type (Typl))
8441 then
8442 Typl := Equivalent_Type (Typl);
8443 Remove_Side_Effects (Lhs);
8444 Remove_Side_Effects (Rhs);
8445 Rewrite (N,
8446 Expand_Record_Equality (N, Typl,
8447 Unchecked_Convert_To (Typl, Lhs),
8448 Unchecked_Convert_To (Typl, Rhs)));
8449
8450 Analyze_And_Resolve (N, Standard_Boolean, Suppress => All_Checks);
8451 end if;
8452
8453 -- Test if result is known at compile time
8454
8455 Rewrite_Comparison (N);
8456
8457 -- Try to narrow the operation
8458
8459 if Typl = Universal_Integer and then Nkind (N) = N_Op_Eq then
8460 Narrow_Large_Operation (N);
8461 end if;
8462
8463 -- Special optimization of length comparison
8464
8465 Optimize_Length_Comparison (N);
8466
8467 -- One more special case: if we have a comparison of X'Result = expr
8468 -- in floating-point, then if not already there, change expr to be
8469 -- f'Machine (expr) to eliminate surprise from extra precision.
8470
8471 if Is_Floating_Point_Type (Typl)
8472 and then Is_Attribute_Result (Original_Node (Lhs))
8473 then
8474 -- Stick in the Typ'Machine call if not already there
8475
8476 if Nkind (Rhs) /= N_Attribute_Reference
8477 or else Attribute_Name (Rhs) /= Name_Machine
8478 then
8479 Rewrite (Rhs,
8480 Make_Attribute_Reference (Loc,
8481 Prefix => New_Occurrence_Of (Typl, Loc),
8482 Attribute_Name => Name_Machine,
8483 Expressions => New_List (Relocate_Node (Rhs))));
8484 Analyze_And_Resolve (Rhs, Typl);
8485 end if;
8486 end if;
8487 end Expand_N_Op_Eq;
8488
8489 -----------------------
8490 -- Expand_N_Op_Expon --
8491 -----------------------
8492
8493 procedure Expand_N_Op_Expon (N : Node_Id) is
8494 Loc : constant Source_Ptr := Sloc (N);
8495 Ovflo : constant Boolean := Do_Overflow_Check (N);
8496 Typ : constant Entity_Id := Etype (N);
8497 Rtyp : constant Entity_Id := Root_Type (Typ);
8498
8499 Bastyp : Entity_Id;
8500
8501 function Wrap_MA (Exp : Node_Id) return Node_Id;
8502 -- Given an expression Exp, if the root type is Float or Long_Float,
8503 -- then wrap the expression in a call of Bastyp'Machine, to stop any
8504 -- extra precision. This is done to ensure that X**A = X**B when A is
8505 -- a static constant and B is a variable with the same value. For any
8506 -- other type, the node Exp is returned unchanged.
8507
8508 -------------
8509 -- Wrap_MA --
8510 -------------
8511
8512 function Wrap_MA (Exp : Node_Id) return Node_Id is
8513 Loc : constant Source_Ptr := Sloc (Exp);
8514
8515 begin
8516 if Rtyp = Standard_Float or else Rtyp = Standard_Long_Float then
8517 return
8518 Make_Attribute_Reference (Loc,
8519 Attribute_Name => Name_Machine,
8520 Prefix => New_Occurrence_Of (Bastyp, Loc),
8521 Expressions => New_List (Relocate_Node (Exp)));
8522 else
8523 return Exp;
8524 end if;
8525 end Wrap_MA;
8526
8527 -- Local variables
8528
8529 Base : Node_Id;
8530 Ent : Entity_Id;
8531 Etyp : Entity_Id;
8532 Exp : Node_Id;
8533 Exptyp : Entity_Id;
8534 Expv : Uint;
8535 Rent : RE_Id;
8536 Temp : Node_Id;
8537 Xnode : Node_Id;
8538
8539 -- Start of processing for Expand_N_Op_Expon
8540
8541 begin
8542 Binary_Op_Validity_Checks (N);
8543
8544 -- CodePeer wants to see the unexpanded N_Op_Expon node
8545
8546 if CodePeer_Mode then
8547 return;
8548 end if;
8549
8550 -- Relocation of left and right operands must be done after performing
8551 -- the validity checks since the generation of validation checks may
8552 -- remove side effects.
8553
8554 Base := Relocate_Node (Left_Opnd (N));
8555 Bastyp := Etype (Base);
8556 Exp := Relocate_Node (Right_Opnd (N));
8557 Exptyp := Etype (Exp);
8558
8559 -- If either operand is of a private type, then we have the use of an
8560 -- intrinsic operator, and we get rid of the privateness, by using root
8561 -- types of underlying types for the actual operation. Otherwise the
8562 -- private types will cause trouble if we expand multiplications or
8563 -- shifts etc. We also do this transformation if the result type is
8564 -- different from the base type.
8565
8566 if Is_Private_Type (Etype (Base))
8567 or else Is_Private_Type (Typ)
8568 or else Is_Private_Type (Exptyp)
8569 or else Rtyp /= Root_Type (Bastyp)
8570 then
8571 declare
8572 Bt : constant Entity_Id := Root_Type (Underlying_Type (Bastyp));
8573 Et : constant Entity_Id := Root_Type (Underlying_Type (Exptyp));
8574 begin
8575 Rewrite (N,
8576 Unchecked_Convert_To (Typ,
8577 Make_Op_Expon (Loc,
8578 Left_Opnd => Unchecked_Convert_To (Bt, Base),
8579 Right_Opnd => Unchecked_Convert_To (Et, Exp))));
8580 Analyze_And_Resolve (N, Typ);
8581 return;
8582 end;
8583 end if;
8584
8585 -- Check for MINIMIZED/ELIMINATED overflow mode
8586
8587 if Minimized_Eliminated_Overflow_Check (N) then
8588 Apply_Arithmetic_Overflow_Check (N);
8589 return;
8590 end if;
8591
8592 -- Test for case of known right argument where we can replace the
8593 -- exponentiation by an equivalent expression using multiplication.
8594
8595 -- Note: use CRT_Safe version of Compile_Time_Known_Value because in
8596 -- configurable run-time mode, we may not have the exponentiation
8597 -- routine available, and we don't want the legality of the program
8598 -- to depend on how clever the compiler is in knowing values.
8599
8600 if CRT_Safe_Compile_Time_Known_Value (Exp) then
8601 Expv := Expr_Value (Exp);
8602
8603 -- We only fold small non-negative exponents. You might think we
8604 -- could fold small negative exponents for the real case, but we
8605 -- can't because we are required to raise Constraint_Error for
8606 -- the case of 0.0 ** (negative) even if Machine_Overflows = False.
8607 -- See ACVC test C4A012B, and it is not worth generating the test.
8608
8609 -- For small negative exponents, we return the reciprocal of
8610 -- the folding of the exponentiation for the opposite (positive)
8611 -- exponent, as required by Ada RM 4.5.6(11/3).
8612
8613 if abs Expv <= 4 then
8614
8615 -- X ** 0 = 1 (or 1.0)
8616
8617 if Expv = 0 then
8618
8619 -- Call Remove_Side_Effects to ensure that any side effects
8620 -- in the ignored left operand (in particular function calls
8621 -- to user defined functions) are properly executed.
8622
8623 Remove_Side_Effects (Base);
8624
8625 if Ekind (Typ) in Integer_Kind then
8626 Xnode := Make_Integer_Literal (Loc, Intval => 1);
8627 else
8628 Xnode := Make_Real_Literal (Loc, Ureal_1);
8629 end if;
8630
8631 -- X ** 1 = X
8632
8633 elsif Expv = 1 then
8634 Xnode := Base;
8635
8636 -- X ** 2 = X * X
8637
8638 elsif Expv = 2 then
8639 Xnode :=
8640 Wrap_MA (
8641 Make_Op_Multiply (Loc,
8642 Left_Opnd => Duplicate_Subexpr (Base),
8643 Right_Opnd => Duplicate_Subexpr_No_Checks (Base)));
8644
8645 -- X ** 3 = X * X * X
8646
8647 elsif Expv = 3 then
8648 Xnode :=
8649 Wrap_MA (
8650 Make_Op_Multiply (Loc,
8651 Left_Opnd =>
8652 Make_Op_Multiply (Loc,
8653 Left_Opnd => Duplicate_Subexpr (Base),
8654 Right_Opnd => Duplicate_Subexpr_No_Checks (Base)),
8655 Right_Opnd => Duplicate_Subexpr_No_Checks (Base)));
8656
8657 -- X ** 4 ->
8658
8659 -- do
8660 -- En : constant base'type := base * base;
8661 -- in
8662 -- En * En
8663
8664 elsif Expv = 4 then
8665 Temp := Make_Temporary (Loc, 'E', Base);
8666
8667 Xnode :=
8668 Make_Expression_With_Actions (Loc,
8669 Actions => New_List (
8670 Make_Object_Declaration (Loc,
8671 Defining_Identifier => Temp,
8672 Constant_Present => True,
8673 Object_Definition => New_Occurrence_Of (Typ, Loc),
8674 Expression =>
8675 Wrap_MA (
8676 Make_Op_Multiply (Loc,
8677 Left_Opnd =>
8678 Duplicate_Subexpr (Base),
8679 Right_Opnd =>
8680 Duplicate_Subexpr_No_Checks (Base))))),
8681
8682 Expression =>
8683 Wrap_MA (
8684 Make_Op_Multiply (Loc,
8685 Left_Opnd => New_Occurrence_Of (Temp, Loc),
8686 Right_Opnd => New_Occurrence_Of (Temp, Loc))));
8687
8688 -- X ** N = 1.0 / X ** (-N)
8689 -- N in -4 .. -1
8690
8691 else
8692 pragma Assert
8693 (Expv = -1 or Expv = -2 or Expv = -3 or Expv = -4);
8694
8695 Xnode :=
8696 Make_Op_Divide (Loc,
8697 Left_Opnd =>
8698 Make_Float_Literal (Loc,
8699 Radix => Uint_1,
8700 Significand => Uint_1,
8701 Exponent => Uint_0),
8702 Right_Opnd =>
8703 Make_Op_Expon (Loc,
8704 Left_Opnd => Duplicate_Subexpr (Base),
8705 Right_Opnd =>
8706 Make_Integer_Literal (Loc,
8707 Intval => -Expv)));
8708 end if;
8709
8710 Rewrite (N, Xnode);
8711 Analyze_And_Resolve (N, Typ);
8712 return;
8713 end if;
8714 end if;
8715
8716 -- Optimize 2 ** expression to shift where possible
8717
8718 -- Note: we used to check that Exptyp was an unsigned type. But that is
8719 -- an unnecessary check, since if Exp is negative, we have a run-time
8720 -- error that is either caught (so we get the right result) or we have
8721 -- suppressed the check, in which case the code is erroneous anyway.
8722
8723 if Is_Integer_Type (Rtyp)
8724
8725 -- The base value must be "safe compile-time known", and exactly 2
8726
8727 and then Nkind (Base) = N_Integer_Literal
8728 and then CRT_Safe_Compile_Time_Known_Value (Base)
8729 and then Expr_Value (Base) = Uint_2
8730
8731 -- This transformation is not applicable for a modular type with a
8732 -- nonbinary modulus because shifting makes no sense in that case.
8733
8734 and then not Non_Binary_Modulus (Typ)
8735 then
8736 -- Handle the cases where our parent is a division or multiplication
8737 -- specially. In these cases we can convert to using a shift at the
8738 -- parent level if we are not doing overflow checking, since it is
8739 -- too tricky to combine the overflow check at the parent level.
8740
8741 if not Ovflo
8742 and then Nkind (Parent (N)) in N_Op_Divide | N_Op_Multiply
8743 then
8744 declare
8745 P : constant Node_Id := Parent (N);
8746 L : constant Node_Id := Left_Opnd (P);
8747 R : constant Node_Id := Right_Opnd (P);
8748
8749 begin
8750 if (Nkind (P) = N_Op_Multiply
8751 and then
8752 ((Is_Integer_Type (Etype (L)) and then R = N)
8753 or else
8754 (Is_Integer_Type (Etype (R)) and then L = N))
8755 and then not Do_Overflow_Check (P))
8756
8757 or else
8758 (Nkind (P) = N_Op_Divide
8759 and then Is_Integer_Type (Etype (L))
8760 and then Is_Unsigned_Type (Etype (L))
8761 and then R = N
8762 and then not Do_Overflow_Check (P))
8763 then
8764 Set_Is_Power_Of_2_For_Shift (N);
8765 return;
8766 end if;
8767 end;
8768
8769 -- Here we have 2 ** N on its own, so we can convert this into a
8770 -- shift.
8771
8772 else
8773 -- Op_Shift_Left (generated below) has modular-shift semantics;
8774 -- therefore we might need to generate an overflow check here
8775 -- if the type is signed.
8776
8777 if Is_Signed_Integer_Type (Typ) and then Ovflo then
8778 declare
8779 OK : Boolean;
8780 Lo : Uint;
8781 Hi : Uint;
8782
8783 MaxS : constant Uint := Esize (Rtyp) - 2;
8784 -- Maximum shift count with no overflow
8785 begin
8786 Determine_Range (Exp, OK, Lo, Hi, Assume_Valid => True);
8787
8788 if not OK or else Hi > MaxS then
8789 Insert_Action (N,
8790 Make_Raise_Constraint_Error (Loc,
8791 Condition =>
8792 Make_Op_Gt (Loc,
8793 Left_Opnd => Duplicate_Subexpr (Exp),
8794 Right_Opnd => Make_Integer_Literal (Loc, MaxS)),
8795 Reason => CE_Overflow_Check_Failed));
8796 end if;
8797 end;
8798 end if;
8799
8800 -- Generate Shift_Left (1, Exp)
8801
8802 Rewrite (N,
8803 Make_Op_Shift_Left (Loc,
8804 Left_Opnd => Make_Integer_Literal (Loc, Uint_1),
8805 Right_Opnd => Exp));
8806
8807 Analyze_And_Resolve (N, Typ);
8808 return;
8809 end if;
8810 end if;
8811
8812 -- Fall through if exponentiation must be done using a runtime routine
8813
8814 -- First deal with modular case
8815
8816 if Is_Modular_Integer_Type (Rtyp) then
8817
8818 -- Nonbinary modular case, we call the special exponentiation
8819 -- routine for the nonbinary case, converting the argument to
8820 -- Long_Long_Integer and passing the modulus value. Then the
8821 -- result is converted back to the base type.
8822
8823 if Non_Binary_Modulus (Rtyp) then
8824 Rewrite (N,
8825 Convert_To (Typ,
8826 Make_Function_Call (Loc,
8827 Name =>
8828 New_Occurrence_Of (RTE (RE_Exp_Modular), Loc),
8829 Parameter_Associations => New_List (
8830 Convert_To (RTE (RE_Unsigned), Base),
8831 Make_Integer_Literal (Loc, Modulus (Rtyp)),
8832 Exp))));
8833
8834 -- Binary modular case, in this case, we call one of three routines,
8835 -- either the unsigned integer case, or the unsigned long long
8836 -- integer case, or the unsigned long long long integer case, with a
8837 -- final "and" operation to do the required mod.
8838
8839 else
8840 if Esize (Rtyp) <= Standard_Integer_Size then
8841 Ent := RTE (RE_Exp_Unsigned);
8842 elsif Esize (Rtyp) <= Standard_Long_Long_Integer_Size then
8843 Ent := RTE (RE_Exp_Long_Long_Unsigned);
8844 else
8845 Ent := RTE (RE_Exp_Long_Long_Long_Unsigned);
8846 end if;
8847
8848 Rewrite (N,
8849 Convert_To (Typ,
8850 Make_Op_And (Loc,
8851 Left_Opnd =>
8852 Make_Function_Call (Loc,
8853 Name => New_Occurrence_Of (Ent, Loc),
8854 Parameter_Associations => New_List (
8855 Convert_To (Etype (First_Formal (Ent)), Base),
8856 Exp)),
8857 Right_Opnd =>
8858 Make_Integer_Literal (Loc, Modulus (Rtyp) - 1))));
8859
8860 end if;
8861
8862 -- Common exit point for modular type case
8863
8864 Analyze_And_Resolve (N, Typ);
8865 return;
8866
8867 -- Signed integer cases, using either Integer, Long_Long_Integer or
8868 -- Long_Long_Long_Integer. It is not worth also having routines for
8869 -- Short_[Short_]Integer, since for most machines it would not help,
8870 -- and it would generate more code that might need certification when
8871 -- a certified run time is required.
8872
8873 -- In the integer cases, we have two routines, one for when overflow
8874 -- checks are required, and one when they are not required, since there
8875 -- is a real gain in omitting checks on many machines.
8876
8877 elsif Is_Signed_Integer_Type (Rtyp) then
8878 if Esize (Rtyp) <= Standard_Integer_Size then
8879 Etyp := Standard_Integer;
8880
8881 if Ovflo then
8882 Rent := RE_Exp_Integer;
8883 else
8884 Rent := RE_Exn_Integer;
8885 end if;
8886
8887 elsif Esize (Rtyp) <= Standard_Long_Long_Integer_Size then
8888 Etyp := Standard_Long_Long_Integer;
8889
8890 if Ovflo then
8891 Rent := RE_Exp_Long_Long_Integer;
8892 else
8893 Rent := RE_Exn_Long_Long_Integer;
8894 end if;
8895
8896 else
8897 Etyp := Standard_Long_Long_Long_Integer;
8898
8899 if Ovflo then
8900 Rent := RE_Exp_Long_Long_Long_Integer;
8901 else
8902 Rent := RE_Exn_Long_Long_Long_Integer;
8903 end if;
8904 end if;
8905
8906 -- Floating-point cases. We do not need separate routines for the
8907 -- overflow case here, since in the case of floating-point, we generate
8908 -- infinities anyway as a rule (either that or we automatically trap
8909 -- overflow), and if there is an infinity generated and a range check
8910 -- is required, the check will fail anyway.
8911
8912 else
8913 pragma Assert (Is_Floating_Point_Type (Rtyp));
8914
8915 -- Short_Float and Float are the same type for GNAT
8916
8917 if Rtyp = Standard_Short_Float or else Rtyp = Standard_Float then
8918 Etyp := Standard_Float;
8919 Rent := RE_Exn_Float;
8920
8921 elsif Rtyp = Standard_Long_Float then
8922 Etyp := Standard_Long_Float;
8923 Rent := RE_Exn_Long_Float;
8924
8925 else
8926 Etyp := Standard_Long_Long_Float;
8927 Rent := RE_Exn_Long_Long_Float;
8928 end if;
8929 end if;
8930
8931 -- Common processing for integer cases and floating-point cases.
8932 -- If we are in the right type, we can call runtime routine directly
8933
8934 if Typ = Etyp
8935 and then not Is_Universal_Numeric_Type (Rtyp)
8936 then
8937 Rewrite (N,
8938 Wrap_MA (
8939 Make_Function_Call (Loc,
8940 Name => New_Occurrence_Of (RTE (Rent), Loc),
8941 Parameter_Associations => New_List (Base, Exp))));
8942
8943 -- Otherwise we have to introduce conversions (conversions are also
8944 -- required in the universal cases, since the runtime routine is
8945 -- typed using one of the standard types).
8946
8947 else
8948 Rewrite (N,
8949 Convert_To (Typ,
8950 Make_Function_Call (Loc,
8951 Name => New_Occurrence_Of (RTE (Rent), Loc),
8952 Parameter_Associations => New_List (
8953 Convert_To (Etyp, Base),
8954 Exp))));
8955 end if;
8956
8957 Analyze_And_Resolve (N, Typ);
8958 return;
8959
8960 exception
8961 when RE_Not_Available =>
8962 return;
8963 end Expand_N_Op_Expon;
8964
8965 --------------------
8966 -- Expand_N_Op_Ge --
8967 --------------------
8968
8969 procedure Expand_N_Op_Ge (N : Node_Id) is
8970 Typ : constant Entity_Id := Etype (N);
8971 Op1 : constant Node_Id := Left_Opnd (N);
8972 Op2 : constant Node_Id := Right_Opnd (N);
8973 Typ1 : constant Entity_Id := Base_Type (Etype (Op1));
8974
8975 begin
8976 Binary_Op_Validity_Checks (N);
8977
8978 -- Deal with overflow checks in MINIMIZED/ELIMINATED mode and if that
8979 -- means we no longer have a comparison operation, we are all done.
8980
8981 if Minimized_Eliminated_Overflow_Check (Op1) then
8982 Expand_Compare_Minimize_Eliminate_Overflow (N);
8983 end if;
8984
8985 if Nkind (N) /= N_Op_Ge then
8986 return;
8987 end if;
8988
8989 -- Array type case
8990
8991 if Is_Array_Type (Typ1) then
8992 Expand_Array_Comparison (N);
8993 return;
8994 end if;
8995
8996 -- Deal with boolean operands
8997
8998 if Is_Boolean_Type (Typ1) then
8999 Adjust_Condition (Op1);
9000 Adjust_Condition (Op2);
9001 Set_Etype (N, Standard_Boolean);
9002 Adjust_Result_Type (N, Typ);
9003 end if;
9004
9005 Rewrite_Comparison (N);
9006
9007 -- Try to narrow the operation
9008
9009 if Typ1 = Universal_Integer and then Nkind (N) = N_Op_Ge then
9010 Narrow_Large_Operation (N);
9011 end if;
9012
9013 Optimize_Length_Comparison (N);
9014 end Expand_N_Op_Ge;
9015
9016 --------------------
9017 -- Expand_N_Op_Gt --
9018 --------------------
9019
9020 procedure Expand_N_Op_Gt (N : Node_Id) is
9021 Typ : constant Entity_Id := Etype (N);
9022 Op1 : constant Node_Id := Left_Opnd (N);
9023 Op2 : constant Node_Id := Right_Opnd (N);
9024 Typ1 : constant Entity_Id := Base_Type (Etype (Op1));
9025
9026 begin
9027 Binary_Op_Validity_Checks (N);
9028
9029 -- Deal with overflow checks in MINIMIZED/ELIMINATED mode and if that
9030 -- means we no longer have a comparison operation, we are all done.
9031
9032 if Minimized_Eliminated_Overflow_Check (Op1) then
9033 Expand_Compare_Minimize_Eliminate_Overflow (N);
9034 end if;
9035
9036 if Nkind (N) /= N_Op_Gt then
9037 return;
9038 end if;
9039
9040 -- Deal with array type operands
9041
9042 if Is_Array_Type (Typ1) then
9043 Expand_Array_Comparison (N);
9044 return;
9045 end if;
9046
9047 -- Deal with boolean type operands
9048
9049 if Is_Boolean_Type (Typ1) then
9050 Adjust_Condition (Op1);
9051 Adjust_Condition (Op2);
9052 Set_Etype (N, Standard_Boolean);
9053 Adjust_Result_Type (N, Typ);
9054 end if;
9055
9056 Rewrite_Comparison (N);
9057
9058 -- Try to narrow the operation
9059
9060 if Typ1 = Universal_Integer and then Nkind (N) = N_Op_Gt then
9061 Narrow_Large_Operation (N);
9062 end if;
9063
9064 Optimize_Length_Comparison (N);
9065 end Expand_N_Op_Gt;
9066
9067 --------------------
9068 -- Expand_N_Op_Le --
9069 --------------------
9070
9071 procedure Expand_N_Op_Le (N : Node_Id) is
9072 Typ : constant Entity_Id := Etype (N);
9073 Op1 : constant Node_Id := Left_Opnd (N);
9074 Op2 : constant Node_Id := Right_Opnd (N);
9075 Typ1 : constant Entity_Id := Base_Type (Etype (Op1));
9076
9077 begin
9078 Binary_Op_Validity_Checks (N);
9079
9080 -- Deal with overflow checks in MINIMIZED/ELIMINATED mode and if that
9081 -- means we no longer have a comparison operation, we are all done.
9082
9083 if Minimized_Eliminated_Overflow_Check (Op1) then
9084 Expand_Compare_Minimize_Eliminate_Overflow (N);
9085 end if;
9086
9087 if Nkind (N) /= N_Op_Le then
9088 return;
9089 end if;
9090
9091 -- Deal with array type operands
9092
9093 if Is_Array_Type (Typ1) then
9094 Expand_Array_Comparison (N);
9095 return;
9096 end if;
9097
9098 -- Deal with Boolean type operands
9099
9100 if Is_Boolean_Type (Typ1) then
9101 Adjust_Condition (Op1);
9102 Adjust_Condition (Op2);
9103 Set_Etype (N, Standard_Boolean);
9104 Adjust_Result_Type (N, Typ);
9105 end if;
9106
9107 Rewrite_Comparison (N);
9108
9109 -- Try to narrow the operation
9110
9111 if Typ1 = Universal_Integer and then Nkind (N) = N_Op_Le then
9112 Narrow_Large_Operation (N);
9113 end if;
9114
9115 Optimize_Length_Comparison (N);
9116 end Expand_N_Op_Le;
9117
9118 --------------------
9119 -- Expand_N_Op_Lt --
9120 --------------------
9121
9122 procedure Expand_N_Op_Lt (N : Node_Id) is
9123 Typ : constant Entity_Id := Etype (N);
9124 Op1 : constant Node_Id := Left_Opnd (N);
9125 Op2 : constant Node_Id := Right_Opnd (N);
9126 Typ1 : constant Entity_Id := Base_Type (Etype (Op1));
9127
9128 begin
9129 Binary_Op_Validity_Checks (N);
9130
9131 -- Deal with overflow checks in MINIMIZED/ELIMINATED mode and if that
9132 -- means we no longer have a comparison operation, we are all done.
9133
9134 if Minimized_Eliminated_Overflow_Check (Op1) then
9135 Expand_Compare_Minimize_Eliminate_Overflow (N);
9136 end if;
9137
9138 if Nkind (N) /= N_Op_Lt then
9139 return;
9140 end if;
9141
9142 -- Deal with array type operands
9143
9144 if Is_Array_Type (Typ1) then
9145 Expand_Array_Comparison (N);
9146 return;
9147 end if;
9148
9149 -- Deal with Boolean type operands
9150
9151 if Is_Boolean_Type (Typ1) then
9152 Adjust_Condition (Op1);
9153 Adjust_Condition (Op2);
9154 Set_Etype (N, Standard_Boolean);
9155 Adjust_Result_Type (N, Typ);
9156 end if;
9157
9158 Rewrite_Comparison (N);
9159
9160 -- Try to narrow the operation
9161
9162 if Typ1 = Universal_Integer and then Nkind (N) = N_Op_Lt then
9163 Narrow_Large_Operation (N);
9164 end if;
9165
9166 Optimize_Length_Comparison (N);
9167 end Expand_N_Op_Lt;
9168
9169 -----------------------
9170 -- Expand_N_Op_Minus --
9171 -----------------------
9172
9173 procedure Expand_N_Op_Minus (N : Node_Id) is
9174 Loc : constant Source_Ptr := Sloc (N);
9175 Typ : constant Entity_Id := Etype (N);
9176
9177 begin
9178 Unary_Op_Validity_Checks (N);
9179
9180 -- Check for MINIMIZED/ELIMINATED overflow mode
9181
9182 if Minimized_Eliminated_Overflow_Check (N) then
9183 Apply_Arithmetic_Overflow_Check (N);
9184 return;
9185 end if;
9186
9187 -- Try to narrow the operation
9188
9189 if Typ = Universal_Integer then
9190 Narrow_Large_Operation (N);
9191
9192 if Nkind (N) /= N_Op_Minus then
9193 return;
9194 end if;
9195 end if;
9196
9197 if not Backend_Overflow_Checks_On_Target
9198 and then Is_Signed_Integer_Type (Typ)
9199 and then Do_Overflow_Check (N)
9200 then
9201 -- Software overflow checking expands -expr into (0 - expr)
9202
9203 Rewrite (N,
9204 Make_Op_Subtract (Loc,
9205 Left_Opnd => Make_Integer_Literal (Loc, 0),
9206 Right_Opnd => Right_Opnd (N)));
9207
9208 Analyze_And_Resolve (N, Typ);
9209 end if;
9210
9211 Expand_Nonbinary_Modular_Op (N);
9212 end Expand_N_Op_Minus;
9213
9214 ---------------------
9215 -- Expand_N_Op_Mod --
9216 ---------------------
9217
9218 procedure Expand_N_Op_Mod (N : Node_Id) is
9219 Loc : constant Source_Ptr := Sloc (N);
9220 Typ : constant Entity_Id := Etype (N);
9221 DDC : constant Boolean := Do_Division_Check (N);
9222
9223 Is_Stoele_Mod : constant Boolean :=
9224 Is_RTE (Typ, RE_Address)
9225 and then Nkind (Right_Opnd (N)) = N_Unchecked_Type_Conversion
9226 and then
9227 Is_RTE (Etype (Expression (Right_Opnd (N))), RE_Storage_Offset);
9228 -- True if this is the special mod operator of System.Storage_Elements
9229
9230 Left : Node_Id;
9231 Right : Node_Id;
9232
9233 LLB : Uint;
9234 Llo : Uint;
9235 Lhi : Uint;
9236 LOK : Boolean;
9237 Rlo : Uint;
9238 Rhi : Uint;
9239 ROK : Boolean;
9240
9241 pragma Warnings (Off, Lhi);
9242
9243 begin
9244 Binary_Op_Validity_Checks (N);
9245
9246 -- Check for MINIMIZED/ELIMINATED overflow mode
9247
9248 if Minimized_Eliminated_Overflow_Check (N) then
9249 Apply_Arithmetic_Overflow_Check (N);
9250 return;
9251 end if;
9252
9253 -- Try to narrow the operation
9254
9255 if Typ = Universal_Integer then
9256 Narrow_Large_Operation (N);
9257
9258 if Nkind (N) /= N_Op_Mod then
9259 return;
9260 end if;
9261 end if;
9262
9263 -- For the special mod operator of System.Storage_Elements, the checks
9264 -- are subsumed into the handling of the negative case below.
9265
9266 if Is_Integer_Type (Typ) and then not Is_Stoele_Mod then
9267 Apply_Divide_Checks (N);
9268
9269 -- All done if we don't have a MOD any more, which can happen as a
9270 -- result of overflow expansion in MINIMIZED or ELIMINATED modes.
9271
9272 if Nkind (N) /= N_Op_Mod then
9273 return;
9274 end if;
9275 end if;
9276
9277 -- Proceed with expansion of mod operator
9278
9279 Left := Left_Opnd (N);
9280 Right := Right_Opnd (N);
9281
9282 Determine_Range (Right, ROK, Rlo, Rhi, Assume_Valid => True);
9283 Determine_Range (Left, LOK, Llo, Lhi, Assume_Valid => True);
9284
9285 -- Convert mod to rem if operands are both known to be non-negative, or
9286 -- both known to be non-positive (these are the cases in which rem and
9287 -- mod are the same, see (RM 4.5.5(28-30)). We do this since it is quite
9288 -- likely that this will improve the quality of code, (the operation now
9289 -- corresponds to the hardware remainder), and it does not seem likely
9290 -- that it could be harmful. It also avoids some cases of the elaborate
9291 -- expansion in Modify_Tree_For_C mode below (since Ada rem = C %).
9292
9293 if (LOK and ROK)
9294 and then ((Llo >= 0 and then Rlo >= 0)
9295 or else
9296 (Lhi <= 0 and then Rhi <= 0))
9297 and then not Is_Stoele_Mod
9298 then
9299 Rewrite (N,
9300 Make_Op_Rem (Sloc (N),
9301 Left_Opnd => Left_Opnd (N),
9302 Right_Opnd => Right_Opnd (N)));
9303
9304 -- Instead of reanalyzing the node we do the analysis manually. This
9305 -- avoids anomalies when the replacement is done in an instance and
9306 -- is epsilon more efficient.
9307
9308 pragma Assert (Entity (N) = Standard_Op_Rem);
9309 Set_Etype (N, Typ);
9310 Set_Do_Division_Check (N, DDC);
9311 Expand_N_Op_Rem (N);
9312 Set_Analyzed (N);
9313 return;
9314
9315 -- Otherwise, normal mod processing
9316
9317 else
9318 -- Apply optimization x mod 1 = 0. We don't really need that with
9319 -- gcc, but it is useful with other back ends and is certainly
9320 -- harmless.
9321
9322 if Is_Integer_Type (Etype (N))
9323 and then Compile_Time_Known_Value (Right)
9324 and then Expr_Value (Right) = Uint_1
9325 then
9326 -- Call Remove_Side_Effects to ensure that any side effects in
9327 -- the ignored left operand (in particular function calls to
9328 -- user defined functions) are properly executed.
9329
9330 Remove_Side_Effects (Left);
9331
9332 Rewrite (N, Make_Integer_Literal (Loc, 0));
9333 Analyze_And_Resolve (N, Typ);
9334 return;
9335 end if;
9336
9337 -- The negative case makes no sense since it is a case of a mod where
9338 -- the left argument is unsigned and the right argument is signed. In
9339 -- accordance with the (spirit of the) permission of RM 13.7.1(16),
9340 -- we raise CE, and also include the zero case here. Yes, the RM says
9341 -- PE, but this really is so obviously more like a constraint error.
9342
9343 if Is_Stoele_Mod and then (not ROK or else Rlo <= 0) then
9344 Insert_Action (N,
9345 Make_Raise_Constraint_Error (Loc,
9346 Condition =>
9347 Make_Op_Le (Loc,
9348 Left_Opnd =>
9349 Duplicate_Subexpr_No_Checks (Expression (Right)),
9350 Right_Opnd => Make_Integer_Literal (Loc, 0)),
9351 Reason => CE_Overflow_Check_Failed));
9352 return;
9353 end if;
9354
9355 -- If we still have a mod operator and we are in Modify_Tree_For_C
9356 -- mode, and we have a signed integer type, then here is where we do
9357 -- the rewrite in terms of Rem. Note this rewrite bypasses the need
9358 -- for the special handling of the annoying case of largest negative
9359 -- number mod minus one.
9360
9361 if Nkind (N) = N_Op_Mod
9362 and then Is_Signed_Integer_Type (Typ)
9363 and then Modify_Tree_For_C
9364 then
9365 -- In the general case, we expand A mod B as
9366
9367 -- Tnn : constant typ := A rem B;
9368 -- ..
9369 -- (if (A >= 0) = (B >= 0) then Tnn
9370 -- elsif Tnn = 0 then 0
9371 -- else Tnn + B)
9372
9373 -- The comparison can be written simply as A >= 0 if we know that
9374 -- B >= 0 which is a very common case.
9375
9376 -- An important optimization is when B is known at compile time
9377 -- to be 2**K for some constant. In this case we can simply AND
9378 -- the left operand with the bit string 2**K-1 (i.e. K 1-bits)
9379 -- and that works for both the positive and negative cases.
9380
9381 declare
9382 P2 : constant Nat := Power_Of_Two (Right);
9383
9384 begin
9385 if P2 /= 0 then
9386 Rewrite (N,
9387 Unchecked_Convert_To (Typ,
9388 Make_Op_And (Loc,
9389 Left_Opnd =>
9390 Unchecked_Convert_To
9391 (Corresponding_Unsigned_Type (Typ), Left),
9392 Right_Opnd =>
9393 Make_Integer_Literal (Loc, 2 ** P2 - 1))));
9394 Analyze_And_Resolve (N, Typ);
9395 return;
9396 end if;
9397 end;
9398
9399 -- Here for the full rewrite
9400
9401 declare
9402 Tnn : constant Entity_Id := Make_Temporary (Sloc (N), 'T', N);
9403 Cmp : Node_Id;
9404
9405 begin
9406 Cmp :=
9407 Make_Op_Ge (Loc,
9408 Left_Opnd => Duplicate_Subexpr_No_Checks (Left),
9409 Right_Opnd => Make_Integer_Literal (Loc, 0));
9410
9411 if not LOK or else Rlo < 0 then
9412 Cmp :=
9413 Make_Op_Eq (Loc,
9414 Left_Opnd => Cmp,
9415 Right_Opnd =>
9416 Make_Op_Ge (Loc,
9417 Left_Opnd => Duplicate_Subexpr_No_Checks (Right),
9418 Right_Opnd => Make_Integer_Literal (Loc, 0)));
9419 end if;
9420
9421 Insert_Action (N,
9422 Make_Object_Declaration (Loc,
9423 Defining_Identifier => Tnn,
9424 Constant_Present => True,
9425 Object_Definition => New_Occurrence_Of (Typ, Loc),
9426 Expression =>
9427 Make_Op_Rem (Loc,
9428 Left_Opnd => Left,
9429 Right_Opnd => Right)));
9430
9431 Rewrite (N,
9432 Make_If_Expression (Loc,
9433 Expressions => New_List (
9434 Cmp,
9435 New_Occurrence_Of (Tnn, Loc),
9436 Make_If_Expression (Loc,
9437 Is_Elsif => True,
9438 Expressions => New_List (
9439 Make_Op_Eq (Loc,
9440 Left_Opnd => New_Occurrence_Of (Tnn, Loc),
9441 Right_Opnd => Make_Integer_Literal (Loc, 0)),
9442 Make_Integer_Literal (Loc, 0),
9443 Make_Op_Add (Loc,
9444 Left_Opnd => New_Occurrence_Of (Tnn, Loc),
9445 Right_Opnd =>
9446 Duplicate_Subexpr_No_Checks (Right)))))));
9447
9448 Analyze_And_Resolve (N, Typ);
9449 return;
9450 end;
9451 end if;
9452
9453 -- Deal with annoying case of largest negative number mod minus one.
9454 -- Gigi may not handle this case correctly, because on some targets,
9455 -- the mod value is computed using a divide instruction which gives
9456 -- an overflow trap for this case.
9457
9458 -- It would be a bit more efficient to figure out which targets
9459 -- this is really needed for, but in practice it is reasonable
9460 -- to do the following special check in all cases, since it means
9461 -- we get a clearer message, and also the overhead is minimal given
9462 -- that division is expensive in any case.
9463
9464 -- In fact the check is quite easy, if the right operand is -1, then
9465 -- the mod value is always 0, and we can just ignore the left operand
9466 -- completely in this case.
9467
9468 -- This only applies if we still have a mod operator. Skip if we
9469 -- have already rewritten this (e.g. in the case of eliminated
9470 -- overflow checks which have driven us into bignum mode).
9471
9472 if Nkind (N) = N_Op_Mod then
9473
9474 -- The operand type may be private (e.g. in the expansion of an
9475 -- intrinsic operation) so we must use the underlying type to get
9476 -- the bounds, and convert the literals explicitly.
9477
9478 LLB :=
9479 Expr_Value
9480 (Type_Low_Bound (Base_Type (Underlying_Type (Etype (Left)))));
9481
9482 if (not ROK or else (Rlo <= (-1) and then (-1) <= Rhi))
9483 and then (not LOK or else Llo = LLB)
9484 and then not CodePeer_Mode
9485 then
9486 Rewrite (N,
9487 Make_If_Expression (Loc,
9488 Expressions => New_List (
9489 Make_Op_Eq (Loc,
9490 Left_Opnd => Duplicate_Subexpr (Right),
9491 Right_Opnd =>
9492 Unchecked_Convert_To (Typ,
9493 Make_Integer_Literal (Loc, -1))),
9494 Unchecked_Convert_To (Typ,
9495 Make_Integer_Literal (Loc, Uint_0)),
9496 Relocate_Node (N))));
9497
9498 Set_Analyzed (Next (Next (First (Expressions (N)))));
9499 Analyze_And_Resolve (N, Typ);
9500 end if;
9501 end if;
9502 end if;
9503 end Expand_N_Op_Mod;
9504
9505 --------------------------
9506 -- Expand_N_Op_Multiply --
9507 --------------------------
9508
9509 procedure Expand_N_Op_Multiply (N : Node_Id) is
9510 Loc : constant Source_Ptr := Sloc (N);
9511 Lop : constant Node_Id := Left_Opnd (N);
9512 Rop : constant Node_Id := Right_Opnd (N);
9513
9514 Lp2 : constant Boolean :=
9515 Nkind (Lop) = N_Op_Expon and then Is_Power_Of_2_For_Shift (Lop);
9516 Rp2 : constant Boolean :=
9517 Nkind (Rop) = N_Op_Expon and then Is_Power_Of_2_For_Shift (Rop);
9518
9519 Ltyp : constant Entity_Id := Etype (Lop);
9520 Rtyp : constant Entity_Id := Etype (Rop);
9521 Typ : Entity_Id := Etype (N);
9522
9523 begin
9524 Binary_Op_Validity_Checks (N);
9525
9526 -- Check for MINIMIZED/ELIMINATED overflow mode
9527
9528 if Minimized_Eliminated_Overflow_Check (N) then
9529 Apply_Arithmetic_Overflow_Check (N);
9530 return;
9531 end if;
9532
9533 -- Special optimizations for integer types
9534
9535 if Is_Integer_Type (Typ) then
9536
9537 -- N * 0 = 0 for integer types
9538
9539 if Compile_Time_Known_Value (Rop)
9540 and then Expr_Value (Rop) = Uint_0
9541 then
9542 -- Call Remove_Side_Effects to ensure that any side effects in
9543 -- the ignored left operand (in particular function calls to
9544 -- user defined functions) are properly executed.
9545
9546 Remove_Side_Effects (Lop);
9547
9548 Rewrite (N, Make_Integer_Literal (Loc, Uint_0));
9549 Analyze_And_Resolve (N, Typ);
9550 return;
9551 end if;
9552
9553 -- Similar handling for 0 * N = 0
9554
9555 if Compile_Time_Known_Value (Lop)
9556 and then Expr_Value (Lop) = Uint_0
9557 then
9558 Remove_Side_Effects (Rop);
9559 Rewrite (N, Make_Integer_Literal (Loc, Uint_0));
9560 Analyze_And_Resolve (N, Typ);
9561 return;
9562 end if;
9563
9564 -- N * 1 = 1 * N = N for integer types
9565
9566 -- This optimisation is not done if we are going to
9567 -- rewrite the product 1 * 2 ** N to a shift.
9568
9569 if Compile_Time_Known_Value (Rop)
9570 and then Expr_Value (Rop) = Uint_1
9571 and then not Lp2
9572 then
9573 Rewrite (N, Lop);
9574 return;
9575
9576 elsif Compile_Time_Known_Value (Lop)
9577 and then Expr_Value (Lop) = Uint_1
9578 and then not Rp2
9579 then
9580 Rewrite (N, Rop);
9581 return;
9582 end if;
9583 end if;
9584
9585 -- Convert x * 2 ** y to Shift_Left (x, y). Note that the fact that
9586 -- Is_Power_Of_2_For_Shift is set means that we know that our left
9587 -- operand is an integer, as required for this to work.
9588
9589 if Rp2 then
9590 if Lp2 then
9591
9592 -- Convert 2 ** A * 2 ** B into 2 ** (A + B)
9593
9594 Rewrite (N,
9595 Make_Op_Expon (Loc,
9596 Left_Opnd => Make_Integer_Literal (Loc, 2),
9597 Right_Opnd =>
9598 Make_Op_Add (Loc,
9599 Left_Opnd => Right_Opnd (Lop),
9600 Right_Opnd => Right_Opnd (Rop))));
9601 Analyze_And_Resolve (N, Typ);
9602 return;
9603
9604 else
9605 -- If the result is modular, perform the reduction of the result
9606 -- appropriately.
9607
9608 if Is_Modular_Integer_Type (Typ)
9609 and then not Non_Binary_Modulus (Typ)
9610 then
9611 Rewrite (N,
9612 Make_Op_And (Loc,
9613 Left_Opnd =>
9614 Make_Op_Shift_Left (Loc,
9615 Left_Opnd => Lop,
9616 Right_Opnd =>
9617 Convert_To (Standard_Natural, Right_Opnd (Rop))),
9618 Right_Opnd =>
9619 Make_Integer_Literal (Loc, Modulus (Typ) - 1)));
9620
9621 else
9622 Rewrite (N,
9623 Make_Op_Shift_Left (Loc,
9624 Left_Opnd => Lop,
9625 Right_Opnd =>
9626 Convert_To (Standard_Natural, Right_Opnd (Rop))));
9627 end if;
9628
9629 Analyze_And_Resolve (N, Typ);
9630 return;
9631 end if;
9632
9633 -- Same processing for the operands the other way round
9634
9635 elsif Lp2 then
9636 if Is_Modular_Integer_Type (Typ)
9637 and then not Non_Binary_Modulus (Typ)
9638 then
9639 Rewrite (N,
9640 Make_Op_And (Loc,
9641 Left_Opnd =>
9642 Make_Op_Shift_Left (Loc,
9643 Left_Opnd => Rop,
9644 Right_Opnd =>
9645 Convert_To (Standard_Natural, Right_Opnd (Lop))),
9646 Right_Opnd =>
9647 Make_Integer_Literal (Loc, Modulus (Typ) - 1)));
9648
9649 else
9650 Rewrite (N,
9651 Make_Op_Shift_Left (Loc,
9652 Left_Opnd => Rop,
9653 Right_Opnd =>
9654 Convert_To (Standard_Natural, Right_Opnd (Lop))));
9655 end if;
9656
9657 Analyze_And_Resolve (N, Typ);
9658 return;
9659 end if;
9660
9661 -- Try to narrow the operation
9662
9663 if Typ = Universal_Integer then
9664 Narrow_Large_Operation (N);
9665
9666 if Nkind (N) /= N_Op_Multiply then
9667 return;
9668 end if;
9669 end if;
9670
9671 -- Do required fixup of universal fixed operation
9672
9673 if Typ = Universal_Fixed then
9674 Fixup_Universal_Fixed_Operation (N);
9675 Typ := Etype (N);
9676 end if;
9677
9678 -- Multiplications with fixed-point results
9679
9680 if Is_Fixed_Point_Type (Typ) then
9681
9682 -- Case of fixed * integer => fixed
9683
9684 if Is_Integer_Type (Rtyp) then
9685 Expand_Multiply_Fixed_By_Integer_Giving_Fixed (N);
9686
9687 -- Case of integer * fixed => fixed
9688
9689 elsif Is_Integer_Type (Ltyp) then
9690 Expand_Multiply_Integer_By_Fixed_Giving_Fixed (N);
9691
9692 -- Case of fixed * fixed => fixed
9693
9694 else
9695 Expand_Multiply_Fixed_By_Fixed_Giving_Fixed (N);
9696 end if;
9697
9698 -- Other cases of multiplication of fixed-point operands
9699
9700 elsif Is_Fixed_Point_Type (Ltyp) or else Is_Fixed_Point_Type (Rtyp) then
9701 if Is_Integer_Type (Typ) then
9702 Expand_Multiply_Fixed_By_Fixed_Giving_Integer (N);
9703 else
9704 pragma Assert (Is_Floating_Point_Type (Typ));
9705 Expand_Multiply_Fixed_By_Fixed_Giving_Float (N);
9706 end if;
9707
9708 -- Mixed-mode operations can appear in a non-static universal context,
9709 -- in which case the integer argument must be converted explicitly.
9710
9711 elsif Typ = Universal_Real and then Is_Integer_Type (Rtyp) then
9712 Rewrite (Rop, Convert_To (Universal_Real, Relocate_Node (Rop)));
9713 Analyze_And_Resolve (Rop, Universal_Real);
9714
9715 elsif Typ = Universal_Real and then Is_Integer_Type (Ltyp) then
9716 Rewrite (Lop, Convert_To (Universal_Real, Relocate_Node (Lop)));
9717 Analyze_And_Resolve (Lop, Universal_Real);
9718
9719 -- Non-fixed point cases, check software overflow checking required
9720
9721 elsif Is_Signed_Integer_Type (Etype (N)) then
9722 Apply_Arithmetic_Overflow_Check (N);
9723 end if;
9724
9725 -- Overflow checks for floating-point if -gnateF mode active
9726
9727 Check_Float_Op_Overflow (N);
9728
9729 Expand_Nonbinary_Modular_Op (N);
9730 end Expand_N_Op_Multiply;
9731
9732 --------------------
9733 -- Expand_N_Op_Ne --
9734 --------------------
9735
9736 procedure Expand_N_Op_Ne (N : Node_Id) is
9737 Typ : constant Entity_Id := Etype (Left_Opnd (N));
9738
9739 begin
9740 -- Case of elementary type with standard operator. But if unnesting,
9741 -- handle elementary types whose Equivalent_Types are records because
9742 -- there may be padding or undefined fields.
9743
9744 if Is_Elementary_Type (Typ)
9745 and then Sloc (Entity (N)) = Standard_Location
9746 and then not (Ekind (Typ) in E_Class_Wide_Type
9747 | E_Class_Wide_Subtype
9748 | E_Access_Subprogram_Type
9749 | E_Access_Protected_Subprogram_Type
9750 | E_Anonymous_Access_Protected_Subprogram_Type
9751 | E_Exception_Type
9752 and then Present (Equivalent_Type (Typ))
9753 and then Is_Record_Type (Equivalent_Type (Typ)))
9754 then
9755 Binary_Op_Validity_Checks (N);
9756
9757 -- Deal with overflow checks in MINIMIZED/ELIMINATED mode and if
9758 -- means we no longer have a /= operation, we are all done.
9759
9760 if Minimized_Eliminated_Overflow_Check (Left_Opnd (N)) then
9761 Expand_Compare_Minimize_Eliminate_Overflow (N);
9762 end if;
9763
9764 if Nkind (N) /= N_Op_Ne then
9765 return;
9766 end if;
9767
9768 -- Boolean types (requiring handling of non-standard case)
9769
9770 if Is_Boolean_Type (Typ) then
9771 Adjust_Condition (Left_Opnd (N));
9772 Adjust_Condition (Right_Opnd (N));
9773 Set_Etype (N, Standard_Boolean);
9774 Adjust_Result_Type (N, Typ);
9775 end if;
9776
9777 Rewrite_Comparison (N);
9778
9779 -- Try to narrow the operation
9780
9781 if Typ = Universal_Integer and then Nkind (N) = N_Op_Ne then
9782 Narrow_Large_Operation (N);
9783 end if;
9784
9785 -- For all cases other than elementary types, we rewrite node as the
9786 -- negation of an equality operation, and reanalyze. The equality to be
9787 -- used is defined in the same scope and has the same signature. This
9788 -- signature must be set explicitly since in an instance it may not have
9789 -- the same visibility as in the generic unit. This avoids duplicating
9790 -- or factoring the complex code for record/array equality tests etc.
9791
9792 -- This case is also used for the minimal expansion performed in
9793 -- GNATprove mode.
9794
9795 else
9796 declare
9797 Loc : constant Source_Ptr := Sloc (N);
9798 Neg : Node_Id;
9799 Ne : constant Entity_Id := Entity (N);
9800
9801 begin
9802 Binary_Op_Validity_Checks (N);
9803
9804 Neg :=
9805 Make_Op_Not (Loc,
9806 Right_Opnd =>
9807 Make_Op_Eq (Loc,
9808 Left_Opnd => Left_Opnd (N),
9809 Right_Opnd => Right_Opnd (N)));
9810
9811 if Scope (Ne) /= Standard_Standard then
9812 Set_Entity (Right_Opnd (Neg), Corresponding_Equality (Ne));
9813 end if;
9814
9815 -- For navigation purposes, we want to treat the inequality as an
9816 -- implicit reference to the corresponding equality. Preserve the
9817 -- Comes_From_ source flag to generate proper Xref entries.
9818
9819 Preserve_Comes_From_Source (Neg, N);
9820 Preserve_Comes_From_Source (Right_Opnd (Neg), N);
9821 Rewrite (N, Neg);
9822 Analyze_And_Resolve (N, Standard_Boolean);
9823 end;
9824 end if;
9825
9826 -- No need for optimization in GNATprove mode, where we would rather see
9827 -- the original source expression.
9828
9829 if not GNATprove_Mode then
9830 Optimize_Length_Comparison (N);
9831 end if;
9832 end Expand_N_Op_Ne;
9833
9834 ---------------------
9835 -- Expand_N_Op_Not --
9836 ---------------------
9837
9838 -- If the argument is other than a Boolean array type, there is no special
9839 -- expansion required, except for dealing with validity checks, and non-
9840 -- standard boolean representations.
9841
9842 -- For the packed array case, we call the special routine in Exp_Pakd,
9843 -- except that if the component size is greater than one, we use the
9844 -- standard routine generating a gruesome loop (it is so peculiar to have
9845 -- packed arrays with non-standard Boolean representations anyway, so it
9846 -- does not matter that we do not handle this case efficiently).
9847
9848 -- For the unpacked array case (and for the special packed case where we
9849 -- have non standard Booleans, as discussed above), we generate and insert
9850 -- into the tree the following function definition:
9851
9852 -- function Nnnn (A : arr) is
9853 -- B : arr;
9854 -- begin
9855 -- for J in a'range loop
9856 -- B (J) := not A (J);
9857 -- end loop;
9858 -- return B;
9859 -- end Nnnn;
9860
9861 -- or in the case of Transform_Function_Array:
9862
9863 -- procedure Nnnn (A : arr; RESULT : out arr) is
9864 -- begin
9865 -- for J in a'range loop
9866 -- RESULT (J) := not A (J);
9867 -- end loop;
9868 -- end Nnnn;
9869
9870 -- Here arr is the actual subtype of the parameter (and hence always
9871 -- constrained). Then we replace the not with a call to this subprogram.
9872
9873 procedure Expand_N_Op_Not (N : Node_Id) is
9874 Loc : constant Source_Ptr := Sloc (N);
9875 Typ : constant Entity_Id := Etype (Right_Opnd (N));
9876 Opnd : Node_Id;
9877 Arr : Entity_Id;
9878 A : Entity_Id;
9879 B : Entity_Id;
9880 J : Entity_Id;
9881 A_J : Node_Id;
9882 B_J : Node_Id;
9883
9884 Func_Name : Entity_Id;
9885 Loop_Statement : Node_Id;
9886
9887 begin
9888 Unary_Op_Validity_Checks (N);
9889
9890 -- For boolean operand, deal with non-standard booleans
9891
9892 if Is_Boolean_Type (Typ) then
9893 Adjust_Condition (Right_Opnd (N));
9894 Set_Etype (N, Standard_Boolean);
9895 Adjust_Result_Type (N, Typ);
9896 return;
9897 end if;
9898
9899 -- Only array types need any other processing
9900
9901 if not Is_Array_Type (Typ) then
9902 return;
9903 end if;
9904
9905 -- Case of array operand. If bit packed with a component size of 1,
9906 -- handle it in Exp_Pakd if the operand is known to be aligned.
9907
9908 if Is_Bit_Packed_Array (Typ)
9909 and then Component_Size (Typ) = 1
9910 and then not Is_Possibly_Unaligned_Object (Right_Opnd (N))
9911 then
9912 Expand_Packed_Not (N);
9913 return;
9914 end if;
9915
9916 -- Case of array operand which is not bit-packed. If the context is
9917 -- a safe assignment, call in-place operation, If context is a larger
9918 -- boolean expression in the context of a safe assignment, expansion is
9919 -- done by enclosing operation.
9920
9921 Opnd := Relocate_Node (Right_Opnd (N));
9922 Convert_To_Actual_Subtype (Opnd);
9923 Arr := Etype (Opnd);
9924 Ensure_Defined (Arr, N);
9925 Silly_Boolean_Array_Not_Test (N, Arr);
9926
9927 if Nkind (Parent (N)) = N_Assignment_Statement then
9928 if Safe_In_Place_Array_Op (Name (Parent (N)), N, Empty) then
9929 Build_Boolean_Array_Proc_Call (Parent (N), Opnd, Empty);
9930 return;
9931
9932 -- Special case the negation of a binary operation
9933
9934 elsif Nkind (Opnd) in N_Op_And | N_Op_Or | N_Op_Xor
9935 and then Safe_In_Place_Array_Op
9936 (Name (Parent (N)), Left_Opnd (Opnd), Right_Opnd (Opnd))
9937 then
9938 Build_Boolean_Array_Proc_Call (Parent (N), Opnd, Empty);
9939 return;
9940 end if;
9941
9942 elsif Nkind (Parent (N)) in N_Binary_Op
9943 and then Nkind (Parent (Parent (N))) = N_Assignment_Statement
9944 then
9945 declare
9946 Op1 : constant Node_Id := Left_Opnd (Parent (N));
9947 Op2 : constant Node_Id := Right_Opnd (Parent (N));
9948 Lhs : constant Node_Id := Name (Parent (Parent (N)));
9949
9950 begin
9951 if Safe_In_Place_Array_Op (Lhs, Op1, Op2) then
9952
9953 -- (not A) op (not B) can be reduced to a single call
9954
9955 if N = Op1 and then Nkind (Op2) = N_Op_Not then
9956 return;
9957
9958 elsif N = Op2 and then Nkind (Op1) = N_Op_Not then
9959 return;
9960
9961 -- A xor (not B) can also be special-cased
9962
9963 elsif N = Op2 and then Nkind (Parent (N)) = N_Op_Xor then
9964 return;
9965 end if;
9966 end if;
9967 end;
9968 end if;
9969
9970 A := Make_Defining_Identifier (Loc, Name_uA);
9971
9972 if Transform_Function_Array then
9973 B := Make_Defining_Identifier (Loc, Name_UP_RESULT);
9974 else
9975 B := Make_Defining_Identifier (Loc, Name_uB);
9976 end if;
9977
9978 J := Make_Defining_Identifier (Loc, Name_uJ);
9979
9980 A_J :=
9981 Make_Indexed_Component (Loc,
9982 Prefix => New_Occurrence_Of (A, Loc),
9983 Expressions => New_List (New_Occurrence_Of (J, Loc)));
9984
9985 B_J :=
9986 Make_Indexed_Component (Loc,
9987 Prefix => New_Occurrence_Of (B, Loc),
9988 Expressions => New_List (New_Occurrence_Of (J, Loc)));
9989
9990 Loop_Statement :=
9991 Make_Implicit_Loop_Statement (N,
9992 Identifier => Empty,
9993
9994 Iteration_Scheme =>
9995 Make_Iteration_Scheme (Loc,
9996 Loop_Parameter_Specification =>
9997 Make_Loop_Parameter_Specification (Loc,
9998 Defining_Identifier => J,
9999 Discrete_Subtype_Definition =>
10000 Make_Attribute_Reference (Loc,
10001 Prefix => Make_Identifier (Loc, Chars (A)),
10002 Attribute_Name => Name_Range))),
10003
10004 Statements => New_List (
10005 Make_Assignment_Statement (Loc,
10006 Name => B_J,
10007 Expression => Make_Op_Not (Loc, A_J))));
10008
10009 Func_Name := Make_Temporary (Loc, 'N');
10010 Set_Is_Inlined (Func_Name);
10011
10012 if Transform_Function_Array then
10013 Insert_Action (N,
10014 Make_Subprogram_Body (Loc,
10015 Specification =>
10016 Make_Procedure_Specification (Loc,
10017 Defining_Unit_Name => Func_Name,
10018 Parameter_Specifications => New_List (
10019 Make_Parameter_Specification (Loc,
10020 Defining_Identifier => A,
10021 Parameter_Type => New_Occurrence_Of (Typ, Loc)),
10022 Make_Parameter_Specification (Loc,
10023 Defining_Identifier => B,
10024 Out_Present => True,
10025 Parameter_Type => New_Occurrence_Of (Typ, Loc)))),
10026
10027 Declarations => New_List,
10028
10029 Handled_Statement_Sequence =>
10030 Make_Handled_Sequence_Of_Statements (Loc,
10031 Statements => New_List (Loop_Statement))));
10032
10033 declare
10034 Temp_Id : constant Entity_Id := Make_Temporary (Loc, 'T');
10035 Call : Node_Id;
10036 Decl : Node_Id;
10037
10038 begin
10039 -- Generate:
10040 -- Temp : ...;
10041
10042 Decl :=
10043 Make_Object_Declaration (Loc,
10044 Defining_Identifier => Temp_Id,
10045 Object_Definition => New_Occurrence_Of (Typ, Loc));
10046
10047 -- Generate:
10048 -- Proc_Call (Opnd, Temp);
10049
10050 Call :=
10051 Make_Procedure_Call_Statement (Loc,
10052 Name => New_Occurrence_Of (Func_Name, Loc),
10053 Parameter_Associations =>
10054 New_List (Opnd, New_Occurrence_Of (Temp_Id, Loc)));
10055
10056 Insert_Actions (Parent (N), New_List (Decl, Call));
10057 Rewrite (N, New_Occurrence_Of (Temp_Id, Loc));
10058 end;
10059 else
10060 Insert_Action (N,
10061 Make_Subprogram_Body (Loc,
10062 Specification =>
10063 Make_Function_Specification (Loc,
10064 Defining_Unit_Name => Func_Name,
10065 Parameter_Specifications => New_List (
10066 Make_Parameter_Specification (Loc,
10067 Defining_Identifier => A,
10068 Parameter_Type => New_Occurrence_Of (Typ, Loc))),
10069 Result_Definition => New_Occurrence_Of (Typ, Loc)),
10070
10071 Declarations => New_List (
10072 Make_Object_Declaration (Loc,
10073 Defining_Identifier => B,
10074 Object_Definition => New_Occurrence_Of (Arr, Loc))),
10075
10076 Handled_Statement_Sequence =>
10077 Make_Handled_Sequence_Of_Statements (Loc,
10078 Statements => New_List (
10079 Loop_Statement,
10080 Make_Simple_Return_Statement (Loc,
10081 Expression => Make_Identifier (Loc, Chars (B)))))));
10082
10083 Rewrite (N,
10084 Make_Function_Call (Loc,
10085 Name => New_Occurrence_Of (Func_Name, Loc),
10086 Parameter_Associations => New_List (Opnd)));
10087 end if;
10088
10089 Analyze_And_Resolve (N, Typ);
10090 end Expand_N_Op_Not;
10091
10092 --------------------
10093 -- Expand_N_Op_Or --
10094 --------------------
10095
10096 procedure Expand_N_Op_Or (N : Node_Id) is
10097 Typ : constant Entity_Id := Etype (N);
10098
10099 begin
10100 Binary_Op_Validity_Checks (N);
10101
10102 if Is_Array_Type (Etype (N)) then
10103 Expand_Boolean_Operator (N);
10104
10105 elsif Is_Boolean_Type (Etype (N)) then
10106 Adjust_Condition (Left_Opnd (N));
10107 Adjust_Condition (Right_Opnd (N));
10108 Set_Etype (N, Standard_Boolean);
10109 Adjust_Result_Type (N, Typ);
10110
10111 elsif Is_Intrinsic_Subprogram (Entity (N)) then
10112 Expand_Intrinsic_Call (N, Entity (N));
10113 end if;
10114
10115 Expand_Nonbinary_Modular_Op (N);
10116 end Expand_N_Op_Or;
10117
10118 ----------------------
10119 -- Expand_N_Op_Plus --
10120 ----------------------
10121
10122 procedure Expand_N_Op_Plus (N : Node_Id) is
10123 Typ : constant Entity_Id := Etype (N);
10124
10125 begin
10126 Unary_Op_Validity_Checks (N);
10127
10128 -- Check for MINIMIZED/ELIMINATED overflow mode
10129
10130 if Minimized_Eliminated_Overflow_Check (N) then
10131 Apply_Arithmetic_Overflow_Check (N);
10132 return;
10133 end if;
10134
10135 -- Try to narrow the operation
10136
10137 if Typ = Universal_Integer then
10138 Narrow_Large_Operation (N);
10139 end if;
10140 end Expand_N_Op_Plus;
10141
10142 ---------------------
10143 -- Expand_N_Op_Rem --
10144 ---------------------
10145
10146 procedure Expand_N_Op_Rem (N : Node_Id) is
10147 Loc : constant Source_Ptr := Sloc (N);
10148 Typ : constant Entity_Id := Etype (N);
10149
10150 Left : Node_Id;
10151 Right : Node_Id;
10152
10153 Lo : Uint;
10154 Hi : Uint;
10155 OK : Boolean;
10156
10157 Lneg : Boolean;
10158 Rneg : Boolean;
10159 -- Set if corresponding operand can be negative
10160
10161 begin
10162 Binary_Op_Validity_Checks (N);
10163
10164 -- Check for MINIMIZED/ELIMINATED overflow mode
10165
10166 if Minimized_Eliminated_Overflow_Check (N) then
10167 Apply_Arithmetic_Overflow_Check (N);
10168 return;
10169 end if;
10170
10171 -- Try to narrow the operation
10172
10173 if Typ = Universal_Integer then
10174 Narrow_Large_Operation (N);
10175
10176 if Nkind (N) /= N_Op_Rem then
10177 return;
10178 end if;
10179 end if;
10180
10181 if Is_Integer_Type (Etype (N)) then
10182 Apply_Divide_Checks (N);
10183
10184 -- All done if we don't have a REM any more, which can happen as a
10185 -- result of overflow expansion in MINIMIZED or ELIMINATED modes.
10186
10187 if Nkind (N) /= N_Op_Rem then
10188 return;
10189 end if;
10190 end if;
10191
10192 -- Proceed with expansion of REM
10193
10194 Left := Left_Opnd (N);
10195 Right := Right_Opnd (N);
10196
10197 -- Apply optimization x rem 1 = 0. We don't really need that with gcc,
10198 -- but it is useful with other back ends, and is certainly harmless.
10199
10200 if Is_Integer_Type (Etype (N))
10201 and then Compile_Time_Known_Value (Right)
10202 and then Expr_Value (Right) = Uint_1
10203 then
10204 -- Call Remove_Side_Effects to ensure that any side effects in the
10205 -- ignored left operand (in particular function calls to user defined
10206 -- functions) are properly executed.
10207
10208 Remove_Side_Effects (Left);
10209
10210 Rewrite (N, Make_Integer_Literal (Loc, 0));
10211 Analyze_And_Resolve (N, Typ);
10212 return;
10213 end if;
10214
10215 -- Deal with annoying case of largest negative number remainder minus
10216 -- one. Gigi may not handle this case correctly, because on some
10217 -- targets, the mod value is computed using a divide instruction
10218 -- which gives an overflow trap for this case.
10219
10220 -- It would be a bit more efficient to figure out which targets this
10221 -- is really needed for, but in practice it is reasonable to do the
10222 -- following special check in all cases, since it means we get a clearer
10223 -- message, and also the overhead is minimal given that division is
10224 -- expensive in any case.
10225
10226 -- In fact the check is quite easy, if the right operand is -1, then
10227 -- the remainder is always 0, and we can just ignore the left operand
10228 -- completely in this case.
10229
10230 Determine_Range (Right, OK, Lo, Hi, Assume_Valid => True);
10231 Lneg := not OK or else Lo < 0;
10232
10233 Determine_Range (Left, OK, Lo, Hi, Assume_Valid => True);
10234 Rneg := not OK or else Lo < 0;
10235
10236 -- We won't mess with trying to find out if the left operand can really
10237 -- be the largest negative number (that's a pain in the case of private
10238 -- types and this is really marginal). We will just assume that we need
10239 -- the test if the left operand can be negative at all.
10240
10241 if (Lneg and Rneg)
10242 and then not CodePeer_Mode
10243 then
10244 Rewrite (N,
10245 Make_If_Expression (Loc,
10246 Expressions => New_List (
10247 Make_Op_Eq (Loc,
10248 Left_Opnd => Duplicate_Subexpr (Right),
10249 Right_Opnd =>
10250 Unchecked_Convert_To (Typ, Make_Integer_Literal (Loc, -1))),
10251
10252 Unchecked_Convert_To (Typ,
10253 Make_Integer_Literal (Loc, Uint_0)),
10254
10255 Relocate_Node (N))));
10256
10257 Set_Analyzed (Next (Next (First (Expressions (N)))));
10258 Analyze_And_Resolve (N, Typ);
10259 end if;
10260 end Expand_N_Op_Rem;
10261
10262 -----------------------------
10263 -- Expand_N_Op_Rotate_Left --
10264 -----------------------------
10265
10266 procedure Expand_N_Op_Rotate_Left (N : Node_Id) is
10267 begin
10268 Binary_Op_Validity_Checks (N);
10269
10270 -- If we are in Modify_Tree_For_C mode, there is no rotate left in C,
10271 -- so we rewrite in terms of logical shifts
10272
10273 -- Shift_Left (Num, Bits) or Shift_Right (num, Esize - Bits)
10274
10275 -- where Bits is the shift count mod Esize (the mod operation here
10276 -- deals with ludicrous large shift counts, which are apparently OK).
10277
10278 if Modify_Tree_For_C then
10279 declare
10280 Loc : constant Source_Ptr := Sloc (N);
10281 Rtp : constant Entity_Id := Etype (Right_Opnd (N));
10282 Typ : constant Entity_Id := Etype (N);
10283
10284 begin
10285 -- Sem_Intr should prevent getting there with a non binary modulus
10286
10287 pragma Assert (not Non_Binary_Modulus (Typ));
10288
10289 Rewrite (Right_Opnd (N),
10290 Make_Op_Rem (Loc,
10291 Left_Opnd => Relocate_Node (Right_Opnd (N)),
10292 Right_Opnd => Make_Integer_Literal (Loc, Esize (Typ))));
10293
10294 Analyze_And_Resolve (Right_Opnd (N), Rtp);
10295
10296 Rewrite (N,
10297 Make_Op_Or (Loc,
10298 Left_Opnd =>
10299 Make_Op_Shift_Left (Loc,
10300 Left_Opnd => Left_Opnd (N),
10301 Right_Opnd => Right_Opnd (N)),
10302
10303 Right_Opnd =>
10304 Make_Op_Shift_Right (Loc,
10305 Left_Opnd => Duplicate_Subexpr_No_Checks (Left_Opnd (N)),
10306 Right_Opnd =>
10307 Make_Op_Subtract (Loc,
10308 Left_Opnd => Make_Integer_Literal (Loc, Esize (Typ)),
10309 Right_Opnd =>
10310 Duplicate_Subexpr_No_Checks (Right_Opnd (N))))));
10311
10312 Analyze_And_Resolve (N, Typ);
10313 end;
10314 end if;
10315 end Expand_N_Op_Rotate_Left;
10316
10317 ------------------------------
10318 -- Expand_N_Op_Rotate_Right --
10319 ------------------------------
10320
10321 procedure Expand_N_Op_Rotate_Right (N : Node_Id) is
10322 begin
10323 Binary_Op_Validity_Checks (N);
10324
10325 -- If we are in Modify_Tree_For_C mode, there is no rotate right in C,
10326 -- so we rewrite in terms of logical shifts
10327
10328 -- Shift_Right (Num, Bits) or Shift_Left (num, Esize - Bits)
10329
10330 -- where Bits is the shift count mod Esize (the mod operation here
10331 -- deals with ludicrous large shift counts, which are apparently OK).
10332
10333 if Modify_Tree_For_C then
10334 declare
10335 Loc : constant Source_Ptr := Sloc (N);
10336 Rtp : constant Entity_Id := Etype (Right_Opnd (N));
10337 Typ : constant Entity_Id := Etype (N);
10338
10339 begin
10340 -- Sem_Intr should prevent getting there with a non binary modulus
10341
10342 pragma Assert (not Non_Binary_Modulus (Typ));
10343
10344 Rewrite (Right_Opnd (N),
10345 Make_Op_Rem (Loc,
10346 Left_Opnd => Relocate_Node (Right_Opnd (N)),
10347 Right_Opnd => Make_Integer_Literal (Loc, Esize (Typ))));
10348
10349 Analyze_And_Resolve (Right_Opnd (N), Rtp);
10350
10351 Rewrite (N,
10352 Make_Op_Or (Loc,
10353 Left_Opnd =>
10354 Make_Op_Shift_Right (Loc,
10355 Left_Opnd => Left_Opnd (N),
10356 Right_Opnd => Right_Opnd (N)),
10357
10358 Right_Opnd =>
10359 Make_Op_Shift_Left (Loc,
10360 Left_Opnd => Duplicate_Subexpr_No_Checks (Left_Opnd (N)),
10361 Right_Opnd =>
10362 Make_Op_Subtract (Loc,
10363 Left_Opnd => Make_Integer_Literal (Loc, Esize (Typ)),
10364 Right_Opnd =>
10365 Duplicate_Subexpr_No_Checks (Right_Opnd (N))))));
10366
10367 Analyze_And_Resolve (N, Typ);
10368 end;
10369 end if;
10370 end Expand_N_Op_Rotate_Right;
10371
10372 ----------------------------
10373 -- Expand_N_Op_Shift_Left --
10374 ----------------------------
10375
10376 -- Note: nothing in this routine depends on left as opposed to right shifts
10377 -- so we share the routine for expanding shift right operations.
10378
10379 procedure Expand_N_Op_Shift_Left (N : Node_Id) is
10380 begin
10381 Binary_Op_Validity_Checks (N);
10382
10383 -- If we are in Modify_Tree_For_C mode, then ensure that the right
10384 -- operand is not greater than the word size (since that would not
10385 -- be defined properly by the corresponding C shift operator).
10386
10387 if Modify_Tree_For_C then
10388 declare
10389 Right : constant Node_Id := Right_Opnd (N);
10390 Loc : constant Source_Ptr := Sloc (Right);
10391 Typ : constant Entity_Id := Etype (N);
10392 Siz : constant Uint := Esize (Typ);
10393 Orig : Node_Id;
10394 OK : Boolean;
10395 Lo : Uint;
10396 Hi : Uint;
10397
10398 begin
10399 -- Sem_Intr should prevent getting there with a non binary modulus
10400
10401 pragma Assert (not Non_Binary_Modulus (Typ));
10402
10403 if Compile_Time_Known_Value (Right) then
10404 if Expr_Value (Right) >= Siz then
10405 Rewrite (N, Make_Integer_Literal (Loc, 0));
10406 Analyze_And_Resolve (N, Typ);
10407 end if;
10408
10409 -- Not compile time known, find range
10410
10411 else
10412 Determine_Range (Right, OK, Lo, Hi, Assume_Valid => True);
10413
10414 -- Nothing to do if known to be OK range, otherwise expand
10415
10416 if not OK or else Hi >= Siz then
10417
10418 -- Prevent recursion on copy of shift node
10419
10420 Orig := Relocate_Node (N);
10421 Set_Analyzed (Orig);
10422
10423 -- Now do the rewrite
10424
10425 Rewrite (N,
10426 Make_If_Expression (Loc,
10427 Expressions => New_List (
10428 Make_Op_Ge (Loc,
10429 Left_Opnd => Duplicate_Subexpr_Move_Checks (Right),
10430 Right_Opnd => Make_Integer_Literal (Loc, Siz)),
10431 Make_Integer_Literal (Loc, 0),
10432 Orig)));
10433 Analyze_And_Resolve (N, Typ);
10434 end if;
10435 end if;
10436 end;
10437 end if;
10438 end Expand_N_Op_Shift_Left;
10439
10440 -----------------------------
10441 -- Expand_N_Op_Shift_Right --
10442 -----------------------------
10443
10444 procedure Expand_N_Op_Shift_Right (N : Node_Id) is
10445 begin
10446 -- Share shift left circuit
10447
10448 Expand_N_Op_Shift_Left (N);
10449 end Expand_N_Op_Shift_Right;
10450
10451 ----------------------------------------
10452 -- Expand_N_Op_Shift_Right_Arithmetic --
10453 ----------------------------------------
10454
10455 procedure Expand_N_Op_Shift_Right_Arithmetic (N : Node_Id) is
10456 begin
10457 Binary_Op_Validity_Checks (N);
10458
10459 -- If we are in Modify_Tree_For_C mode, there is no shift right
10460 -- arithmetic in C, so we rewrite in terms of logical shifts for
10461 -- modular integers, and keep the Shift_Right intrinsic for signed
10462 -- integers: even though doing a shift on a signed integer is not
10463 -- fully guaranteed by the C standard, this is what C compilers
10464 -- implement in practice.
10465 -- Consider also taking advantage of this for modular integers by first
10466 -- performing an unchecked conversion of the modular integer to a signed
10467 -- integer of the same sign, and then convert back.
10468
10469 -- Shift_Right (Num, Bits) or
10470 -- (if Num >= Sign
10471 -- then not (Shift_Right (Mask, bits))
10472 -- else 0)
10473
10474 -- Here Mask is all 1 bits (2**size - 1), and Sign is 2**(size - 1)
10475
10476 -- Note: the above works fine for shift counts greater than or equal
10477 -- to the word size, since in this case (not (Shift_Right (Mask, bits)))
10478 -- generates all 1'bits.
10479
10480 if Modify_Tree_For_C and then Is_Modular_Integer_Type (Etype (N)) then
10481 declare
10482 Loc : constant Source_Ptr := Sloc (N);
10483 Typ : constant Entity_Id := Etype (N);
10484 Sign : constant Uint := 2 ** (Esize (Typ) - 1);
10485 Mask : constant Uint := (2 ** Esize (Typ)) - 1;
10486 Left : constant Node_Id := Left_Opnd (N);
10487 Right : constant Node_Id := Right_Opnd (N);
10488 Maskx : Node_Id;
10489
10490 begin
10491 -- Sem_Intr should prevent getting there with a non binary modulus
10492
10493 pragma Assert (not Non_Binary_Modulus (Typ));
10494
10495 -- Here if not (Shift_Right (Mask, bits)) can be computed at
10496 -- compile time as a single constant.
10497
10498 if Compile_Time_Known_Value (Right) then
10499 declare
10500 Val : constant Uint := Expr_Value (Right);
10501
10502 begin
10503 if Val >= Esize (Typ) then
10504 Maskx := Make_Integer_Literal (Loc, Mask);
10505
10506 else
10507 Maskx :=
10508 Make_Integer_Literal (Loc,
10509 Intval => Mask - (Mask / (2 ** Expr_Value (Right))));
10510 end if;
10511 end;
10512
10513 else
10514 Maskx :=
10515 Make_Op_Not (Loc,
10516 Right_Opnd =>
10517 Make_Op_Shift_Right (Loc,
10518 Left_Opnd => Make_Integer_Literal (Loc, Mask),
10519 Right_Opnd => Duplicate_Subexpr_No_Checks (Right)));
10520 end if;
10521
10522 -- Now do the rewrite
10523
10524 Rewrite (N,
10525 Make_Op_Or (Loc,
10526 Left_Opnd =>
10527 Make_Op_Shift_Right (Loc,
10528 Left_Opnd => Left,
10529 Right_Opnd => Right),
10530 Right_Opnd =>
10531 Make_If_Expression (Loc,
10532 Expressions => New_List (
10533 Make_Op_Ge (Loc,
10534 Left_Opnd => Duplicate_Subexpr_No_Checks (Left),
10535 Right_Opnd => Make_Integer_Literal (Loc, Sign)),
10536 Maskx,
10537 Make_Integer_Literal (Loc, 0)))));
10538 Analyze_And_Resolve (N, Typ);
10539 end;
10540 end if;
10541 end Expand_N_Op_Shift_Right_Arithmetic;
10542
10543 --------------------------
10544 -- Expand_N_Op_Subtract --
10545 --------------------------
10546
10547 procedure Expand_N_Op_Subtract (N : Node_Id) is
10548 Typ : constant Entity_Id := Etype (N);
10549
10550 begin
10551 Binary_Op_Validity_Checks (N);
10552
10553 -- Check for MINIMIZED/ELIMINATED overflow mode
10554
10555 if Minimized_Eliminated_Overflow_Check (N) then
10556 Apply_Arithmetic_Overflow_Check (N);
10557 return;
10558 end if;
10559
10560 -- Try to narrow the operation
10561
10562 if Typ = Universal_Integer then
10563 Narrow_Large_Operation (N);
10564
10565 if Nkind (N) /= N_Op_Subtract then
10566 return;
10567 end if;
10568 end if;
10569
10570 -- N - 0 = N for integer types
10571
10572 if Is_Integer_Type (Typ)
10573 and then Compile_Time_Known_Value (Right_Opnd (N))
10574 and then Expr_Value (Right_Opnd (N)) = 0
10575 then
10576 Rewrite (N, Left_Opnd (N));
10577 return;
10578 end if;
10579
10580 -- Arithmetic overflow checks for signed integer/fixed point types
10581
10582 if Is_Signed_Integer_Type (Typ) or else Is_Fixed_Point_Type (Typ) then
10583 Apply_Arithmetic_Overflow_Check (N);
10584 end if;
10585
10586 -- Overflow checks for floating-point if -gnateF mode active
10587
10588 Check_Float_Op_Overflow (N);
10589
10590 Expand_Nonbinary_Modular_Op (N);
10591 end Expand_N_Op_Subtract;
10592
10593 ---------------------
10594 -- Expand_N_Op_Xor --
10595 ---------------------
10596
10597 procedure Expand_N_Op_Xor (N : Node_Id) is
10598 Typ : constant Entity_Id := Etype (N);
10599
10600 begin
10601 Binary_Op_Validity_Checks (N);
10602
10603 if Is_Array_Type (Etype (N)) then
10604 Expand_Boolean_Operator (N);
10605
10606 elsif Is_Boolean_Type (Etype (N)) then
10607 Adjust_Condition (Left_Opnd (N));
10608 Adjust_Condition (Right_Opnd (N));
10609 Set_Etype (N, Standard_Boolean);
10610 Adjust_Result_Type (N, Typ);
10611
10612 elsif Is_Intrinsic_Subprogram (Entity (N)) then
10613 Expand_Intrinsic_Call (N, Entity (N));
10614 end if;
10615
10616 Expand_Nonbinary_Modular_Op (N);
10617 end Expand_N_Op_Xor;
10618
10619 ----------------------
10620 -- Expand_N_Or_Else --
10621 ----------------------
10622
10623 procedure Expand_N_Or_Else (N : Node_Id)
10624 renames Expand_Short_Circuit_Operator;
10625
10626 -----------------------------------
10627 -- Expand_N_Qualified_Expression --
10628 -----------------------------------
10629
10630 procedure Expand_N_Qualified_Expression (N : Node_Id) is
10631 Operand : constant Node_Id := Expression (N);
10632 Target_Type : constant Entity_Id := Entity (Subtype_Mark (N));
10633
10634 begin
10635 -- Do validity check if validity checking operands
10636
10637 if Validity_Checks_On and Validity_Check_Operands then
10638 Ensure_Valid (Operand);
10639 end if;
10640
10641 Freeze_Before (Operand, Target_Type);
10642
10643 -- Apply possible constraint check
10644
10645 Apply_Constraint_Check (Operand, Target_Type, No_Sliding => True);
10646
10647 -- Apply possible predicate check
10648
10649 Apply_Predicate_Check (Operand, Target_Type);
10650
10651 if Do_Range_Check (Operand) then
10652 Generate_Range_Check (Operand, Target_Type, CE_Range_Check_Failed);
10653 end if;
10654 end Expand_N_Qualified_Expression;
10655
10656 ------------------------------------
10657 -- Expand_N_Quantified_Expression --
10658 ------------------------------------
10659
10660 -- We expand:
10661
10662 -- for all X in range => Cond
10663
10664 -- into:
10665
10666 -- T := True;
10667 -- for X in range loop
10668 -- if not Cond then
10669 -- T := False;
10670 -- exit;
10671 -- end if;
10672 -- end loop;
10673
10674 -- Similarly, an existentially quantified expression:
10675
10676 -- for some X in range => Cond
10677
10678 -- becomes:
10679
10680 -- T := False;
10681 -- for X in range loop
10682 -- if Cond then
10683 -- T := True;
10684 -- exit;
10685 -- end if;
10686 -- end loop;
10687
10688 -- In both cases, the iteration may be over a container in which case it is
10689 -- given by an iterator specification, not a loop parameter specification.
10690
10691 procedure Expand_N_Quantified_Expression (N : Node_Id) is
10692 Actions : constant List_Id := New_List;
10693 For_All : constant Boolean := All_Present (N);
10694 Iter_Spec : constant Node_Id := Iterator_Specification (N);
10695 Loc : constant Source_Ptr := Sloc (N);
10696 Loop_Spec : constant Node_Id := Loop_Parameter_Specification (N);
10697 Cond : Node_Id;
10698 Flag : Entity_Id;
10699 Scheme : Node_Id;
10700 Stmts : List_Id;
10701 Var : Entity_Id;
10702
10703 begin
10704 -- Ensure that the bound variable as well as the type of Name of the
10705 -- Iter_Spec if present are properly frozen. We must do this before
10706 -- expansion because the expression is about to be converted into a
10707 -- loop, and resulting freeze nodes may end up in the wrong place in the
10708 -- tree.
10709
10710 if Present (Iter_Spec) then
10711 Var := Defining_Identifier (Iter_Spec);
10712 else
10713 Var := Defining_Identifier (Loop_Spec);
10714 end if;
10715
10716 declare
10717 P : Node_Id := Parent (N);
10718 begin
10719 while Nkind (P) in N_Subexpr loop
10720 P := Parent (P);
10721 end loop;
10722
10723 if Present (Iter_Spec) then
10724 Freeze_Before (P, Etype (Name (Iter_Spec)));
10725 end if;
10726
10727 Freeze_Before (P, Etype (Var));
10728 end;
10729
10730 -- Create the declaration of the flag which tracks the status of the
10731 -- quantified expression. Generate:
10732
10733 -- Flag : Boolean := (True | False);
10734
10735 Flag := Make_Temporary (Loc, 'T', N);
10736
10737 Append_To (Actions,
10738 Make_Object_Declaration (Loc,
10739 Defining_Identifier => Flag,
10740 Object_Definition => New_Occurrence_Of (Standard_Boolean, Loc),
10741 Expression =>
10742 New_Occurrence_Of (Boolean_Literals (For_All), Loc)));
10743
10744 -- Construct the circuitry which tracks the status of the quantified
10745 -- expression. Generate:
10746
10747 -- if [not] Cond then
10748 -- Flag := (False | True);
10749 -- exit;
10750 -- end if;
10751
10752 Cond := Relocate_Node (Condition (N));
10753
10754 if For_All then
10755 Cond := Make_Op_Not (Loc, Cond);
10756 end if;
10757
10758 Stmts := New_List (
10759 Make_Implicit_If_Statement (N,
10760 Condition => Cond,
10761 Then_Statements => New_List (
10762 Make_Assignment_Statement (Loc,
10763 Name => New_Occurrence_Of (Flag, Loc),
10764 Expression =>
10765 New_Occurrence_Of (Boolean_Literals (not For_All), Loc)),
10766 Make_Exit_Statement (Loc))));
10767
10768 -- Build the loop equivalent of the quantified expression
10769
10770 if Present (Iter_Spec) then
10771 Scheme :=
10772 Make_Iteration_Scheme (Loc,
10773 Iterator_Specification => Iter_Spec);
10774 else
10775 Scheme :=
10776 Make_Iteration_Scheme (Loc,
10777 Loop_Parameter_Specification => Loop_Spec);
10778 end if;
10779
10780 Append_To (Actions,
10781 Make_Loop_Statement (Loc,
10782 Iteration_Scheme => Scheme,
10783 Statements => Stmts,
10784 End_Label => Empty));
10785
10786 -- Transform the quantified expression
10787
10788 Rewrite (N,
10789 Make_Expression_With_Actions (Loc,
10790 Expression => New_Occurrence_Of (Flag, Loc),
10791 Actions => Actions));
10792 Analyze_And_Resolve (N, Standard_Boolean);
10793 end Expand_N_Quantified_Expression;
10794
10795 ---------------------------------
10796 -- Expand_N_Selected_Component --
10797 ---------------------------------
10798
10799 procedure Expand_N_Selected_Component (N : Node_Id) is
10800 Loc : constant Source_Ptr := Sloc (N);
10801 Par : constant Node_Id := Parent (N);
10802 P : constant Node_Id := Prefix (N);
10803 S : constant Node_Id := Selector_Name (N);
10804 Ptyp : constant Entity_Id := Underlying_Type (Etype (P));
10805 Disc : Entity_Id;
10806 New_N : Node_Id;
10807 Dcon : Elmt_Id;
10808 Dval : Node_Id;
10809
10810 function In_Left_Hand_Side (Comp : Node_Id) return Boolean;
10811 -- Gigi needs a temporary for prefixes that depend on a discriminant,
10812 -- unless the context of an assignment can provide size information.
10813 -- Don't we have a general routine that does this???
10814
10815 function Is_Subtype_Declaration return Boolean;
10816 -- The replacement of a discriminant reference by its value is required
10817 -- if this is part of the initialization of an temporary generated by a
10818 -- change of representation. This shows up as the construction of a
10819 -- discriminant constraint for a subtype declared at the same point as
10820 -- the entity in the prefix of the selected component. We recognize this
10821 -- case when the context of the reference is:
10822 -- subtype ST is T(Obj.D);
10823 -- where the entity for Obj comes from source, and ST has the same sloc.
10824
10825 -----------------------
10826 -- In_Left_Hand_Side --
10827 -----------------------
10828
10829 function In_Left_Hand_Side (Comp : Node_Id) return Boolean is
10830 begin
10831 return (Nkind (Parent (Comp)) = N_Assignment_Statement
10832 and then Comp = Name (Parent (Comp)))
10833 or else (Present (Parent (Comp))
10834 and then Nkind (Parent (Comp)) in N_Subexpr
10835 and then In_Left_Hand_Side (Parent (Comp)));
10836 end In_Left_Hand_Side;
10837
10838 -----------------------------
10839 -- Is_Subtype_Declaration --
10840 -----------------------------
10841
10842 function Is_Subtype_Declaration return Boolean is
10843 Par : constant Node_Id := Parent (N);
10844 begin
10845 return
10846 Nkind (Par) = N_Index_Or_Discriminant_Constraint
10847 and then Nkind (Parent (Parent (Par))) = N_Subtype_Declaration
10848 and then Comes_From_Source (Entity (Prefix (N)))
10849 and then Sloc (Par) = Sloc (Entity (Prefix (N)));
10850 end Is_Subtype_Declaration;
10851
10852 -- Start of processing for Expand_N_Selected_Component
10853
10854 begin
10855 -- Deal with discriminant check required
10856
10857 if Do_Discriminant_Check (N) then
10858 if Present (Discriminant_Checking_Func
10859 (Original_Record_Component (Entity (S))))
10860 then
10861 -- Present the discriminant checking function to the backend, so
10862 -- that it can inline the call to the function.
10863
10864 Add_Inlined_Body
10865 (Discriminant_Checking_Func
10866 (Original_Record_Component (Entity (S))),
10867 N);
10868
10869 -- Now reset the flag and generate the call
10870
10871 Set_Do_Discriminant_Check (N, False);
10872 Generate_Discriminant_Check (N);
10873
10874 -- In the case of Unchecked_Union, no discriminant checking is
10875 -- actually performed.
10876
10877 else
10878 if not Is_Unchecked_Union
10879 (Implementation_Base_Type (Etype (Prefix (N))))
10880 and then not Is_Predefined_Unit (Get_Source_Unit (N))
10881 then
10882 Error_Msg_N
10883 ("sorry - unable to generate discriminant check for" &
10884 " reference to variant component &",
10885 Selector_Name (N));
10886 end if;
10887
10888 Set_Do_Discriminant_Check (N, False);
10889 end if;
10890 end if;
10891
10892 -- Ada 2005 (AI-318-02): If the prefix is a call to a build-in-place
10893 -- function, then additional actuals must be passed.
10894
10895 if Is_Build_In_Place_Function_Call (P) then
10896 Make_Build_In_Place_Call_In_Anonymous_Context (P);
10897
10898 -- Ada 2005 (AI-318-02): Specialization of the previous case for prefix
10899 -- containing build-in-place function calls whose returned object covers
10900 -- interface types.
10901
10902 elsif Present (Unqual_BIP_Iface_Function_Call (P)) then
10903 Make_Build_In_Place_Iface_Call_In_Anonymous_Context (P);
10904 end if;
10905
10906 -- Gigi cannot handle unchecked conversions that are the prefix of a
10907 -- selected component with discriminants. This must be checked during
10908 -- expansion, because during analysis the type of the selector is not
10909 -- known at the point the prefix is analyzed. If the conversion is the
10910 -- target of an assignment, then we cannot force the evaluation.
10911
10912 if Nkind (Prefix (N)) = N_Unchecked_Type_Conversion
10913 and then Has_Discriminants (Etype (N))
10914 and then not In_Left_Hand_Side (N)
10915 then
10916 Force_Evaluation (Prefix (N));
10917 end if;
10918
10919 -- Remaining processing applies only if selector is a discriminant
10920
10921 if Ekind (Entity (Selector_Name (N))) = E_Discriminant then
10922
10923 -- If the selector is a discriminant of a constrained record type,
10924 -- we may be able to rewrite the expression with the actual value
10925 -- of the discriminant, a useful optimization in some cases.
10926
10927 if Is_Record_Type (Ptyp)
10928 and then Has_Discriminants (Ptyp)
10929 and then Is_Constrained (Ptyp)
10930 then
10931 -- Do this optimization for discrete types only, and not for
10932 -- access types (access discriminants get us into trouble).
10933
10934 if not Is_Discrete_Type (Etype (N)) then
10935 null;
10936
10937 -- Don't do this on the left-hand side of an assignment statement.
10938 -- Normally one would think that references like this would not
10939 -- occur, but they do in generated code, and mean that we really
10940 -- do want to assign the discriminant.
10941
10942 elsif Nkind (Par) = N_Assignment_Statement
10943 and then Name (Par) = N
10944 then
10945 null;
10946
10947 -- Don't do this optimization for the prefix of an attribute or
10948 -- the name of an object renaming declaration since these are
10949 -- contexts where we do not want the value anyway.
10950
10951 elsif (Nkind (Par) = N_Attribute_Reference
10952 and then Prefix (Par) = N)
10953 or else Is_Renamed_Object (N)
10954 then
10955 null;
10956
10957 -- Don't do this optimization if we are within the code for a
10958 -- discriminant check, since the whole point of such a check may
10959 -- be to verify the condition on which the code below depends.
10960
10961 elsif Is_In_Discriminant_Check (N) then
10962 null;
10963
10964 -- Green light to see if we can do the optimization. There is
10965 -- still one condition that inhibits the optimization below but
10966 -- now is the time to check the particular discriminant.
10967
10968 else
10969 -- Loop through discriminants to find the matching discriminant
10970 -- constraint to see if we can copy it.
10971
10972 Disc := First_Discriminant (Ptyp);
10973 Dcon := First_Elmt (Discriminant_Constraint (Ptyp));
10974 Discr_Loop : while Present (Dcon) loop
10975 Dval := Node (Dcon);
10976
10977 -- Check if this is the matching discriminant and if the
10978 -- discriminant value is simple enough to make sense to
10979 -- copy. We don't want to copy complex expressions, and
10980 -- indeed to do so can cause trouble (before we put in
10981 -- this guard, a discriminant expression containing an
10982 -- AND THEN was copied, causing problems for coverage
10983 -- analysis tools).
10984
10985 -- However, if the reference is part of the initialization
10986 -- code generated for an object declaration, we must use
10987 -- the discriminant value from the subtype constraint,
10988 -- because the selected component may be a reference to the
10989 -- object being initialized, whose discriminant is not yet
10990 -- set. This only happens in complex cases involving changes
10991 -- of representation.
10992
10993 if Disc = Entity (Selector_Name (N))
10994 and then (Is_Entity_Name (Dval)
10995 or else Compile_Time_Known_Value (Dval)
10996 or else Is_Subtype_Declaration)
10997 then
10998 -- Here we have the matching discriminant. Check for
10999 -- the case of a discriminant of a component that is
11000 -- constrained by an outer discriminant, which cannot
11001 -- be optimized away.
11002
11003 if Denotes_Discriminant (Dval, Check_Concurrent => True)
11004 then
11005 exit Discr_Loop;
11006
11007 -- Do not retrieve value if constraint is not static. It
11008 -- is generally not useful, and the constraint may be a
11009 -- rewritten outer discriminant in which case it is in
11010 -- fact incorrect.
11011
11012 elsif Is_Entity_Name (Dval)
11013 and then
11014 Nkind (Parent (Entity (Dval))) = N_Object_Declaration
11015 and then Present (Expression (Parent (Entity (Dval))))
11016 and then not
11017 Is_OK_Static_Expression
11018 (Expression (Parent (Entity (Dval))))
11019 then
11020 exit Discr_Loop;
11021
11022 -- In the context of a case statement, the expression may
11023 -- have the base type of the discriminant, and we need to
11024 -- preserve the constraint to avoid spurious errors on
11025 -- missing cases.
11026
11027 elsif Nkind (Parent (N)) = N_Case_Statement
11028 and then Etype (Dval) /= Etype (Disc)
11029 then
11030 Rewrite (N,
11031 Make_Qualified_Expression (Loc,
11032 Subtype_Mark =>
11033 New_Occurrence_Of (Etype (Disc), Loc),
11034 Expression =>
11035 New_Copy_Tree (Dval)));
11036 Analyze_And_Resolve (N, Etype (Disc));
11037
11038 -- In case that comes out as a static expression,
11039 -- reset it (a selected component is never static).
11040
11041 Set_Is_Static_Expression (N, False);
11042 return;
11043
11044 -- Otherwise we can just copy the constraint, but the
11045 -- result is certainly not static. In some cases the
11046 -- discriminant constraint has been analyzed in the
11047 -- context of the original subtype indication, but for
11048 -- itypes the constraint might not have been analyzed
11049 -- yet, and this must be done now.
11050
11051 else
11052 Rewrite (N, New_Copy_Tree (Dval));
11053 Analyze_And_Resolve (N);
11054 Set_Is_Static_Expression (N, False);
11055 return;
11056 end if;
11057 end if;
11058
11059 Next_Elmt (Dcon);
11060 Next_Discriminant (Disc);
11061 end loop Discr_Loop;
11062
11063 -- Note: the above loop should always find a matching
11064 -- discriminant, but if it does not, we just missed an
11065 -- optimization due to some glitch (perhaps a previous
11066 -- error), so ignore.
11067
11068 end if;
11069 end if;
11070
11071 -- The only remaining processing is in the case of a discriminant of
11072 -- a concurrent object, where we rewrite the prefix to denote the
11073 -- corresponding record type. If the type is derived and has renamed
11074 -- discriminants, use corresponding discriminant, which is the one
11075 -- that appears in the corresponding record.
11076
11077 if not Is_Concurrent_Type (Ptyp) then
11078 return;
11079 end if;
11080
11081 Disc := Entity (Selector_Name (N));
11082
11083 if Is_Derived_Type (Ptyp)
11084 and then Present (Corresponding_Discriminant (Disc))
11085 then
11086 Disc := Corresponding_Discriminant (Disc);
11087 end if;
11088
11089 New_N :=
11090 Make_Selected_Component (Loc,
11091 Prefix =>
11092 Unchecked_Convert_To (Corresponding_Record_Type (Ptyp),
11093 New_Copy_Tree (P)),
11094 Selector_Name => Make_Identifier (Loc, Chars (Disc)));
11095
11096 Rewrite (N, New_N);
11097 Analyze (N);
11098 end if;
11099
11100 -- Set Atomic_Sync_Required if necessary for atomic component
11101
11102 if Nkind (N) = N_Selected_Component then
11103 declare
11104 E : constant Entity_Id := Entity (Selector_Name (N));
11105 Set : Boolean;
11106
11107 begin
11108 -- If component is atomic, but type is not, setting depends on
11109 -- disable/enable state for the component.
11110
11111 if Is_Atomic (E) and then not Is_Atomic (Etype (E)) then
11112 Set := not Atomic_Synchronization_Disabled (E);
11113
11114 -- If component is not atomic, but its type is atomic, setting
11115 -- depends on disable/enable state for the type.
11116
11117 elsif not Is_Atomic (E) and then Is_Atomic (Etype (E)) then
11118 Set := not Atomic_Synchronization_Disabled (Etype (E));
11119
11120 -- If both component and type are atomic, we disable if either
11121 -- component or its type have sync disabled.
11122
11123 elsif Is_Atomic (E) and then Is_Atomic (Etype (E)) then
11124 Set := not Atomic_Synchronization_Disabled (E)
11125 and then
11126 not Atomic_Synchronization_Disabled (Etype (E));
11127
11128 else
11129 Set := False;
11130 end if;
11131
11132 -- Set flag if required
11133
11134 if Set then
11135 Activate_Atomic_Synchronization (N);
11136 end if;
11137 end;
11138 end if;
11139 end Expand_N_Selected_Component;
11140
11141 --------------------
11142 -- Expand_N_Slice --
11143 --------------------
11144
11145 procedure Expand_N_Slice (N : Node_Id) is
11146 Loc : constant Source_Ptr := Sloc (N);
11147 Typ : constant Entity_Id := Etype (N);
11148
11149 function Is_Procedure_Actual (N : Node_Id) return Boolean;
11150 -- Check whether the argument is an actual for a procedure call, in
11151 -- which case the expansion of a bit-packed slice is deferred until the
11152 -- call itself is expanded. The reason this is required is that we might
11153 -- have an IN OUT or OUT parameter, and the copy out is essential, and
11154 -- that copy out would be missed if we created a temporary here in
11155 -- Expand_N_Slice. Note that we don't bother to test specifically for an
11156 -- IN OUT or OUT mode parameter, since it is a bit tricky to do, and it
11157 -- is harmless to defer expansion in the IN case, since the call
11158 -- processing will still generate the appropriate copy in operation,
11159 -- which will take care of the slice.
11160
11161 procedure Make_Temporary_For_Slice;
11162 -- Create a named variable for the value of the slice, in cases where
11163 -- the back end cannot handle it properly, e.g. when packed types or
11164 -- unaligned slices are involved.
11165
11166 -------------------------
11167 -- Is_Procedure_Actual --
11168 -------------------------
11169
11170 function Is_Procedure_Actual (N : Node_Id) return Boolean is
11171 Par : Node_Id := Parent (N);
11172
11173 begin
11174 loop
11175 -- If our parent is a procedure call we can return
11176
11177 if Nkind (Par) = N_Procedure_Call_Statement then
11178 return True;
11179
11180 -- If our parent is a type conversion, keep climbing the tree,
11181 -- since a type conversion can be a procedure actual. Also keep
11182 -- climbing if parameter association or a qualified expression,
11183 -- since these are additional cases that do can appear on
11184 -- procedure actuals.
11185
11186 elsif Nkind (Par) in N_Type_Conversion
11187 | N_Parameter_Association
11188 | N_Qualified_Expression
11189 then
11190 Par := Parent (Par);
11191
11192 -- Any other case is not what we are looking for
11193
11194 else
11195 return False;
11196 end if;
11197 end loop;
11198 end Is_Procedure_Actual;
11199
11200 ------------------------------
11201 -- Make_Temporary_For_Slice --
11202 ------------------------------
11203
11204 procedure Make_Temporary_For_Slice is
11205 Ent : constant Entity_Id := Make_Temporary (Loc, 'T', N);
11206 Decl : Node_Id;
11207
11208 begin
11209 Decl :=
11210 Make_Object_Declaration (Loc,
11211 Defining_Identifier => Ent,
11212 Object_Definition => New_Occurrence_Of (Typ, Loc));
11213
11214 Set_No_Initialization (Decl);
11215
11216 Insert_Actions (N, New_List (
11217 Decl,
11218 Make_Assignment_Statement (Loc,
11219 Name => New_Occurrence_Of (Ent, Loc),
11220 Expression => Relocate_Node (N))));
11221
11222 Rewrite (N, New_Occurrence_Of (Ent, Loc));
11223 Analyze_And_Resolve (N, Typ);
11224 end Make_Temporary_For_Slice;
11225
11226 -- Local variables
11227
11228 Pref : constant Node_Id := Prefix (N);
11229
11230 -- Start of processing for Expand_N_Slice
11231
11232 begin
11233 -- Ada 2005 (AI-318-02): If the prefix is a call to a build-in-place
11234 -- function, then additional actuals must be passed.
11235
11236 if Is_Build_In_Place_Function_Call (Pref) then
11237 Make_Build_In_Place_Call_In_Anonymous_Context (Pref);
11238
11239 -- Ada 2005 (AI-318-02): Specialization of the previous case for prefix
11240 -- containing build-in-place function calls whose returned object covers
11241 -- interface types.
11242
11243 elsif Present (Unqual_BIP_Iface_Function_Call (Pref)) then
11244 Make_Build_In_Place_Iface_Call_In_Anonymous_Context (Pref);
11245 end if;
11246
11247 -- The remaining case to be handled is packed slices. We can leave
11248 -- packed slices as they are in the following situations:
11249
11250 -- 1. Right or left side of an assignment (we can handle this
11251 -- situation correctly in the assignment statement expansion).
11252
11253 -- 2. Prefix of indexed component (the slide is optimized away in this
11254 -- case, see the start of Expand_N_Indexed_Component.)
11255
11256 -- 3. Object renaming declaration, since we want the name of the
11257 -- slice, not the value.
11258
11259 -- 4. Argument to procedure call, since copy-in/copy-out handling may
11260 -- be required, and this is handled in the expansion of call
11261 -- itself.
11262
11263 -- 5. Prefix of an address attribute (this is an error which is caught
11264 -- elsewhere, and the expansion would interfere with generating the
11265 -- error message) or of a size attribute (because 'Size may change
11266 -- when applied to the temporary instead of the slice directly).
11267
11268 if not Is_Packed (Typ) then
11269
11270 -- Apply transformation for actuals of a function call, where
11271 -- Expand_Actuals is not used.
11272
11273 if Nkind (Parent (N)) = N_Function_Call
11274 and then Is_Possibly_Unaligned_Slice (N)
11275 then
11276 Make_Temporary_For_Slice;
11277 end if;
11278
11279 elsif Nkind (Parent (N)) = N_Assignment_Statement
11280 or else (Nkind (Parent (Parent (N))) = N_Assignment_Statement
11281 and then Parent (N) = Name (Parent (Parent (N))))
11282 then
11283 return;
11284
11285 elsif Nkind (Parent (N)) = N_Indexed_Component
11286 or else Is_Renamed_Object (N)
11287 or else Is_Procedure_Actual (N)
11288 then
11289 return;
11290
11291 elsif Nkind (Parent (N)) = N_Attribute_Reference
11292 and then (Attribute_Name (Parent (N)) = Name_Address
11293 or else Attribute_Name (Parent (N)) = Name_Size)
11294 then
11295 return;
11296
11297 else
11298 Make_Temporary_For_Slice;
11299 end if;
11300 end Expand_N_Slice;
11301
11302 ------------------------------
11303 -- Expand_N_Type_Conversion --
11304 ------------------------------
11305
11306 procedure Expand_N_Type_Conversion (N : Node_Id) is
11307 Loc : constant Source_Ptr := Sloc (N);
11308 Operand : constant Node_Id := Expression (N);
11309 Operand_Acc : Node_Id := Operand;
11310 Target_Type : Entity_Id := Etype (N);
11311 Operand_Type : Entity_Id := Etype (Operand);
11312
11313 procedure Discrete_Range_Check;
11314 -- Handles generation of range check for discrete target value
11315
11316 procedure Handle_Changed_Representation;
11317 -- This is called in the case of record and array type conversions to
11318 -- see if there is a change of representation to be handled. Change of
11319 -- representation is actually handled at the assignment statement level,
11320 -- and what this procedure does is rewrite node N conversion as an
11321 -- assignment to temporary. If there is no change of representation,
11322 -- then the conversion node is unchanged.
11323
11324 procedure Raise_Accessibility_Error;
11325 -- Called when we know that an accessibility check will fail. Rewrites
11326 -- node N to an appropriate raise statement and outputs warning msgs.
11327 -- The Etype of the raise node is set to Target_Type. Note that in this
11328 -- case the rest of the processing should be skipped (i.e. the call to
11329 -- this procedure will be followed by "goto Done").
11330
11331 procedure Real_Range_Check;
11332 -- Handles generation of range check for real target value
11333
11334 function Has_Extra_Accessibility (Id : Entity_Id) return Boolean;
11335 -- True iff Present (Effective_Extra_Accessibility (Id)) successfully
11336 -- evaluates to True.
11337
11338 function Statically_Deeper_Relation_Applies (Targ_Typ : Entity_Id)
11339 return Boolean;
11340 -- Given a target type for a conversion, determine whether the
11341 -- statically deeper accessibility rules apply to it.
11342
11343 --------------------------
11344 -- Discrete_Range_Check --
11345 --------------------------
11346
11347 -- Case of conversions to a discrete type. We let Generate_Range_Check
11348 -- do the heavy lifting, after converting a fixed-point operand to an
11349 -- appropriate integer type.
11350
11351 procedure Discrete_Range_Check is
11352 Expr : Node_Id;
11353 Ityp : Entity_Id;
11354
11355 procedure Generate_Temporary;
11356 -- Generate a temporary to facilitate in the C backend the code
11357 -- generation of the unchecked conversion since the size of the
11358 -- source type may differ from the size of the target type.
11359
11360 ------------------------
11361 -- Generate_Temporary --
11362 ------------------------
11363
11364 procedure Generate_Temporary is
11365 begin
11366 if Esize (Etype (Expr)) < Esize (Etype (Ityp)) then
11367 declare
11368 Exp_Type : constant Entity_Id := Ityp;
11369 Def_Id : constant Entity_Id :=
11370 Make_Temporary (Loc, 'R', Expr);
11371 E : Node_Id;
11372 Res : Node_Id;
11373
11374 begin
11375 Set_Is_Internal (Def_Id);
11376 Set_Etype (Def_Id, Exp_Type);
11377 Res := New_Occurrence_Of (Def_Id, Loc);
11378
11379 E :=
11380 Make_Object_Declaration (Loc,
11381 Defining_Identifier => Def_Id,
11382 Object_Definition => New_Occurrence_Of
11383 (Exp_Type, Loc),
11384 Constant_Present => True,
11385 Expression => Relocate_Node (Expr));
11386
11387 Set_Assignment_OK (E);
11388 Insert_Action (Expr, E);
11389
11390 Set_Assignment_OK (Res, Assignment_OK (Expr));
11391
11392 Rewrite (Expr, Res);
11393 Analyze_And_Resolve (Expr, Exp_Type);
11394 end;
11395 end if;
11396 end Generate_Temporary;
11397
11398 -- Start of processing for Discrete_Range_Check
11399
11400 begin
11401 -- Nothing more to do if conversion was rewritten
11402
11403 if Nkind (N) /= N_Type_Conversion then
11404 return;
11405 end if;
11406
11407 Expr := Expression (N);
11408
11409 -- Clear the Do_Range_Check flag on Expr
11410
11411 Set_Do_Range_Check (Expr, False);
11412
11413 -- Nothing to do if range checks suppressed
11414
11415 if Range_Checks_Suppressed (Target_Type) then
11416 return;
11417 end if;
11418
11419 -- Nothing to do if expression is an entity on which checks have been
11420 -- suppressed.
11421
11422 if Is_Entity_Name (Expr)
11423 and then Range_Checks_Suppressed (Entity (Expr))
11424 then
11425 return;
11426 end if;
11427
11428 -- Before we do a range check, we have to deal with treating
11429 -- a fixed-point operand as an integer. The way we do this
11430 -- is simply to do an unchecked conversion to an appropriate
11431 -- integer type with the smallest size, so that we can suppress
11432 -- trivial checks.
11433
11434 if Is_Fixed_Point_Type (Etype (Expr)) then
11435 Ityp := Small_Integer_Type_For
11436 (Esize (Base_Type (Etype (Expr))), Uns => False);
11437
11438 -- Generate a temporary with the integer type to facilitate in the
11439 -- C backend the code generation for the unchecked conversion.
11440
11441 if Modify_Tree_For_C then
11442 Generate_Temporary;
11443 end if;
11444
11445 Rewrite (Expr, Unchecked_Convert_To (Ityp, Expr));
11446 end if;
11447
11448 -- Reset overflow flag, since the range check will include
11449 -- dealing with possible overflow, and generate the check.
11450
11451 Set_Do_Overflow_Check (N, False);
11452
11453 Generate_Range_Check (Expr, Target_Type, CE_Range_Check_Failed);
11454 end Discrete_Range_Check;
11455
11456 -----------------------------------
11457 -- Handle_Changed_Representation --
11458 -----------------------------------
11459
11460 procedure Handle_Changed_Representation is
11461 Temp : Entity_Id;
11462 Decl : Node_Id;
11463 Odef : Node_Id;
11464 N_Ix : Node_Id;
11465 Cons : List_Id;
11466
11467 begin
11468 -- Nothing else to do if no change of representation
11469
11470 if Has_Compatible_Representation (Target_Type, Operand_Type) then
11471 return;
11472
11473 -- The real change of representation work is done by the assignment
11474 -- statement processing. So if this type conversion is appearing as
11475 -- the expression of an assignment statement, nothing needs to be
11476 -- done to the conversion.
11477
11478 elsif Nkind (Parent (N)) = N_Assignment_Statement then
11479 return;
11480
11481 -- Otherwise we need to generate a temporary variable, and do the
11482 -- change of representation assignment into that temporary variable.
11483 -- The conversion is then replaced by a reference to this variable.
11484
11485 else
11486 Cons := No_List;
11487
11488 -- If type is unconstrained we have to add a constraint, copied
11489 -- from the actual value of the left-hand side.
11490
11491 if not Is_Constrained (Target_Type) then
11492 if Has_Discriminants (Operand_Type) then
11493
11494 -- A change of representation can only apply to untagged
11495 -- types. We need to build the constraint that applies to
11496 -- the target type, using the constraints of the operand.
11497 -- The analysis is complicated if there are both inherited
11498 -- discriminants and constrained discriminants.
11499 -- We iterate over the discriminants of the target, and
11500 -- find the discriminant of the same name:
11501
11502 -- a) If there is a corresponding discriminant in the object
11503 -- then the value is a selected component of the operand.
11504
11505 -- b) Otherwise the value of a constrained discriminant is
11506 -- found in the stored constraint of the operand.
11507
11508 declare
11509 Stored : constant Elist_Id :=
11510 Stored_Constraint (Operand_Type);
11511 -- Stored constraints of the operand. If present, they
11512 -- correspond to the discriminants of the parent type.
11513
11514 Disc_O : Entity_Id;
11515 -- Discriminant of the operand type. Its value in the
11516 -- object is captured in a selected component.
11517
11518 Disc_T : Entity_Id;
11519 -- Discriminant of the target type
11520
11521 Elmt : Elmt_Id;
11522
11523 begin
11524 Disc_O := First_Discriminant (Operand_Type);
11525 Disc_T := First_Discriminant (Target_Type);
11526 Elmt := (if Present (Stored)
11527 then First_Elmt (Stored)
11528 else No_Elmt);
11529
11530 Cons := New_List;
11531 while Present (Disc_T) loop
11532 if Present (Disc_O)
11533 and then Chars (Disc_T) = Chars (Disc_O)
11534 then
11535 Append_To (Cons,
11536 Make_Selected_Component (Loc,
11537 Prefix =>
11538 Duplicate_Subexpr_Move_Checks (Operand),
11539 Selector_Name =>
11540 Make_Identifier (Loc, Chars (Disc_O))));
11541 Next_Discriminant (Disc_O);
11542
11543 elsif Present (Elmt) then
11544 Append_To (Cons, New_Copy_Tree (Node (Elmt)));
11545 end if;
11546
11547 if Present (Elmt) then
11548 Next_Elmt (Elmt);
11549 end if;
11550
11551 Next_Discriminant (Disc_T);
11552 end loop;
11553 end;
11554
11555 elsif Is_Array_Type (Operand_Type) then
11556 N_Ix := First_Index (Target_Type);
11557 Cons := New_List;
11558
11559 for J in 1 .. Number_Dimensions (Operand_Type) loop
11560
11561 -- We convert the bounds explicitly. We use an unchecked
11562 -- conversion because bounds checks are done elsewhere.
11563
11564 Append_To (Cons,
11565 Make_Range (Loc,
11566 Low_Bound =>
11567 Unchecked_Convert_To (Etype (N_Ix),
11568 Make_Attribute_Reference (Loc,
11569 Prefix =>
11570 Duplicate_Subexpr_No_Checks
11571 (Operand, Name_Req => True),
11572 Attribute_Name => Name_First,
11573 Expressions => New_List (
11574 Make_Integer_Literal (Loc, J)))),
11575
11576 High_Bound =>
11577 Unchecked_Convert_To (Etype (N_Ix),
11578 Make_Attribute_Reference (Loc,
11579 Prefix =>
11580 Duplicate_Subexpr_No_Checks
11581 (Operand, Name_Req => True),
11582 Attribute_Name => Name_Last,
11583 Expressions => New_List (
11584 Make_Integer_Literal (Loc, J))))));
11585
11586 Next_Index (N_Ix);
11587 end loop;
11588 end if;
11589 end if;
11590
11591 Odef := New_Occurrence_Of (Target_Type, Loc);
11592
11593 if Present (Cons) then
11594 Odef :=
11595 Make_Subtype_Indication (Loc,
11596 Subtype_Mark => Odef,
11597 Constraint =>
11598 Make_Index_Or_Discriminant_Constraint (Loc,
11599 Constraints => Cons));
11600 end if;
11601
11602 Temp := Make_Temporary (Loc, 'C');
11603 Decl :=
11604 Make_Object_Declaration (Loc,
11605 Defining_Identifier => Temp,
11606 Object_Definition => Odef);
11607
11608 Set_No_Initialization (Decl, True);
11609
11610 -- Insert required actions. It is essential to suppress checks
11611 -- since we have suppressed default initialization, which means
11612 -- that the variable we create may have no discriminants.
11613
11614 Insert_Actions (N,
11615 New_List (
11616 Decl,
11617 Make_Assignment_Statement (Loc,
11618 Name => New_Occurrence_Of (Temp, Loc),
11619 Expression => Relocate_Node (N))),
11620 Suppress => All_Checks);
11621
11622 Rewrite (N, New_Occurrence_Of (Temp, Loc));
11623 return;
11624 end if;
11625 end Handle_Changed_Representation;
11626
11627 -------------------------------
11628 -- Raise_Accessibility_Error --
11629 -------------------------------
11630
11631 procedure Raise_Accessibility_Error is
11632 begin
11633 Error_Msg_Warn := SPARK_Mode /= On;
11634 Rewrite (N,
11635 Make_Raise_Program_Error (Sloc (N),
11636 Reason => PE_Accessibility_Check_Failed));
11637 Set_Etype (N, Target_Type);
11638
11639 Error_Msg_N ("accessibility check failure<<", N);
11640 Error_Msg_N ("\Program_Error [<<", N);
11641 end Raise_Accessibility_Error;
11642
11643 ----------------------
11644 -- Real_Range_Check --
11645 ----------------------
11646
11647 -- Case of conversions to floating-point or fixed-point. If range checks
11648 -- are enabled and the target type has a range constraint, we convert:
11649
11650 -- typ (x)
11651
11652 -- to
11653
11654 -- Tnn : typ'Base := typ'Base (x);
11655 -- [constraint_error when Tnn < typ'First or else Tnn > typ'Last]
11656 -- typ (Tnn)
11657
11658 -- This is necessary when there is a conversion of integer to float or
11659 -- to fixed-point to ensure that the correct checks are made. It is not
11660 -- necessary for the float-to-float case where it is enough to just set
11661 -- the Do_Range_Check flag on the expression.
11662
11663 procedure Real_Range_Check is
11664 Btyp : constant Entity_Id := Base_Type (Target_Type);
11665 Lo : constant Node_Id := Type_Low_Bound (Target_Type);
11666 Hi : constant Node_Id := Type_High_Bound (Target_Type);
11667
11668 Conv : Node_Id;
11669 Hi_Arg : Node_Id;
11670 Hi_Val : Node_Id;
11671 Lo_Arg : Node_Id;
11672 Lo_Val : Node_Id;
11673 Expr : Entity_Id;
11674 Tnn : Entity_Id;
11675
11676 begin
11677 -- Nothing more to do if conversion was rewritten
11678
11679 if Nkind (N) /= N_Type_Conversion then
11680 return;
11681 end if;
11682
11683 Expr := Expression (N);
11684
11685 -- Clear the Do_Range_Check flag on Expr
11686
11687 Set_Do_Range_Check (Expr, False);
11688
11689 -- Nothing to do if range checks suppressed, or target has the same
11690 -- range as the base type (or is the base type).
11691
11692 if Range_Checks_Suppressed (Target_Type)
11693 or else (Lo = Type_Low_Bound (Btyp)
11694 and then
11695 Hi = Type_High_Bound (Btyp))
11696 then
11697 return;
11698 end if;
11699
11700 -- Nothing to do if expression is an entity on which checks have been
11701 -- suppressed.
11702
11703 if Is_Entity_Name (Expr)
11704 and then Range_Checks_Suppressed (Entity (Expr))
11705 then
11706 return;
11707 end if;
11708
11709 -- Nothing to do if expression was rewritten into a float-to-float
11710 -- conversion, since this kind of conversion is handled elsewhere.
11711
11712 if Is_Floating_Point_Type (Etype (Expr))
11713 and then Is_Floating_Point_Type (Target_Type)
11714 then
11715 return;
11716 end if;
11717
11718 -- Nothing to do if bounds are all static and we can tell that the
11719 -- expression is within the bounds of the target. Note that if the
11720 -- operand is of an unconstrained floating-point type, then we do
11721 -- not trust it to be in range (might be infinite)
11722
11723 declare
11724 S_Lo : constant Node_Id := Type_Low_Bound (Etype (Expr));
11725 S_Hi : constant Node_Id := Type_High_Bound (Etype (Expr));
11726
11727 begin
11728 if (not Is_Floating_Point_Type (Etype (Expr))
11729 or else Is_Constrained (Etype (Expr)))
11730 and then Compile_Time_Known_Value (S_Lo)
11731 and then Compile_Time_Known_Value (S_Hi)
11732 and then Compile_Time_Known_Value (Hi)
11733 and then Compile_Time_Known_Value (Lo)
11734 then
11735 declare
11736 D_Lov : constant Ureal := Expr_Value_R (Lo);
11737 D_Hiv : constant Ureal := Expr_Value_R (Hi);
11738 S_Lov : Ureal;
11739 S_Hiv : Ureal;
11740
11741 begin
11742 if Is_Real_Type (Etype (Expr)) then
11743 S_Lov := Expr_Value_R (S_Lo);
11744 S_Hiv := Expr_Value_R (S_Hi);
11745 else
11746 S_Lov := UR_From_Uint (Expr_Value (S_Lo));
11747 S_Hiv := UR_From_Uint (Expr_Value (S_Hi));
11748 end if;
11749
11750 if D_Hiv > D_Lov
11751 and then S_Lov >= D_Lov
11752 and then S_Hiv <= D_Hiv
11753 then
11754 return;
11755 end if;
11756 end;
11757 end if;
11758 end;
11759
11760 -- Otherwise rewrite the conversion as described above
11761
11762 Conv := Convert_To (Btyp, Expr);
11763
11764 -- If a conversion is necessary, then copy the specific flags from
11765 -- the original one and also move the Do_Overflow_Check flag since
11766 -- this new conversion is to the base type.
11767
11768 if Nkind (Conv) = N_Type_Conversion then
11769 Set_Conversion_OK (Conv, Conversion_OK (N));
11770 Set_Float_Truncate (Conv, Float_Truncate (N));
11771 Set_Rounded_Result (Conv, Rounded_Result (N));
11772
11773 if Do_Overflow_Check (N) then
11774 Set_Do_Overflow_Check (Conv);
11775 Set_Do_Overflow_Check (N, False);
11776 end if;
11777 end if;
11778
11779 Tnn := Make_Temporary (Loc, 'T', Conv);
11780
11781 -- For a conversion from Float to Fixed where the bounds of the
11782 -- fixed-point type are static, we can obtain a more accurate
11783 -- fixed-point value by converting the result of the floating-
11784 -- point expression to an appropriate integer type, and then
11785 -- performing an unchecked conversion to the target fixed-point
11786 -- type. The range check can then use the corresponding integer
11787 -- value of the bounds instead of requiring further conversions.
11788 -- This preserves the identity:
11789
11790 -- Fix_Val = Fixed_Type (Float_Type (Fix_Val))
11791
11792 -- which used to fail when Fix_Val was a bound of the type and
11793 -- the 'Small was not a representable number.
11794 -- This transformation requires an integer type large enough to
11795 -- accommodate a fixed-point value.
11796
11797 if Is_Ordinary_Fixed_Point_Type (Target_Type)
11798 and then Is_Floating_Point_Type (Etype (Expr))
11799 and then RM_Size (Btyp) <= System_Max_Integer_Size
11800 and then Nkind (Lo) = N_Real_Literal
11801 and then Nkind (Hi) = N_Real_Literal
11802 then
11803 declare
11804 Expr_Id : constant Entity_Id := Make_Temporary (Loc, 'T', Conv);
11805 Int_Typ : constant Entity_Id :=
11806 Small_Integer_Type_For (RM_Size (Btyp), Uns => False);
11807 Trunc : constant Boolean := Float_Truncate (Conv);
11808
11809 begin
11810 Conv := Convert_To (Int_Typ, Expression (Conv));
11811 Set_Float_Truncate (Conv, Trunc);
11812
11813 -- Generate a temporary with the integer value. Required in the
11814 -- CCG compiler to ensure that run-time checks reference this
11815 -- integer expression (instead of the resulting fixed-point
11816 -- value because fixed-point values are handled by means of
11817 -- unsigned integer types).
11818
11819 Insert_Action (N,
11820 Make_Object_Declaration (Loc,
11821 Defining_Identifier => Expr_Id,
11822 Object_Definition => New_Occurrence_Of (Int_Typ, Loc),
11823 Constant_Present => True,
11824 Expression => Conv));
11825
11826 -- Create integer objects for range checking of result.
11827
11828 Lo_Arg :=
11829 Unchecked_Convert_To
11830 (Int_Typ, New_Occurrence_Of (Expr_Id, Loc));
11831
11832 Lo_Val :=
11833 Make_Integer_Literal (Loc, Corresponding_Integer_Value (Lo));
11834
11835 Hi_Arg :=
11836 Unchecked_Convert_To
11837 (Int_Typ, New_Occurrence_Of (Expr_Id, Loc));
11838
11839 Hi_Val :=
11840 Make_Integer_Literal (Loc, Corresponding_Integer_Value (Hi));
11841
11842 -- Rewrite conversion as an integer conversion of the
11843 -- original floating-point expression, followed by an
11844 -- unchecked conversion to the target fixed-point type.
11845
11846 Conv :=
11847 Unchecked_Convert_To
11848 (Target_Type, New_Occurrence_Of (Expr_Id, Loc));
11849 end;
11850
11851 -- All other conversions
11852
11853 else
11854 Lo_Arg := New_Occurrence_Of (Tnn, Loc);
11855 Lo_Val :=
11856 Make_Attribute_Reference (Loc,
11857 Prefix => New_Occurrence_Of (Target_Type, Loc),
11858 Attribute_Name => Name_First);
11859
11860 Hi_Arg := New_Occurrence_Of (Tnn, Loc);
11861 Hi_Val :=
11862 Make_Attribute_Reference (Loc,
11863 Prefix => New_Occurrence_Of (Target_Type, Loc),
11864 Attribute_Name => Name_Last);
11865 end if;
11866
11867 -- Build code for range checking. Note that checks are suppressed
11868 -- here since we don't want a recursive range check popping up.
11869
11870 Insert_Actions (N, New_List (
11871 Make_Object_Declaration (Loc,
11872 Defining_Identifier => Tnn,
11873 Object_Definition => New_Occurrence_Of (Btyp, Loc),
11874 Constant_Present => True,
11875 Expression => Conv),
11876
11877 Make_Raise_Constraint_Error (Loc,
11878 Condition =>
11879 Make_Or_Else (Loc,
11880 Left_Opnd =>
11881 Make_Op_Lt (Loc,
11882 Left_Opnd => Lo_Arg,
11883 Right_Opnd => Lo_Val),
11884
11885 Right_Opnd =>
11886 Make_Op_Gt (Loc,
11887 Left_Opnd => Hi_Arg,
11888 Right_Opnd => Hi_Val)),
11889 Reason => CE_Range_Check_Failed)),
11890 Suppress => All_Checks);
11891
11892 Rewrite (Expr, New_Occurrence_Of (Tnn, Loc));
11893 end Real_Range_Check;
11894
11895 -----------------------------
11896 -- Has_Extra_Accessibility --
11897 -----------------------------
11898
11899 -- Returns true for a formal of an anonymous access type or for an Ada
11900 -- 2012-style stand-alone object of an anonymous access type.
11901
11902 function Has_Extra_Accessibility (Id : Entity_Id) return Boolean is
11903 begin
11904 if Is_Formal (Id) or else Ekind (Id) in E_Constant | E_Variable then
11905 return Present (Effective_Extra_Accessibility (Id));
11906 else
11907 return False;
11908 end if;
11909 end Has_Extra_Accessibility;
11910
11911 ----------------------------------------
11912 -- Statically_Deeper_Relation_Applies --
11913 ----------------------------------------
11914
11915 function Statically_Deeper_Relation_Applies (Targ_Typ : Entity_Id)
11916 return Boolean
11917 is
11918 begin
11919 -- The case where the target type is an anonymous access type is
11920 -- ignored since they have different semantics and get covered by
11921 -- various runtime checks depending on context.
11922
11923 -- Note, the current implementation of this predicate is incomplete
11924 -- and doesn't fully reflect the rules given in RM 3.10.2 (19) and
11925 -- (19.1) ???
11926
11927 return Ekind (Targ_Typ) /= E_Anonymous_Access_Type;
11928 end Statically_Deeper_Relation_Applies;
11929
11930 -- Start of processing for Expand_N_Type_Conversion
11931
11932 begin
11933 -- First remove check marks put by the semantic analysis on the type
11934 -- conversion between array types. We need these checks, and they will
11935 -- be generated by this expansion routine, but we do not depend on these
11936 -- flags being set, and since we do intend to expand the checks in the
11937 -- front end, we don't want them on the tree passed to the back end.
11938
11939 if Is_Array_Type (Target_Type) then
11940 if Is_Constrained (Target_Type) then
11941 Set_Do_Length_Check (N, False);
11942 else
11943 Set_Do_Range_Check (Operand, False);
11944 end if;
11945 end if;
11946
11947 -- Nothing at all to do if conversion is to the identical type so remove
11948 -- the conversion completely, it is useless, except that it may carry
11949 -- an Assignment_OK attribute, which must be propagated to the operand
11950 -- and the Do_Range_Check flag on the operand must be cleared, if any.
11951
11952 if Operand_Type = Target_Type then
11953 if Assignment_OK (N) then
11954 Set_Assignment_OK (Operand);
11955 end if;
11956
11957 Set_Do_Range_Check (Operand, False);
11958
11959 Rewrite (N, Relocate_Node (Operand));
11960
11961 goto Done;
11962 end if;
11963
11964 -- Nothing to do if this is the second argument of read. This is a
11965 -- "backwards" conversion that will be handled by the specialized code
11966 -- in attribute processing.
11967
11968 if Nkind (Parent (N)) = N_Attribute_Reference
11969 and then Attribute_Name (Parent (N)) = Name_Read
11970 and then Next (First (Expressions (Parent (N)))) = N
11971 then
11972 goto Done;
11973 end if;
11974
11975 -- Check for case of converting to a type that has an invariant
11976 -- associated with it. This requires an invariant check. We insert
11977 -- a call:
11978
11979 -- invariant_check (typ (expr))
11980
11981 -- in the code, after removing side effects from the expression.
11982 -- This is clearer than replacing the conversion into an expression
11983 -- with actions, because the context may impose additional actions
11984 -- (tag checks, membership tests, etc.) that conflict with this
11985 -- rewriting (used previously).
11986
11987 -- Note: the Comes_From_Source check, and then the resetting of this
11988 -- flag prevents what would otherwise be an infinite recursion.
11989
11990 if Has_Invariants (Target_Type)
11991 and then Present (Invariant_Procedure (Target_Type))
11992 and then Comes_From_Source (N)
11993 then
11994 Set_Comes_From_Source (N, False);
11995 Remove_Side_Effects (N);
11996 Insert_Action (N, Make_Invariant_Call (Duplicate_Subexpr (N)));
11997 goto Done;
11998
11999 -- AI12-0042: For a view conversion to a class-wide type occurring
12000 -- within the immediate scope of T, from a specific type that is
12001 -- a descendant of T (including T itself), an invariant check is
12002 -- performed on the part of the object that is of type T. (We don't
12003 -- need to explicitly check for the operand type being a descendant,
12004 -- just that it's a specific type, because the conversion would be
12005 -- illegal if it's specific and not a descendant -- downward conversion
12006 -- is not allowed).
12007
12008 elsif Is_Class_Wide_Type (Target_Type)
12009 and then not Is_Class_Wide_Type (Etype (Expression (N)))
12010 and then Present (Invariant_Procedure (Root_Type (Target_Type)))
12011 and then Comes_From_Source (N)
12012 and then Within_Scope (Find_Enclosing_Scope (N), Scope (Target_Type))
12013 then
12014 Remove_Side_Effects (N);
12015
12016 -- Perform the invariant check on a conversion to the class-wide
12017 -- type's root type.
12018
12019 declare
12020 Root_Conv : constant Node_Id :=
12021 Make_Type_Conversion (Loc,
12022 Subtype_Mark =>
12023 New_Occurrence_Of (Root_Type (Target_Type), Loc),
12024 Expression => Duplicate_Subexpr (Expression (N)));
12025 begin
12026 Set_Etype (Root_Conv, Root_Type (Target_Type));
12027
12028 Insert_Action (N, Make_Invariant_Call (Root_Conv));
12029 goto Done;
12030 end;
12031 end if;
12032
12033 -- Here if we may need to expand conversion
12034
12035 -- If the operand of the type conversion is an arithmetic operation on
12036 -- signed integers, and the based type of the signed integer type in
12037 -- question is smaller than Standard.Integer, we promote both of the
12038 -- operands to type Integer.
12039
12040 -- For example, if we have
12041
12042 -- target-type (opnd1 + opnd2)
12043
12044 -- and opnd1 and opnd2 are of type short integer, then we rewrite
12045 -- this as:
12046
12047 -- target-type (integer(opnd1) + integer(opnd2))
12048
12049 -- We do this because we are always allowed to compute in a larger type
12050 -- if we do the right thing with the result, and in this case we are
12051 -- going to do a conversion which will do an appropriate check to make
12052 -- sure that things are in range of the target type in any case. This
12053 -- avoids some unnecessary intermediate overflows.
12054
12055 -- We might consider a similar transformation in the case where the
12056 -- target is a real type or a 64-bit integer type, and the operand
12057 -- is an arithmetic operation using a 32-bit integer type. However,
12058 -- we do not bother with this case, because it could cause significant
12059 -- inefficiencies on 32-bit machines. On a 64-bit machine it would be
12060 -- much cheaper, but we don't want different behavior on 32-bit and
12061 -- 64-bit machines. Note that the exclusion of the 64-bit case also
12062 -- handles the configurable run-time cases where 64-bit arithmetic
12063 -- may simply be unavailable.
12064
12065 -- Note: this circuit is partially redundant with respect to the circuit
12066 -- in Checks.Apply_Arithmetic_Overflow_Check, but we catch more cases in
12067 -- the processing here. Also we still need the Checks circuit, since we
12068 -- have to be sure not to generate junk overflow checks in the first
12069 -- place, since it would be tricky to remove them here.
12070
12071 if Integer_Promotion_Possible (N) then
12072
12073 -- All conditions met, go ahead with transformation
12074
12075 declare
12076 Opnd : Node_Id;
12077 L, R : Node_Id;
12078
12079 begin
12080 Opnd := New_Op_Node (Nkind (Operand), Loc);
12081
12082 R := Convert_To (Standard_Integer, Right_Opnd (Operand));
12083 Set_Right_Opnd (Opnd, R);
12084
12085 if Nkind (Operand) in N_Binary_Op then
12086 L := Convert_To (Standard_Integer, Left_Opnd (Operand));
12087 Set_Left_Opnd (Opnd, L);
12088 end if;
12089
12090 Rewrite (N,
12091 Make_Type_Conversion (Loc,
12092 Subtype_Mark => Relocate_Node (Subtype_Mark (N)),
12093 Expression => Opnd));
12094
12095 Analyze_And_Resolve (N, Target_Type);
12096 goto Done;
12097 end;
12098 end if;
12099
12100 -- If the conversion is from Universal_Integer and requires an overflow
12101 -- check, try to do an intermediate conversion to a narrower type first
12102 -- without overflow check, in order to avoid doing the overflow check
12103 -- in Universal_Integer, which can be a very large type.
12104
12105 if Operand_Type = Universal_Integer and then Do_Overflow_Check (N) then
12106 declare
12107 Lo, Hi, Siz : Uint;
12108 OK : Boolean;
12109 Typ : Entity_Id;
12110
12111 begin
12112 Determine_Range (Operand, OK, Lo, Hi, Assume_Valid => True);
12113
12114 if OK then
12115 Siz := Get_Size_For_Range (Lo, Hi);
12116
12117 -- We use the base type instead of the first subtype because
12118 -- overflow checks are done in the base type, so this avoids
12119 -- the need for useless conversions.
12120
12121 if Siz < System_Max_Integer_Size then
12122 Typ := Etype (Integer_Type_For (Siz, Uns => False));
12123
12124 Convert_To_And_Rewrite (Typ, Operand);
12125 Analyze_And_Resolve
12126 (Operand, Typ, Suppress => Overflow_Check);
12127
12128 Analyze_And_Resolve (N, Target_Type);
12129 goto Done;
12130 end if;
12131 end if;
12132 end;
12133 end if;
12134
12135 -- Do validity check if validity checking operands
12136
12137 if Validity_Checks_On and Validity_Check_Operands then
12138 Ensure_Valid (Operand);
12139 end if;
12140
12141 -- Special case of converting from non-standard boolean type
12142
12143 if Is_Boolean_Type (Operand_Type)
12144 and then Nonzero_Is_True (Operand_Type)
12145 then
12146 Adjust_Condition (Operand);
12147 Set_Etype (Operand, Standard_Boolean);
12148 Operand_Type := Standard_Boolean;
12149 end if;
12150
12151 -- Case of converting to an access type
12152
12153 if Is_Access_Type (Target_Type) then
12154 -- In terms of accessibility rules, an anonymous access discriminant
12155 -- is not considered separate from its parent object.
12156
12157 if Nkind (Operand) = N_Selected_Component
12158 and then Ekind (Entity (Selector_Name (Operand))) = E_Discriminant
12159 and then Ekind (Operand_Type) = E_Anonymous_Access_Type
12160 then
12161 Operand_Acc := Original_Node (Prefix (Operand));
12162 end if;
12163
12164 -- If this type conversion was internally generated by the front end
12165 -- to displace the pointer to the object to reference an interface
12166 -- type and the original node was an Unrestricted_Access attribute,
12167 -- then skip applying accessibility checks (because, according to the
12168 -- GNAT Reference Manual, this attribute is similar to 'Access except
12169 -- that all accessibility and aliased view checks are omitted).
12170
12171 if not Comes_From_Source (N)
12172 and then Is_Interface (Designated_Type (Target_Type))
12173 and then Nkind (Original_Node (N)) = N_Attribute_Reference
12174 and then Attribute_Name (Original_Node (N)) =
12175 Name_Unrestricted_Access
12176 then
12177 null;
12178
12179 -- Apply an accessibility check when the conversion operand is an
12180 -- access parameter (or a renaming thereof), unless conversion was
12181 -- expanded from an Unchecked_ or Unrestricted_Access attribute,
12182 -- or for the actual of a class-wide interface parameter. Note that
12183 -- other checks may still need to be applied below (such as tagged
12184 -- type checks).
12185
12186 elsif Is_Entity_Name (Operand_Acc)
12187 and then Has_Extra_Accessibility (Entity (Operand_Acc))
12188 and then Ekind (Etype (Operand_Acc)) = E_Anonymous_Access_Type
12189 and then (Nkind (Original_Node (N)) /= N_Attribute_Reference
12190 or else Attribute_Name (Original_Node (N)) = Name_Access)
12191 and then not No_Dynamic_Accessibility_Checks_Enabled (N)
12192 then
12193 if not Comes_From_Source (N)
12194 and then Nkind (Parent (N)) in N_Function_Call
12195 | N_Parameter_Association
12196 | N_Procedure_Call_Statement
12197 and then Is_Interface (Designated_Type (Target_Type))
12198 and then Is_Class_Wide_Type (Designated_Type (Target_Type))
12199 then
12200 null;
12201
12202 else
12203 Apply_Accessibility_Check
12204 (Operand, Target_Type, Insert_Node => Operand);
12205 end if;
12206
12207 -- If the level of the operand type is statically deeper than the
12208 -- level of the target type, then force Program_Error. Note that this
12209 -- can only occur for cases where the attribute is within the body of
12210 -- an instantiation, otherwise the conversion will already have been
12211 -- rejected as illegal.
12212
12213 -- Note: warnings are issued by the analyzer for the instance cases,
12214 -- and, since we are late in expansion, a check is performed to
12215 -- verify that neither the target type nor the operand type are
12216 -- internally generated - as this can lead to spurious errors when,
12217 -- for example, the operand type is a result of BIP expansion.
12218
12219 elsif In_Instance_Body
12220 and then Statically_Deeper_Relation_Applies (Target_Type)
12221 and then not Is_Internal (Target_Type)
12222 and then not Is_Internal (Operand_Type)
12223 and then
12224 Type_Access_Level (Operand_Type) > Type_Access_Level (Target_Type)
12225 then
12226 Raise_Accessibility_Error;
12227 goto Done;
12228
12229 -- When the operand is a selected access discriminant the check needs
12230 -- to be made against the level of the object denoted by the prefix
12231 -- of the selected name. Force Program_Error for this case as well
12232 -- (this accessibility violation can only happen if within the body
12233 -- of an instantiation).
12234
12235 elsif In_Instance_Body
12236 and then Ekind (Operand_Type) = E_Anonymous_Access_Type
12237 and then Nkind (Operand) = N_Selected_Component
12238 and then Ekind (Entity (Selector_Name (Operand))) = E_Discriminant
12239 and then Static_Accessibility_Level (Operand, Zero_On_Dynamic_Level)
12240 > Type_Access_Level (Target_Type)
12241 then
12242 Raise_Accessibility_Error;
12243 goto Done;
12244 end if;
12245 end if;
12246
12247 -- Case of conversions of tagged types and access to tagged types
12248
12249 -- When needed, that is to say when the expression is class-wide, Add
12250 -- runtime a tag check for (strict) downward conversion by using the
12251 -- membership test, generating:
12252
12253 -- [constraint_error when Operand not in Target_Type'Class]
12254
12255 -- or in the access type case
12256
12257 -- [constraint_error
12258 -- when Operand /= null
12259 -- and then Operand.all not in
12260 -- Designated_Type (Target_Type)'Class]
12261
12262 if (Is_Access_Type (Target_Type)
12263 and then Is_Tagged_Type (Designated_Type (Target_Type)))
12264 or else Is_Tagged_Type (Target_Type)
12265 then
12266 -- Do not do any expansion in the access type case if the parent is a
12267 -- renaming, since this is an error situation which will be caught by
12268 -- Sem_Ch8, and the expansion can interfere with this error check.
12269
12270 if Is_Access_Type (Target_Type) and then Is_Renamed_Object (N) then
12271 goto Done;
12272 end if;
12273
12274 -- Otherwise, proceed with processing tagged conversion
12275
12276 Tagged_Conversion : declare
12277 Actual_Op_Typ : Entity_Id;
12278 Actual_Targ_Typ : Entity_Id;
12279 Root_Op_Typ : Entity_Id;
12280
12281 procedure Make_Tag_Check (Targ_Typ : Entity_Id);
12282 -- Create a membership check to test whether Operand is a member
12283 -- of Targ_Typ. If the original Target_Type is an access, include
12284 -- a test for null value. The check is inserted at N.
12285
12286 --------------------
12287 -- Make_Tag_Check --
12288 --------------------
12289
12290 procedure Make_Tag_Check (Targ_Typ : Entity_Id) is
12291 Cond : Node_Id;
12292
12293 begin
12294 -- Generate:
12295 -- [Constraint_Error
12296 -- when Operand /= null
12297 -- and then Operand.all not in Targ_Typ]
12298
12299 if Is_Access_Type (Target_Type) then
12300 Cond :=
12301 Make_And_Then (Loc,
12302 Left_Opnd =>
12303 Make_Op_Ne (Loc,
12304 Left_Opnd => Duplicate_Subexpr_No_Checks (Operand),
12305 Right_Opnd => Make_Null (Loc)),
12306
12307 Right_Opnd =>
12308 Make_Not_In (Loc,
12309 Left_Opnd =>
12310 Make_Explicit_Dereference (Loc,
12311 Prefix => Duplicate_Subexpr_No_Checks (Operand)),
12312 Right_Opnd => New_Occurrence_Of (Targ_Typ, Loc)));
12313
12314 -- Generate:
12315 -- [Constraint_Error when Operand not in Targ_Typ]
12316
12317 else
12318 Cond :=
12319 Make_Not_In (Loc,
12320 Left_Opnd => Duplicate_Subexpr_No_Checks (Operand),
12321 Right_Opnd => New_Occurrence_Of (Targ_Typ, Loc));
12322 end if;
12323
12324 Insert_Action (N,
12325 Make_Raise_Constraint_Error (Loc,
12326 Condition => Cond,
12327 Reason => CE_Tag_Check_Failed),
12328 Suppress => All_Checks);
12329 end Make_Tag_Check;
12330
12331 -- Start of processing for Tagged_Conversion
12332
12333 begin
12334 -- Handle entities from the limited view
12335
12336 if Is_Access_Type (Operand_Type) then
12337 Actual_Op_Typ :=
12338 Available_View (Designated_Type (Operand_Type));
12339 else
12340 Actual_Op_Typ := Operand_Type;
12341 end if;
12342
12343 if Is_Access_Type (Target_Type) then
12344 Actual_Targ_Typ :=
12345 Available_View (Designated_Type (Target_Type));
12346 else
12347 Actual_Targ_Typ := Target_Type;
12348 end if;
12349
12350 Root_Op_Typ := Root_Type (Actual_Op_Typ);
12351
12352 -- Ada 2005 (AI-251): Handle interface type conversion
12353
12354 if Is_Interface (Actual_Op_Typ)
12355 or else
12356 Is_Interface (Actual_Targ_Typ)
12357 then
12358 Expand_Interface_Conversion (N);
12359 goto Done;
12360 end if;
12361
12362 -- Create a runtime tag check for a downward CW type conversion
12363
12364 if Is_Class_Wide_Type (Actual_Op_Typ)
12365 and then Actual_Op_Typ /= Actual_Targ_Typ
12366 and then Root_Op_Typ /= Actual_Targ_Typ
12367 and then Is_Ancestor
12368 (Root_Op_Typ, Actual_Targ_Typ, Use_Full_View => True)
12369 and then not Tag_Checks_Suppressed (Actual_Targ_Typ)
12370 then
12371 declare
12372 Conv : Node_Id;
12373 begin
12374 Make_Tag_Check (Class_Wide_Type (Actual_Targ_Typ));
12375 Conv := Unchecked_Convert_To (Target_Type, Expression (N));
12376 Rewrite (N, Conv);
12377 Analyze_And_Resolve (N, Target_Type);
12378 end;
12379 end if;
12380 end Tagged_Conversion;
12381
12382 -- Case of other access type conversions
12383
12384 elsif Is_Access_Type (Target_Type) then
12385 Apply_Constraint_Check (Operand, Target_Type);
12386
12387 -- Case of conversions from a fixed-point type
12388
12389 -- These conversions require special expansion and processing, found in
12390 -- the Exp_Fixd package. We ignore cases where Conversion_OK is set,
12391 -- since from a semantic point of view, these are simple integer
12392 -- conversions, which do not need further processing except for the
12393 -- generation of range checks, which is performed at the end of this
12394 -- procedure.
12395
12396 elsif Is_Fixed_Point_Type (Operand_Type)
12397 and then not Conversion_OK (N)
12398 then
12399 -- We should never see universal fixed at this case, since the
12400 -- expansion of the constituent divide or multiply should have
12401 -- eliminated the explicit mention of universal fixed.
12402
12403 pragma Assert (Operand_Type /= Universal_Fixed);
12404
12405 -- Check for special case of the conversion to universal real that
12406 -- occurs as a result of the use of a round attribute. In this case,
12407 -- the real type for the conversion is taken from the target type of
12408 -- the Round attribute and the result must be marked as rounded.
12409
12410 if Target_Type = Universal_Real
12411 and then Nkind (Parent (N)) = N_Attribute_Reference
12412 and then Attribute_Name (Parent (N)) = Name_Round
12413 then
12414 Set_Etype (N, Etype (Parent (N)));
12415 Target_Type := Etype (N);
12416 Set_Rounded_Result (N);
12417 end if;
12418
12419 if Is_Fixed_Point_Type (Target_Type) then
12420 Expand_Convert_Fixed_To_Fixed (N);
12421 elsif Is_Integer_Type (Target_Type) then
12422 Expand_Convert_Fixed_To_Integer (N);
12423 else
12424 pragma Assert (Is_Floating_Point_Type (Target_Type));
12425 Expand_Convert_Fixed_To_Float (N);
12426 end if;
12427
12428 -- Case of conversions to a fixed-point type
12429
12430 -- These conversions require special expansion and processing, found in
12431 -- the Exp_Fixd package. Again, ignore cases where Conversion_OK is set,
12432 -- since from a semantic point of view, these are simple integer
12433 -- conversions, which do not need further processing.
12434
12435 elsif Is_Fixed_Point_Type (Target_Type)
12436 and then not Conversion_OK (N)
12437 then
12438 if Is_Integer_Type (Operand_Type) then
12439 Expand_Convert_Integer_To_Fixed (N);
12440 else
12441 pragma Assert (Is_Floating_Point_Type (Operand_Type));
12442 Expand_Convert_Float_To_Fixed (N);
12443 end if;
12444
12445 -- Case of array conversions
12446
12447 -- Expansion of array conversions, add required length/range checks but
12448 -- only do this if there is no change of representation. For handling of
12449 -- this case, see Handle_Changed_Representation.
12450
12451 elsif Is_Array_Type (Target_Type) then
12452 if Is_Constrained (Target_Type) then
12453 Apply_Length_Check (Operand, Target_Type);
12454 else
12455 -- If the object has an unconstrained array subtype with fixed
12456 -- lower bound, then sliding to that bound may be needed.
12457
12458 if Is_Fixed_Lower_Bound_Array_Subtype (Target_Type) then
12459 Expand_Sliding_Conversion (Operand, Target_Type);
12460 end if;
12461
12462 Apply_Range_Check (Operand, Target_Type);
12463 end if;
12464
12465 Handle_Changed_Representation;
12466
12467 -- Case of conversions of discriminated types
12468
12469 -- Add required discriminant checks if target is constrained. Again this
12470 -- change is skipped if we have a change of representation.
12471
12472 elsif Has_Discriminants (Target_Type)
12473 and then Is_Constrained (Target_Type)
12474 then
12475 Apply_Discriminant_Check (Operand, Target_Type);
12476 Handle_Changed_Representation;
12477
12478 -- Case of all other record conversions. The only processing required
12479 -- is to check for a change of representation requiring the special
12480 -- assignment processing.
12481
12482 elsif Is_Record_Type (Target_Type) then
12483
12484 -- Ada 2005 (AI-216): Program_Error is raised when converting from
12485 -- a derived Unchecked_Union type to an unconstrained type that is
12486 -- not Unchecked_Union if the operand lacks inferable discriminants.
12487
12488 if Is_Derived_Type (Operand_Type)
12489 and then Is_Unchecked_Union (Base_Type (Operand_Type))
12490 and then not Is_Constrained (Target_Type)
12491 and then not Is_Unchecked_Union (Base_Type (Target_Type))
12492 and then not Has_Inferable_Discriminants (Operand)
12493 then
12494 -- To prevent Gigi from generating illegal code, we generate a
12495 -- Program_Error node, but we give it the target type of the
12496 -- conversion (is this requirement documented somewhere ???)
12497
12498 declare
12499 PE : constant Node_Id := Make_Raise_Program_Error (Loc,
12500 Reason => PE_Unchecked_Union_Restriction);
12501
12502 begin
12503 Set_Etype (PE, Target_Type);
12504 Rewrite (N, PE);
12505
12506 end;
12507 else
12508 Handle_Changed_Representation;
12509 end if;
12510
12511 -- Case of conversions of enumeration types
12512
12513 elsif Is_Enumeration_Type (Target_Type) then
12514
12515 -- Special processing is required if there is a change of
12516 -- representation (from enumeration representation clauses).
12517
12518 if not Has_Compatible_Representation (Target_Type, Operand_Type)
12519 and then not Conversion_OK (N)
12520 then
12521 if Optimization_Level > 0
12522 and then Is_Boolean_Type (Target_Type)
12523 then
12524 -- Convert x(y) to (if y then x'(True) else x'(False)).
12525 -- Use literals, instead of indexing x'val, to enable
12526 -- further optimizations in the middle-end.
12527
12528 Rewrite (N,
12529 Make_If_Expression (Loc,
12530 Expressions => New_List (
12531 Operand,
12532 Convert_To (Target_Type,
12533 New_Occurrence_Of (Standard_True, Loc)),
12534 Convert_To (Target_Type,
12535 New_Occurrence_Of (Standard_False, Loc)))));
12536
12537 else
12538 -- Convert: x(y) to x'val (ytyp'pos (y))
12539
12540 Rewrite (N,
12541 Make_Attribute_Reference (Loc,
12542 Prefix => New_Occurrence_Of (Target_Type, Loc),
12543 Attribute_Name => Name_Val,
12544 Expressions => New_List (
12545 Make_Attribute_Reference (Loc,
12546 Prefix => New_Occurrence_Of (Operand_Type, Loc),
12547 Attribute_Name => Name_Pos,
12548 Expressions => New_List (Operand)))));
12549 end if;
12550
12551 Analyze_And_Resolve (N, Target_Type);
12552 end if;
12553 end if;
12554
12555 -- At this stage, either the conversion node has been transformed into
12556 -- some other equivalent expression, or left as a conversion that can be
12557 -- handled by Gigi.
12558
12559 -- The only remaining step is to generate a range check if we still have
12560 -- a type conversion at this stage and Do_Range_Check is set. Note that
12561 -- we need to deal with at most 8 out of the 9 possible cases of numeric
12562 -- conversions here, because the float-to-integer case is entirely dealt
12563 -- with by Apply_Float_Conversion_Check.
12564
12565 if Nkind (N) = N_Type_Conversion
12566 and then Do_Range_Check (Expression (N))
12567 then
12568 -- Float-to-float conversions
12569
12570 if Is_Floating_Point_Type (Target_Type)
12571 and then Is_Floating_Point_Type (Etype (Expression (N)))
12572 then
12573 -- Reset overflow flag, since the range check will include
12574 -- dealing with possible overflow, and generate the check.
12575
12576 Set_Do_Overflow_Check (N, False);
12577
12578 Generate_Range_Check
12579 (Expression (N), Target_Type, CE_Range_Check_Failed);
12580
12581 -- Discrete-to-discrete conversions or fixed-point-to-discrete
12582 -- conversions when Conversion_OK is set.
12583
12584 elsif Is_Discrete_Type (Target_Type)
12585 and then (Is_Discrete_Type (Etype (Expression (N)))
12586 or else (Is_Fixed_Point_Type (Etype (Expression (N)))
12587 and then Conversion_OK (N)))
12588 then
12589 -- If Address is either a source type or target type,
12590 -- suppress range check to avoid typing anomalies when
12591 -- it is a visible integer type.
12592
12593 if Is_Descendant_Of_Address (Etype (Expression (N)))
12594 or else Is_Descendant_Of_Address (Target_Type)
12595 then
12596 Set_Do_Range_Check (Expression (N), False);
12597 else
12598 Discrete_Range_Check;
12599 end if;
12600
12601 -- Conversions to floating- or fixed-point when Conversion_OK is set
12602
12603 elsif Is_Floating_Point_Type (Target_Type)
12604 or else (Is_Fixed_Point_Type (Target_Type)
12605 and then Conversion_OK (N))
12606 then
12607 Real_Range_Check;
12608 end if;
12609
12610 pragma Assert (not Do_Range_Check (Expression (N)));
12611 end if;
12612
12613 -- Here at end of processing
12614
12615 <<Done>>
12616 -- Apply predicate check if required. Note that we can't just call
12617 -- Apply_Predicate_Check here, because the type looks right after
12618 -- the conversion and it would omit the check. The Comes_From_Source
12619 -- guard is necessary to prevent infinite recursions when we generate
12620 -- internal conversions for the purpose of checking predicates.
12621
12622 -- A view conversion of a tagged object is an object and can appear
12623 -- in an assignment context, in which case no predicate check applies
12624 -- to the now-dead value.
12625
12626 if Nkind (Parent (N)) = N_Assignment_Statement
12627 and then N = Name (Parent (N))
12628 then
12629 null;
12630
12631 elsif Predicate_Enabled (Target_Type)
12632 and then Target_Type /= Operand_Type
12633 and then Comes_From_Source (N)
12634 then
12635 declare
12636 New_Expr : constant Node_Id := Duplicate_Subexpr (N);
12637
12638 begin
12639 -- Avoid infinite recursion on the subsequent expansion of the
12640 -- copy of the original type conversion. When needed, a range
12641 -- check has already been applied to the expression.
12642
12643 Set_Comes_From_Source (New_Expr, False);
12644 Insert_Action (N,
12645 Make_Predicate_Check (Target_Type, New_Expr),
12646 Suppress => Range_Check);
12647 end;
12648 end if;
12649 end Expand_N_Type_Conversion;
12650
12651 -----------------------------------
12652 -- Expand_N_Unchecked_Expression --
12653 -----------------------------------
12654
12655 -- Remove the unchecked expression node from the tree. Its job was simply
12656 -- to make sure that its constituent expression was handled with checks
12657 -- off, and now that is done, we can remove it from the tree, and indeed
12658 -- must, since Gigi does not expect to see these nodes.
12659
12660 procedure Expand_N_Unchecked_Expression (N : Node_Id) is
12661 Exp : constant Node_Id := Expression (N);
12662 begin
12663 Set_Assignment_OK (Exp, Assignment_OK (N) or else Assignment_OK (Exp));
12664 Rewrite (N, Exp);
12665 end Expand_N_Unchecked_Expression;
12666
12667 ----------------------------------------
12668 -- Expand_N_Unchecked_Type_Conversion --
12669 ----------------------------------------
12670
12671 -- If this cannot be handled by Gigi and we haven't already made a
12672 -- temporary for it, do it now.
12673
12674 procedure Expand_N_Unchecked_Type_Conversion (N : Node_Id) is
12675 Target_Type : constant Entity_Id := Etype (N);
12676 Operand : constant Node_Id := Expression (N);
12677 Operand_Type : constant Entity_Id := Etype (Operand);
12678
12679 begin
12680 -- Nothing at all to do if conversion is to the identical type so remove
12681 -- the conversion completely, it is useless, except that it may carry
12682 -- an Assignment_OK indication which must be propagated to the operand.
12683
12684 if Operand_Type = Target_Type then
12685 Expand_N_Unchecked_Expression (N);
12686 return;
12687 end if;
12688
12689 -- Generate an extra temporary for cases unsupported by the C backend
12690
12691 if Modify_Tree_For_C then
12692 declare
12693 Source : constant Node_Id := Unqual_Conv (Expression (N));
12694 Source_Typ : Entity_Id := Get_Full_View (Etype (Source));
12695
12696 begin
12697 if Is_Packed_Array (Source_Typ) then
12698 Source_Typ := Packed_Array_Impl_Type (Source_Typ);
12699 end if;
12700
12701 if Nkind (Source) = N_Function_Call
12702 and then (Is_Composite_Type (Etype (Source))
12703 or else Is_Composite_Type (Target_Type))
12704 then
12705 Force_Evaluation (Source);
12706 end if;
12707 end;
12708 end if;
12709
12710 -- Nothing to do if conversion is safe
12711
12712 if Safe_Unchecked_Type_Conversion (N) then
12713 return;
12714 end if;
12715
12716 if Assignment_OK (N) then
12717 null;
12718 else
12719 Force_Evaluation (N);
12720 end if;
12721 end Expand_N_Unchecked_Type_Conversion;
12722
12723 ----------------------------
12724 -- Expand_Record_Equality --
12725 ----------------------------
12726
12727 -- For non-variant records, Equality is expanded when needed into:
12728
12729 -- and then Lhs.Discr1 = Rhs.Discr1
12730 -- and then ...
12731 -- and then Lhs.Discrn = Rhs.Discrn
12732 -- and then Lhs.Cmp1 = Rhs.Cmp1
12733 -- and then ...
12734 -- and then Lhs.Cmpn = Rhs.Cmpn
12735
12736 -- The expression is folded by the back end for adjacent fields. This
12737 -- function is called for tagged record in only one occasion: for imple-
12738 -- menting predefined primitive equality (see Predefined_Primitives_Bodies)
12739 -- otherwise the primitive "=" is used directly.
12740
12741 function Expand_Record_Equality
12742 (Nod : Node_Id;
12743 Typ : Entity_Id;
12744 Lhs : Node_Id;
12745 Rhs : Node_Id) return Node_Id
12746 is
12747 Loc : constant Source_Ptr := Sloc (Nod);
12748
12749 Result : Node_Id;
12750 C : Entity_Id;
12751
12752 First_Time : Boolean := True;
12753
12754 function Element_To_Compare (C : Entity_Id) return Entity_Id;
12755 -- Return the next discriminant or component to compare, starting with
12756 -- C, skipping inherited components.
12757
12758 ------------------------
12759 -- Element_To_Compare --
12760 ------------------------
12761
12762 function Element_To_Compare (C : Entity_Id) return Entity_Id is
12763 Comp : Entity_Id := C;
12764
12765 begin
12766 while Present (Comp) loop
12767 -- Skip inherited components
12768
12769 -- Note: for a tagged type, we always generate the "=" primitive
12770 -- for the base type (not on the first subtype), so the test for
12771 -- Comp /= Original_Record_Component (Comp) is True for inherited
12772 -- components only.
12773
12774 if (Is_Tagged_Type (Typ)
12775 and then Comp /= Original_Record_Component (Comp))
12776
12777 -- Skip _Tag
12778
12779 or else Chars (Comp) = Name_uTag
12780
12781 -- Skip interface elements (secondary tags???)
12782
12783 or else Is_Interface (Etype (Comp))
12784 then
12785 Next_Component_Or_Discriminant (Comp);
12786 else
12787 return Comp;
12788 end if;
12789 end loop;
12790
12791 return Empty;
12792 end Element_To_Compare;
12793
12794 -- Start of processing for Expand_Record_Equality
12795
12796 begin
12797 -- Generates the following code: (assuming that Typ has one Discr and
12798 -- component C2 is also a record)
12799
12800 -- Lhs.Discr1 = Rhs.Discr1
12801 -- and then Lhs.C1 = Rhs.C1
12802 -- and then Lhs.C2.C1=Rhs.C2.C1 and then ... Lhs.C2.Cn=Rhs.C2.Cn
12803 -- and then ...
12804 -- and then Lhs.Cmpn = Rhs.Cmpn
12805
12806 Result := New_Occurrence_Of (Standard_True, Loc);
12807 C := Element_To_Compare (First_Component_Or_Discriminant (Typ));
12808 while Present (C) loop
12809 declare
12810 New_Lhs : Node_Id;
12811 New_Rhs : Node_Id;
12812 Check : Node_Id;
12813
12814 begin
12815 if First_Time then
12816 New_Lhs := Lhs;
12817 New_Rhs := Rhs;
12818 else
12819 New_Lhs := New_Copy_Tree (Lhs);
12820 New_Rhs := New_Copy_Tree (Rhs);
12821 end if;
12822
12823 Check :=
12824 Expand_Composite_Equality
12825 (Outer_Type => Typ, Nod => Nod, Comp_Type => Etype (C),
12826 Lhs =>
12827 Make_Selected_Component (Loc,
12828 Prefix => New_Lhs,
12829 Selector_Name => New_Occurrence_Of (C, Loc)),
12830 Rhs =>
12831 Make_Selected_Component (Loc,
12832 Prefix => New_Rhs,
12833 Selector_Name => New_Occurrence_Of (C, Loc)));
12834
12835 -- If some (sub)component is an unchecked_union, the whole
12836 -- operation will raise program error.
12837
12838 if Nkind (Check) = N_Raise_Program_Error then
12839 Result := Check;
12840 Set_Etype (Result, Standard_Boolean);
12841 exit;
12842 else
12843 if First_Time then
12844 Result := Check;
12845
12846 -- Generate logical "and" for CodePeer to simplify the
12847 -- generated code and analysis.
12848
12849 elsif CodePeer_Mode then
12850 Result :=
12851 Make_Op_And (Loc,
12852 Left_Opnd => Result,
12853 Right_Opnd => Check);
12854
12855 else
12856 Result :=
12857 Make_And_Then (Loc,
12858 Left_Opnd => Result,
12859 Right_Opnd => Check);
12860 end if;
12861 end if;
12862 end;
12863
12864 First_Time := False;
12865 C := Element_To_Compare (Next_Component_Or_Discriminant (C));
12866 end loop;
12867
12868 return Result;
12869 end Expand_Record_Equality;
12870
12871 ---------------------------
12872 -- Expand_Set_Membership --
12873 ---------------------------
12874
12875 procedure Expand_Set_Membership (N : Node_Id) is
12876 Lop : constant Node_Id := Left_Opnd (N);
12877
12878 function Make_Cond (Alt : Node_Id) return Node_Id;
12879 -- If the alternative is a subtype mark, create a simple membership
12880 -- test. Otherwise create an equality test for it.
12881
12882 ---------------
12883 -- Make_Cond --
12884 ---------------
12885
12886 function Make_Cond (Alt : Node_Id) return Node_Id is
12887 Cond : Node_Id;
12888 L : constant Node_Id := New_Copy_Tree (Lop);
12889 R : constant Node_Id := Relocate_Node (Alt);
12890
12891 begin
12892 if (Is_Entity_Name (Alt) and then Is_Type (Entity (Alt)))
12893 or else Nkind (Alt) = N_Range
12894 then
12895 Cond := Make_In (Sloc (Alt), Left_Opnd => L, Right_Opnd => R);
12896
12897 else
12898 Cond := Make_Op_Eq (Sloc (Alt), Left_Opnd => L, Right_Opnd => R);
12899 Resolve_Membership_Equality (Cond, Etype (Alt));
12900 end if;
12901
12902 return Cond;
12903 end Make_Cond;
12904
12905 -- Local variables
12906
12907 Alt : Node_Id;
12908 Res : Node_Id := Empty;
12909
12910 -- Start of processing for Expand_Set_Membership
12911
12912 begin
12913 Remove_Side_Effects (Lop);
12914
12915 -- We use left associativity as in the equivalent boolean case. This
12916 -- kind of canonicalization helps the optimizer of the code generator.
12917
12918 Alt := First (Alternatives (N));
12919 while Present (Alt) loop
12920 Evolve_Or_Else (Res, Make_Cond (Alt));
12921 Next (Alt);
12922 end loop;
12923
12924 Rewrite (N, Res);
12925 Analyze_And_Resolve (N, Standard_Boolean);
12926 end Expand_Set_Membership;
12927
12928 -----------------------------------
12929 -- Expand_Short_Circuit_Operator --
12930 -----------------------------------
12931
12932 -- Deal with special expansion if actions are present for the right operand
12933 -- and deal with optimizing case of arguments being True or False. We also
12934 -- deal with the special case of non-standard boolean values.
12935
12936 procedure Expand_Short_Circuit_Operator (N : Node_Id) is
12937 Loc : constant Source_Ptr := Sloc (N);
12938 Typ : constant Entity_Id := Etype (N);
12939 Left : constant Node_Id := Left_Opnd (N);
12940 Right : constant Node_Id := Right_Opnd (N);
12941 LocR : constant Source_Ptr := Sloc (Right);
12942 Actlist : List_Id;
12943
12944 Shortcut_Value : constant Boolean := Nkind (N) = N_Or_Else;
12945 Shortcut_Ent : constant Entity_Id := Boolean_Literals (Shortcut_Value);
12946 -- If Left = Shortcut_Value then Right need not be evaluated
12947
12948 function Make_Test_Expr (Opnd : Node_Id) return Node_Id;
12949 -- For Opnd a boolean expression, return a Boolean expression equivalent
12950 -- to Opnd /= Shortcut_Value.
12951
12952 function Useful (Actions : List_Id) return Boolean;
12953 -- Return True if Actions is not empty and contains useful nodes to
12954 -- process.
12955
12956 --------------------
12957 -- Make_Test_Expr --
12958 --------------------
12959
12960 function Make_Test_Expr (Opnd : Node_Id) return Node_Id is
12961 begin
12962 if Shortcut_Value then
12963 return Make_Op_Not (Sloc (Opnd), Opnd);
12964 else
12965 return Opnd;
12966 end if;
12967 end Make_Test_Expr;
12968
12969 ------------
12970 -- Useful --
12971 ------------
12972
12973 function Useful (Actions : List_Id) return Boolean is
12974 L : Node_Id;
12975 begin
12976 if Present (Actions) then
12977 L := First (Actions);
12978
12979 -- For now "useful" means not N_Variable_Reference_Marker.
12980 -- Consider stripping other nodes in the future.
12981
12982 while Present (L) loop
12983 if Nkind (L) /= N_Variable_Reference_Marker then
12984 return True;
12985 end if;
12986
12987 Next (L);
12988 end loop;
12989 end if;
12990
12991 return False;
12992 end Useful;
12993
12994 -- Local variables
12995
12996 Op_Var : Entity_Id;
12997 -- Entity for a temporary variable holding the value of the operator,
12998 -- used for expansion in the case where actions are present.
12999
13000 -- Start of processing for Expand_Short_Circuit_Operator
13001
13002 begin
13003 -- Deal with non-standard booleans
13004
13005 if Is_Boolean_Type (Typ) then
13006 Adjust_Condition (Left);
13007 Adjust_Condition (Right);
13008 Set_Etype (N, Standard_Boolean);
13009 end if;
13010
13011 -- Check for cases where left argument is known to be True or False
13012
13013 if Compile_Time_Known_Value (Left) then
13014
13015 -- Mark SCO for left condition as compile time known
13016
13017 if Generate_SCO and then Comes_From_Source (Left) then
13018 Set_SCO_Condition (Left, Expr_Value_E (Left) = Standard_True);
13019 end if;
13020
13021 -- Rewrite True AND THEN Right / False OR ELSE Right to Right.
13022 -- Any actions associated with Right will be executed unconditionally
13023 -- and can thus be inserted into the tree unconditionally.
13024
13025 if Expr_Value_E (Left) /= Shortcut_Ent then
13026 if Present (Actions (N)) then
13027 Insert_Actions (N, Actions (N));
13028 end if;
13029
13030 Rewrite (N, Right);
13031
13032 -- Rewrite False AND THEN Right / True OR ELSE Right to Left.
13033 -- In this case we can forget the actions associated with Right,
13034 -- since they will never be executed.
13035
13036 else
13037 Kill_Dead_Code (Right);
13038 Kill_Dead_Code (Actions (N));
13039 Rewrite (N, New_Occurrence_Of (Shortcut_Ent, Loc));
13040 end if;
13041
13042 Adjust_Result_Type (N, Typ);
13043 return;
13044 end if;
13045
13046 -- If Actions are present for the right operand, we have to do some
13047 -- special processing. We can't just let these actions filter back into
13048 -- code preceding the short circuit (which is what would have happened
13049 -- if we had not trapped them in the short-circuit form), since they
13050 -- must only be executed if the right operand of the short circuit is
13051 -- executed and not otherwise.
13052
13053 if Useful (Actions (N)) then
13054 Actlist := Actions (N);
13055
13056 -- The old approach is to expand:
13057
13058 -- left AND THEN right
13059
13060 -- into
13061
13062 -- C : Boolean := False;
13063 -- IF left THEN
13064 -- Actions;
13065 -- IF right THEN
13066 -- C := True;
13067 -- END IF;
13068 -- END IF;
13069
13070 -- and finally rewrite the operator into a reference to C. Similarly
13071 -- for left OR ELSE right, with negated values. Note that this
13072 -- rewrite causes some difficulties for coverage analysis because
13073 -- of the introduction of the new variable C, which obscures the
13074 -- structure of the test.
13075
13076 -- We use this "old approach" if Minimize_Expression_With_Actions
13077 -- is True.
13078
13079 if Minimize_Expression_With_Actions then
13080 Op_Var := Make_Temporary (Loc, 'C', Related_Node => N);
13081
13082 Insert_Action (N,
13083 Make_Object_Declaration (Loc,
13084 Defining_Identifier => Op_Var,
13085 Object_Definition =>
13086 New_Occurrence_Of (Standard_Boolean, Loc),
13087 Expression =>
13088 New_Occurrence_Of (Shortcut_Ent, Loc)));
13089
13090 Append_To (Actlist,
13091 Make_Implicit_If_Statement (Right,
13092 Condition => Make_Test_Expr (Right),
13093 Then_Statements => New_List (
13094 Make_Assignment_Statement (LocR,
13095 Name => New_Occurrence_Of (Op_Var, LocR),
13096 Expression =>
13097 New_Occurrence_Of
13098 (Boolean_Literals (not Shortcut_Value), LocR)))));
13099
13100 Insert_Action (N,
13101 Make_Implicit_If_Statement (Left,
13102 Condition => Make_Test_Expr (Left),
13103 Then_Statements => Actlist));
13104
13105 Rewrite (N, New_Occurrence_Of (Op_Var, Loc));
13106 Analyze_And_Resolve (N, Standard_Boolean);
13107
13108 -- The new approach (the default) is to use an
13109 -- Expression_With_Actions node for the right operand of the
13110 -- short-circuit form. Note that this solves the traceability
13111 -- problems for coverage analysis.
13112
13113 else
13114 Rewrite (Right,
13115 Make_Expression_With_Actions (LocR,
13116 Expression => Relocate_Node (Right),
13117 Actions => Actlist));
13118
13119 Set_Actions (N, No_List);
13120 Analyze_And_Resolve (Right, Standard_Boolean);
13121 end if;
13122
13123 Adjust_Result_Type (N, Typ);
13124 return;
13125 end if;
13126
13127 -- No actions present, check for cases of right argument True/False
13128
13129 if Compile_Time_Known_Value (Right) then
13130
13131 -- Mark SCO for left condition as compile time known
13132
13133 if Generate_SCO and then Comes_From_Source (Right) then
13134 Set_SCO_Condition (Right, Expr_Value_E (Right) = Standard_True);
13135 end if;
13136
13137 -- Change (Left and then True), (Left or else False) to Left. Note
13138 -- that we know there are no actions associated with the right
13139 -- operand, since we just checked for this case above.
13140
13141 if Expr_Value_E (Right) /= Shortcut_Ent then
13142 Rewrite (N, Left);
13143
13144 -- Change (Left and then False), (Left or else True) to Right,
13145 -- making sure to preserve any side effects associated with the Left
13146 -- operand.
13147
13148 else
13149 Remove_Side_Effects (Left);
13150 Rewrite (N, New_Occurrence_Of (Shortcut_Ent, Loc));
13151 end if;
13152 end if;
13153
13154 Adjust_Result_Type (N, Typ);
13155 end Expand_Short_Circuit_Operator;
13156
13157 -------------------------------------
13158 -- Expand_Unchecked_Union_Equality --
13159 -------------------------------------
13160
13161 procedure Expand_Unchecked_Union_Equality
13162 (N : Node_Id;
13163 Eq : Entity_Id;
13164 Lhs : Node_Id;
13165 Rhs : Node_Id)
13166 is
13167 Loc : constant Source_Ptr := Sloc (N);
13168
13169 function Get_Discr_Values (Op : Node_Id; Lhs : Boolean) return Elist_Id;
13170 -- Return the list of inferred discriminant values for Op
13171
13172 ----------------------
13173 -- Get_Discr_Values --
13174 ----------------------
13175
13176 function Get_Discr_Values (Op : Node_Id; Lhs : Boolean) return Elist_Id
13177 is
13178 Typ : constant Entity_Id := Etype (Op);
13179 Values : constant Elist_Id := New_Elmt_List;
13180
13181 function Get_Extra_Formal (Nam : Name_Id) return Entity_Id;
13182 -- Return the extra formal Nam from the current scope, which must be
13183 -- an equality function for an unchecked union type.
13184
13185 ----------------------
13186 -- Get_Extra_Formal --
13187 ----------------------
13188
13189 function Get_Extra_Formal (Nam : Name_Id) return Entity_Id is
13190 Func : constant Entity_Id := Current_Scope;
13191
13192 Formal : Entity_Id;
13193
13194 begin
13195 pragma Assert (Ekind (Func) = E_Function);
13196
13197 Formal := Extra_Formals (Func);
13198 while Present (Formal) loop
13199 if Chars (Formal) = Nam then
13200 return Formal;
13201 end if;
13202
13203 Formal := Extra_Formal (Formal);
13204 end loop;
13205
13206 -- An extra formal of the proper name must be found
13207
13208 raise Program_Error;
13209 end Get_Extra_Formal;
13210
13211 -- Local variables
13212
13213 Discr : Entity_Id;
13214
13215 -- Start of processing for Get_Discr_Values
13216
13217 begin
13218 -- Per-object constrained selected components require special
13219 -- attention. If the enclosing scope of the component is an
13220 -- Unchecked_Union, we cannot reference its discriminants
13221 -- directly. This is why we use the extra parameters of the
13222 -- equality function of the enclosing Unchecked_Union.
13223
13224 -- type UU_Type (Discr : Integer := 0) is
13225 -- . . .
13226 -- end record;
13227 -- pragma Unchecked_Union (UU_Type);
13228
13229 -- 1. Unchecked_Union enclosing record:
13230
13231 -- type Enclosing_UU_Type (Discr : Integer := 0) is record
13232 -- . . .
13233 -- Comp : UU_Type (Discr);
13234 -- . . .
13235 -- end Enclosing_UU_Type;
13236 -- pragma Unchecked_Union (Enclosing_UU_Type);
13237
13238 -- Obj1 : Enclosing_UU_Type;
13239 -- Obj2 : Enclosing_UU_Type (1);
13240
13241 -- [. . .] Obj1 = Obj2 [. . .]
13242
13243 -- Generated code:
13244
13245 -- if not (uu_typeEQ (obj1.comp, obj2.comp, a, b)) then
13246
13247 -- A and B are the formal parameters of the equality function
13248 -- of Enclosing_UU_Type. The function always has two extra
13249 -- formals to capture the inferred discriminant values for
13250 -- each discriminant of the type.
13251
13252 -- 2. Non-Unchecked_Union enclosing record:
13253
13254 -- type
13255 -- Enclosing_Non_UU_Type (Discr : Integer := 0)
13256 -- is record
13257 -- . . .
13258 -- Comp : UU_Type (Discr);
13259 -- . . .
13260 -- end Enclosing_Non_UU_Type;
13261
13262 -- Obj1 : Enclosing_Non_UU_Type;
13263 -- Obj2 : Enclosing_Non_UU_Type (1);
13264
13265 -- ... Obj1 = Obj2 ...
13266
13267 -- Generated code:
13268
13269 -- if not (uu_typeEQ (obj1.comp, obj2.comp,
13270 -- obj1.discr, obj2.discr)) then
13271
13272 -- In this case we can directly reference the discriminants of
13273 -- the enclosing record.
13274
13275 if Nkind (Op) = N_Selected_Component
13276 and then Has_Per_Object_Constraint (Entity (Selector_Name (Op)))
13277 then
13278 -- If enclosing record is an Unchecked_Union, use formals
13279 -- corresponding to each discriminant. The name of the
13280 -- formal is that of the discriminant, with added suffix,
13281 -- see Exp_Ch3.Build_Variant_Record_Equality for details.
13282
13283 if Is_Unchecked_Union (Scope (Entity (Selector_Name (Op)))) then
13284 Discr :=
13285 First_Discriminant
13286 (Scope (Entity (Selector_Name (Op))));
13287 while Present (Discr) loop
13288 Append_Elmt
13289 (New_Occurrence_Of
13290 (Get_Extra_Formal
13291 (New_External_Name
13292 (Chars (Discr), (if Lhs then 'A' else 'B'))), Loc),
13293 To => Values);
13294 Next_Discriminant (Discr);
13295 end loop;
13296
13297 -- If enclosing record is of a non-Unchecked_Union type, it
13298 -- is possible to reference its discriminants directly.
13299
13300 else
13301 Discr := First_Discriminant (Typ);
13302 while Present (Discr) loop
13303 Append_Elmt
13304 (Make_Selected_Component (Loc,
13305 Prefix => Prefix (Op),
13306 Selector_Name =>
13307 New_Copy
13308 (Get_Discriminant_Value (Discr,
13309 Typ,
13310 Stored_Constraint (Typ)))),
13311 To => Values);
13312 Next_Discriminant (Discr);
13313 end loop;
13314 end if;
13315
13316 -- Otherwise operand is on object with a constrained type.
13317 -- Infer the discriminant values from the constraint.
13318
13319 else
13320 Discr := First_Discriminant (Typ);
13321 while Present (Discr) loop
13322 Append_Elmt
13323 (New_Copy
13324 (Get_Discriminant_Value (Discr,
13325 Typ,
13326 Stored_Constraint (Typ))),
13327 To => Values);
13328 Next_Discriminant (Discr);
13329 end loop;
13330 end if;
13331
13332 return Values;
13333 end Get_Discr_Values;
13334
13335 -- Start of processing for Expand_Unchecked_Union_Equality
13336
13337 begin
13338 -- If we can infer the discriminants of the operands, make a call to Eq
13339
13340 if Has_Inferable_Discriminants (Lhs)
13341 and then
13342 Has_Inferable_Discriminants (Rhs)
13343 then
13344 declare
13345 Lhs_Values : constant Elist_Id := Get_Discr_Values (Lhs, True);
13346 Rhs_Values : constant Elist_Id := Get_Discr_Values (Rhs, False);
13347
13348 Formal : Entity_Id;
13349 L_Elmt : Elmt_Id;
13350 R_Elmt : Elmt_Id;
13351
13352 begin
13353 -- Add the inferred discriminant values as extra actuals
13354
13355 Formal := Extra_Formals (Eq);
13356 L_Elmt := First_Elmt (Lhs_Values);
13357 R_Elmt := First_Elmt (Rhs_Values);
13358
13359 while Present (L_Elmt) loop
13360 Analyze_And_Resolve (Node (L_Elmt), Etype (Formal));
13361 Add_Extra_Actual_To_Call (N, Formal, Node (L_Elmt));
13362
13363 Formal := Extra_Formal (Formal);
13364
13365 Analyze_And_Resolve (Node (R_Elmt), Etype (Formal));
13366 Add_Extra_Actual_To_Call (N, Formal, Node (R_Elmt));
13367
13368 Formal := Extra_Formal (Formal);
13369 Next_Elmt (L_Elmt);
13370 Next_Elmt (R_Elmt);
13371 end loop;
13372 end;
13373
13374 -- Ada 2005 (AI-216): Program_Error is raised when evaluating
13375 -- the predefined equality operator for an Unchecked_Union type
13376 -- if either of the operands lack inferable discriminants.
13377
13378 else
13379 Insert_Action (N,
13380 Make_Raise_Program_Error (Loc,
13381 Reason => PE_Unchecked_Union_Restriction));
13382
13383 -- Give a warning on source equalities only, otherwise the message
13384 -- may appear out of place due to internal use. It is unconditional
13385 -- because it is required by the language.
13386
13387 if Comes_From_Source (Original_Node (N)) then
13388 Error_Msg_N
13389 ("Unchecked_Union discriminants cannot be determined??", N);
13390 Error_Msg_N
13391 ("\Program_Error will be raised for equality operation??", N);
13392 end if;
13393
13394 Rewrite (N, New_Occurrence_Of (Standard_False, Loc));
13395 end if;
13396 end Expand_Unchecked_Union_Equality;
13397
13398 ------------------------------------
13399 -- Fixup_Universal_Fixed_Operation --
13400 -------------------------------------
13401
13402 procedure Fixup_Universal_Fixed_Operation (N : Node_Id) is
13403 Conv : constant Node_Id := Parent (N);
13404
13405 begin
13406 -- We must have a type conversion immediately above us
13407
13408 pragma Assert (Nkind (Conv) = N_Type_Conversion);
13409
13410 -- Normally the type conversion gives our target type. The exception
13411 -- occurs in the case of the Round attribute, where the conversion
13412 -- will be to universal real, and our real type comes from the Round
13413 -- attribute (as well as an indication that we must round the result)
13414
13415 if Etype (Conv) = Universal_Real
13416 and then Nkind (Parent (Conv)) = N_Attribute_Reference
13417 and then Attribute_Name (Parent (Conv)) = Name_Round
13418 then
13419 Set_Etype (N, Base_Type (Etype (Parent (Conv))));
13420 Set_Rounded_Result (N);
13421
13422 -- Normal case where type comes from conversion above us
13423
13424 else
13425 Set_Etype (N, Base_Type (Etype (Conv)));
13426 end if;
13427 end Fixup_Universal_Fixed_Operation;
13428
13429 ----------------------------
13430 -- Get_First_Index_Bounds --
13431 ----------------------------
13432
13433 procedure Get_First_Index_Bounds (T : Entity_Id; Lo, Hi : out Uint) is
13434 Typ : Entity_Id;
13435
13436 begin
13437 pragma Assert (Is_Array_Type (T));
13438
13439 -- This follows Sem_Eval.Compile_Time_Known_Bounds
13440
13441 if Ekind (T) = E_String_Literal_Subtype then
13442 Lo := Expr_Value (String_Literal_Low_Bound (T));
13443 Hi := Lo + String_Literal_Length (T) - 1;
13444
13445 else
13446 Typ := Underlying_Type (Etype (First_Index (T)));
13447
13448 Lo := Expr_Value (Type_Low_Bound (Typ));
13449 Hi := Expr_Value (Type_High_Bound (Typ));
13450 end if;
13451 end Get_First_Index_Bounds;
13452
13453 ------------------------
13454 -- Get_Size_For_Range --
13455 ------------------------
13456
13457 function Get_Size_For_Range (Lo, Hi : Uint) return Uint is
13458
13459 function Is_OK_For_Range (Siz : Uint) return Boolean;
13460 -- Return True if a signed integer with given size can cover Lo .. Hi
13461
13462 --------------------------
13463 -- Is_OK_For_Range --
13464 --------------------------
13465
13466 function Is_OK_For_Range (Siz : Uint) return Boolean is
13467 B : constant Uint := Uint_2 ** (Siz - 1);
13468
13469 begin
13470 -- Test B = 2 ** (size - 1) (can accommodate -B .. +(B - 1))
13471
13472 return Lo >= -B and then Hi >= -B and then Lo < B and then Hi < B;
13473 end Is_OK_For_Range;
13474
13475 begin
13476 -- This is (almost always) the size of Integer
13477
13478 if Is_OK_For_Range (Uint_32) then
13479 return Uint_32;
13480
13481 -- Check 63
13482
13483 elsif Is_OK_For_Range (Uint_63) then
13484 return Uint_63;
13485
13486 -- This is (almost always) the size of Long_Long_Integer
13487
13488 elsif Is_OK_For_Range (Uint_64) then
13489 return Uint_64;
13490
13491 -- Check 127
13492
13493 elsif Is_OK_For_Range (Uint_127) then
13494 return Uint_127;
13495
13496 else
13497 return Uint_128;
13498 end if;
13499 end Get_Size_For_Range;
13500
13501 -------------------------------
13502 -- Insert_Dereference_Action --
13503 -------------------------------
13504
13505 procedure Insert_Dereference_Action (N : Node_Id) is
13506 function Is_Checked_Storage_Pool (P : Entity_Id) return Boolean;
13507 -- Return true if type of P is derived from Checked_Pool;
13508
13509 -----------------------------
13510 -- Is_Checked_Storage_Pool --
13511 -----------------------------
13512
13513 function Is_Checked_Storage_Pool (P : Entity_Id) return Boolean is
13514 T : Entity_Id;
13515
13516 begin
13517 if No (P) then
13518 return False;
13519 end if;
13520
13521 T := Etype (P);
13522 while T /= Etype (T) loop
13523 if Is_RTE (T, RE_Checked_Pool) then
13524 return True;
13525 else
13526 T := Etype (T);
13527 end if;
13528 end loop;
13529
13530 return False;
13531 end Is_Checked_Storage_Pool;
13532
13533 -- Local variables
13534
13535 Context : constant Node_Id := Parent (N);
13536 Ptr_Typ : constant Entity_Id := Etype (N);
13537 Desig_Typ : constant Entity_Id :=
13538 Available_View (Designated_Type (Ptr_Typ));
13539 Loc : constant Source_Ptr := Sloc (N);
13540 Pool : constant Entity_Id := Associated_Storage_Pool (Ptr_Typ);
13541
13542 Addr : Entity_Id;
13543 Alig : Entity_Id;
13544 Deref : Node_Id;
13545 Size : Entity_Id;
13546 Size_Bits : Node_Id;
13547 Stmt : Node_Id;
13548
13549 -- Start of processing for Insert_Dereference_Action
13550
13551 begin
13552 pragma Assert (Nkind (Context) = N_Explicit_Dereference);
13553
13554 -- Do not re-expand a dereference which has already been processed by
13555 -- this routine.
13556
13557 if Has_Dereference_Action (Context) then
13558 return;
13559
13560 -- Do not perform this type of expansion for internally-generated
13561 -- dereferences.
13562
13563 elsif not Comes_From_Source (Original_Node (Context)) then
13564 return;
13565
13566 -- A dereference action is only applicable to objects which have been
13567 -- allocated on a checked pool.
13568
13569 elsif not Is_Checked_Storage_Pool (Pool) then
13570 return;
13571 end if;
13572
13573 -- Extract the address of the dereferenced object. Generate:
13574
13575 -- Addr : System.Address := <N>'Pool_Address;
13576
13577 Addr := Make_Temporary (Loc, 'P');
13578
13579 Insert_Action (N,
13580 Make_Object_Declaration (Loc,
13581 Defining_Identifier => Addr,
13582 Object_Definition =>
13583 New_Occurrence_Of (RTE (RE_Address), Loc),
13584 Expression =>
13585 Make_Attribute_Reference (Loc,
13586 Prefix => Duplicate_Subexpr_Move_Checks (N),
13587 Attribute_Name => Name_Pool_Address)));
13588
13589 -- Calculate the size of the dereferenced object. Generate:
13590
13591 -- Size : Storage_Count := <N>.all'Size / Storage_Unit;
13592
13593 Deref :=
13594 Make_Explicit_Dereference (Loc,
13595 Prefix => Duplicate_Subexpr_Move_Checks (N));
13596 Set_Has_Dereference_Action (Deref);
13597
13598 Size_Bits :=
13599 Make_Attribute_Reference (Loc,
13600 Prefix => Deref,
13601 Attribute_Name => Name_Size);
13602
13603 -- Special case of an unconstrained array: need to add descriptor size
13604
13605 if Is_Array_Type (Desig_Typ)
13606 and then not Is_Constrained (First_Subtype (Desig_Typ))
13607 then
13608 Size_Bits :=
13609 Make_Op_Add (Loc,
13610 Left_Opnd =>
13611 Make_Attribute_Reference (Loc,
13612 Prefix =>
13613 New_Occurrence_Of (First_Subtype (Desig_Typ), Loc),
13614 Attribute_Name => Name_Descriptor_Size),
13615 Right_Opnd => Size_Bits);
13616 end if;
13617
13618 Size := Make_Temporary (Loc, 'S');
13619 Insert_Action (N,
13620 Make_Object_Declaration (Loc,
13621 Defining_Identifier => Size,
13622 Object_Definition =>
13623 New_Occurrence_Of (RTE (RE_Storage_Count), Loc),
13624 Expression =>
13625 Make_Op_Divide (Loc,
13626 Left_Opnd => Size_Bits,
13627 Right_Opnd => Make_Integer_Literal (Loc, System_Storage_Unit))));
13628
13629 -- Calculate the alignment of the dereferenced object. Generate:
13630 -- Alig : constant Storage_Count := <N>.all'Alignment;
13631
13632 Deref :=
13633 Make_Explicit_Dereference (Loc,
13634 Prefix => Duplicate_Subexpr_Move_Checks (N));
13635 Set_Has_Dereference_Action (Deref);
13636
13637 Alig := Make_Temporary (Loc, 'A');
13638 Insert_Action (N,
13639 Make_Object_Declaration (Loc,
13640 Defining_Identifier => Alig,
13641 Object_Definition =>
13642 New_Occurrence_Of (RTE (RE_Storage_Count), Loc),
13643 Expression =>
13644 Make_Attribute_Reference (Loc,
13645 Prefix => Deref,
13646 Attribute_Name => Name_Alignment)));
13647
13648 -- A dereference of a controlled object requires special processing. The
13649 -- finalization machinery requests additional space from the underlying
13650 -- pool to allocate and hide two pointers. As a result, a checked pool
13651 -- may mark the wrong memory as valid. Since checked pools do not have
13652 -- knowledge of hidden pointers, we have to bring the two pointers back
13653 -- in view in order to restore the original state of the object.
13654
13655 -- The address manipulation is not performed for access types that are
13656 -- subject to pragma No_Heap_Finalization because the two pointers do
13657 -- not exist in the first place.
13658
13659 if No_Heap_Finalization (Ptr_Typ) then
13660 null;
13661
13662 elsif Needs_Finalization (Desig_Typ) then
13663
13664 -- Adjust the address and size of the dereferenced object. Generate:
13665 -- Adjust_Controlled_Dereference (Addr, Size, Alig);
13666
13667 Stmt :=
13668 Make_Procedure_Call_Statement (Loc,
13669 Name =>
13670 New_Occurrence_Of (RTE (RE_Adjust_Controlled_Dereference), Loc),
13671 Parameter_Associations => New_List (
13672 New_Occurrence_Of (Addr, Loc),
13673 New_Occurrence_Of (Size, Loc),
13674 New_Occurrence_Of (Alig, Loc)));
13675
13676 -- Class-wide types complicate things because we cannot determine
13677 -- statically whether the actual object is truly controlled. We must
13678 -- generate a runtime check to detect this property. Generate:
13679 --
13680 -- if Needs_Finalization (<N>.all'Tag) then
13681 -- <Stmt>;
13682 -- end if;
13683
13684 if Is_Class_Wide_Type (Desig_Typ) then
13685 Deref :=
13686 Make_Explicit_Dereference (Loc,
13687 Prefix => Duplicate_Subexpr_Move_Checks (N));
13688 Set_Has_Dereference_Action (Deref);
13689
13690 Stmt :=
13691 Make_Implicit_If_Statement (N,
13692 Condition =>
13693 Make_Function_Call (Loc,
13694 Name =>
13695 New_Occurrence_Of (RTE (RE_Needs_Finalization), Loc),
13696 Parameter_Associations => New_List (
13697 Make_Attribute_Reference (Loc,
13698 Prefix => Deref,
13699 Attribute_Name => Name_Tag))),
13700 Then_Statements => New_List (Stmt));
13701 end if;
13702
13703 Insert_Action (N, Stmt);
13704 end if;
13705
13706 -- Generate:
13707 -- Dereference (Pool, Addr, Size, Alig);
13708
13709 Insert_Action (N,
13710 Make_Procedure_Call_Statement (Loc,
13711 Name =>
13712 New_Occurrence_Of
13713 (Find_Prim_Op (Etype (Pool), Name_Dereference), Loc),
13714 Parameter_Associations => New_List (
13715 New_Occurrence_Of (Pool, Loc),
13716 New_Occurrence_Of (Addr, Loc),
13717 New_Occurrence_Of (Size, Loc),
13718 New_Occurrence_Of (Alig, Loc))));
13719
13720 -- Mark the explicit dereference as processed to avoid potential
13721 -- infinite expansion.
13722
13723 Set_Has_Dereference_Action (Context);
13724
13725 exception
13726 when RE_Not_Available =>
13727 return;
13728 end Insert_Dereference_Action;
13729
13730 --------------------------------
13731 -- Integer_Promotion_Possible --
13732 --------------------------------
13733
13734 function Integer_Promotion_Possible (N : Node_Id) return Boolean is
13735 Operand : constant Node_Id := Expression (N);
13736 Operand_Type : constant Entity_Id := Etype (Operand);
13737 Root_Operand_Type : constant Entity_Id := Root_Type (Operand_Type);
13738
13739 begin
13740 pragma Assert (Nkind (N) = N_Type_Conversion);
13741
13742 return
13743
13744 -- We only do the transformation for source constructs. We assume
13745 -- that the expander knows what it is doing when it generates code.
13746
13747 Comes_From_Source (N)
13748
13749 -- If the operand type is Short_Integer or Short_Short_Integer,
13750 -- then we will promote to Integer, which is available on all
13751 -- targets, and is sufficient to ensure no intermediate overflow.
13752 -- Furthermore it is likely to be as efficient or more efficient
13753 -- than using the smaller type for the computation so we do this
13754 -- unconditionally.
13755
13756 and then
13757 (Root_Operand_Type = Base_Type (Standard_Short_Integer)
13758 or else
13759 Root_Operand_Type = Base_Type (Standard_Short_Short_Integer))
13760
13761 -- Test for interesting operation, which includes addition,
13762 -- division, exponentiation, multiplication, subtraction, absolute
13763 -- value and unary negation. Unary "+" is omitted since it is a
13764 -- no-op and thus can't overflow.
13765
13766 and then Nkind (Operand) in
13767 N_Op_Abs | N_Op_Add | N_Op_Divide | N_Op_Expon |
13768 N_Op_Minus | N_Op_Multiply | N_Op_Subtract;
13769 end Integer_Promotion_Possible;
13770
13771 ------------------------------
13772 -- Make_Array_Comparison_Op --
13773 ------------------------------
13774
13775 -- This is a hand-coded expansion of the following generic function:
13776
13777 -- generic
13778 -- type elem is (<>);
13779 -- type index is (<>);
13780 -- type a is array (index range <>) of elem;
13781
13782 -- function Gnnn (X : a; Y: a) return boolean is
13783 -- J : index := Y'first;
13784
13785 -- begin
13786 -- if X'length = 0 then
13787 -- return false;
13788
13789 -- elsif Y'length = 0 then
13790 -- return true;
13791
13792 -- else
13793 -- for I in X'range loop
13794 -- if X (I) = Y (J) then
13795 -- if J = Y'last then
13796 -- exit;
13797 -- else
13798 -- J := index'succ (J);
13799 -- end if;
13800
13801 -- else
13802 -- return X (I) > Y (J);
13803 -- end if;
13804 -- end loop;
13805
13806 -- return X'length > Y'length;
13807 -- end if;
13808 -- end Gnnn;
13809
13810 -- Note that since we are essentially doing this expansion by hand, we
13811 -- do not need to generate an actual or formal generic part, just the
13812 -- instantiated function itself.
13813
13814 function Make_Array_Comparison_Op
13815 (Typ : Entity_Id;
13816 Nod : Node_Id) return Node_Id
13817 is
13818 Loc : constant Source_Ptr := Sloc (Nod);
13819
13820 X : constant Entity_Id := Make_Defining_Identifier (Loc, Name_uX);
13821 Y : constant Entity_Id := Make_Defining_Identifier (Loc, Name_uY);
13822 I : constant Entity_Id := Make_Defining_Identifier (Loc, Name_uI);
13823 J : constant Entity_Id := Make_Defining_Identifier (Loc, Name_uJ);
13824
13825 Index : constant Entity_Id := Base_Type (Etype (First_Index (Typ)));
13826
13827 Loop_Statement : Node_Id;
13828 Loop_Body : Node_Id;
13829 If_Stat : Node_Id;
13830 Inner_If : Node_Id;
13831 Final_Expr : Node_Id;
13832 Func_Body : Node_Id;
13833 Func_Name : Entity_Id;
13834 Formals : List_Id;
13835 Length1 : Node_Id;
13836 Length2 : Node_Id;
13837
13838 begin
13839 -- if J = Y'last then
13840 -- exit;
13841 -- else
13842 -- J := index'succ (J);
13843 -- end if;
13844
13845 Inner_If :=
13846 Make_Implicit_If_Statement (Nod,
13847 Condition =>
13848 Make_Op_Eq (Loc,
13849 Left_Opnd => New_Occurrence_Of (J, Loc),
13850 Right_Opnd =>
13851 Make_Attribute_Reference (Loc,
13852 Prefix => New_Occurrence_Of (Y, Loc),
13853 Attribute_Name => Name_Last)),
13854
13855 Then_Statements => New_List (
13856 Make_Exit_Statement (Loc)),
13857
13858 Else_Statements =>
13859 New_List (
13860 Make_Assignment_Statement (Loc,
13861 Name => New_Occurrence_Of (J, Loc),
13862 Expression =>
13863 Make_Attribute_Reference (Loc,
13864 Prefix => New_Occurrence_Of (Index, Loc),
13865 Attribute_Name => Name_Succ,
13866 Expressions => New_List (New_Occurrence_Of (J, Loc))))));
13867
13868 -- if X (I) = Y (J) then
13869 -- if ... end if;
13870 -- else
13871 -- return X (I) > Y (J);
13872 -- end if;
13873
13874 Loop_Body :=
13875 Make_Implicit_If_Statement (Nod,
13876 Condition =>
13877 Make_Op_Eq (Loc,
13878 Left_Opnd =>
13879 Make_Indexed_Component (Loc,
13880 Prefix => New_Occurrence_Of (X, Loc),
13881 Expressions => New_List (New_Occurrence_Of (I, Loc))),
13882
13883 Right_Opnd =>
13884 Make_Indexed_Component (Loc,
13885 Prefix => New_Occurrence_Of (Y, Loc),
13886 Expressions => New_List (New_Occurrence_Of (J, Loc)))),
13887
13888 Then_Statements => New_List (Inner_If),
13889
13890 Else_Statements => New_List (
13891 Make_Simple_Return_Statement (Loc,
13892 Expression =>
13893 Make_Op_Gt (Loc,
13894 Left_Opnd =>
13895 Make_Indexed_Component (Loc,
13896 Prefix => New_Occurrence_Of (X, Loc),
13897 Expressions => New_List (New_Occurrence_Of (I, Loc))),
13898
13899 Right_Opnd =>
13900 Make_Indexed_Component (Loc,
13901 Prefix => New_Occurrence_Of (Y, Loc),
13902 Expressions => New_List (
13903 New_Occurrence_Of (J, Loc)))))));
13904
13905 -- for I in X'range loop
13906 -- if ... end if;
13907 -- end loop;
13908
13909 Loop_Statement :=
13910 Make_Implicit_Loop_Statement (Nod,
13911 Identifier => Empty,
13912
13913 Iteration_Scheme =>
13914 Make_Iteration_Scheme (Loc,
13915 Loop_Parameter_Specification =>
13916 Make_Loop_Parameter_Specification (Loc,
13917 Defining_Identifier => I,
13918 Discrete_Subtype_Definition =>
13919 Make_Attribute_Reference (Loc,
13920 Prefix => New_Occurrence_Of (X, Loc),
13921 Attribute_Name => Name_Range))),
13922
13923 Statements => New_List (Loop_Body));
13924
13925 -- if X'length = 0 then
13926 -- return false;
13927 -- elsif Y'length = 0 then
13928 -- return true;
13929 -- else
13930 -- for ... loop ... end loop;
13931 -- return X'length > Y'length;
13932 -- end if;
13933
13934 Length1 :=
13935 Make_Attribute_Reference (Loc,
13936 Prefix => New_Occurrence_Of (X, Loc),
13937 Attribute_Name => Name_Length);
13938
13939 Length2 :=
13940 Make_Attribute_Reference (Loc,
13941 Prefix => New_Occurrence_Of (Y, Loc),
13942 Attribute_Name => Name_Length);
13943
13944 Final_Expr :=
13945 Make_Op_Gt (Loc,
13946 Left_Opnd => Length1,
13947 Right_Opnd => Length2);
13948
13949 If_Stat :=
13950 Make_Implicit_If_Statement (Nod,
13951 Condition =>
13952 Make_Op_Eq (Loc,
13953 Left_Opnd =>
13954 Make_Attribute_Reference (Loc,
13955 Prefix => New_Occurrence_Of (X, Loc),
13956 Attribute_Name => Name_Length),
13957 Right_Opnd =>
13958 Make_Integer_Literal (Loc, 0)),
13959
13960 Then_Statements =>
13961 New_List (
13962 Make_Simple_Return_Statement (Loc,
13963 Expression => New_Occurrence_Of (Standard_False, Loc))),
13964
13965 Elsif_Parts => New_List (
13966 Make_Elsif_Part (Loc,
13967 Condition =>
13968 Make_Op_Eq (Loc,
13969 Left_Opnd =>
13970 Make_Attribute_Reference (Loc,
13971 Prefix => New_Occurrence_Of (Y, Loc),
13972 Attribute_Name => Name_Length),
13973 Right_Opnd =>
13974 Make_Integer_Literal (Loc, 0)),
13975
13976 Then_Statements =>
13977 New_List (
13978 Make_Simple_Return_Statement (Loc,
13979 Expression => New_Occurrence_Of (Standard_True, Loc))))),
13980
13981 Else_Statements => New_List (
13982 Loop_Statement,
13983 Make_Simple_Return_Statement (Loc,
13984 Expression => Final_Expr)));
13985
13986 -- (X : a; Y: a)
13987
13988 Formals := New_List (
13989 Make_Parameter_Specification (Loc,
13990 Defining_Identifier => X,
13991 Parameter_Type => New_Occurrence_Of (Typ, Loc)),
13992
13993 Make_Parameter_Specification (Loc,
13994 Defining_Identifier => Y,
13995 Parameter_Type => New_Occurrence_Of (Typ, Loc)));
13996
13997 -- function Gnnn (...) return boolean is
13998 -- J : index := Y'first;
13999 -- begin
14000 -- if ... end if;
14001 -- end Gnnn;
14002
14003 Func_Name := Make_Temporary (Loc, 'G');
14004
14005 Func_Body :=
14006 Make_Subprogram_Body (Loc,
14007 Specification =>
14008 Make_Function_Specification (Loc,
14009 Defining_Unit_Name => Func_Name,
14010 Parameter_Specifications => Formals,
14011 Result_Definition => New_Occurrence_Of (Standard_Boolean, Loc)),
14012
14013 Declarations => New_List (
14014 Make_Object_Declaration (Loc,
14015 Defining_Identifier => J,
14016 Object_Definition => New_Occurrence_Of (Index, Loc),
14017 Expression =>
14018 Make_Attribute_Reference (Loc,
14019 Prefix => New_Occurrence_Of (Y, Loc),
14020 Attribute_Name => Name_First))),
14021
14022 Handled_Statement_Sequence =>
14023 Make_Handled_Sequence_Of_Statements (Loc,
14024 Statements => New_List (If_Stat)));
14025
14026 return Func_Body;
14027 end Make_Array_Comparison_Op;
14028
14029 ---------------------------
14030 -- Make_Boolean_Array_Op --
14031 ---------------------------
14032
14033 -- For logical operations on boolean arrays, expand in line the following,
14034 -- replacing 'and' with 'or' or 'xor' where needed:
14035
14036 -- function Annn (A : typ; B: typ) return typ is
14037 -- C : typ;
14038 -- begin
14039 -- for J in A'range loop
14040 -- C (J) := A (J) op B (J);
14041 -- end loop;
14042 -- return C;
14043 -- end Annn;
14044
14045 -- or in the case of Transform_Function_Array:
14046
14047 -- procedure Annn (A : typ; B: typ; RESULT: out typ) is
14048 -- begin
14049 -- for J in A'range loop
14050 -- RESULT (J) := A (J) op B (J);
14051 -- end loop;
14052 -- end Annn;
14053
14054 -- Here typ is the boolean array type
14055
14056 function Make_Boolean_Array_Op
14057 (Typ : Entity_Id;
14058 N : Node_Id) return Node_Id
14059 is
14060 Loc : constant Source_Ptr := Sloc (N);
14061
14062 A : constant Entity_Id := Make_Defining_Identifier (Loc, Name_uA);
14063 B : constant Entity_Id := Make_Defining_Identifier (Loc, Name_uB);
14064 J : constant Entity_Id := Make_Defining_Identifier (Loc, Name_uJ);
14065
14066 C : Entity_Id;
14067
14068 A_J : Node_Id;
14069 B_J : Node_Id;
14070 C_J : Node_Id;
14071 Op : Node_Id;
14072
14073 Formals : List_Id;
14074 Func_Name : Entity_Id;
14075 Func_Body : Node_Id;
14076 Loop_Statement : Node_Id;
14077
14078 begin
14079 if Transform_Function_Array then
14080 C := Make_Defining_Identifier (Loc, Name_UP_RESULT);
14081 else
14082 C := Make_Defining_Identifier (Loc, Name_uC);
14083 end if;
14084
14085 A_J :=
14086 Make_Indexed_Component (Loc,
14087 Prefix => New_Occurrence_Of (A, Loc),
14088 Expressions => New_List (New_Occurrence_Of (J, Loc)));
14089
14090 B_J :=
14091 Make_Indexed_Component (Loc,
14092 Prefix => New_Occurrence_Of (B, Loc),
14093 Expressions => New_List (New_Occurrence_Of (J, Loc)));
14094
14095 C_J :=
14096 Make_Indexed_Component (Loc,
14097 Prefix => New_Occurrence_Of (C, Loc),
14098 Expressions => New_List (New_Occurrence_Of (J, Loc)));
14099
14100 if Nkind (N) = N_Op_And then
14101 Op :=
14102 Make_Op_And (Loc,
14103 Left_Opnd => A_J,
14104 Right_Opnd => B_J);
14105
14106 elsif Nkind (N) = N_Op_Or then
14107 Op :=
14108 Make_Op_Or (Loc,
14109 Left_Opnd => A_J,
14110 Right_Opnd => B_J);
14111
14112 else
14113 Op :=
14114 Make_Op_Xor (Loc,
14115 Left_Opnd => A_J,
14116 Right_Opnd => B_J);
14117 end if;
14118
14119 Loop_Statement :=
14120 Make_Implicit_Loop_Statement (N,
14121 Identifier => Empty,
14122
14123 Iteration_Scheme =>
14124 Make_Iteration_Scheme (Loc,
14125 Loop_Parameter_Specification =>
14126 Make_Loop_Parameter_Specification (Loc,
14127 Defining_Identifier => J,
14128 Discrete_Subtype_Definition =>
14129 Make_Attribute_Reference (Loc,
14130 Prefix => New_Occurrence_Of (A, Loc),
14131 Attribute_Name => Name_Range))),
14132
14133 Statements => New_List (
14134 Make_Assignment_Statement (Loc,
14135 Name => C_J,
14136 Expression => Op)));
14137
14138 Formals := New_List (
14139 Make_Parameter_Specification (Loc,
14140 Defining_Identifier => A,
14141 Parameter_Type => New_Occurrence_Of (Typ, Loc)),
14142
14143 Make_Parameter_Specification (Loc,
14144 Defining_Identifier => B,
14145 Parameter_Type => New_Occurrence_Of (Typ, Loc)));
14146
14147 if Transform_Function_Array then
14148 Append_To (Formals,
14149 Make_Parameter_Specification (Loc,
14150 Defining_Identifier => C,
14151 Out_Present => True,
14152 Parameter_Type => New_Occurrence_Of (Typ, Loc)));
14153 end if;
14154
14155 Func_Name := Make_Temporary (Loc, 'A');
14156 Set_Is_Inlined (Func_Name);
14157
14158 if Transform_Function_Array then
14159 Func_Body :=
14160 Make_Subprogram_Body (Loc,
14161 Specification =>
14162 Make_Procedure_Specification (Loc,
14163 Defining_Unit_Name => Func_Name,
14164 Parameter_Specifications => Formals),
14165
14166 Declarations => New_List,
14167
14168 Handled_Statement_Sequence =>
14169 Make_Handled_Sequence_Of_Statements (Loc,
14170 Statements => New_List (Loop_Statement)));
14171
14172 else
14173 Func_Body :=
14174 Make_Subprogram_Body (Loc,
14175 Specification =>
14176 Make_Function_Specification (Loc,
14177 Defining_Unit_Name => Func_Name,
14178 Parameter_Specifications => Formals,
14179 Result_Definition => New_Occurrence_Of (Typ, Loc)),
14180
14181 Declarations => New_List (
14182 Make_Object_Declaration (Loc,
14183 Defining_Identifier => C,
14184 Object_Definition => New_Occurrence_Of (Typ, Loc))),
14185
14186 Handled_Statement_Sequence =>
14187 Make_Handled_Sequence_Of_Statements (Loc,
14188 Statements => New_List (
14189 Loop_Statement,
14190 Make_Simple_Return_Statement (Loc,
14191 Expression => New_Occurrence_Of (C, Loc)))));
14192 end if;
14193
14194 return Func_Body;
14195 end Make_Boolean_Array_Op;
14196
14197 -----------------------------------------
14198 -- Minimized_Eliminated_Overflow_Check --
14199 -----------------------------------------
14200
14201 function Minimized_Eliminated_Overflow_Check (N : Node_Id) return Boolean is
14202 begin
14203 -- The MINIMIZED mode operates in Long_Long_Integer so we cannot use it
14204 -- if the type of the expression is already larger.
14205
14206 return
14207 Is_Signed_Integer_Type (Etype (N))
14208 and then Overflow_Check_Mode in Minimized_Or_Eliminated
14209 and then not (Overflow_Check_Mode = Minimized
14210 and then
14211 Esize (Etype (N)) > Standard_Long_Long_Integer_Size);
14212 end Minimized_Eliminated_Overflow_Check;
14213
14214 ----------------------------
14215 -- Narrow_Large_Operation --
14216 ----------------------------
14217
14218 procedure Narrow_Large_Operation (N : Node_Id) is
14219 Kind : constant Node_Kind := Nkind (N);
14220 Otyp : constant Entity_Id := Etype (N);
14221 In_Rng : constant Boolean := Kind = N_In;
14222 Binary : constant Boolean := Kind in N_Binary_Op or else In_Rng;
14223 Compar : constant Boolean := Kind in N_Op_Compare or else In_Rng;
14224 R : constant Node_Id := Right_Opnd (N);
14225 Typ : constant Entity_Id := Etype (R);
14226 Tsiz : constant Uint := RM_Size (Typ);
14227
14228 -- Local variables
14229
14230 L : Node_Id;
14231 Llo, Lhi : Uint;
14232 Rlo, Rhi : Uint;
14233 Lsiz, Rsiz : Uint;
14234 Nlo, Nhi : Uint;
14235 Nsiz : Uint;
14236 Ntyp : Entity_Id;
14237 Nop : Node_Id;
14238 OK : Boolean;
14239
14240 -- Start of processing for Narrow_Large_Operation
14241
14242 begin
14243 -- First, determine the range of the left operand, if any
14244
14245 if Binary then
14246 L := Left_Opnd (N);
14247 Determine_Range (L, OK, Llo, Lhi, Assume_Valid => True);
14248 if not OK then
14249 return;
14250 end if;
14251
14252 else
14253 L := Empty;
14254 Llo := Uint_0;
14255 Lhi := Uint_0;
14256 end if;
14257
14258 -- Second, determine the range of the right operand, which can itself
14259 -- be a range, in which case we take the lower bound of the low bound
14260 -- and the upper bound of the high bound.
14261
14262 if In_Rng then
14263 declare
14264 Zlo, Zhi : Uint;
14265
14266 begin
14267 Determine_Range
14268 (Low_Bound (R), OK, Rlo, Zhi, Assume_Valid => True);
14269 if not OK then
14270 return;
14271 end if;
14272
14273 Determine_Range
14274 (High_Bound (R), OK, Zlo, Rhi, Assume_Valid => True);
14275 if not OK then
14276 return;
14277 end if;
14278 end;
14279
14280 else
14281 Determine_Range (R, OK, Rlo, Rhi, Assume_Valid => True);
14282 if not OK then
14283 return;
14284 end if;
14285 end if;
14286
14287 -- Then compute a size suitable for each range
14288
14289 if Binary then
14290 Lsiz := Get_Size_For_Range (Llo, Lhi);
14291 else
14292 Lsiz := Uint_0;
14293 end if;
14294
14295 Rsiz := Get_Size_For_Range (Rlo, Rhi);
14296
14297 -- Now compute the size of the narrower type
14298
14299 if Compar then
14300 -- The type must be able to accommodate the operands
14301
14302 Nsiz := UI_Max (Lsiz, Rsiz);
14303
14304 else
14305 -- The type must be able to accommodate the operand(s) and result.
14306
14307 -- Note that Determine_Range typically does not report the bounds of
14308 -- the value as being larger than those of the base type, which means
14309 -- that it does not report overflow (see also Enable_Overflow_Check).
14310
14311 Determine_Range (N, OK, Nlo, Nhi, Assume_Valid => True);
14312 if not OK then
14313 return;
14314 end if;
14315
14316 -- Therefore, if Nsiz is not lower than the size of the original type
14317 -- here, we cannot be sure that the operation does not overflow.
14318
14319 Nsiz := Get_Size_For_Range (Nlo, Nhi);
14320 Nsiz := UI_Max (Nsiz, Lsiz);
14321 Nsiz := UI_Max (Nsiz, Rsiz);
14322 end if;
14323
14324 -- If the size is not lower than the size of the original type, then
14325 -- there is no point in changing the type, except in the case where
14326 -- we can remove a conversion to the original type from an operand.
14327
14328 if Nsiz >= Tsiz
14329 and then not (Binary
14330 and then Nkind (L) = N_Type_Conversion
14331 and then Entity (Subtype_Mark (L)) = Typ)
14332 and then not (Nkind (R) = N_Type_Conversion
14333 and then Entity (Subtype_Mark (R)) = Typ)
14334 then
14335 return;
14336 end if;
14337
14338 -- Now pick the narrower type according to the size. We use the base
14339 -- type instead of the first subtype because operations are done in
14340 -- the base type, so this avoids the need for useless conversions.
14341
14342 if Nsiz <= System_Max_Integer_Size then
14343 Ntyp := Etype (Integer_Type_For (Nsiz, Uns => False));
14344 else
14345 return;
14346 end if;
14347
14348 -- Finally, rewrite the operation in the narrower type, but make sure
14349 -- not to perform name resolution for the operator again.
14350
14351 Nop := New_Op_Node (Kind, Sloc (N));
14352 if Nkind (N) in N_Has_Entity then
14353 Set_Entity (Nop, Entity (N));
14354 end if;
14355
14356 if Binary then
14357 Set_Left_Opnd (Nop, Convert_To (Ntyp, L));
14358 end if;
14359
14360 if In_Rng then
14361 Set_Right_Opnd (Nop,
14362 Make_Range (Sloc (N),
14363 Convert_To (Ntyp, Low_Bound (R)),
14364 Convert_To (Ntyp, High_Bound (R))));
14365 else
14366 Set_Right_Opnd (Nop, Convert_To (Ntyp, R));
14367 end if;
14368
14369 Rewrite (N, Nop);
14370
14371 if Compar then
14372 -- Analyze it with the comparison type and checks suppressed since
14373 -- the conversions of the operands cannot overflow.
14374
14375 Analyze_And_Resolve (N, Otyp, Suppress => Overflow_Check);
14376
14377 else
14378 -- Analyze it with the narrower type and checks suppressed, but only
14379 -- when we are sure that the operation does not overflow, see above.
14380
14381 if Nsiz < Tsiz then
14382 Analyze_And_Resolve (N, Ntyp, Suppress => Overflow_Check);
14383 else
14384 Analyze_And_Resolve (N, Ntyp);
14385 end if;
14386
14387 -- Put back a conversion to the original type
14388
14389 Convert_To_And_Rewrite (Typ, N);
14390 end if;
14391 end Narrow_Large_Operation;
14392
14393 --------------------------------
14394 -- Optimize_Length_Comparison --
14395 --------------------------------
14396
14397 procedure Optimize_Length_Comparison (N : Node_Id) is
14398 Loc : constant Source_Ptr := Sloc (N);
14399 Typ : constant Entity_Id := Etype (N);
14400 Result : Node_Id;
14401
14402 Left : Node_Id;
14403 Right : Node_Id;
14404 -- First and Last attribute reference nodes, which end up as left and
14405 -- right operands of the optimized result.
14406
14407 Is_Zero : Boolean;
14408 -- True for comparison operand of zero
14409
14410 Maybe_Superflat : Boolean;
14411 -- True if we may be in the dynamic superflat case, i.e. Is_Zero is set
14412 -- to false but the comparison operand can be zero at run time. In this
14413 -- case, we normally cannot do anything because the canonical formula of
14414 -- the length is not valid, but there is one exception: when the operand
14415 -- is itself the length of an array with the same bounds as the array on
14416 -- the LHS, we can entirely optimize away the comparison.
14417
14418 Comp : Node_Id;
14419 -- Comparison operand, set only if Is_Zero is false
14420
14421 Ent : array (Pos range 1 .. 2) of Entity_Id := (Empty, Empty);
14422 -- Entities whose length is being compared
14423
14424 Index : array (Pos range 1 .. 2) of Node_Id := (Empty, Empty);
14425 -- Integer_Literal nodes for length attribute expressions, or Empty
14426 -- if there is no such expression present.
14427
14428 Op : Node_Kind := Nkind (N);
14429 -- Kind of comparison operator, gets flipped if operands backwards
14430
14431 function Convert_To_Long_Long_Integer (N : Node_Id) return Node_Id;
14432 -- Given a discrete expression, returns a Long_Long_Integer typed
14433 -- expression representing the underlying value of the expression.
14434 -- This is done with an unchecked conversion to Long_Long_Integer.
14435 -- We use unchecked conversion to handle the enumeration type case.
14436
14437 function Is_Entity_Length (N : Node_Id; Num : Pos) return Boolean;
14438 -- Tests if N is a length attribute applied to a simple entity. If so,
14439 -- returns True, and sets Ent to the entity, and Index to the integer
14440 -- literal provided as an attribute expression, or to Empty if none.
14441 -- Num is the index designating the relevant slot in Ent and Index.
14442 -- Also returns True if the expression is a generated type conversion
14443 -- whose expression is of the desired form. This latter case arises
14444 -- when Apply_Universal_Integer_Attribute_Check installs a conversion
14445 -- to check for being in range, which is not needed in this context.
14446 -- Returns False if neither condition holds.
14447
14448 function Is_Optimizable (N : Node_Id) return Boolean;
14449 -- Tests N to see if it is an optimizable comparison value (defined as
14450 -- constant zero or one, or something else where the value is known to
14451 -- be nonnegative and in the 32-bit range and where the corresponding
14452 -- Length value is also known to be 32 bits). If result is true, sets
14453 -- Is_Zero, Maybe_Superflat and Comp accordingly.
14454
14455 procedure Rewrite_For_Equal_Lengths;
14456 -- Rewrite the comparison of two equal lengths into either True or False
14457
14458 ----------------------------------
14459 -- Convert_To_Long_Long_Integer --
14460 ----------------------------------
14461
14462 function Convert_To_Long_Long_Integer (N : Node_Id) return Node_Id is
14463 begin
14464 return Unchecked_Convert_To (Standard_Long_Long_Integer, N);
14465 end Convert_To_Long_Long_Integer;
14466
14467 ----------------------
14468 -- Is_Entity_Length --
14469 ----------------------
14470
14471 function Is_Entity_Length (N : Node_Id; Num : Pos) return Boolean is
14472 begin
14473 if Nkind (N) = N_Attribute_Reference
14474 and then Attribute_Name (N) = Name_Length
14475 and then Is_Entity_Name (Prefix (N))
14476 then
14477 Ent (Num) := Entity (Prefix (N));
14478
14479 if Present (Expressions (N)) then
14480 Index (Num) := First (Expressions (N));
14481 else
14482 Index (Num) := Empty;
14483 end if;
14484
14485 return True;
14486
14487 elsif Nkind (N) = N_Type_Conversion
14488 and then not Comes_From_Source (N)
14489 then
14490 return Is_Entity_Length (Expression (N), Num);
14491
14492 else
14493 return False;
14494 end if;
14495 end Is_Entity_Length;
14496
14497 --------------------
14498 -- Is_Optimizable --
14499 --------------------
14500
14501 function Is_Optimizable (N : Node_Id) return Boolean is
14502 Val : Uint;
14503 OK : Boolean;
14504 Lo : Uint;
14505 Hi : Uint;
14506 Indx : Node_Id;
14507 Dbl : Boolean;
14508 Ityp : Entity_Id;
14509
14510 begin
14511 if Compile_Time_Known_Value (N) then
14512 Val := Expr_Value (N);
14513
14514 if Val = Uint_0 then
14515 Is_Zero := True;
14516 Maybe_Superflat := False;
14517 Comp := Empty;
14518 return True;
14519
14520 elsif Val = Uint_1 then
14521 Is_Zero := False;
14522 Maybe_Superflat := False;
14523 Comp := Empty;
14524 return True;
14525 end if;
14526 end if;
14527
14528 -- Here we have to make sure of being within a 32-bit range (take the
14529 -- full unsigned range so the length of 32-bit arrays is accepted).
14530
14531 Determine_Range (N, OK, Lo, Hi, Assume_Valid => True);
14532
14533 if not OK
14534 or else Lo < Uint_0
14535 or else Hi > Uint_2 ** 32
14536 then
14537 return False;
14538 end if;
14539
14540 Maybe_Superflat := (Lo = Uint_0);
14541
14542 -- Tests if N is also a length attribute applied to a simple entity
14543
14544 Dbl := Is_Entity_Length (N, 2);
14545
14546 -- We can deal with the superflat case only if N is also a length
14547
14548 if Maybe_Superflat and then not Dbl then
14549 return False;
14550 end if;
14551
14552 -- Comparison value was within range, so now we must check the index
14553 -- value to make sure it is also within 32 bits.
14554
14555 for K in Pos range 1 .. 2 loop
14556 Indx := First_Index (Etype (Ent (K)));
14557
14558 if Present (Index (K)) then
14559 for J in 2 .. UI_To_Int (Intval (Index (K))) loop
14560 Next_Index (Indx);
14561 end loop;
14562 end if;
14563
14564 Ityp := Etype (Indx);
14565
14566 if Esize (Ityp) > 32 then
14567 return False;
14568 end if;
14569
14570 exit when not Dbl;
14571 end loop;
14572
14573 Is_Zero := False;
14574 Comp := N;
14575 return True;
14576 end Is_Optimizable;
14577
14578 -------------------------------
14579 -- Rewrite_For_Equal_Lengths --
14580 -------------------------------
14581
14582 procedure Rewrite_For_Equal_Lengths is
14583 begin
14584 case Op is
14585 when N_Op_Eq
14586 | N_Op_Ge
14587 | N_Op_Le
14588 =>
14589 Rewrite (N,
14590 Convert_To (Typ,
14591 New_Occurrence_Of (Standard_True, Sloc (N))));
14592
14593 when N_Op_Ne
14594 | N_Op_Gt
14595 | N_Op_Lt
14596 =>
14597 Rewrite (N,
14598 Convert_To (Typ,
14599 New_Occurrence_Of (Standard_False, Sloc (N))));
14600
14601 when others =>
14602 raise Program_Error;
14603 end case;
14604
14605 Analyze_And_Resolve (N, Typ);
14606 end Rewrite_For_Equal_Lengths;
14607
14608 -- Start of processing for Optimize_Length_Comparison
14609
14610 begin
14611 -- Nothing to do if not a comparison
14612
14613 if Op not in N_Op_Compare then
14614 return;
14615 end if;
14616
14617 -- Nothing to do if special -gnatd.P debug flag set.
14618
14619 if Debug_Flag_Dot_PP then
14620 return;
14621 end if;
14622
14623 -- Ent'Length op 0/1
14624
14625 if Is_Entity_Length (Left_Opnd (N), 1)
14626 and then Is_Optimizable (Right_Opnd (N))
14627 then
14628 null;
14629
14630 -- 0/1 op Ent'Length
14631
14632 elsif Is_Entity_Length (Right_Opnd (N), 1)
14633 and then Is_Optimizable (Left_Opnd (N))
14634 then
14635 -- Flip comparison to opposite sense
14636
14637 case Op is
14638 when N_Op_Lt => Op := N_Op_Gt;
14639 when N_Op_Le => Op := N_Op_Ge;
14640 when N_Op_Gt => Op := N_Op_Lt;
14641 when N_Op_Ge => Op := N_Op_Le;
14642 when others => null;
14643 end case;
14644
14645 -- Else optimization not possible
14646
14647 else
14648 return;
14649 end if;
14650
14651 -- Fall through if we will do the optimization
14652
14653 -- Cases to handle:
14654
14655 -- X'Length = 0 => X'First > X'Last
14656 -- X'Length = 1 => X'First = X'Last
14657 -- X'Length = n => X'First + (n - 1) = X'Last
14658
14659 -- X'Length /= 0 => X'First <= X'Last
14660 -- X'Length /= 1 => X'First /= X'Last
14661 -- X'Length /= n => X'First + (n - 1) /= X'Last
14662
14663 -- X'Length >= 0 => always true, warn
14664 -- X'Length >= 1 => X'First <= X'Last
14665 -- X'Length >= n => X'First + (n - 1) <= X'Last
14666
14667 -- X'Length > 0 => X'First <= X'Last
14668 -- X'Length > 1 => X'First < X'Last
14669 -- X'Length > n => X'First + (n - 1) < X'Last
14670
14671 -- X'Length <= 0 => X'First > X'Last (warn, could be =)
14672 -- X'Length <= 1 => X'First >= X'Last
14673 -- X'Length <= n => X'First + (n - 1) >= X'Last
14674
14675 -- X'Length < 0 => always false (warn)
14676 -- X'Length < 1 => X'First > X'Last
14677 -- X'Length < n => X'First + (n - 1) > X'Last
14678
14679 -- Note: for the cases of n (not constant 0,1), we require that the
14680 -- corresponding index type be integer or shorter (i.e. not 64-bit),
14681 -- and the same for the comparison value. Then we do the comparison
14682 -- using 64-bit arithmetic (actually long long integer), so that we
14683 -- cannot have overflow intefering with the result.
14684
14685 -- First deal with warning cases
14686
14687 if Is_Zero then
14688 case Op is
14689
14690 -- X'Length >= 0
14691
14692 when N_Op_Ge =>
14693 Rewrite (N,
14694 Convert_To (Typ, New_Occurrence_Of (Standard_True, Loc)));
14695 Analyze_And_Resolve (N, Typ);
14696 Warn_On_Known_Condition (N);
14697 return;
14698
14699 -- X'Length < 0
14700
14701 when N_Op_Lt =>
14702 Rewrite (N,
14703 Convert_To (Typ, New_Occurrence_Of (Standard_False, Loc)));
14704 Analyze_And_Resolve (N, Typ);
14705 Warn_On_Known_Condition (N);
14706 return;
14707
14708 when N_Op_Le =>
14709 if Constant_Condition_Warnings
14710 and then Comes_From_Source (Original_Node (N))
14711 then
14712 Error_Msg_N ("could replace by ""'=""?c?", N);
14713 end if;
14714
14715 Op := N_Op_Eq;
14716
14717 when others =>
14718 null;
14719 end case;
14720 end if;
14721
14722 -- Build the First reference we will use
14723
14724 Left :=
14725 Make_Attribute_Reference (Loc,
14726 Prefix => New_Occurrence_Of (Ent (1), Loc),
14727 Attribute_Name => Name_First);
14728
14729 if Present (Index (1)) then
14730 Set_Expressions (Left, New_List (New_Copy (Index (1))));
14731 end if;
14732
14733 -- Build the Last reference we will use
14734
14735 Right :=
14736 Make_Attribute_Reference (Loc,
14737 Prefix => New_Occurrence_Of (Ent (1), Loc),
14738 Attribute_Name => Name_Last);
14739
14740 if Present (Index (1)) then
14741 Set_Expressions (Right, New_List (New_Copy (Index (1))));
14742 end if;
14743
14744 -- If general value case, then do the addition of (n - 1), and
14745 -- also add the needed conversions to type Long_Long_Integer.
14746
14747 -- If n = Y'Length, we rewrite X'First + (n - 1) op X'Last into:
14748
14749 -- Y'Last + (X'First - Y'First) op X'Last
14750
14751 -- in the hope that X'First - Y'First can be computed statically.
14752
14753 if Present (Comp) then
14754 if Present (Ent (2)) then
14755 declare
14756 Y_First : constant Node_Id :=
14757 Make_Attribute_Reference (Loc,
14758 Prefix => New_Occurrence_Of (Ent (2), Loc),
14759 Attribute_Name => Name_First);
14760 Y_Last : constant Node_Id :=
14761 Make_Attribute_Reference (Loc,
14762 Prefix => New_Occurrence_Of (Ent (2), Loc),
14763 Attribute_Name => Name_Last);
14764 R : Compare_Result;
14765
14766 begin
14767 if Present (Index (2)) then
14768 Set_Expressions (Y_First, New_List (New_Copy (Index (2))));
14769 Set_Expressions (Y_Last, New_List (New_Copy (Index (2))));
14770 end if;
14771
14772 Analyze (Left);
14773 Analyze (Y_First);
14774
14775 -- If X'First = Y'First, simplify the above formula into a
14776 -- direct comparison of Y'Last and X'Last.
14777
14778 R := Compile_Time_Compare (Left, Y_First, Assume_Valid => True);
14779
14780 if R = EQ then
14781 Analyze (Right);
14782 Analyze (Y_Last);
14783
14784 R := Compile_Time_Compare
14785 (Right, Y_Last, Assume_Valid => True);
14786
14787 -- If the pairs of attributes are equal, we are done
14788
14789 if R = EQ then
14790 Rewrite_For_Equal_Lengths;
14791 return;
14792 end if;
14793
14794 -- If the base types are different, convert both operands to
14795 -- Long_Long_Integer, else compare them directly.
14796
14797 if Base_Type (Etype (Right)) /= Base_Type (Etype (Y_Last))
14798 then
14799 Left := Convert_To_Long_Long_Integer (Y_Last);
14800 else
14801 Left := Y_Last;
14802 Comp := Empty;
14803 end if;
14804
14805 -- Otherwise, use the above formula as-is
14806
14807 else
14808 Left :=
14809 Make_Op_Add (Loc,
14810 Left_Opnd =>
14811 Convert_To_Long_Long_Integer (Y_Last),
14812 Right_Opnd =>
14813 Make_Op_Subtract (Loc,
14814 Left_Opnd =>
14815 Convert_To_Long_Long_Integer (Left),
14816 Right_Opnd =>
14817 Convert_To_Long_Long_Integer (Y_First)));
14818 end if;
14819 end;
14820
14821 -- General value case
14822
14823 else
14824 Left :=
14825 Make_Op_Add (Loc,
14826 Left_Opnd => Convert_To_Long_Long_Integer (Left),
14827 Right_Opnd =>
14828 Make_Op_Subtract (Loc,
14829 Left_Opnd => Convert_To_Long_Long_Integer (Comp),
14830 Right_Opnd => Make_Integer_Literal (Loc, 1)));
14831 end if;
14832 end if;
14833
14834 -- We cannot do anything in the superflat case past this point
14835
14836 if Maybe_Superflat then
14837 return;
14838 end if;
14839
14840 -- If general operand, convert Last reference to Long_Long_Integer
14841
14842 if Present (Comp) then
14843 Right := Convert_To_Long_Long_Integer (Right);
14844 end if;
14845
14846 -- Check for cases to optimize
14847
14848 -- X'Length = 0 => X'First > X'Last
14849 -- X'Length < 1 => X'First > X'Last
14850 -- X'Length < n => X'First + (n - 1) > X'Last
14851
14852 if (Is_Zero and then Op = N_Op_Eq)
14853 or else (not Is_Zero and then Op = N_Op_Lt)
14854 then
14855 Result :=
14856 Make_Op_Gt (Loc,
14857 Left_Opnd => Left,
14858 Right_Opnd => Right);
14859
14860 -- X'Length = 1 => X'First = X'Last
14861 -- X'Length = n => X'First + (n - 1) = X'Last
14862
14863 elsif not Is_Zero and then Op = N_Op_Eq then
14864 Result :=
14865 Make_Op_Eq (Loc,
14866 Left_Opnd => Left,
14867 Right_Opnd => Right);
14868
14869 -- X'Length /= 0 => X'First <= X'Last
14870 -- X'Length > 0 => X'First <= X'Last
14871
14872 elsif Is_Zero and (Op = N_Op_Ne or else Op = N_Op_Gt) then
14873 Result :=
14874 Make_Op_Le (Loc,
14875 Left_Opnd => Left,
14876 Right_Opnd => Right);
14877
14878 -- X'Length /= 1 => X'First /= X'Last
14879 -- X'Length /= n => X'First + (n - 1) /= X'Last
14880
14881 elsif not Is_Zero and then Op = N_Op_Ne then
14882 Result :=
14883 Make_Op_Ne (Loc,
14884 Left_Opnd => Left,
14885 Right_Opnd => Right);
14886
14887 -- X'Length >= 1 => X'First <= X'Last
14888 -- X'Length >= n => X'First + (n - 1) <= X'Last
14889
14890 elsif not Is_Zero and then Op = N_Op_Ge then
14891 Result :=
14892 Make_Op_Le (Loc,
14893 Left_Opnd => Left,
14894 Right_Opnd => Right);
14895
14896 -- X'Length > 1 => X'First < X'Last
14897 -- X'Length > n => X'First + (n = 1) < X'Last
14898
14899 elsif not Is_Zero and then Op = N_Op_Gt then
14900 Result :=
14901 Make_Op_Lt (Loc,
14902 Left_Opnd => Left,
14903 Right_Opnd => Right);
14904
14905 -- X'Length <= 1 => X'First >= X'Last
14906 -- X'Length <= n => X'First + (n - 1) >= X'Last
14907
14908 elsif not Is_Zero and then Op = N_Op_Le then
14909 Result :=
14910 Make_Op_Ge (Loc,
14911 Left_Opnd => Left,
14912 Right_Opnd => Right);
14913
14914 -- Should not happen at this stage
14915
14916 else
14917 raise Program_Error;
14918 end if;
14919
14920 -- Rewrite and finish up (we can suppress overflow checks, see above)
14921
14922 Rewrite (N, Result);
14923 Analyze_And_Resolve (N, Typ, Suppress => Overflow_Check);
14924 end Optimize_Length_Comparison;
14925
14926 --------------------------------
14927 -- Process_If_Case_Statements --
14928 --------------------------------
14929
14930 procedure Process_If_Case_Statements (N : Node_Id; Stmts : List_Id) is
14931 Decl : Node_Id;
14932
14933 begin
14934 Decl := First (Stmts);
14935 while Present (Decl) loop
14936 if Nkind (Decl) = N_Object_Declaration
14937 and then Is_Finalizable_Transient (Decl, N)
14938 then
14939 Process_Transient_In_Expression (Decl, N, Stmts);
14940 end if;
14941
14942 Next (Decl);
14943 end loop;
14944 end Process_If_Case_Statements;
14945
14946 -------------------------------------
14947 -- Process_Transient_In_Expression --
14948 -------------------------------------
14949
14950 procedure Process_Transient_In_Expression
14951 (Obj_Decl : Node_Id;
14952 Expr : Node_Id;
14953 Stmts : List_Id)
14954 is
14955 Loc : constant Source_Ptr := Sloc (Obj_Decl);
14956 Obj_Id : constant Entity_Id := Defining_Identifier (Obj_Decl);
14957
14958 Hook_Context : constant Node_Id := Find_Hook_Context (Expr);
14959 -- The node on which to insert the hook as an action. This is usually
14960 -- the innermost enclosing non-transient construct.
14961
14962 Fin_Call : Node_Id;
14963 Hook_Assign : Node_Id;
14964 Hook_Clear : Node_Id;
14965 Hook_Decl : Node_Id;
14966 Hook_Insert : Node_Id;
14967 Ptr_Decl : Node_Id;
14968
14969 Fin_Context : Node_Id;
14970 -- The node after which to insert the finalization actions of the
14971 -- transient object.
14972
14973 begin
14974 pragma Assert (Nkind (Expr) in N_Case_Expression
14975 | N_Expression_With_Actions
14976 | N_If_Expression);
14977
14978 -- When the context is a Boolean evaluation, all three nodes capture the
14979 -- result of their computation in a local temporary:
14980
14981 -- do
14982 -- Trans_Id : Ctrl_Typ := ...;
14983 -- Result : constant Boolean := ... Trans_Id ...;
14984 -- <finalize Trans_Id>
14985 -- in Result end;
14986
14987 -- As a result, the finalization of any transient objects can take place
14988 -- just after the result is captured, except for the case of conditional
14989 -- expressions in a simple return statement because the return statement
14990 -- will be distributed into the conditional expressions (see the special
14991 -- handling of simple return statements a few lines below).
14992
14993 -- ??? could this be extended to elementary types?
14994
14995 if Is_Boolean_Type (Etype (Expr))
14996 and then (Nkind (Expr) = N_Expression_With_Actions
14997 or else Nkind (Parent (Expr)) /= N_Simple_Return_Statement)
14998 then
14999 Fin_Context := Last (Stmts);
15000
15001 -- Otherwise the immediate context may not be safe enough to carry
15002 -- out transient object finalization due to aliasing and nesting of
15003 -- constructs. Insert calls to [Deep_]Finalize after the innermost
15004 -- enclosing non-transient construct.
15005
15006 else
15007 Fin_Context := Hook_Context;
15008 end if;
15009
15010 -- Mark the transient object as successfully processed to avoid double
15011 -- finalization.
15012
15013 Set_Is_Finalized_Transient (Obj_Id);
15014
15015 -- Construct all the pieces necessary to hook and finalize a transient
15016 -- object.
15017
15018 Build_Transient_Object_Statements
15019 (Obj_Decl => Obj_Decl,
15020 Fin_Call => Fin_Call,
15021 Hook_Assign => Hook_Assign,
15022 Hook_Clear => Hook_Clear,
15023 Hook_Decl => Hook_Decl,
15024 Ptr_Decl => Ptr_Decl,
15025 Finalize_Obj => False);
15026
15027 -- Add the access type which provides a reference to the transient
15028 -- object. Generate:
15029
15030 -- type Ptr_Typ is access all Desig_Typ;
15031
15032 Insert_Action (Hook_Context, Ptr_Decl);
15033
15034 -- Add the temporary which acts as a hook to the transient object.
15035 -- Generate:
15036
15037 -- Hook : Ptr_Id := null;
15038
15039 Insert_Action (Hook_Context, Hook_Decl);
15040
15041 -- When the transient object is initialized by an aggregate, the hook
15042 -- must capture the object after the last aggregate assignment takes
15043 -- place. Only then is the object considered initialized. Generate:
15044
15045 -- Hook := Ptr_Typ (Obj_Id);
15046 -- <or>
15047 -- Hook := Obj_Id'Unrestricted_Access;
15048
15049 if Ekind (Obj_Id) in E_Constant | E_Variable
15050 and then Present (Last_Aggregate_Assignment (Obj_Id))
15051 then
15052 Hook_Insert := Last_Aggregate_Assignment (Obj_Id);
15053
15054 -- Otherwise the hook seizes the related object immediately
15055
15056 else
15057 Hook_Insert := Obj_Decl;
15058 end if;
15059
15060 Insert_After_And_Analyze (Hook_Insert, Hook_Assign);
15061
15062 -- When the node is part of a return statement, there is no need to
15063 -- insert a finalization call, as the general finalization mechanism
15064 -- (see Build_Finalizer) would take care of the transient object on
15065 -- subprogram exit. Note that it would also be impossible to insert the
15066 -- finalization code after the return statement as this will render it
15067 -- unreachable.
15068
15069 if Nkind (Fin_Context) = N_Simple_Return_Statement then
15070 null;
15071
15072 -- Finalize the hook after the context has been evaluated. Generate:
15073
15074 -- if Hook /= null then
15075 -- [Deep_]Finalize (Hook.all);
15076 -- Hook := null;
15077 -- end if;
15078
15079 -- Note that the value returned by Find_Hook_Context may be an operator
15080 -- node, which is not a list member. We must locate the proper node in
15081 -- in the tree after which to insert the finalization code.
15082
15083 else
15084 while not Is_List_Member (Fin_Context) loop
15085 Fin_Context := Parent (Fin_Context);
15086 end loop;
15087
15088 pragma Assert (Present (Fin_Context));
15089
15090 Insert_Action_After (Fin_Context,
15091 Make_Implicit_If_Statement (Obj_Decl,
15092 Condition =>
15093 Make_Op_Ne (Loc,
15094 Left_Opnd =>
15095 New_Occurrence_Of (Defining_Entity (Hook_Decl), Loc),
15096 Right_Opnd => Make_Null (Loc)),
15097
15098 Then_Statements => New_List (
15099 Fin_Call,
15100 Hook_Clear)));
15101 end if;
15102 end Process_Transient_In_Expression;
15103
15104 ------------------------
15105 -- Rewrite_Comparison --
15106 ------------------------
15107
15108 procedure Rewrite_Comparison (N : Node_Id) is
15109 Typ : constant Entity_Id := Etype (N);
15110
15111 False_Result : Boolean;
15112 True_Result : Boolean;
15113
15114 begin
15115 if Nkind (N) = N_Type_Conversion then
15116 Rewrite_Comparison (Expression (N));
15117 return;
15118
15119 elsif Nkind (N) not in N_Op_Compare then
15120 return;
15121 end if;
15122
15123 -- If both operands are static, then the comparison has been already
15124 -- folded in evaluation.
15125
15126 pragma Assert
15127 (not Is_Static_Expression (Left_Opnd (N))
15128 or else
15129 not Is_Static_Expression (Right_Opnd (N)));
15130
15131 -- Determine the potential outcome of the comparison assuming that the
15132 -- operands are valid and emit a warning when the comparison evaluates
15133 -- to True or False only in the presence of invalid values.
15134
15135 Warn_On_Constant_Valid_Condition (N);
15136
15137 -- Determine the potential outcome of the comparison assuming that the
15138 -- operands are not valid.
15139
15140 Test_Comparison
15141 (Op => N,
15142 Assume_Valid => False,
15143 True_Result => True_Result,
15144 False_Result => False_Result);
15145
15146 -- The outcome is a decisive False or True, rewrite the operator into a
15147 -- non-static literal.
15148
15149 if False_Result or True_Result then
15150 Rewrite (N,
15151 Convert_To (Typ,
15152 New_Occurrence_Of (Boolean_Literals (True_Result), Sloc (N))));
15153
15154 Analyze_And_Resolve (N, Typ);
15155 Set_Is_Static_Expression (N, False);
15156 Warn_On_Known_Condition (N);
15157 end if;
15158 end Rewrite_Comparison;
15159
15160 ----------------------------
15161 -- Safe_In_Place_Array_Op --
15162 ----------------------------
15163
15164 function Safe_In_Place_Array_Op
15165 (Lhs : Node_Id;
15166 Op1 : Node_Id;
15167 Op2 : Node_Id) return Boolean
15168 is
15169 Target : Entity_Id;
15170
15171 function Is_Safe_Operand (Op : Node_Id) return Boolean;
15172 -- Operand is safe if it cannot overlap part of the target of the
15173 -- operation. If the operand and the target are identical, the operand
15174 -- is safe. The operand can be empty in the case of negation.
15175
15176 function Is_Unaliased (N : Node_Id) return Boolean;
15177 -- Check that N is a stand-alone entity
15178
15179 ------------------
15180 -- Is_Unaliased --
15181 ------------------
15182
15183 function Is_Unaliased (N : Node_Id) return Boolean is
15184 begin
15185 return
15186 Is_Entity_Name (N)
15187 and then No (Address_Clause (Entity (N)))
15188 and then No (Renamed_Object (Entity (N)));
15189 end Is_Unaliased;
15190
15191 ---------------------
15192 -- Is_Safe_Operand --
15193 ---------------------
15194
15195 function Is_Safe_Operand (Op : Node_Id) return Boolean is
15196 begin
15197 if No (Op) then
15198 return True;
15199
15200 elsif Is_Entity_Name (Op) then
15201 return Is_Unaliased (Op);
15202
15203 elsif Nkind (Op) in N_Indexed_Component | N_Selected_Component then
15204 return Is_Unaliased (Prefix (Op));
15205
15206 elsif Nkind (Op) = N_Slice then
15207 return
15208 Is_Unaliased (Prefix (Op))
15209 and then Entity (Prefix (Op)) /= Target;
15210
15211 elsif Nkind (Op) = N_Op_Not then
15212 return Is_Safe_Operand (Right_Opnd (Op));
15213
15214 else
15215 return False;
15216 end if;
15217 end Is_Safe_Operand;
15218
15219 -- Start of processing for Safe_In_Place_Array_Op
15220
15221 begin
15222 -- Skip this processing if the component size is different from system
15223 -- storage unit (since at least for NOT this would cause problems).
15224
15225 if Component_Size (Etype (Lhs)) /= System_Storage_Unit then
15226 return False;
15227
15228 -- Cannot do in place stuff if non-standard Boolean representation
15229
15230 elsif Has_Non_Standard_Rep (Component_Type (Etype (Lhs))) then
15231 return False;
15232
15233 elsif not Is_Unaliased (Lhs) then
15234 return False;
15235
15236 else
15237 Target := Entity (Lhs);
15238 return Is_Safe_Operand (Op1) and then Is_Safe_Operand (Op2);
15239 end if;
15240 end Safe_In_Place_Array_Op;
15241
15242 -----------------------
15243 -- Tagged_Membership --
15244 -----------------------
15245
15246 -- There are two different cases to consider depending on whether the right
15247 -- operand is a class-wide type or not. If not we just compare the actual
15248 -- tag of the left expr to the target type tag:
15249 --
15250 -- Left_Expr.Tag = Right_Type'Tag;
15251 --
15252 -- If it is a class-wide type we use the RT function CW_Membership which is
15253 -- usually implemented by looking in the ancestor tables contained in the
15254 -- dispatch table pointed by Left_Expr.Tag for Typ'Tag
15255
15256 -- In both cases if Left_Expr is an access type, we first check whether it
15257 -- is null.
15258
15259 -- Ada 2005 (AI-251): If it is a class-wide interface type we use the RT
15260 -- function IW_Membership which is usually implemented by looking in the
15261 -- table of abstract interface types plus the ancestor table contained in
15262 -- the dispatch table pointed by Left_Expr.Tag for Typ'Tag
15263
15264 procedure Tagged_Membership
15265 (N : Node_Id;
15266 SCIL_Node : out Node_Id;
15267 Result : out Node_Id)
15268 is
15269 Left : constant Node_Id := Left_Opnd (N);
15270 Right : constant Node_Id := Right_Opnd (N);
15271 Loc : constant Source_Ptr := Sloc (N);
15272
15273 -- Handle entities from the limited view
15274
15275 Orig_Right_Type : constant Entity_Id := Available_View (Etype (Right));
15276
15277 Full_R_Typ : Entity_Id;
15278 Left_Type : Entity_Id := Available_View (Etype (Left));
15279 Right_Type : Entity_Id := Orig_Right_Type;
15280 Obj_Tag : Node_Id;
15281
15282 begin
15283 SCIL_Node := Empty;
15284
15285 -- We have to examine the corresponding record type when dealing with
15286 -- protected types instead of the original, unexpanded, type.
15287
15288 if Ekind (Right_Type) = E_Protected_Type then
15289 Right_Type := Corresponding_Record_Type (Right_Type);
15290 end if;
15291
15292 if Ekind (Left_Type) = E_Protected_Type then
15293 Left_Type := Corresponding_Record_Type (Left_Type);
15294 end if;
15295
15296 -- In the case where the type is an access type, the test is applied
15297 -- using the designated types (needed in Ada 2012 for implicit anonymous
15298 -- access conversions, for AI05-0149).
15299
15300 if Is_Access_Type (Right_Type) then
15301 Left_Type := Designated_Type (Left_Type);
15302 Right_Type := Designated_Type (Right_Type);
15303 end if;
15304
15305 if Is_Class_Wide_Type (Left_Type) then
15306 Left_Type := Root_Type (Left_Type);
15307 end if;
15308
15309 if Is_Class_Wide_Type (Right_Type) then
15310 Full_R_Typ := Underlying_Type (Root_Type (Right_Type));
15311 else
15312 Full_R_Typ := Underlying_Type (Right_Type);
15313 end if;
15314
15315 Obj_Tag :=
15316 Make_Selected_Component (Loc,
15317 Prefix => Relocate_Node (Left),
15318 Selector_Name =>
15319 New_Occurrence_Of (First_Tag_Component (Left_Type), Loc));
15320
15321 if Is_Class_Wide_Type (Right_Type) then
15322
15323 -- No need to issue a run-time check if we statically know that the
15324 -- result of this membership test is always true. For example,
15325 -- considering the following declarations:
15326
15327 -- type Iface is interface;
15328 -- type T is tagged null record;
15329 -- type DT is new T and Iface with null record;
15330
15331 -- Obj1 : T;
15332 -- Obj2 : DT;
15333
15334 -- These membership tests are always true:
15335
15336 -- Obj1 in T'Class
15337 -- Obj2 in T'Class;
15338 -- Obj2 in Iface'Class;
15339
15340 -- We do not need to handle cases where the membership is illegal.
15341 -- For example:
15342
15343 -- Obj1 in DT'Class; -- Compile time error
15344 -- Obj1 in Iface'Class; -- Compile time error
15345
15346 if not Is_Interface (Left_Type)
15347 and then not Is_Class_Wide_Type (Left_Type)
15348 and then (Is_Ancestor (Etype (Right_Type), Left_Type,
15349 Use_Full_View => True)
15350 or else (Is_Interface (Etype (Right_Type))
15351 and then Interface_Present_In_Ancestor
15352 (Typ => Left_Type,
15353 Iface => Etype (Right_Type))))
15354 then
15355 Result := New_Occurrence_Of (Standard_True, Loc);
15356 return;
15357 end if;
15358
15359 -- Ada 2005 (AI-251): Class-wide applied to interfaces
15360
15361 if Is_Interface (Etype (Class_Wide_Type (Right_Type)))
15362
15363 -- Support to: "Iface_CW_Typ in Typ'Class"
15364
15365 or else Is_Interface (Left_Type)
15366 then
15367 -- Issue error if IW_Membership operation not available in a
15368 -- configurable run-time setting.
15369
15370 if not RTE_Available (RE_IW_Membership) then
15371 Error_Msg_CRT
15372 ("dynamic membership test on interface types", N);
15373 Result := Empty;
15374 return;
15375 end if;
15376
15377 Result :=
15378 Make_Function_Call (Loc,
15379 Name => New_Occurrence_Of (RTE (RE_IW_Membership), Loc),
15380 Parameter_Associations => New_List (
15381 Make_Attribute_Reference (Loc,
15382 Prefix => Obj_Tag,
15383 Attribute_Name => Name_Address),
15384 New_Occurrence_Of (
15385 Node (First_Elmt (Access_Disp_Table (Full_R_Typ))),
15386 Loc)));
15387
15388 -- Ada 95: Normal case
15389
15390 else
15391 -- Issue error if CW_Membership operation not available in a
15392 -- configurable run-time setting.
15393
15394 if not RTE_Available (RE_CW_Membership) then
15395 Error_Msg_CRT
15396 ("dynamic membership test on tagged types", N);
15397 Result := Empty;
15398 return;
15399 end if;
15400
15401 Result :=
15402 Make_Function_Call (Loc,
15403 Name => New_Occurrence_Of (RTE (RE_CW_Membership), Loc),
15404 Parameter_Associations => New_List (
15405 Obj_Tag,
15406 New_Occurrence_Of (
15407 Node (First_Elmt (Access_Disp_Table (Full_R_Typ))),
15408 Loc)));
15409
15410 -- Generate the SCIL node for this class-wide membership test.
15411
15412 if Generate_SCIL then
15413 SCIL_Node := Make_SCIL_Membership_Test (Sloc (N));
15414 Set_SCIL_Entity (SCIL_Node, Etype (Right_Type));
15415 Set_SCIL_Tag_Value (SCIL_Node, Obj_Tag);
15416 end if;
15417 end if;
15418
15419 -- Right_Type is not a class-wide type
15420
15421 else
15422 -- No need to check the tag of the object if Right_Typ is abstract
15423
15424 if Is_Abstract_Type (Right_Type) then
15425 Result := New_Occurrence_Of (Standard_False, Loc);
15426
15427 else
15428 Result :=
15429 Make_Op_Eq (Loc,
15430 Left_Opnd => Obj_Tag,
15431 Right_Opnd =>
15432 New_Occurrence_Of
15433 (Node (First_Elmt (Access_Disp_Table (Full_R_Typ))), Loc));
15434 end if;
15435 end if;
15436
15437 -- if Left is an access object then generate test of the form:
15438 -- * if Right_Type excludes null: Left /= null and then ...
15439 -- * if Right_Type includes null: Left = null or else ...
15440
15441 if Is_Access_Type (Orig_Right_Type) then
15442 if Can_Never_Be_Null (Orig_Right_Type) then
15443 Result := Make_And_Then (Loc,
15444 Left_Opnd =>
15445 Make_Op_Ne (Loc,
15446 Left_Opnd => Left,
15447 Right_Opnd => Make_Null (Loc)),
15448 Right_Opnd => Result);
15449
15450 else
15451 Result := Make_Or_Else (Loc,
15452 Left_Opnd =>
15453 Make_Op_Eq (Loc,
15454 Left_Opnd => Left,
15455 Right_Opnd => Make_Null (Loc)),
15456 Right_Opnd => Result);
15457 end if;
15458 end if;
15459 end Tagged_Membership;
15460
15461 ------------------------------
15462 -- Unary_Op_Validity_Checks --
15463 ------------------------------
15464
15465 procedure Unary_Op_Validity_Checks (N : Node_Id) is
15466 begin
15467 if Validity_Checks_On and Validity_Check_Operands then
15468 Ensure_Valid (Right_Opnd (N));
15469 end if;
15470 end Unary_Op_Validity_Checks;
15471
15472 end Exp_Ch4;