* c-cppbuiltin.c (c_cpp_builtins): Define __pic__ and __PIC__ when
[official-gcc.git] / gcc / ada / exp_ch4.adb
blob2e1f38f88e4110a8a0bcb01d7e38a70cebbee489
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-2005, Free Software Foundation, Inc. --
10 -- --
11 -- GNAT is free software; you can redistribute it and/or modify it under --
12 -- terms of the GNU General Public License as published by the Free Soft- --
13 -- ware Foundation; either version 2, or (at your option) any later ver- --
14 -- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
15 -- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
16 -- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License --
17 -- for more details. You should have received a copy of the GNU General --
18 -- Public License distributed with GNAT; see file COPYING. If not, write --
19 -- to the Free Software Foundation, 51 Franklin Street, Fifth Floor, --
20 -- Boston, MA 02110-1301, USA. --
21 -- --
22 -- GNAT was originally developed by the GNAT team at New York University. --
23 -- Extensive contributions were provided by Ada Core Technologies Inc. --
24 -- --
25 ------------------------------------------------------------------------------
27 with Atree; use Atree;
28 with Checks; use Checks;
29 with Einfo; use Einfo;
30 with Elists; use Elists;
31 with Errout; use Errout;
32 with Exp_Aggr; use Exp_Aggr;
33 with Exp_Ch3; use Exp_Ch3;
34 with Exp_Ch7; use Exp_Ch7;
35 with Exp_Ch9; use Exp_Ch9;
36 with Exp_Fixd; use Exp_Fixd;
37 with Exp_Pakd; use Exp_Pakd;
38 with Exp_Tss; use Exp_Tss;
39 with Exp_Util; use Exp_Util;
40 with Exp_VFpt; use Exp_VFpt;
41 with Freeze; use Freeze;
42 with Hostparm; use Hostparm;
43 with Inline; use Inline;
44 with Nlists; use Nlists;
45 with Nmake; use Nmake;
46 with Opt; use Opt;
47 with Rtsfind; use Rtsfind;
48 with Sem; use Sem;
49 with Sem_Cat; use Sem_Cat;
50 with Sem_Ch3; use Sem_Ch3;
51 with Sem_Ch13; use Sem_Ch13;
52 with Sem_Eval; use Sem_Eval;
53 with Sem_Res; use Sem_Res;
54 with Sem_Type; use Sem_Type;
55 with Sem_Util; use Sem_Util;
56 with Sem_Warn; use Sem_Warn;
57 with Sinfo; use Sinfo;
58 with Snames; use Snames;
59 with Stand; use Stand;
60 with Targparm; use Targparm;
61 with Tbuild; use Tbuild;
62 with Ttypes; use Ttypes;
63 with Uintp; use Uintp;
64 with Urealp; use Urealp;
65 with Validsw; use Validsw;
67 package body Exp_Ch4 is
69 -----------------------
70 -- Local Subprograms --
71 -----------------------
73 procedure Binary_Op_Validity_Checks (N : Node_Id);
74 pragma Inline (Binary_Op_Validity_Checks);
75 -- Performs validity checks for a binary operator
77 procedure Build_Boolean_Array_Proc_Call
78 (N : Node_Id;
79 Op1 : Node_Id;
80 Op2 : Node_Id);
81 -- If an boolean array assignment can be done in place, build call to
82 -- corresponding library procedure.
84 procedure Expand_Allocator_Expression (N : Node_Id);
85 -- Subsidiary to Expand_N_Allocator, for the case when the expression
86 -- is a qualified expression or an aggregate.
88 procedure Expand_Array_Comparison (N : Node_Id);
89 -- This routine handles expansion of the comparison operators (N_Op_Lt,
90 -- N_Op_Le, N_Op_Gt, N_Op_Ge) when operating on an array type. The basic
91 -- code for these operators is similar, differing only in the details of
92 -- the actual comparison call that is made. Special processing (call a
93 -- run-time routine)
95 function Expand_Array_Equality
96 (Nod : Node_Id;
97 Lhs : Node_Id;
98 Rhs : Node_Id;
99 Bodies : List_Id;
100 Typ : Entity_Id) return Node_Id;
101 -- Expand an array equality into a call to a function implementing this
102 -- equality, and a call to it. Loc is the location for the generated
103 -- nodes. Lhs and Rhs are the array expressions to be compared.
104 -- Bodies is a list on which to attach bodies of local functions that
105 -- are created in the process. It is the responsibility of the
106 -- caller to insert those bodies at the right place. Nod provides
107 -- the Sloc value for the generated code. Normally the types used
108 -- for the generated equality routine are taken from Lhs and Rhs.
109 -- However, in some situations of generated code, the Etype fields
110 -- of Lhs and Rhs are not set yet. In such cases, Typ supplies the
111 -- type to be used for the formal parameters.
113 procedure Expand_Boolean_Operator (N : Node_Id);
114 -- Common expansion processing for Boolean operators (And, Or, Xor)
115 -- for the case of array type arguments.
117 function Expand_Composite_Equality
118 (Nod : Node_Id;
119 Typ : Entity_Id;
120 Lhs : Node_Id;
121 Rhs : Node_Id;
122 Bodies : List_Id) return Node_Id;
123 -- Local recursive function used to expand equality for nested
124 -- composite types. Used by Expand_Record/Array_Equality, Bodies
125 -- is a list on which to attach bodies of local functions that are
126 -- created in the process. This is the responsability of the caller
127 -- to insert those bodies at the right place. Nod provides the Sloc
128 -- value for generated code. Lhs and Rhs are the left and right sides
129 -- for the comparison, and Typ is the type of the arrays to compare.
131 procedure Expand_Concatenate_Other (Cnode : Node_Id; Opnds : List_Id);
132 -- This routine handles expansion of concatenation operations, where
133 -- N is the N_Op_Concat node being expanded and Operands is the list
134 -- of operands (at least two are present). The caller has dealt with
135 -- converting any singleton operands into singleton aggregates.
137 procedure Expand_Concatenate_String (Cnode : Node_Id; Opnds : List_Id);
138 -- Routine to expand concatenation of 2-5 operands (in the list Operands)
139 -- and replace node Cnode with the result of the contatenation. If there
140 -- are two operands, they can be string or character. If there are more
141 -- than two operands, then are always of type string (i.e. the caller has
142 -- already converted character operands to strings in this case).
144 procedure Fixup_Universal_Fixed_Operation (N : Node_Id);
145 -- N is either an N_Op_Divide or N_Op_Multiply node whose result is
146 -- universal fixed. We do not have such a type at runtime, so the
147 -- purpose of this routine is to find the real type by looking up
148 -- the tree. We also determine if the operation must be rounded.
150 function Get_Allocator_Final_List
151 (N : Node_Id;
152 T : Entity_Id;
153 PtrT : Entity_Id) return Entity_Id;
154 -- If the designated type is controlled, build final_list expression
155 -- for created object. If context is an access parameter, create a
156 -- local access type to have a usable finalization list.
158 function Has_Inferable_Discriminants (N : Node_Id) return Boolean;
159 -- Ada 2005 (AI-216): A view of an Unchecked_Union object has inferable
160 -- discriminants if it has a constrained nominal type, unless the object
161 -- is a component of an enclosing Unchecked_Union object that is subject
162 -- to a per-object constraint and the enclosing object lacks inferable
163 -- discriminants.
165 -- An expression of an Unchecked_Union type has inferable discriminants
166 -- if it is either a name of an object with inferable discriminants or a
167 -- qualified expression whose subtype mark denotes a constrained subtype.
169 procedure Insert_Dereference_Action (N : Node_Id);
170 -- N is an expression whose type is an access. When the type of the
171 -- associated storage pool is derived from Checked_Pool, generate a
172 -- call to the 'Dereference' primitive operation.
174 function Make_Array_Comparison_Op
175 (Typ : Entity_Id;
176 Nod : Node_Id) return Node_Id;
177 -- Comparisons between arrays are expanded in line. This function
178 -- produces the body of the implementation of (a > b), where a and b
179 -- are one-dimensional arrays of some discrete type. The original
180 -- node is then expanded into the appropriate call to this function.
181 -- Nod provides the Sloc value for the generated code.
183 function Make_Boolean_Array_Op
184 (Typ : Entity_Id;
185 N : Node_Id) return Node_Id;
186 -- Boolean operations on boolean arrays are expanded in line. This
187 -- function produce the body for the node N, which is (a and b),
188 -- (a or b), or (a xor b). It is used only the normal case and not
189 -- the packed case. The type involved, Typ, is the Boolean array type,
190 -- and the logical operations in the body are simple boolean operations.
191 -- Note that Typ is always a constrained type (the caller has ensured
192 -- this by using Convert_To_Actual_Subtype if necessary).
194 procedure Rewrite_Comparison (N : Node_Id);
195 -- N is the node for a compile time comparison. If this outcome of this
196 -- comparison can be determined at compile time, then the node N can be
197 -- rewritten with True or False. If the outcome cannot be determined at
198 -- compile time, the call has no effect.
200 function Tagged_Membership (N : Node_Id) return Node_Id;
201 -- Construct the expression corresponding to the tagged membership test.
202 -- Deals with a second operand being (or not) a class-wide type.
204 function Safe_In_Place_Array_Op
205 (Lhs : Node_Id;
206 Op1 : Node_Id;
207 Op2 : Node_Id) return Boolean;
208 -- In the context of an assignment, where the right-hand side is a
209 -- boolean operation on arrays, check whether operation can be performed
210 -- in place.
212 procedure Unary_Op_Validity_Checks (N : Node_Id);
213 pragma Inline (Unary_Op_Validity_Checks);
214 -- Performs validity checks for a unary operator
216 -------------------------------
217 -- Binary_Op_Validity_Checks --
218 -------------------------------
220 procedure Binary_Op_Validity_Checks (N : Node_Id) is
221 begin
222 if Validity_Checks_On and Validity_Check_Operands then
223 Ensure_Valid (Left_Opnd (N));
224 Ensure_Valid (Right_Opnd (N));
225 end if;
226 end Binary_Op_Validity_Checks;
228 ------------------------------------
229 -- Build_Boolean_Array_Proc_Call --
230 ------------------------------------
232 procedure Build_Boolean_Array_Proc_Call
233 (N : Node_Id;
234 Op1 : Node_Id;
235 Op2 : Node_Id)
237 Loc : constant Source_Ptr := Sloc (N);
238 Kind : constant Node_Kind := Nkind (Expression (N));
239 Target : constant Node_Id :=
240 Make_Attribute_Reference (Loc,
241 Prefix => Name (N),
242 Attribute_Name => Name_Address);
244 Arg1 : constant Node_Id := Op1;
245 Arg2 : Node_Id := Op2;
246 Call_Node : Node_Id;
247 Proc_Name : Entity_Id;
249 begin
250 if Kind = N_Op_Not then
251 if Nkind (Op1) in N_Binary_Op then
253 -- Use negated version of the binary operators
255 if Nkind (Op1) = N_Op_And then
256 Proc_Name := RTE (RE_Vector_Nand);
258 elsif Nkind (Op1) = N_Op_Or then
259 Proc_Name := RTE (RE_Vector_Nor);
261 else pragma Assert (Nkind (Op1) = N_Op_Xor);
262 Proc_Name := RTE (RE_Vector_Xor);
263 end if;
265 Call_Node :=
266 Make_Procedure_Call_Statement (Loc,
267 Name => New_Occurrence_Of (Proc_Name, Loc),
269 Parameter_Associations => New_List (
270 Target,
271 Make_Attribute_Reference (Loc,
272 Prefix => Left_Opnd (Op1),
273 Attribute_Name => Name_Address),
275 Make_Attribute_Reference (Loc,
276 Prefix => Right_Opnd (Op1),
277 Attribute_Name => Name_Address),
279 Make_Attribute_Reference (Loc,
280 Prefix => Left_Opnd (Op1),
281 Attribute_Name => Name_Length)));
283 else
284 Proc_Name := RTE (RE_Vector_Not);
286 Call_Node :=
287 Make_Procedure_Call_Statement (Loc,
288 Name => New_Occurrence_Of (Proc_Name, Loc),
289 Parameter_Associations => New_List (
290 Target,
292 Make_Attribute_Reference (Loc,
293 Prefix => Op1,
294 Attribute_Name => Name_Address),
296 Make_Attribute_Reference (Loc,
297 Prefix => Op1,
298 Attribute_Name => Name_Length)));
299 end if;
301 else
302 -- We use the following equivalences:
304 -- (not X) or (not Y) = not (X and Y) = Nand (X, Y)
305 -- (not X) and (not Y) = not (X or Y) = Nor (X, Y)
306 -- (not X) xor (not Y) = X xor Y
307 -- X xor (not Y) = not (X xor Y) = Nxor (X, Y)
309 if Nkind (Op1) = N_Op_Not then
310 if Kind = N_Op_And then
311 Proc_Name := RTE (RE_Vector_Nor);
313 elsif Kind = N_Op_Or then
314 Proc_Name := RTE (RE_Vector_Nand);
316 else
317 Proc_Name := RTE (RE_Vector_Xor);
318 end if;
320 else
321 if Kind = N_Op_And then
322 Proc_Name := RTE (RE_Vector_And);
324 elsif Kind = N_Op_Or then
325 Proc_Name := RTE (RE_Vector_Or);
327 elsif Nkind (Op2) = N_Op_Not then
328 Proc_Name := RTE (RE_Vector_Nxor);
329 Arg2 := Right_Opnd (Op2);
331 else
332 Proc_Name := RTE (RE_Vector_Xor);
333 end if;
334 end if;
336 Call_Node :=
337 Make_Procedure_Call_Statement (Loc,
338 Name => New_Occurrence_Of (Proc_Name, Loc),
339 Parameter_Associations => New_List (
340 Target,
341 Make_Attribute_Reference (Loc,
342 Prefix => Arg1,
343 Attribute_Name => Name_Address),
344 Make_Attribute_Reference (Loc,
345 Prefix => Arg2,
346 Attribute_Name => Name_Address),
347 Make_Attribute_Reference (Loc,
348 Prefix => Op1,
349 Attribute_Name => Name_Length)));
350 end if;
352 Rewrite (N, Call_Node);
353 Analyze (N);
355 exception
356 when RE_Not_Available =>
357 return;
358 end Build_Boolean_Array_Proc_Call;
360 ---------------------------------
361 -- Expand_Allocator_Expression --
362 ---------------------------------
364 procedure Expand_Allocator_Expression (N : Node_Id) is
365 Loc : constant Source_Ptr := Sloc (N);
366 Exp : constant Node_Id := Expression (Expression (N));
367 Indic : constant Node_Id := Subtype_Mark (Expression (N));
368 PtrT : constant Entity_Id := Etype (N);
369 DesigT : constant Entity_Id := Designated_Type (PtrT);
370 T : constant Entity_Id := Entity (Indic);
371 Flist : Node_Id;
372 Node : Node_Id;
373 Temp : Entity_Id;
375 Aggr_In_Place : constant Boolean := Is_Delayed_Aggregate (Exp);
377 Tag_Assign : Node_Id;
378 Tmp_Node : Node_Id;
380 begin
381 if Is_Tagged_Type (T) or else Controlled_Type (T) then
383 -- Actions inserted before:
384 -- Temp : constant ptr_T := new T'(Expression);
385 -- <no CW> Temp._tag := T'tag;
386 -- <CTRL> Adjust (Finalizable (Temp.all));
387 -- <CTRL> Attach_To_Final_List (Finalizable (Temp.all));
389 -- We analyze by hand the new internal allocator to avoid
390 -- any recursion and inappropriate call to Initialize
392 if not Aggr_In_Place then
393 Remove_Side_Effects (Exp);
394 end if;
396 Temp :=
397 Make_Defining_Identifier (Loc, New_Internal_Name ('P'));
399 -- For a class wide allocation generate the following code:
401 -- type Equiv_Record is record ... end record;
402 -- implicit subtype CW is <Class_Wide_Subytpe>;
403 -- temp : PtrT := new CW'(CW!(expr));
405 if Is_Class_Wide_Type (T) then
406 Expand_Subtype_From_Expr (Empty, T, Indic, Exp);
408 Set_Expression (Expression (N),
409 Unchecked_Convert_To (Entity (Indic), Exp));
411 Analyze_And_Resolve (Expression (N), Entity (Indic));
412 end if;
414 if Aggr_In_Place then
415 Tmp_Node :=
416 Make_Object_Declaration (Loc,
417 Defining_Identifier => Temp,
418 Object_Definition => New_Reference_To (PtrT, Loc),
419 Expression =>
420 Make_Allocator (Loc,
421 New_Reference_To (Etype (Exp), Loc)));
423 Set_Comes_From_Source
424 (Expression (Tmp_Node), Comes_From_Source (N));
426 Set_No_Initialization (Expression (Tmp_Node));
427 Insert_Action (N, Tmp_Node);
429 if Controlled_Type (T)
430 and then Ekind (PtrT) = E_Anonymous_Access_Type
431 then
432 -- Create local finalization list for access parameter
434 Flist := Get_Allocator_Final_List (N, Base_Type (T), PtrT);
435 end if;
437 Convert_Aggr_In_Allocator (Tmp_Node, Exp);
438 else
439 Node := Relocate_Node (N);
440 Set_Analyzed (Node);
441 Insert_Action (N,
442 Make_Object_Declaration (Loc,
443 Defining_Identifier => Temp,
444 Constant_Present => True,
445 Object_Definition => New_Reference_To (PtrT, Loc),
446 Expression => Node));
447 end if;
449 -- Ada 2005 (AI-344): For an allocator with a class-wide designated
450 -- type, generate an accessibility check to verify that the level of
451 -- the type of the created object is not deeper than the level of the
452 -- access type. If the type of the qualified expression is class-
453 -- wide, then always generate the check. Otherwise, only generate the
454 -- check if the level of the qualified expression type is statically
455 -- deeper than the access type. Although the static accessibility
456 -- will generally have been performed as a legality check, it won't
457 -- have been done in cases where the allocator appears in generic
458 -- body, so a run-time check is needed in general.
460 if Ada_Version >= Ada_05
461 and then Is_Class_Wide_Type (DesigT)
462 and then not Scope_Suppress (Accessibility_Check)
463 and then
464 (Is_Class_Wide_Type (Etype (Exp))
465 or else
466 Type_Access_Level (Etype (Exp)) > Type_Access_Level (PtrT))
467 then
468 Insert_Action (N,
469 Make_Raise_Program_Error (Loc,
470 Condition =>
471 Make_Op_Gt (Loc,
472 Left_Opnd =>
473 Make_Function_Call (Loc,
474 Name =>
475 New_Reference_To (RTE (RE_Get_Access_Level), Loc),
476 Parameter_Associations =>
477 New_List (Make_Attribute_Reference (Loc,
478 Prefix =>
479 New_Reference_To (Temp, Loc),
480 Attribute_Name =>
481 Name_Tag))),
482 Right_Opnd =>
483 Make_Integer_Literal (Loc, Type_Access_Level (PtrT))),
484 Reason => PE_Accessibility_Check_Failed));
485 end if;
487 -- Suppress the tag assignment when Java_VM because JVM tags
488 -- are represented implicitly in objects.
490 if Is_Tagged_Type (T)
491 and then not Is_Class_Wide_Type (T)
492 and then not Java_VM
493 then
494 Tag_Assign :=
495 Make_Assignment_Statement (Loc,
496 Name =>
497 Make_Selected_Component (Loc,
498 Prefix => New_Reference_To (Temp, Loc),
499 Selector_Name =>
500 New_Reference_To (First_Tag_Component (T), Loc)),
502 Expression =>
503 Unchecked_Convert_To (RTE (RE_Tag),
504 New_Reference_To
505 (Elists.Node (First_Elmt (Access_Disp_Table (T))),
506 Loc)));
508 -- The previous assignment has to be done in any case
510 Set_Assignment_OK (Name (Tag_Assign));
511 Insert_Action (N, Tag_Assign);
513 elsif Is_Private_Type (T)
514 and then Is_Tagged_Type (Underlying_Type (T))
515 and then not Java_VM
516 then
517 declare
518 Utyp : constant Entity_Id := Underlying_Type (T);
519 Ref : constant Node_Id :=
520 Unchecked_Convert_To (Utyp,
521 Make_Explicit_Dereference (Loc,
522 New_Reference_To (Temp, Loc)));
524 begin
525 Tag_Assign :=
526 Make_Assignment_Statement (Loc,
527 Name =>
528 Make_Selected_Component (Loc,
529 Prefix => Ref,
530 Selector_Name =>
531 New_Reference_To (First_Tag_Component (Utyp), Loc)),
533 Expression =>
534 Unchecked_Convert_To (RTE (RE_Tag),
535 New_Reference_To (
536 Elists.Node (First_Elmt (Access_Disp_Table (Utyp))),
537 Loc)));
539 Set_Assignment_OK (Name (Tag_Assign));
540 Insert_Action (N, Tag_Assign);
541 end;
542 end if;
544 if Controlled_Type (DesigT)
545 and then Controlled_Type (T)
546 then
547 declare
548 Attach : Node_Id;
549 Apool : constant Entity_Id :=
550 Associated_Storage_Pool (PtrT);
552 begin
553 -- If it is an allocation on the secondary stack
554 -- (i.e. a value returned from a function), the object
555 -- is attached on the caller side as soon as the call
556 -- is completed (see Expand_Ctrl_Function_Call)
558 if Is_RTE (Apool, RE_SS_Pool) then
559 declare
560 F : constant Entity_Id :=
561 Make_Defining_Identifier (Loc,
562 New_Internal_Name ('F'));
563 begin
564 Insert_Action (N,
565 Make_Object_Declaration (Loc,
566 Defining_Identifier => F,
567 Object_Definition => New_Reference_To (RTE
568 (RE_Finalizable_Ptr), Loc)));
570 Flist := New_Reference_To (F, Loc);
571 Attach := Make_Integer_Literal (Loc, 1);
572 end;
574 -- Normal case, not a secondary stack allocation
576 else
577 if Controlled_Type (T)
578 and then Ekind (PtrT) = E_Anonymous_Access_Type
579 then
580 -- Create local finalization list for access parameter
582 Flist :=
583 Get_Allocator_Final_List (N, Base_Type (T), PtrT);
584 else
585 Flist := Find_Final_List (PtrT);
586 end if;
588 Attach := Make_Integer_Literal (Loc, 2);
589 end if;
591 if not Aggr_In_Place then
592 Insert_Actions (N,
593 Make_Adjust_Call (
594 Ref =>
596 -- An unchecked conversion is needed in the
597 -- classwide case because the designated type
598 -- can be an ancestor of the subtype mark of
599 -- the allocator.
601 Unchecked_Convert_To (T,
602 Make_Explicit_Dereference (Loc,
603 New_Reference_To (Temp, Loc))),
605 Typ => T,
606 Flist_Ref => Flist,
607 With_Attach => Attach));
608 end if;
609 end;
610 end if;
612 Rewrite (N, New_Reference_To (Temp, Loc));
613 Analyze_And_Resolve (N, PtrT);
615 elsif Aggr_In_Place then
616 Temp :=
617 Make_Defining_Identifier (Loc, New_Internal_Name ('P'));
618 Tmp_Node :=
619 Make_Object_Declaration (Loc,
620 Defining_Identifier => Temp,
621 Object_Definition => New_Reference_To (PtrT, Loc),
622 Expression => Make_Allocator (Loc,
623 New_Reference_To (Etype (Exp), Loc)));
625 Set_Comes_From_Source
626 (Expression (Tmp_Node), Comes_From_Source (N));
628 Set_No_Initialization (Expression (Tmp_Node));
629 Insert_Action (N, Tmp_Node);
630 Convert_Aggr_In_Allocator (Tmp_Node, Exp);
631 Rewrite (N, New_Reference_To (Temp, Loc));
632 Analyze_And_Resolve (N, PtrT);
634 elsif Is_Access_Type (DesigT)
635 and then Nkind (Exp) = N_Allocator
636 and then Nkind (Expression (Exp)) /= N_Qualified_Expression
637 then
638 -- Apply constraint to designated subtype indication
640 Apply_Constraint_Check (Expression (Exp),
641 Designated_Type (DesigT),
642 No_Sliding => True);
644 if Nkind (Expression (Exp)) = N_Raise_Constraint_Error then
646 -- Propagate constraint_error to enclosing allocator
648 Rewrite (Exp, New_Copy (Expression (Exp)));
649 end if;
650 else
651 -- First check against the type of the qualified expression
653 -- NOTE: The commented call should be correct, but for
654 -- some reason causes the compiler to bomb (sigsegv) on
655 -- ACVC test c34007g, so for now we just perform the old
656 -- (incorrect) test against the designated subtype with
657 -- no sliding in the else part of the if statement below.
658 -- ???
660 -- Apply_Constraint_Check (Exp, T, No_Sliding => True);
662 -- A check is also needed in cases where the designated
663 -- subtype is constrained and differs from the subtype
664 -- given in the qualified expression. Note that the check
665 -- on the qualified expression does not allow sliding,
666 -- but this check does (a relaxation from Ada 83).
668 if Is_Constrained (DesigT)
669 and then not Subtypes_Statically_Match
670 (T, DesigT)
671 then
672 Apply_Constraint_Check
673 (Exp, DesigT, No_Sliding => False);
675 -- The nonsliding check should really be performed
676 -- (unconditionally) against the subtype of the
677 -- qualified expression, but that causes a problem
678 -- with c34007g (see above), so for now we retain this.
680 else
681 Apply_Constraint_Check
682 (Exp, DesigT, No_Sliding => True);
683 end if;
685 -- For an access to unconstrained packed array, GIGI needs
686 -- to see an expression with a constrained subtype in order
687 -- to compute the proper size for the allocator.
689 if Is_Array_Type (T)
690 and then not Is_Constrained (T)
691 and then Is_Packed (T)
692 then
693 declare
694 ConstrT : constant Entity_Id :=
695 Make_Defining_Identifier (Loc,
696 Chars => New_Internal_Name ('A'));
697 Internal_Exp : constant Node_Id := Relocate_Node (Exp);
698 begin
699 Insert_Action (Exp,
700 Make_Subtype_Declaration (Loc,
701 Defining_Identifier => ConstrT,
702 Subtype_Indication =>
703 Make_Subtype_From_Expr (Exp, T)));
704 Freeze_Itype (ConstrT, Exp);
705 Rewrite (Exp, OK_Convert_To (ConstrT, Internal_Exp));
706 end;
707 end if;
709 end if;
711 exception
712 when RE_Not_Available =>
713 return;
714 end Expand_Allocator_Expression;
716 -----------------------------
717 -- Expand_Array_Comparison --
718 -----------------------------
720 -- Expansion is only required in the case of array types. For the
721 -- unpacked case, an appropriate runtime routine is called. For
722 -- packed cases, and also in some other cases where a runtime
723 -- routine cannot be called, the form of the expansion is:
725 -- [body for greater_nn; boolean_expression]
727 -- The body is built by Make_Array_Comparison_Op, and the form of the
728 -- Boolean expression depends on the operator involved.
730 procedure Expand_Array_Comparison (N : Node_Id) is
731 Loc : constant Source_Ptr := Sloc (N);
732 Op1 : Node_Id := Left_Opnd (N);
733 Op2 : Node_Id := Right_Opnd (N);
734 Typ1 : constant Entity_Id := Base_Type (Etype (Op1));
735 Ctyp : constant Entity_Id := Component_Type (Typ1);
737 Expr : Node_Id;
738 Func_Body : Node_Id;
739 Func_Name : Entity_Id;
741 Comp : RE_Id;
743 Byte_Addressable : constant Boolean := System_Storage_Unit = Byte'Size;
744 -- True for byte addressable target
746 function Length_Less_Than_4 (Opnd : Node_Id) return Boolean;
747 -- Returns True if the length of the given operand is known to be
748 -- less than 4. Returns False if this length is known to be four
749 -- or greater or is not known at compile time.
751 ------------------------
752 -- Length_Less_Than_4 --
753 ------------------------
755 function Length_Less_Than_4 (Opnd : Node_Id) return Boolean is
756 Otyp : constant Entity_Id := Etype (Opnd);
758 begin
759 if Ekind (Otyp) = E_String_Literal_Subtype then
760 return String_Literal_Length (Otyp) < 4;
762 else
763 declare
764 Ityp : constant Entity_Id := Etype (First_Index (Otyp));
765 Lo : constant Node_Id := Type_Low_Bound (Ityp);
766 Hi : constant Node_Id := Type_High_Bound (Ityp);
767 Lov : Uint;
768 Hiv : Uint;
770 begin
771 if Compile_Time_Known_Value (Lo) then
772 Lov := Expr_Value (Lo);
773 else
774 return False;
775 end if;
777 if Compile_Time_Known_Value (Hi) then
778 Hiv := Expr_Value (Hi);
779 else
780 return False;
781 end if;
783 return Hiv < Lov + 3;
784 end;
785 end if;
786 end Length_Less_Than_4;
788 -- Start of processing for Expand_Array_Comparison
790 begin
791 -- Deal first with unpacked case, where we can call a runtime routine
792 -- except that we avoid this for targets for which are not addressable
793 -- by bytes, and for the JVM, since the JVM does not support direct
794 -- addressing of array components.
796 if not Is_Bit_Packed_Array (Typ1)
797 and then Byte_Addressable
798 and then not Java_VM
799 then
800 -- The call we generate is:
802 -- Compare_Array_xn[_Unaligned]
803 -- (left'address, right'address, left'length, right'length) <op> 0
805 -- x = U for unsigned, S for signed
806 -- n = 8,16,32,64 for component size
807 -- Add _Unaligned if length < 4 and component size is 8.
808 -- <op> is the standard comparison operator
810 if Component_Size (Typ1) = 8 then
811 if Length_Less_Than_4 (Op1)
812 or else
813 Length_Less_Than_4 (Op2)
814 then
815 if Is_Unsigned_Type (Ctyp) then
816 Comp := RE_Compare_Array_U8_Unaligned;
817 else
818 Comp := RE_Compare_Array_S8_Unaligned;
819 end if;
821 else
822 if Is_Unsigned_Type (Ctyp) then
823 Comp := RE_Compare_Array_U8;
824 else
825 Comp := RE_Compare_Array_S8;
826 end if;
827 end if;
829 elsif Component_Size (Typ1) = 16 then
830 if Is_Unsigned_Type (Ctyp) then
831 Comp := RE_Compare_Array_U16;
832 else
833 Comp := RE_Compare_Array_S16;
834 end if;
836 elsif Component_Size (Typ1) = 32 then
837 if Is_Unsigned_Type (Ctyp) then
838 Comp := RE_Compare_Array_U32;
839 else
840 Comp := RE_Compare_Array_S32;
841 end if;
843 else pragma Assert (Component_Size (Typ1) = 64);
844 if Is_Unsigned_Type (Ctyp) then
845 Comp := RE_Compare_Array_U64;
846 else
847 Comp := RE_Compare_Array_S64;
848 end if;
849 end if;
851 Remove_Side_Effects (Op1, Name_Req => True);
852 Remove_Side_Effects (Op2, Name_Req => True);
854 Rewrite (Op1,
855 Make_Function_Call (Sloc (Op1),
856 Name => New_Occurrence_Of (RTE (Comp), Loc),
858 Parameter_Associations => New_List (
859 Make_Attribute_Reference (Loc,
860 Prefix => Relocate_Node (Op1),
861 Attribute_Name => Name_Address),
863 Make_Attribute_Reference (Loc,
864 Prefix => Relocate_Node (Op2),
865 Attribute_Name => Name_Address),
867 Make_Attribute_Reference (Loc,
868 Prefix => Relocate_Node (Op1),
869 Attribute_Name => Name_Length),
871 Make_Attribute_Reference (Loc,
872 Prefix => Relocate_Node (Op2),
873 Attribute_Name => Name_Length))));
875 Rewrite (Op2,
876 Make_Integer_Literal (Sloc (Op2),
877 Intval => Uint_0));
879 Analyze_And_Resolve (Op1, Standard_Integer);
880 Analyze_And_Resolve (Op2, Standard_Integer);
881 return;
882 end if;
884 -- Cases where we cannot make runtime call
886 -- For (a <= b) we convert to not (a > b)
888 if Chars (N) = Name_Op_Le then
889 Rewrite (N,
890 Make_Op_Not (Loc,
891 Right_Opnd =>
892 Make_Op_Gt (Loc,
893 Left_Opnd => Op1,
894 Right_Opnd => Op2)));
895 Analyze_And_Resolve (N, Standard_Boolean);
896 return;
898 -- For < the Boolean expression is
899 -- greater__nn (op2, op1)
901 elsif Chars (N) = Name_Op_Lt then
902 Func_Body := Make_Array_Comparison_Op (Typ1, N);
904 -- Switch operands
906 Op1 := Right_Opnd (N);
907 Op2 := Left_Opnd (N);
909 -- For (a >= b) we convert to not (a < b)
911 elsif Chars (N) = Name_Op_Ge then
912 Rewrite (N,
913 Make_Op_Not (Loc,
914 Right_Opnd =>
915 Make_Op_Lt (Loc,
916 Left_Opnd => Op1,
917 Right_Opnd => Op2)));
918 Analyze_And_Resolve (N, Standard_Boolean);
919 return;
921 -- For > the Boolean expression is
922 -- greater__nn (op1, op2)
924 else
925 pragma Assert (Chars (N) = Name_Op_Gt);
926 Func_Body := Make_Array_Comparison_Op (Typ1, N);
927 end if;
929 Func_Name := Defining_Unit_Name (Specification (Func_Body));
930 Expr :=
931 Make_Function_Call (Loc,
932 Name => New_Reference_To (Func_Name, Loc),
933 Parameter_Associations => New_List (Op1, Op2));
935 Insert_Action (N, Func_Body);
936 Rewrite (N, Expr);
937 Analyze_And_Resolve (N, Standard_Boolean);
939 exception
940 when RE_Not_Available =>
941 return;
942 end Expand_Array_Comparison;
944 ---------------------------
945 -- Expand_Array_Equality --
946 ---------------------------
948 -- Expand an equality function for multi-dimensional arrays. Here is
949 -- an example of such a function for Nb_Dimension = 2
951 -- function Enn (A : atyp; B : btyp) return boolean is
952 -- begin
953 -- if (A'length (1) = 0 or else A'length (2) = 0)
954 -- and then
955 -- (B'length (1) = 0 or else B'length (2) = 0)
956 -- then
957 -- return True; -- RM 4.5.2(22)
958 -- end if;
960 -- if A'length (1) /= B'length (1)
961 -- or else
962 -- A'length (2) /= B'length (2)
963 -- then
964 -- return False; -- RM 4.5.2(23)
965 -- end if;
967 -- declare
968 -- A1 : Index_T1 := A'first (1);
969 -- B1 : Index_T1 := B'first (1);
970 -- begin
971 -- loop
972 -- declare
973 -- A2 : Index_T2 := A'first (2);
974 -- B2 : Index_T2 := B'first (2);
975 -- begin
976 -- loop
977 -- if A (A1, A2) /= B (B1, B2) then
978 -- return False;
979 -- end if;
981 -- exit when A2 = A'last (2);
982 -- A2 := Index_T2'succ (A2);
983 -- B2 := Index_T2'succ (B2);
984 -- end loop;
985 -- end;
987 -- exit when A1 = A'last (1);
988 -- A1 := Index_T1'succ (A1);
989 -- B1 := Index_T1'succ (B1);
990 -- end loop;
991 -- end;
993 -- return true;
994 -- end Enn;
996 -- Note on the formal types used (atyp and btyp). If either of the
997 -- arrays is of a private type, we use the underlying type, and
998 -- do an unchecked conversion of the actual. If either of the arrays
999 -- has a bound depending on a discriminant, then we use the base type
1000 -- since otherwise we have an escaped discriminant in the function.
1002 -- If both arrays are constrained and have the same bounds, we can
1003 -- generate a loop with an explicit iteration scheme using a 'Range
1004 -- attribute over the first array.
1006 function Expand_Array_Equality
1007 (Nod : Node_Id;
1008 Lhs : Node_Id;
1009 Rhs : Node_Id;
1010 Bodies : List_Id;
1011 Typ : Entity_Id) return Node_Id
1013 Loc : constant Source_Ptr := Sloc (Nod);
1014 Decls : constant List_Id := New_List;
1015 Index_List1 : constant List_Id := New_List;
1016 Index_List2 : constant List_Id := New_List;
1018 Actuals : List_Id;
1019 Formals : List_Id;
1020 Func_Name : Entity_Id;
1021 Func_Body : Node_Id;
1023 A : constant Entity_Id := Make_Defining_Identifier (Loc, Name_uA);
1024 B : constant Entity_Id := Make_Defining_Identifier (Loc, Name_uB);
1026 Ltyp : Entity_Id;
1027 Rtyp : Entity_Id;
1028 -- The parameter types to be used for the formals
1030 function Arr_Attr
1031 (Arr : Entity_Id;
1032 Nam : Name_Id;
1033 Num : Int) return Node_Id;
1034 -- This builds the attribute reference Arr'Nam (Expr)
1036 function Component_Equality (Typ : Entity_Id) return Node_Id;
1037 -- Create one statement to compare corresponding components,
1038 -- designated by a full set of indices.
1040 function Get_Arg_Type (N : Node_Id) return Entity_Id;
1041 -- Given one of the arguments, computes the appropriate type to
1042 -- be used for that argument in the corresponding function formal
1044 function Handle_One_Dimension
1045 (N : Int;
1046 Index : Node_Id) return Node_Id;
1047 -- This procedure returns the following code
1049 -- declare
1050 -- Bn : Index_T := B'First (N);
1051 -- begin
1052 -- loop
1053 -- xxx
1054 -- exit when An = A'Last (N);
1055 -- An := Index_T'Succ (An)
1056 -- Bn := Index_T'Succ (Bn)
1057 -- end loop;
1058 -- end;
1060 -- If both indices are constrained and identical, the procedure
1061 -- returns a simpler loop:
1063 -- for An in A'Range (N) loop
1064 -- xxx
1065 -- end loop
1067 -- N is the dimension for which we are generating a loop. Index is the
1068 -- N'th index node, whose Etype is Index_Type_n in the above code.
1069 -- The xxx statement is either the loop or declare for the next
1070 -- dimension or if this is the last dimension the comparison
1071 -- of corresponding components of the arrays.
1073 -- The actual way the code works is to return the comparison
1074 -- of corresponding components for the N+1 call. That's neater!
1076 function Test_Empty_Arrays return Node_Id;
1077 -- This function constructs the test for both arrays being empty
1078 -- (A'length (1) = 0 or else A'length (2) = 0 or else ...)
1079 -- and then
1080 -- (B'length (1) = 0 or else B'length (2) = 0 or else ...)
1082 function Test_Lengths_Correspond return Node_Id;
1083 -- This function constructs the test for arrays having different
1084 -- lengths in at least one index position, in which case resull
1086 -- A'length (1) /= B'length (1)
1087 -- or else
1088 -- A'length (2) /= B'length (2)
1089 -- or else
1090 -- ...
1092 --------------
1093 -- Arr_Attr --
1094 --------------
1096 function Arr_Attr
1097 (Arr : Entity_Id;
1098 Nam : Name_Id;
1099 Num : Int) return Node_Id
1101 begin
1102 return
1103 Make_Attribute_Reference (Loc,
1104 Attribute_Name => Nam,
1105 Prefix => New_Reference_To (Arr, Loc),
1106 Expressions => New_List (Make_Integer_Literal (Loc, Num)));
1107 end Arr_Attr;
1109 ------------------------
1110 -- Component_Equality --
1111 ------------------------
1113 function Component_Equality (Typ : Entity_Id) return Node_Id is
1114 Test : Node_Id;
1115 L, R : Node_Id;
1117 begin
1118 -- if a(i1...) /= b(j1...) then return false; end if;
1120 L :=
1121 Make_Indexed_Component (Loc,
1122 Prefix => Make_Identifier (Loc, Chars (A)),
1123 Expressions => Index_List1);
1125 R :=
1126 Make_Indexed_Component (Loc,
1127 Prefix => Make_Identifier (Loc, Chars (B)),
1128 Expressions => Index_List2);
1130 Test := Expand_Composite_Equality
1131 (Nod, Component_Type (Typ), L, R, Decls);
1133 -- If some (sub)component is an unchecked_union, the whole operation
1134 -- will raise program error.
1136 if Nkind (Test) = N_Raise_Program_Error then
1138 -- This node is going to be inserted at a location where a
1139 -- statement is expected: clear its Etype so analysis will
1140 -- set it to the expected Standard_Void_Type.
1142 Set_Etype (Test, Empty);
1143 return Test;
1145 else
1146 return
1147 Make_Implicit_If_Statement (Nod,
1148 Condition => Make_Op_Not (Loc, Right_Opnd => Test),
1149 Then_Statements => New_List (
1150 Make_Return_Statement (Loc,
1151 Expression => New_Occurrence_Of (Standard_False, Loc))));
1152 end if;
1153 end Component_Equality;
1155 ------------------
1156 -- Get_Arg_Type --
1157 ------------------
1159 function Get_Arg_Type (N : Node_Id) return Entity_Id is
1160 T : Entity_Id;
1161 X : Node_Id;
1163 begin
1164 T := Etype (N);
1166 if No (T) then
1167 return Typ;
1169 else
1170 T := Underlying_Type (T);
1172 X := First_Index (T);
1173 while Present (X) loop
1174 if Denotes_Discriminant (Type_Low_Bound (Etype (X)))
1175 or else
1176 Denotes_Discriminant (Type_High_Bound (Etype (X)))
1177 then
1178 T := Base_Type (T);
1179 exit;
1180 end if;
1182 Next_Index (X);
1183 end loop;
1185 return T;
1186 end if;
1187 end Get_Arg_Type;
1189 --------------------------
1190 -- Handle_One_Dimension --
1191 ---------------------------
1193 function Handle_One_Dimension
1194 (N : Int;
1195 Index : Node_Id) return Node_Id
1197 Need_Separate_Indexes : constant Boolean :=
1198 Ltyp /= Rtyp
1199 or else not Is_Constrained (Ltyp);
1200 -- If the index types are identical, and we are working with
1201 -- constrained types, then we can use the same index for both of
1202 -- the arrays.
1204 An : constant Entity_Id := Make_Defining_Identifier (Loc,
1205 Chars => New_Internal_Name ('A'));
1207 Bn : Entity_Id;
1208 Index_T : Entity_Id;
1209 Stm_List : List_Id;
1210 Loop_Stm : Node_Id;
1212 begin
1213 if N > Number_Dimensions (Ltyp) then
1214 return Component_Equality (Ltyp);
1215 end if;
1217 -- Case where we generate a loop
1219 Index_T := Base_Type (Etype (Index));
1221 if Need_Separate_Indexes then
1222 Bn :=
1223 Make_Defining_Identifier (Loc,
1224 Chars => New_Internal_Name ('B'));
1225 else
1226 Bn := An;
1227 end if;
1229 Append (New_Reference_To (An, Loc), Index_List1);
1230 Append (New_Reference_To (Bn, Loc), Index_List2);
1232 Stm_List := New_List (
1233 Handle_One_Dimension (N + 1, Next_Index (Index)));
1235 if Need_Separate_Indexes then
1237 -- Generate guard for loop, followed by increments of indices
1239 Append_To (Stm_List,
1240 Make_Exit_Statement (Loc,
1241 Condition =>
1242 Make_Op_Eq (Loc,
1243 Left_Opnd => New_Reference_To (An, Loc),
1244 Right_Opnd => Arr_Attr (A, Name_Last, N))));
1246 Append_To (Stm_List,
1247 Make_Assignment_Statement (Loc,
1248 Name => New_Reference_To (An, Loc),
1249 Expression =>
1250 Make_Attribute_Reference (Loc,
1251 Prefix => New_Reference_To (Index_T, Loc),
1252 Attribute_Name => Name_Succ,
1253 Expressions => New_List (New_Reference_To (An, Loc)))));
1255 Append_To (Stm_List,
1256 Make_Assignment_Statement (Loc,
1257 Name => New_Reference_To (Bn, Loc),
1258 Expression =>
1259 Make_Attribute_Reference (Loc,
1260 Prefix => New_Reference_To (Index_T, Loc),
1261 Attribute_Name => Name_Succ,
1262 Expressions => New_List (New_Reference_To (Bn, Loc)))));
1263 end if;
1265 -- If separate indexes, we need a declare block for An and Bn, and a
1266 -- loop without an iteration scheme.
1268 if Need_Separate_Indexes then
1269 Loop_Stm :=
1270 Make_Implicit_Loop_Statement (Nod, Statements => Stm_List);
1272 return
1273 Make_Block_Statement (Loc,
1274 Declarations => New_List (
1275 Make_Object_Declaration (Loc,
1276 Defining_Identifier => An,
1277 Object_Definition => New_Reference_To (Index_T, Loc),
1278 Expression => Arr_Attr (A, Name_First, N)),
1280 Make_Object_Declaration (Loc,
1281 Defining_Identifier => Bn,
1282 Object_Definition => New_Reference_To (Index_T, Loc),
1283 Expression => Arr_Attr (B, Name_First, N))),
1285 Handled_Statement_Sequence =>
1286 Make_Handled_Sequence_Of_Statements (Loc,
1287 Statements => New_List (Loop_Stm)));
1289 -- If no separate indexes, return loop statement with explicit
1290 -- iteration scheme on its own
1292 else
1293 Loop_Stm :=
1294 Make_Implicit_Loop_Statement (Nod,
1295 Statements => Stm_List,
1296 Iteration_Scheme =>
1297 Make_Iteration_Scheme (Loc,
1298 Loop_Parameter_Specification =>
1299 Make_Loop_Parameter_Specification (Loc,
1300 Defining_Identifier => An,
1301 Discrete_Subtype_Definition =>
1302 Arr_Attr (A, Name_Range, N))));
1303 return Loop_Stm;
1304 end if;
1305 end Handle_One_Dimension;
1307 -----------------------
1308 -- Test_Empty_Arrays --
1309 -----------------------
1311 function Test_Empty_Arrays return Node_Id is
1312 Alist : Node_Id;
1313 Blist : Node_Id;
1315 Atest : Node_Id;
1316 Btest : Node_Id;
1318 begin
1319 Alist := Empty;
1320 Blist := Empty;
1321 for J in 1 .. Number_Dimensions (Ltyp) loop
1322 Atest :=
1323 Make_Op_Eq (Loc,
1324 Left_Opnd => Arr_Attr (A, Name_Length, J),
1325 Right_Opnd => Make_Integer_Literal (Loc, 0));
1327 Btest :=
1328 Make_Op_Eq (Loc,
1329 Left_Opnd => Arr_Attr (B, Name_Length, J),
1330 Right_Opnd => Make_Integer_Literal (Loc, 0));
1332 if No (Alist) then
1333 Alist := Atest;
1334 Blist := Btest;
1336 else
1337 Alist :=
1338 Make_Or_Else (Loc,
1339 Left_Opnd => Relocate_Node (Alist),
1340 Right_Opnd => Atest);
1342 Blist :=
1343 Make_Or_Else (Loc,
1344 Left_Opnd => Relocate_Node (Blist),
1345 Right_Opnd => Btest);
1346 end if;
1347 end loop;
1349 return
1350 Make_And_Then (Loc,
1351 Left_Opnd => Alist,
1352 Right_Opnd => Blist);
1353 end Test_Empty_Arrays;
1355 -----------------------------
1356 -- Test_Lengths_Correspond --
1357 -----------------------------
1359 function Test_Lengths_Correspond return Node_Id is
1360 Result : Node_Id;
1361 Rtest : Node_Id;
1363 begin
1364 Result := Empty;
1365 for J in 1 .. Number_Dimensions (Ltyp) loop
1366 Rtest :=
1367 Make_Op_Ne (Loc,
1368 Left_Opnd => Arr_Attr (A, Name_Length, J),
1369 Right_Opnd => Arr_Attr (B, Name_Length, J));
1371 if No (Result) then
1372 Result := Rtest;
1373 else
1374 Result :=
1375 Make_Or_Else (Loc,
1376 Left_Opnd => Relocate_Node (Result),
1377 Right_Opnd => Rtest);
1378 end if;
1379 end loop;
1381 return Result;
1382 end Test_Lengths_Correspond;
1384 -- Start of processing for Expand_Array_Equality
1386 begin
1387 Ltyp := Get_Arg_Type (Lhs);
1388 Rtyp := Get_Arg_Type (Rhs);
1390 -- For now, if the argument types are not the same, go to the
1391 -- base type, since the code assumes that the formals have the
1392 -- same type. This is fixable in future ???
1394 if Ltyp /= Rtyp then
1395 Ltyp := Base_Type (Ltyp);
1396 Rtyp := Base_Type (Rtyp);
1397 pragma Assert (Ltyp = Rtyp);
1398 end if;
1400 -- Build list of formals for function
1402 Formals := New_List (
1403 Make_Parameter_Specification (Loc,
1404 Defining_Identifier => A,
1405 Parameter_Type => New_Reference_To (Ltyp, Loc)),
1407 Make_Parameter_Specification (Loc,
1408 Defining_Identifier => B,
1409 Parameter_Type => New_Reference_To (Rtyp, Loc)));
1411 Func_Name := Make_Defining_Identifier (Loc, New_Internal_Name ('E'));
1413 -- Build statement sequence for function
1415 Func_Body :=
1416 Make_Subprogram_Body (Loc,
1417 Specification =>
1418 Make_Function_Specification (Loc,
1419 Defining_Unit_Name => Func_Name,
1420 Parameter_Specifications => Formals,
1421 Result_Definition => New_Reference_To (Standard_Boolean, Loc)),
1423 Declarations => Decls,
1425 Handled_Statement_Sequence =>
1426 Make_Handled_Sequence_Of_Statements (Loc,
1427 Statements => New_List (
1429 Make_Implicit_If_Statement (Nod,
1430 Condition => Test_Empty_Arrays,
1431 Then_Statements => New_List (
1432 Make_Return_Statement (Loc,
1433 Expression =>
1434 New_Occurrence_Of (Standard_True, Loc)))),
1436 Make_Implicit_If_Statement (Nod,
1437 Condition => Test_Lengths_Correspond,
1438 Then_Statements => New_List (
1439 Make_Return_Statement (Loc,
1440 Expression =>
1441 New_Occurrence_Of (Standard_False, Loc)))),
1443 Handle_One_Dimension (1, First_Index (Ltyp)),
1445 Make_Return_Statement (Loc,
1446 Expression => New_Occurrence_Of (Standard_True, Loc)))));
1448 Set_Has_Completion (Func_Name, True);
1449 Set_Is_Inlined (Func_Name);
1451 -- If the array type is distinct from the type of the arguments,
1452 -- it is the full view of a private type. Apply an unchecked
1453 -- conversion to insure that analysis of the call succeeds.
1455 declare
1456 L, R : Node_Id;
1458 begin
1459 L := Lhs;
1460 R := Rhs;
1462 if No (Etype (Lhs))
1463 or else Base_Type (Etype (Lhs)) /= Base_Type (Ltyp)
1464 then
1465 L := OK_Convert_To (Ltyp, Lhs);
1466 end if;
1468 if No (Etype (Rhs))
1469 or else Base_Type (Etype (Rhs)) /= Base_Type (Rtyp)
1470 then
1471 R := OK_Convert_To (Rtyp, Rhs);
1472 end if;
1474 Actuals := New_List (L, R);
1475 end;
1477 Append_To (Bodies, Func_Body);
1479 return
1480 Make_Function_Call (Loc,
1481 Name => New_Reference_To (Func_Name, Loc),
1482 Parameter_Associations => Actuals);
1483 end Expand_Array_Equality;
1485 -----------------------------
1486 -- Expand_Boolean_Operator --
1487 -----------------------------
1489 -- Note that we first get the actual subtypes of the operands,
1490 -- since we always want to deal with types that have bounds.
1492 procedure Expand_Boolean_Operator (N : Node_Id) is
1493 Typ : constant Entity_Id := Etype (N);
1495 begin
1496 -- Special case of bit packed array where both operands are known
1497 -- to be properly aligned. In this case we use an efficient run time
1498 -- routine to carry out the operation (see System.Bit_Ops).
1500 if Is_Bit_Packed_Array (Typ)
1501 and then not Is_Possibly_Unaligned_Object (Left_Opnd (N))
1502 and then not Is_Possibly_Unaligned_Object (Right_Opnd (N))
1503 then
1504 Expand_Packed_Boolean_Operator (N);
1505 return;
1506 end if;
1508 -- For the normal non-packed case, the general expansion is to build
1509 -- function for carrying out the comparison (use Make_Boolean_Array_Op)
1510 -- and then inserting it into the tree. The original operator node is
1511 -- then rewritten as a call to this function. We also use this in the
1512 -- packed case if either operand is a possibly unaligned object.
1514 declare
1515 Loc : constant Source_Ptr := Sloc (N);
1516 L : constant Node_Id := Relocate_Node (Left_Opnd (N));
1517 R : constant Node_Id := Relocate_Node (Right_Opnd (N));
1518 Func_Body : Node_Id;
1519 Func_Name : Entity_Id;
1521 begin
1522 Convert_To_Actual_Subtype (L);
1523 Convert_To_Actual_Subtype (R);
1524 Ensure_Defined (Etype (L), N);
1525 Ensure_Defined (Etype (R), N);
1526 Apply_Length_Check (R, Etype (L));
1528 if Nkind (Parent (N)) = N_Assignment_Statement
1529 and then Safe_In_Place_Array_Op (Name (Parent (N)), L, R)
1530 then
1531 Build_Boolean_Array_Proc_Call (Parent (N), L, R);
1533 elsif Nkind (Parent (N)) = N_Op_Not
1534 and then Nkind (N) = N_Op_And
1535 and then
1536 Safe_In_Place_Array_Op (Name (Parent (Parent (N))), L, R)
1537 then
1538 return;
1539 else
1541 Func_Body := Make_Boolean_Array_Op (Etype (L), N);
1542 Func_Name := Defining_Unit_Name (Specification (Func_Body));
1543 Insert_Action (N, Func_Body);
1545 -- Now rewrite the expression with a call
1547 Rewrite (N,
1548 Make_Function_Call (Loc,
1549 Name => New_Reference_To (Func_Name, Loc),
1550 Parameter_Associations =>
1551 New_List (
1553 Make_Type_Conversion
1554 (Loc, New_Reference_To (Etype (L), Loc), R))));
1556 Analyze_And_Resolve (N, Typ);
1557 end if;
1558 end;
1559 end Expand_Boolean_Operator;
1561 -------------------------------
1562 -- Expand_Composite_Equality --
1563 -------------------------------
1565 -- This function is only called for comparing internal fields of composite
1566 -- types when these fields are themselves composites. This is a special
1567 -- case because it is not possible to respect normal Ada visibility rules.
1569 function Expand_Composite_Equality
1570 (Nod : Node_Id;
1571 Typ : Entity_Id;
1572 Lhs : Node_Id;
1573 Rhs : Node_Id;
1574 Bodies : List_Id) return Node_Id
1576 Loc : constant Source_Ptr := Sloc (Nod);
1577 Full_Type : Entity_Id;
1578 Prim : Elmt_Id;
1579 Eq_Op : Entity_Id;
1581 begin
1582 if Is_Private_Type (Typ) then
1583 Full_Type := Underlying_Type (Typ);
1584 else
1585 Full_Type := Typ;
1586 end if;
1588 -- Defense against malformed private types with no completion
1589 -- the error will be diagnosed later by check_completion
1591 if No (Full_Type) then
1592 return New_Reference_To (Standard_False, Loc);
1593 end if;
1595 Full_Type := Base_Type (Full_Type);
1597 if Is_Array_Type (Full_Type) then
1599 -- If the operand is an elementary type other than a floating-point
1600 -- type, then we can simply use the built-in block bitwise equality,
1601 -- since the predefined equality operators always apply and bitwise
1602 -- equality is fine for all these cases.
1604 if Is_Elementary_Type (Component_Type (Full_Type))
1605 and then not Is_Floating_Point_Type (Component_Type (Full_Type))
1606 then
1607 return Make_Op_Eq (Loc, Left_Opnd => Lhs, Right_Opnd => Rhs);
1609 -- For composite component types, and floating-point types, use
1610 -- the expansion. This deals with tagged component types (where
1611 -- we use the applicable equality routine) and floating-point,
1612 -- (where we need to worry about negative zeroes), and also the
1613 -- case of any composite type recursively containing such fields.
1615 else
1616 return Expand_Array_Equality (Nod, Lhs, Rhs, Bodies, Full_Type);
1617 end if;
1619 elsif Is_Tagged_Type (Full_Type) then
1621 -- Call the primitive operation "=" of this type
1623 if Is_Class_Wide_Type (Full_Type) then
1624 Full_Type := Root_Type (Full_Type);
1625 end if;
1627 -- If this is derived from an untagged private type completed
1628 -- with a tagged type, it does not have a full view, so we
1629 -- use the primitive operations of the private type.
1630 -- This check should no longer be necessary when these
1631 -- types receive their full views ???
1633 if Is_Private_Type (Typ)
1634 and then not Is_Tagged_Type (Typ)
1635 and then not Is_Controlled (Typ)
1636 and then Is_Derived_Type (Typ)
1637 and then No (Full_View (Typ))
1638 then
1639 Prim := First_Elmt (Collect_Primitive_Operations (Typ));
1640 else
1641 Prim := First_Elmt (Primitive_Operations (Full_Type));
1642 end if;
1644 loop
1645 Eq_Op := Node (Prim);
1646 exit when Chars (Eq_Op) = Name_Op_Eq
1647 and then Etype (First_Formal (Eq_Op)) =
1648 Etype (Next_Formal (First_Formal (Eq_Op)))
1649 and then Base_Type (Etype (Eq_Op)) = Standard_Boolean;
1650 Next_Elmt (Prim);
1651 pragma Assert (Present (Prim));
1652 end loop;
1654 Eq_Op := Node (Prim);
1656 return
1657 Make_Function_Call (Loc,
1658 Name => New_Reference_To (Eq_Op, Loc),
1659 Parameter_Associations =>
1660 New_List
1661 (Unchecked_Convert_To (Etype (First_Formal (Eq_Op)), Lhs),
1662 Unchecked_Convert_To (Etype (First_Formal (Eq_Op)), Rhs)));
1664 elsif Is_Record_Type (Full_Type) then
1665 Eq_Op := TSS (Full_Type, TSS_Composite_Equality);
1667 if Present (Eq_Op) then
1668 if Etype (First_Formal (Eq_Op)) /= Full_Type then
1670 -- Inherited equality from parent type. Convert the actuals
1671 -- to match signature of operation.
1673 declare
1674 T : constant Entity_Id := Etype (First_Formal (Eq_Op));
1676 begin
1677 return
1678 Make_Function_Call (Loc,
1679 Name => New_Reference_To (Eq_Op, Loc),
1680 Parameter_Associations =>
1681 New_List (OK_Convert_To (T, Lhs),
1682 OK_Convert_To (T, Rhs)));
1683 end;
1685 else
1686 -- Comparison between Unchecked_Union components
1688 if Is_Unchecked_Union (Full_Type) then
1689 declare
1690 Lhs_Type : Node_Id := Full_Type;
1691 Rhs_Type : Node_Id := Full_Type;
1692 Lhs_Discr_Val : Node_Id;
1693 Rhs_Discr_Val : Node_Id;
1695 begin
1696 -- Lhs subtype
1698 if Nkind (Lhs) = N_Selected_Component then
1699 Lhs_Type := Etype (Entity (Selector_Name (Lhs)));
1700 end if;
1702 -- Rhs subtype
1704 if Nkind (Rhs) = N_Selected_Component then
1705 Rhs_Type := Etype (Entity (Selector_Name (Rhs)));
1706 end if;
1708 -- Lhs of the composite equality
1710 if Is_Constrained (Lhs_Type) then
1712 -- Since the enclosing record can never be an
1713 -- Unchecked_Union (this code is executed for records
1714 -- that do not have variants), we may reference its
1715 -- discriminant(s).
1717 if Nkind (Lhs) = N_Selected_Component
1718 and then Has_Per_Object_Constraint (
1719 Entity (Selector_Name (Lhs)))
1720 then
1721 Lhs_Discr_Val :=
1722 Make_Selected_Component (Loc,
1723 Prefix => Prefix (Lhs),
1724 Selector_Name =>
1725 New_Copy (
1726 Get_Discriminant_Value (
1727 First_Discriminant (Lhs_Type),
1728 Lhs_Type,
1729 Stored_Constraint (Lhs_Type))));
1731 else
1732 Lhs_Discr_Val := New_Copy (
1733 Get_Discriminant_Value (
1734 First_Discriminant (Lhs_Type),
1735 Lhs_Type,
1736 Stored_Constraint (Lhs_Type)));
1738 end if;
1739 else
1740 -- It is not possible to infer the discriminant since
1741 -- the subtype is not constrained.
1743 return
1744 Make_Raise_Program_Error (Loc,
1745 Reason => PE_Unchecked_Union_Restriction);
1746 end if;
1748 -- Rhs of the composite equality
1750 if Is_Constrained (Rhs_Type) then
1751 if Nkind (Rhs) = N_Selected_Component
1752 and then Has_Per_Object_Constraint (
1753 Entity (Selector_Name (Rhs)))
1754 then
1755 Rhs_Discr_Val :=
1756 Make_Selected_Component (Loc,
1757 Prefix => Prefix (Rhs),
1758 Selector_Name =>
1759 New_Copy (
1760 Get_Discriminant_Value (
1761 First_Discriminant (Rhs_Type),
1762 Rhs_Type,
1763 Stored_Constraint (Rhs_Type))));
1765 else
1766 Rhs_Discr_Val := New_Copy (
1767 Get_Discriminant_Value (
1768 First_Discriminant (Rhs_Type),
1769 Rhs_Type,
1770 Stored_Constraint (Rhs_Type)));
1772 end if;
1773 else
1774 return
1775 Make_Raise_Program_Error (Loc,
1776 Reason => PE_Unchecked_Union_Restriction);
1777 end if;
1779 -- Call the TSS equality function with the inferred
1780 -- discriminant values.
1782 return
1783 Make_Function_Call (Loc,
1784 Name => New_Reference_To (Eq_Op, Loc),
1785 Parameter_Associations => New_List (
1786 Lhs,
1787 Rhs,
1788 Lhs_Discr_Val,
1789 Rhs_Discr_Val));
1790 end;
1791 end if;
1793 -- Shouldn't this be an else, we can't fall through
1794 -- the above IF, right???
1796 return
1797 Make_Function_Call (Loc,
1798 Name => New_Reference_To (Eq_Op, Loc),
1799 Parameter_Associations => New_List (Lhs, Rhs));
1800 end if;
1802 else
1803 return Expand_Record_Equality (Nod, Full_Type, Lhs, Rhs, Bodies);
1804 end if;
1806 else
1807 -- It can be a simple record or the full view of a scalar private
1809 return Make_Op_Eq (Loc, Left_Opnd => Lhs, Right_Opnd => Rhs);
1810 end if;
1811 end Expand_Composite_Equality;
1813 ------------------------------
1814 -- Expand_Concatenate_Other --
1815 ------------------------------
1817 -- Let n be the number of array operands to be concatenated, Base_Typ
1818 -- their base type, Ind_Typ their index type, and Arr_Typ the original
1819 -- array type to which the concatenantion operator applies, then the
1820 -- following subprogram is constructed:
1822 -- [function Cnn (S1 : Base_Typ; ...; Sn : Base_Typ) return Base_Typ is
1823 -- L : Ind_Typ;
1824 -- begin
1825 -- if S1'Length /= 0 then
1826 -- L := XXX; --> XXX = S1'First if Arr_Typ is unconstrained
1827 -- XXX = Arr_Typ'First otherwise
1828 -- elsif S2'Length /= 0 then
1829 -- L := YYY; --> YYY = S2'First if Arr_Typ is unconstrained
1830 -- YYY = Arr_Typ'First otherwise
1831 -- ...
1832 -- elsif Sn-1'Length /= 0 then
1833 -- L := ZZZ; --> ZZZ = Sn-1'First if Arr_Typ is unconstrained
1834 -- ZZZ = Arr_Typ'First otherwise
1835 -- else
1836 -- return Sn;
1837 -- end if;
1839 -- declare
1840 -- P : Ind_Typ;
1841 -- H : Ind_Typ :=
1842 -- Ind_Typ'Val ((((S1'Length - 1) + S2'Length) + ... + Sn'Length)
1843 -- + Ind_Typ'Pos (L));
1844 -- R : Base_Typ (L .. H);
1845 -- begin
1846 -- if S1'Length /= 0 then
1847 -- P := S1'First;
1848 -- loop
1849 -- R (L) := S1 (P);
1850 -- L := Ind_Typ'Succ (L);
1851 -- exit when P = S1'Last;
1852 -- P := Ind_Typ'Succ (P);
1853 -- end loop;
1854 -- end if;
1856 -- if S2'Length /= 0 then
1857 -- L := Ind_Typ'Succ (L);
1858 -- loop
1859 -- R (L) := S2 (P);
1860 -- L := Ind_Typ'Succ (L);
1861 -- exit when P = S2'Last;
1862 -- P := Ind_Typ'Succ (P);
1863 -- end loop;
1864 -- end if;
1866 -- ...
1868 -- if Sn'Length /= 0 then
1869 -- P := Sn'First;
1870 -- loop
1871 -- R (L) := Sn (P);
1872 -- L := Ind_Typ'Succ (L);
1873 -- exit when P = Sn'Last;
1874 -- P := Ind_Typ'Succ (P);
1875 -- end loop;
1876 -- end if;
1878 -- return R;
1879 -- end;
1880 -- end Cnn;]
1882 procedure Expand_Concatenate_Other (Cnode : Node_Id; Opnds : List_Id) is
1883 Loc : constant Source_Ptr := Sloc (Cnode);
1884 Nb_Opnds : constant Nat := List_Length (Opnds);
1886 Arr_Typ : constant Entity_Id := Etype (Entity (Cnode));
1887 Base_Typ : constant Entity_Id := Base_Type (Etype (Cnode));
1888 Ind_Typ : constant Entity_Id := Etype (First_Index (Base_Typ));
1890 Func_Id : Node_Id;
1891 Func_Spec : Node_Id;
1892 Param_Specs : List_Id;
1894 Func_Body : Node_Id;
1895 Func_Decls : List_Id;
1896 Func_Stmts : List_Id;
1898 L_Decl : Node_Id;
1900 If_Stmt : Node_Id;
1901 Elsif_List : List_Id;
1903 Declare_Block : Node_Id;
1904 Declare_Decls : List_Id;
1905 Declare_Stmts : List_Id;
1907 H_Decl : Node_Id;
1908 H_Init : Node_Id;
1909 P_Decl : Node_Id;
1910 R_Decl : Node_Id;
1911 R_Constr : Node_Id;
1912 R_Range : Node_Id;
1914 Params : List_Id;
1915 Operand : Node_Id;
1917 function Copy_Into_R_S (I : Nat; Last : Boolean) return List_Id;
1918 -- Builds the sequence of statement:
1919 -- P := Si'First;
1920 -- loop
1921 -- R (L) := Si (P);
1922 -- L := Ind_Typ'Succ (L);
1923 -- exit when P = Si'Last;
1924 -- P := Ind_Typ'Succ (P);
1925 -- end loop;
1927 -- where i is the input parameter I given.
1928 -- If the flag Last is true, the exit statement is emitted before
1929 -- incrementing the lower bound, to prevent the creation out of
1930 -- bound values.
1932 function Init_L (I : Nat) return Node_Id;
1933 -- Builds the statement:
1934 -- L := Arr_Typ'First; If Arr_Typ is constrained
1935 -- L := Si'First; otherwise (where I is the input param given)
1937 function H return Node_Id;
1938 -- Builds reference to identifier H
1940 function Ind_Val (E : Node_Id) return Node_Id;
1941 -- Builds expression Ind_Typ'Val (E);
1943 function L return Node_Id;
1944 -- Builds reference to identifier L
1946 function L_Pos return Node_Id;
1947 -- Builds expression Integer_Type'(Ind_Typ'Pos (L)). We qualify the
1948 -- expression to avoid universal_integer computations whenever possible,
1949 -- in the expression for the upper bound H.
1951 function L_Succ return Node_Id;
1952 -- Builds expression Ind_Typ'Succ (L)
1954 function One return Node_Id;
1955 -- Builds integer literal one
1957 function P return Node_Id;
1958 -- Builds reference to identifier P
1960 function P_Succ return Node_Id;
1961 -- Builds expression Ind_Typ'Succ (P)
1963 function R return Node_Id;
1964 -- Builds reference to identifier R
1966 function S (I : Nat) return Node_Id;
1967 -- Builds reference to identifier Si, where I is the value given
1969 function S_First (I : Nat) return Node_Id;
1970 -- Builds expression Si'First, where I is the value given
1972 function S_Last (I : Nat) return Node_Id;
1973 -- Builds expression Si'Last, where I is the value given
1975 function S_Length (I : Nat) return Node_Id;
1976 -- Builds expression Si'Length, where I is the value given
1978 function S_Length_Test (I : Nat) return Node_Id;
1979 -- Builds expression Si'Length /= 0, where I is the value given
1981 -------------------
1982 -- Copy_Into_R_S --
1983 -------------------
1985 function Copy_Into_R_S (I : Nat; Last : Boolean) return List_Id is
1986 Stmts : constant List_Id := New_List;
1987 P_Start : Node_Id;
1988 Loop_Stmt : Node_Id;
1989 R_Copy : Node_Id;
1990 Exit_Stmt : Node_Id;
1991 L_Inc : Node_Id;
1992 P_Inc : Node_Id;
1994 begin
1995 -- First construct the initializations
1997 P_Start := Make_Assignment_Statement (Loc,
1998 Name => P,
1999 Expression => S_First (I));
2000 Append_To (Stmts, P_Start);
2002 -- Then build the loop
2004 R_Copy := Make_Assignment_Statement (Loc,
2005 Name => Make_Indexed_Component (Loc,
2006 Prefix => R,
2007 Expressions => New_List (L)),
2008 Expression => Make_Indexed_Component (Loc,
2009 Prefix => S (I),
2010 Expressions => New_List (P)));
2012 L_Inc := Make_Assignment_Statement (Loc,
2013 Name => L,
2014 Expression => L_Succ);
2016 Exit_Stmt := Make_Exit_Statement (Loc,
2017 Condition => Make_Op_Eq (Loc, P, S_Last (I)));
2019 P_Inc := Make_Assignment_Statement (Loc,
2020 Name => P,
2021 Expression => P_Succ);
2023 if Last then
2024 Loop_Stmt :=
2025 Make_Implicit_Loop_Statement (Cnode,
2026 Statements => New_List (R_Copy, Exit_Stmt, L_Inc, P_Inc));
2027 else
2028 Loop_Stmt :=
2029 Make_Implicit_Loop_Statement (Cnode,
2030 Statements => New_List (R_Copy, L_Inc, Exit_Stmt, P_Inc));
2031 end if;
2033 Append_To (Stmts, Loop_Stmt);
2035 return Stmts;
2036 end Copy_Into_R_S;
2038 -------
2039 -- H --
2040 -------
2042 function H return Node_Id is
2043 begin
2044 return Make_Identifier (Loc, Name_uH);
2045 end H;
2047 -------------
2048 -- Ind_Val --
2049 -------------
2051 function Ind_Val (E : Node_Id) return Node_Id is
2052 begin
2053 return
2054 Make_Attribute_Reference (Loc,
2055 Prefix => New_Reference_To (Ind_Typ, Loc),
2056 Attribute_Name => Name_Val,
2057 Expressions => New_List (E));
2058 end Ind_Val;
2060 ------------
2061 -- Init_L --
2062 ------------
2064 function Init_L (I : Nat) return Node_Id is
2065 E : Node_Id;
2067 begin
2068 if Is_Constrained (Arr_Typ) then
2069 E := Make_Attribute_Reference (Loc,
2070 Prefix => New_Reference_To (Arr_Typ, Loc),
2071 Attribute_Name => Name_First);
2073 else
2074 E := S_First (I);
2075 end if;
2077 return Make_Assignment_Statement (Loc, Name => L, Expression => E);
2078 end Init_L;
2080 -------
2081 -- L --
2082 -------
2084 function L return Node_Id is
2085 begin
2086 return Make_Identifier (Loc, Name_uL);
2087 end L;
2089 -----------
2090 -- L_Pos --
2091 -----------
2093 function L_Pos return Node_Id is
2094 Target_Type : Entity_Id;
2096 begin
2097 -- If the index type is an enumeration type, the computation
2098 -- can be done in standard integer. Otherwise, choose a large
2099 -- enough integer type.
2101 if Is_Enumeration_Type (Ind_Typ)
2102 or else Root_Type (Ind_Typ) = Standard_Integer
2103 or else Root_Type (Ind_Typ) = Standard_Short_Integer
2104 or else Root_Type (Ind_Typ) = Standard_Short_Short_Integer
2105 then
2106 Target_Type := Standard_Integer;
2107 else
2108 Target_Type := Root_Type (Ind_Typ);
2109 end if;
2111 return
2112 Make_Qualified_Expression (Loc,
2113 Subtype_Mark => New_Reference_To (Target_Type, Loc),
2114 Expression =>
2115 Make_Attribute_Reference (Loc,
2116 Prefix => New_Reference_To (Ind_Typ, Loc),
2117 Attribute_Name => Name_Pos,
2118 Expressions => New_List (L)));
2119 end L_Pos;
2121 ------------
2122 -- L_Succ --
2123 ------------
2125 function L_Succ return Node_Id is
2126 begin
2127 return
2128 Make_Attribute_Reference (Loc,
2129 Prefix => New_Reference_To (Ind_Typ, Loc),
2130 Attribute_Name => Name_Succ,
2131 Expressions => New_List (L));
2132 end L_Succ;
2134 ---------
2135 -- One --
2136 ---------
2138 function One return Node_Id is
2139 begin
2140 return Make_Integer_Literal (Loc, 1);
2141 end One;
2143 -------
2144 -- P --
2145 -------
2147 function P return Node_Id is
2148 begin
2149 return Make_Identifier (Loc, Name_uP);
2150 end P;
2152 ------------
2153 -- P_Succ --
2154 ------------
2156 function P_Succ return Node_Id is
2157 begin
2158 return
2159 Make_Attribute_Reference (Loc,
2160 Prefix => New_Reference_To (Ind_Typ, Loc),
2161 Attribute_Name => Name_Succ,
2162 Expressions => New_List (P));
2163 end P_Succ;
2165 -------
2166 -- R --
2167 -------
2169 function R return Node_Id is
2170 begin
2171 return Make_Identifier (Loc, Name_uR);
2172 end R;
2174 -------
2175 -- S --
2176 -------
2178 function S (I : Nat) return Node_Id is
2179 begin
2180 return Make_Identifier (Loc, New_External_Name ('S', I));
2181 end S;
2183 -------------
2184 -- S_First --
2185 -------------
2187 function S_First (I : Nat) return Node_Id is
2188 begin
2189 return Make_Attribute_Reference (Loc,
2190 Prefix => S (I),
2191 Attribute_Name => Name_First);
2192 end S_First;
2194 ------------
2195 -- S_Last --
2196 ------------
2198 function S_Last (I : Nat) return Node_Id is
2199 begin
2200 return Make_Attribute_Reference (Loc,
2201 Prefix => S (I),
2202 Attribute_Name => Name_Last);
2203 end S_Last;
2205 --------------
2206 -- S_Length --
2207 --------------
2209 function S_Length (I : Nat) return Node_Id is
2210 begin
2211 return Make_Attribute_Reference (Loc,
2212 Prefix => S (I),
2213 Attribute_Name => Name_Length);
2214 end S_Length;
2216 -------------------
2217 -- S_Length_Test --
2218 -------------------
2220 function S_Length_Test (I : Nat) return Node_Id is
2221 begin
2222 return
2223 Make_Op_Ne (Loc,
2224 Left_Opnd => S_Length (I),
2225 Right_Opnd => Make_Integer_Literal (Loc, 0));
2226 end S_Length_Test;
2228 -- Start of processing for Expand_Concatenate_Other
2230 begin
2231 -- Construct the parameter specs and the overall function spec
2233 Param_Specs := New_List;
2234 for I in 1 .. Nb_Opnds loop
2235 Append_To
2236 (Param_Specs,
2237 Make_Parameter_Specification (Loc,
2238 Defining_Identifier =>
2239 Make_Defining_Identifier (Loc, New_External_Name ('S', I)),
2240 Parameter_Type => New_Reference_To (Base_Typ, Loc)));
2241 end loop;
2243 Func_Id := Make_Defining_Identifier (Loc, New_Internal_Name ('C'));
2244 Func_Spec :=
2245 Make_Function_Specification (Loc,
2246 Defining_Unit_Name => Func_Id,
2247 Parameter_Specifications => Param_Specs,
2248 Result_Definition => New_Reference_To (Base_Typ, Loc));
2250 -- Construct L's object declaration
2252 L_Decl :=
2253 Make_Object_Declaration (Loc,
2254 Defining_Identifier => Make_Defining_Identifier (Loc, Name_uL),
2255 Object_Definition => New_Reference_To (Ind_Typ, Loc));
2257 Func_Decls := New_List (L_Decl);
2259 -- Construct the if-then-elsif statements
2261 Elsif_List := New_List;
2262 for I in 2 .. Nb_Opnds - 1 loop
2263 Append_To (Elsif_List, Make_Elsif_Part (Loc,
2264 Condition => S_Length_Test (I),
2265 Then_Statements => New_List (Init_L (I))));
2266 end loop;
2268 If_Stmt :=
2269 Make_Implicit_If_Statement (Cnode,
2270 Condition => S_Length_Test (1),
2271 Then_Statements => New_List (Init_L (1)),
2272 Elsif_Parts => Elsif_List,
2273 Else_Statements => New_List (Make_Return_Statement (Loc,
2274 Expression => S (Nb_Opnds))));
2276 -- Construct the declaration for H
2278 P_Decl :=
2279 Make_Object_Declaration (Loc,
2280 Defining_Identifier => Make_Defining_Identifier (Loc, Name_uP),
2281 Object_Definition => New_Reference_To (Ind_Typ, Loc));
2283 H_Init := Make_Op_Subtract (Loc, S_Length (1), One);
2284 for I in 2 .. Nb_Opnds loop
2285 H_Init := Make_Op_Add (Loc, H_Init, S_Length (I));
2286 end loop;
2287 H_Init := Ind_Val (Make_Op_Add (Loc, H_Init, L_Pos));
2289 H_Decl :=
2290 Make_Object_Declaration (Loc,
2291 Defining_Identifier => Make_Defining_Identifier (Loc, Name_uH),
2292 Object_Definition => New_Reference_To (Ind_Typ, Loc),
2293 Expression => H_Init);
2295 -- Construct the declaration for R
2297 R_Range := Make_Range (Loc, Low_Bound => L, High_Bound => H);
2298 R_Constr :=
2299 Make_Index_Or_Discriminant_Constraint (Loc,
2300 Constraints => New_List (R_Range));
2302 R_Decl :=
2303 Make_Object_Declaration (Loc,
2304 Defining_Identifier => Make_Defining_Identifier (Loc, Name_uR),
2305 Object_Definition =>
2306 Make_Subtype_Indication (Loc,
2307 Subtype_Mark => New_Reference_To (Base_Typ, Loc),
2308 Constraint => R_Constr));
2310 -- Construct the declarations for the declare block
2312 Declare_Decls := New_List (P_Decl, H_Decl, R_Decl);
2314 -- Construct list of statements for the declare block
2316 Declare_Stmts := New_List;
2317 for I in 1 .. Nb_Opnds loop
2318 Append_To (Declare_Stmts,
2319 Make_Implicit_If_Statement (Cnode,
2320 Condition => S_Length_Test (I),
2321 Then_Statements => Copy_Into_R_S (I, I = Nb_Opnds)));
2322 end loop;
2324 Append_To (Declare_Stmts, Make_Return_Statement (Loc, Expression => R));
2326 -- Construct the declare block
2328 Declare_Block := Make_Block_Statement (Loc,
2329 Declarations => Declare_Decls,
2330 Handled_Statement_Sequence =>
2331 Make_Handled_Sequence_Of_Statements (Loc, Declare_Stmts));
2333 -- Construct the list of function statements
2335 Func_Stmts := New_List (If_Stmt, Declare_Block);
2337 -- Construct the function body
2339 Func_Body :=
2340 Make_Subprogram_Body (Loc,
2341 Specification => Func_Spec,
2342 Declarations => Func_Decls,
2343 Handled_Statement_Sequence =>
2344 Make_Handled_Sequence_Of_Statements (Loc, Func_Stmts));
2346 -- Insert the newly generated function in the code. This is analyzed
2347 -- with all checks off, since we have completed all the checks.
2349 -- Note that this does *not* fix the array concatenation bug when the
2350 -- low bound is Integer'first sibce that bug comes from the pointer
2351 -- dereferencing an unconstrained array. An there we need a constraint
2352 -- check to make sure the length of the concatenated array is ok. ???
2354 Insert_Action (Cnode, Func_Body, Suppress => All_Checks);
2356 -- Construct list of arguments for the function call
2358 Params := New_List;
2359 Operand := First (Opnds);
2360 for I in 1 .. Nb_Opnds loop
2361 Append_To (Params, Relocate_Node (Operand));
2362 Next (Operand);
2363 end loop;
2365 -- Insert the function call
2367 Rewrite
2368 (Cnode,
2369 Make_Function_Call (Loc, New_Reference_To (Func_Id, Loc), Params));
2371 Analyze_And_Resolve (Cnode, Base_Typ);
2372 Set_Is_Inlined (Func_Id);
2373 end Expand_Concatenate_Other;
2375 -------------------------------
2376 -- Expand_Concatenate_String --
2377 -------------------------------
2379 procedure Expand_Concatenate_String (Cnode : Node_Id; Opnds : List_Id) is
2380 Loc : constant Source_Ptr := Sloc (Cnode);
2381 Opnd1 : constant Node_Id := First (Opnds);
2382 Opnd2 : constant Node_Id := Next (Opnd1);
2383 Typ1 : constant Entity_Id := Base_Type (Etype (Opnd1));
2384 Typ2 : constant Entity_Id := Base_Type (Etype (Opnd2));
2386 R : RE_Id;
2387 -- RE_Id value for function to be called
2389 begin
2390 -- In all cases, we build a call to a routine giving the list of
2391 -- arguments as the parameter list to the routine.
2393 case List_Length (Opnds) is
2394 when 2 =>
2395 if Typ1 = Standard_Character then
2396 if Typ2 = Standard_Character then
2397 R := RE_Str_Concat_CC;
2399 else
2400 pragma Assert (Typ2 = Standard_String);
2401 R := RE_Str_Concat_CS;
2402 end if;
2404 elsif Typ1 = Standard_String then
2405 if Typ2 = Standard_Character then
2406 R := RE_Str_Concat_SC;
2408 else
2409 pragma Assert (Typ2 = Standard_String);
2410 R := RE_Str_Concat;
2411 end if;
2413 -- If we have anything other than Standard_Character or
2414 -- Standard_String, then we must have had a serious error
2415 -- earlier, so we just abandon the attempt at expansion.
2417 else
2418 pragma Assert (Serious_Errors_Detected > 0);
2419 return;
2420 end if;
2422 when 3 =>
2423 R := RE_Str_Concat_3;
2425 when 4 =>
2426 R := RE_Str_Concat_4;
2428 when 5 =>
2429 R := RE_Str_Concat_5;
2431 when others =>
2432 R := RE_Null;
2433 raise Program_Error;
2434 end case;
2436 -- Now generate the appropriate call
2438 Rewrite (Cnode,
2439 Make_Function_Call (Sloc (Cnode),
2440 Name => New_Occurrence_Of (RTE (R), Loc),
2441 Parameter_Associations => Opnds));
2443 Analyze_And_Resolve (Cnode, Standard_String);
2445 exception
2446 when RE_Not_Available =>
2447 return;
2448 end Expand_Concatenate_String;
2450 ------------------------
2451 -- Expand_N_Allocator --
2452 ------------------------
2454 procedure Expand_N_Allocator (N : Node_Id) is
2455 PtrT : constant Entity_Id := Etype (N);
2456 Dtyp : constant Entity_Id := Designated_Type (PtrT);
2457 Desig : Entity_Id;
2458 Loc : constant Source_Ptr := Sloc (N);
2459 Temp : Entity_Id;
2460 Node : Node_Id;
2462 begin
2463 -- RM E.2.3(22). We enforce that the expected type of an allocator
2464 -- shall not be a remote access-to-class-wide-limited-private type
2466 -- Why is this being done at expansion time, seems clearly wrong ???
2468 Validate_Remote_Access_To_Class_Wide_Type (N);
2470 -- Set the Storage Pool
2472 Set_Storage_Pool (N, Associated_Storage_Pool (Root_Type (PtrT)));
2474 if Present (Storage_Pool (N)) then
2475 if Is_RTE (Storage_Pool (N), RE_SS_Pool) then
2476 if not Java_VM then
2477 Set_Procedure_To_Call (N, RTE (RE_SS_Allocate));
2478 end if;
2480 elsif Is_Class_Wide_Type (Etype (Storage_Pool (N))) then
2481 Set_Procedure_To_Call (N, RTE (RE_Allocate_Any));
2483 else
2484 Set_Procedure_To_Call (N,
2485 Find_Prim_Op (Etype (Storage_Pool (N)), Name_Allocate));
2486 end if;
2487 end if;
2489 -- Under certain circumstances we can replace an allocator by an
2490 -- access to statically allocated storage. The conditions, as noted
2491 -- in AARM 3.10 (10c) are as follows:
2493 -- Size and initial value is known at compile time
2494 -- Access type is access-to-constant
2496 -- The allocator is not part of a constraint on a record component,
2497 -- because in that case the inserted actions are delayed until the
2498 -- record declaration is fully analyzed, which is too late for the
2499 -- analysis of the rewritten allocator.
2501 if Is_Access_Constant (PtrT)
2502 and then Nkind (Expression (N)) = N_Qualified_Expression
2503 and then Compile_Time_Known_Value (Expression (Expression (N)))
2504 and then Size_Known_At_Compile_Time (Etype (Expression
2505 (Expression (N))))
2506 and then not Is_Record_Type (Current_Scope)
2507 then
2508 -- Here we can do the optimization. For the allocator
2510 -- new x'(y)
2512 -- We insert an object declaration
2514 -- Tnn : aliased x := y;
2516 -- and replace the allocator by Tnn'Unrestricted_Access.
2517 -- Tnn is marked as requiring static allocation.
2519 Temp :=
2520 Make_Defining_Identifier (Loc, New_Internal_Name ('T'));
2522 Desig := Subtype_Mark (Expression (N));
2524 -- If context is constrained, use constrained subtype directly,
2525 -- so that the constant is not labelled as having a nomimally
2526 -- unconstrained subtype.
2528 if Entity (Desig) = Base_Type (Dtyp) then
2529 Desig := New_Occurrence_Of (Dtyp, Loc);
2530 end if;
2532 Insert_Action (N,
2533 Make_Object_Declaration (Loc,
2534 Defining_Identifier => Temp,
2535 Aliased_Present => True,
2536 Constant_Present => Is_Access_Constant (PtrT),
2537 Object_Definition => Desig,
2538 Expression => Expression (Expression (N))));
2540 Rewrite (N,
2541 Make_Attribute_Reference (Loc,
2542 Prefix => New_Occurrence_Of (Temp, Loc),
2543 Attribute_Name => Name_Unrestricted_Access));
2545 Analyze_And_Resolve (N, PtrT);
2547 -- We set the variable as statically allocated, since we don't
2548 -- want it going on the stack of the current procedure!
2550 Set_Is_Statically_Allocated (Temp);
2551 return;
2552 end if;
2554 -- Handle case of qualified expression (other than optimization above)
2556 if Nkind (Expression (N)) = N_Qualified_Expression then
2557 Expand_Allocator_Expression (N);
2559 -- If the allocator is for a type which requires initialization, and
2560 -- there is no initial value (i.e. operand is a subtype indication
2561 -- rather than a qualifed expression), then we must generate a call
2562 -- to the initialization routine. This is done using an expression
2563 -- actions node:
2565 -- [Pnnn : constant ptr_T := new (T); Init (Pnnn.all,...); Pnnn]
2567 -- Here ptr_T is the pointer type for the allocator, and T is the
2568 -- subtype of the allocator. A special case arises if the designated
2569 -- type of the access type is a task or contains tasks. In this case
2570 -- the call to Init (Temp.all ...) is replaced by code that ensures
2571 -- that tasks get activated (see Exp_Ch9.Build_Task_Allocate_Block
2572 -- for details). In addition, if the type T is a task T, then the
2573 -- first argument to Init must be converted to the task record type.
2575 else
2576 declare
2577 T : constant Entity_Id := Entity (Expression (N));
2578 Init : Entity_Id;
2579 Arg1 : Node_Id;
2580 Args : List_Id;
2581 Decls : List_Id;
2582 Decl : Node_Id;
2583 Discr : Elmt_Id;
2584 Flist : Node_Id;
2585 Temp_Decl : Node_Id;
2586 Temp_Type : Entity_Id;
2587 Attach_Level : Uint;
2589 begin
2590 if No_Initialization (N) then
2591 null;
2593 -- Case of no initialization procedure present
2595 elsif not Has_Non_Null_Base_Init_Proc (T) then
2597 -- Case of simple initialization required
2599 if Needs_Simple_Initialization (T) then
2600 Rewrite (Expression (N),
2601 Make_Qualified_Expression (Loc,
2602 Subtype_Mark => New_Occurrence_Of (T, Loc),
2603 Expression => Get_Simple_Init_Val (T, Loc)));
2605 Analyze_And_Resolve (Expression (Expression (N)), T);
2606 Analyze_And_Resolve (Expression (N), T);
2607 Set_Paren_Count (Expression (Expression (N)), 1);
2608 Expand_N_Allocator (N);
2610 -- No initialization required
2612 else
2613 null;
2614 end if;
2616 -- Case of initialization procedure present, must be called
2618 else
2619 Init := Base_Init_Proc (T);
2620 Node := N;
2621 Temp :=
2622 Make_Defining_Identifier (Loc, New_Internal_Name ('P'));
2624 -- Construct argument list for the initialization routine call
2625 -- The CPP constructor needs the address directly
2627 if Is_CPP_Class (T) then
2628 Arg1 := New_Reference_To (Temp, Loc);
2629 Temp_Type := T;
2631 else
2632 Arg1 :=
2633 Make_Explicit_Dereference (Loc,
2634 Prefix => New_Reference_To (Temp, Loc));
2635 Set_Assignment_OK (Arg1);
2636 Temp_Type := PtrT;
2638 -- The initialization procedure expects a specific type.
2639 -- if the context is access to class wide, indicate that
2640 -- the object being allocated has the right specific type.
2642 if Is_Class_Wide_Type (Dtyp) then
2643 Arg1 := Unchecked_Convert_To (T, Arg1);
2644 end if;
2645 end if;
2647 -- If designated type is a concurrent type or if it is a
2648 -- private type whose definition is a concurrent type,
2649 -- the first argument in the Init routine has to be
2650 -- unchecked conversion to the corresponding record type.
2651 -- If the designated type is a derived type, we also
2652 -- convert the argument to its root type.
2654 if Is_Concurrent_Type (T) then
2655 Arg1 :=
2656 Unchecked_Convert_To (Corresponding_Record_Type (T), Arg1);
2658 elsif Is_Private_Type (T)
2659 and then Present (Full_View (T))
2660 and then Is_Concurrent_Type (Full_View (T))
2661 then
2662 Arg1 :=
2663 Unchecked_Convert_To
2664 (Corresponding_Record_Type (Full_View (T)), Arg1);
2666 elsif Etype (First_Formal (Init)) /= Base_Type (T) then
2668 declare
2669 Ftyp : constant Entity_Id := Etype (First_Formal (Init));
2671 begin
2672 Arg1 := OK_Convert_To (Etype (Ftyp), Arg1);
2673 Set_Etype (Arg1, Ftyp);
2674 end;
2675 end if;
2677 Args := New_List (Arg1);
2679 -- For the task case, pass the Master_Id of the access type
2680 -- as the value of the _Master parameter, and _Chain as the
2681 -- value of the _Chain parameter (_Chain will be defined as
2682 -- part of the generated code for the allocator).
2684 if Has_Task (T) then
2685 if No (Master_Id (Base_Type (PtrT))) then
2687 -- The designated type was an incomplete type, and
2688 -- the access type did not get expanded. Salvage
2689 -- it now.
2691 Expand_N_Full_Type_Declaration
2692 (Parent (Base_Type (PtrT)));
2693 end if;
2695 -- If the context of the allocator is a declaration or
2696 -- an assignment, we can generate a meaningful image for
2697 -- it, even though subsequent assignments might remove
2698 -- the connection between task and entity. We build this
2699 -- image when the left-hand side is a simple variable,
2700 -- a simple indexed assignment or a simple selected
2701 -- component.
2703 if Nkind (Parent (N)) = N_Assignment_Statement then
2704 declare
2705 Nam : constant Node_Id := Name (Parent (N));
2707 begin
2708 if Is_Entity_Name (Nam) then
2709 Decls :=
2710 Build_Task_Image_Decls (
2711 Loc,
2712 New_Occurrence_Of
2713 (Entity (Nam), Sloc (Nam)), T);
2715 elsif (Nkind (Nam) = N_Indexed_Component
2716 or else Nkind (Nam) = N_Selected_Component)
2717 and then Is_Entity_Name (Prefix (Nam))
2718 then
2719 Decls :=
2720 Build_Task_Image_Decls
2721 (Loc, Nam, Etype (Prefix (Nam)));
2722 else
2723 Decls := Build_Task_Image_Decls (Loc, T, T);
2724 end if;
2725 end;
2727 elsif Nkind (Parent (N)) = N_Object_Declaration then
2728 Decls :=
2729 Build_Task_Image_Decls (
2730 Loc, Defining_Identifier (Parent (N)), T);
2732 else
2733 Decls := Build_Task_Image_Decls (Loc, T, T);
2734 end if;
2736 Append_To (Args,
2737 New_Reference_To
2738 (Master_Id (Base_Type (Root_Type (PtrT))), Loc));
2739 Append_To (Args, Make_Identifier (Loc, Name_uChain));
2741 Decl := Last (Decls);
2742 Append_To (Args,
2743 New_Occurrence_Of (Defining_Identifier (Decl), Loc));
2745 -- Has_Task is false, Decls not used
2747 else
2748 Decls := No_List;
2749 end if;
2751 -- Add discriminants if discriminated type
2753 if Has_Discriminants (T) then
2754 Discr := First_Elmt (Discriminant_Constraint (T));
2756 while Present (Discr) loop
2757 Append (New_Copy_Tree (Elists.Node (Discr)), Args);
2758 Next_Elmt (Discr);
2759 end loop;
2761 elsif Is_Private_Type (T)
2762 and then Present (Full_View (T))
2763 and then Has_Discriminants (Full_View (T))
2764 then
2765 Discr :=
2766 First_Elmt (Discriminant_Constraint (Full_View (T)));
2768 while Present (Discr) loop
2769 Append (New_Copy_Tree (Elists.Node (Discr)), Args);
2770 Next_Elmt (Discr);
2771 end loop;
2772 end if;
2774 -- We set the allocator as analyzed so that when we analyze the
2775 -- expression actions node, we do not get an unwanted recursive
2776 -- expansion of the allocator expression.
2778 Set_Analyzed (N, True);
2779 Node := Relocate_Node (N);
2781 -- Here is the transformation:
2782 -- input: new T
2783 -- output: Temp : constant ptr_T := new T;
2784 -- Init (Temp.all, ...);
2785 -- <CTRL> Attach_To_Final_List (Finalizable (Temp.all));
2786 -- <CTRL> Initialize (Finalizable (Temp.all));
2788 -- Here ptr_T is the pointer type for the allocator, and T
2789 -- is the subtype of the allocator.
2791 Temp_Decl :=
2792 Make_Object_Declaration (Loc,
2793 Defining_Identifier => Temp,
2794 Constant_Present => True,
2795 Object_Definition => New_Reference_To (Temp_Type, Loc),
2796 Expression => Node);
2798 Set_Assignment_OK (Temp_Decl);
2800 if Is_CPP_Class (T) then
2801 Set_Aliased_Present (Temp_Decl);
2802 end if;
2804 Insert_Action (N, Temp_Decl, Suppress => All_Checks);
2806 -- If the designated type is task type or contains tasks,
2807 -- Create block to activate created tasks, and insert
2808 -- declaration for Task_Image variable ahead of call.
2810 if Has_Task (T) then
2811 declare
2812 L : constant List_Id := New_List;
2813 Blk : Node_Id;
2815 begin
2816 Build_Task_Allocate_Block (L, Node, Args);
2817 Blk := Last (L);
2819 Insert_List_Before (First (Declarations (Blk)), Decls);
2820 Insert_Actions (N, L);
2821 end;
2823 else
2824 Insert_Action (N,
2825 Make_Procedure_Call_Statement (Loc,
2826 Name => New_Reference_To (Init, Loc),
2827 Parameter_Associations => Args));
2828 end if;
2830 if Controlled_Type (T) then
2831 Flist := Get_Allocator_Final_List (N, Base_Type (T), PtrT);
2832 if Ekind (PtrT) = E_Anonymous_Access_Type then
2833 Attach_Level := Uint_1;
2834 else
2835 Attach_Level := Uint_2;
2836 end if;
2837 Insert_Actions (N,
2838 Make_Init_Call (
2839 Ref => New_Copy_Tree (Arg1),
2840 Typ => T,
2841 Flist_Ref => Flist,
2842 With_Attach => Make_Integer_Literal (Loc,
2843 Attach_Level)));
2844 end if;
2846 if Is_CPP_Class (T) then
2847 Rewrite (N,
2848 Make_Attribute_Reference (Loc,
2849 Prefix => New_Reference_To (Temp, Loc),
2850 Attribute_Name => Name_Unchecked_Access));
2851 else
2852 Rewrite (N, New_Reference_To (Temp, Loc));
2853 end if;
2855 Analyze_And_Resolve (N, PtrT);
2856 end if;
2857 end;
2858 end if;
2860 exception
2861 when RE_Not_Available =>
2862 return;
2863 end Expand_N_Allocator;
2865 -----------------------
2866 -- Expand_N_And_Then --
2867 -----------------------
2869 -- Expand into conditional expression if Actions present, and also
2870 -- deal with optimizing case of arguments being True or False.
2872 procedure Expand_N_And_Then (N : Node_Id) is
2873 Loc : constant Source_Ptr := Sloc (N);
2874 Typ : constant Entity_Id := Etype (N);
2875 Left : constant Node_Id := Left_Opnd (N);
2876 Right : constant Node_Id := Right_Opnd (N);
2877 Actlist : List_Id;
2879 begin
2880 -- Deal with non-standard booleans
2882 if Is_Boolean_Type (Typ) then
2883 Adjust_Condition (Left);
2884 Adjust_Condition (Right);
2885 Set_Etype (N, Standard_Boolean);
2886 end if;
2888 -- Check for cases of left argument is True or False
2890 if Nkind (Left) = N_Identifier then
2892 -- If left argument is True, change (True and then Right) to Right.
2893 -- Any actions associated with Right will be executed unconditionally
2894 -- and can thus be inserted into the tree unconditionally.
2896 if Entity (Left) = Standard_True then
2897 if Present (Actions (N)) then
2898 Insert_Actions (N, Actions (N));
2899 end if;
2901 Rewrite (N, Right);
2902 Adjust_Result_Type (N, Typ);
2903 return;
2905 -- If left argument is False, change (False and then Right) to
2906 -- False. In this case we can forget the actions associated with
2907 -- Right, since they will never be executed.
2909 elsif Entity (Left) = Standard_False then
2910 Kill_Dead_Code (Right);
2911 Kill_Dead_Code (Actions (N));
2912 Rewrite (N, New_Occurrence_Of (Standard_False, Loc));
2913 Adjust_Result_Type (N, Typ);
2914 return;
2915 end if;
2916 end if;
2918 -- If Actions are present, we expand
2920 -- left and then right
2922 -- into
2924 -- if left then right else false end
2926 -- with the actions becoming the Then_Actions of the conditional
2927 -- expression. This conditional expression is then further expanded
2928 -- (and will eventually disappear)
2930 if Present (Actions (N)) then
2931 Actlist := Actions (N);
2932 Rewrite (N,
2933 Make_Conditional_Expression (Loc,
2934 Expressions => New_List (
2935 Left,
2936 Right,
2937 New_Occurrence_Of (Standard_False, Loc))));
2939 Set_Then_Actions (N, Actlist);
2940 Analyze_And_Resolve (N, Standard_Boolean);
2941 Adjust_Result_Type (N, Typ);
2942 return;
2943 end if;
2945 -- No actions present, check for cases of right argument True/False
2947 if Nkind (Right) = N_Identifier then
2949 -- Change (Left and then True) to Left. Note that we know there
2950 -- are no actions associated with the True operand, since we
2951 -- just checked for this case above.
2953 if Entity (Right) = Standard_True then
2954 Rewrite (N, Left);
2956 -- Change (Left and then False) to False, making sure to preserve
2957 -- any side effects associated with the Left operand.
2959 elsif Entity (Right) = Standard_False then
2960 Remove_Side_Effects (Left);
2961 Rewrite
2962 (N, New_Occurrence_Of (Standard_False, Loc));
2963 end if;
2964 end if;
2966 Adjust_Result_Type (N, Typ);
2967 end Expand_N_And_Then;
2969 -------------------------------------
2970 -- Expand_N_Conditional_Expression --
2971 -------------------------------------
2973 -- Expand into expression actions if then/else actions present
2975 procedure Expand_N_Conditional_Expression (N : Node_Id) is
2976 Loc : constant Source_Ptr := Sloc (N);
2977 Cond : constant Node_Id := First (Expressions (N));
2978 Thenx : constant Node_Id := Next (Cond);
2979 Elsex : constant Node_Id := Next (Thenx);
2980 Typ : constant Entity_Id := Etype (N);
2981 Cnn : Entity_Id;
2982 New_If : Node_Id;
2984 begin
2985 -- If either then or else actions are present, then given:
2987 -- if cond then then-expr else else-expr end
2989 -- we insert the following sequence of actions (using Insert_Actions):
2991 -- Cnn : typ;
2992 -- if cond then
2993 -- <<then actions>>
2994 -- Cnn := then-expr;
2995 -- else
2996 -- <<else actions>>
2997 -- Cnn := else-expr
2998 -- end if;
3000 -- and replace the conditional expression by a reference to Cnn
3002 if Present (Then_Actions (N)) or else Present (Else_Actions (N)) then
3003 Cnn := Make_Defining_Identifier (Loc, New_Internal_Name ('C'));
3005 New_If :=
3006 Make_Implicit_If_Statement (N,
3007 Condition => Relocate_Node (Cond),
3009 Then_Statements => New_List (
3010 Make_Assignment_Statement (Sloc (Thenx),
3011 Name => New_Occurrence_Of (Cnn, Sloc (Thenx)),
3012 Expression => Relocate_Node (Thenx))),
3014 Else_Statements => New_List (
3015 Make_Assignment_Statement (Sloc (Elsex),
3016 Name => New_Occurrence_Of (Cnn, Sloc (Elsex)),
3017 Expression => Relocate_Node (Elsex))));
3019 Set_Assignment_OK (Name (First (Then_Statements (New_If))));
3020 Set_Assignment_OK (Name (First (Else_Statements (New_If))));
3022 if Present (Then_Actions (N)) then
3023 Insert_List_Before
3024 (First (Then_Statements (New_If)), Then_Actions (N));
3025 end if;
3027 if Present (Else_Actions (N)) then
3028 Insert_List_Before
3029 (First (Else_Statements (New_If)), Else_Actions (N));
3030 end if;
3032 Rewrite (N, New_Occurrence_Of (Cnn, Loc));
3034 Insert_Action (N,
3035 Make_Object_Declaration (Loc,
3036 Defining_Identifier => Cnn,
3037 Object_Definition => New_Occurrence_Of (Typ, Loc)));
3039 Insert_Action (N, New_If);
3040 Analyze_And_Resolve (N, Typ);
3041 end if;
3042 end Expand_N_Conditional_Expression;
3044 -----------------------------------
3045 -- Expand_N_Explicit_Dereference --
3046 -----------------------------------
3048 procedure Expand_N_Explicit_Dereference (N : Node_Id) is
3049 begin
3050 -- The only processing required is an insertion of an explicit
3051 -- dereference call for the checked storage pool case.
3053 Insert_Dereference_Action (Prefix (N));
3054 end Expand_N_Explicit_Dereference;
3056 -----------------
3057 -- Expand_N_In --
3058 -----------------
3060 procedure Expand_N_In (N : Node_Id) is
3061 Loc : constant Source_Ptr := Sloc (N);
3062 Rtyp : constant Entity_Id := Etype (N);
3063 Lop : constant Node_Id := Left_Opnd (N);
3064 Rop : constant Node_Id := Right_Opnd (N);
3065 Static : constant Boolean := Is_OK_Static_Expression (N);
3067 procedure Substitute_Valid_Check;
3068 -- Replaces node N by Lop'Valid. This is done when we have an explicit
3069 -- test for the left operand being in range of its subtype.
3071 ----------------------------
3072 -- Substitute_Valid_Check --
3073 ----------------------------
3075 procedure Substitute_Valid_Check is
3076 begin
3077 Rewrite (N,
3078 Make_Attribute_Reference (Loc,
3079 Prefix => Relocate_Node (Lop),
3080 Attribute_Name => Name_Valid));
3082 Analyze_And_Resolve (N, Rtyp);
3084 Error_Msg_N ("?explicit membership test may be optimized away", N);
3085 Error_Msg_N ("\?use ''Valid attribute instead", N);
3086 return;
3087 end Substitute_Valid_Check;
3089 -- Start of processing for Expand_N_In
3091 begin
3092 -- Check case of explicit test for an expression in range of its
3093 -- subtype. This is suspicious usage and we replace it with a 'Valid
3094 -- test and give a warning.
3096 if Is_Scalar_Type (Etype (Lop))
3097 and then Nkind (Rop) in N_Has_Entity
3098 and then Etype (Lop) = Entity (Rop)
3099 and then Comes_From_Source (N)
3100 then
3101 Substitute_Valid_Check;
3102 return;
3103 end if;
3105 -- Case of explicit range
3107 if Nkind (Rop) = N_Range then
3108 declare
3109 Lo : constant Node_Id := Low_Bound (Rop);
3110 Hi : constant Node_Id := High_Bound (Rop);
3112 Lo_Orig : constant Node_Id := Original_Node (Lo);
3113 Hi_Orig : constant Node_Id := Original_Node (Hi);
3115 Lcheck : constant Compare_Result := Compile_Time_Compare (Lop, Lo);
3116 Ucheck : constant Compare_Result := Compile_Time_Compare (Lop, Hi);
3118 begin
3119 -- If test is explicit x'first .. x'last, replace by valid check
3121 if Is_Scalar_Type (Etype (Lop))
3122 and then Nkind (Lo_Orig) = N_Attribute_Reference
3123 and then Attribute_Name (Lo_Orig) = Name_First
3124 and then Nkind (Prefix (Lo_Orig)) in N_Has_Entity
3125 and then Entity (Prefix (Lo_Orig)) = Etype (Lop)
3126 and then Nkind (Hi_Orig) = N_Attribute_Reference
3127 and then Attribute_Name (Hi_Orig) = Name_Last
3128 and then Nkind (Prefix (Hi_Orig)) in N_Has_Entity
3129 and then Entity (Prefix (Hi_Orig)) = Etype (Lop)
3130 and then Comes_From_Source (N)
3131 then
3132 Substitute_Valid_Check;
3133 return;
3134 end if;
3136 -- If we have an explicit range, do a bit of optimization based
3137 -- on range analysis (we may be able to kill one or both checks).
3139 -- If either check is known to fail, replace result by False since
3140 -- the other check does not matter. Preserve the static flag for
3141 -- legality checks, because we are constant-folding beyond RM 4.9.
3143 if Lcheck = LT or else Ucheck = GT then
3144 Rewrite (N,
3145 New_Reference_To (Standard_False, Loc));
3146 Analyze_And_Resolve (N, Rtyp);
3147 Set_Is_Static_Expression (N, Static);
3148 return;
3150 -- If both checks are known to succeed, replace result
3151 -- by True, since we know we are in range.
3153 elsif Lcheck in Compare_GE and then Ucheck in Compare_LE then
3154 Rewrite (N,
3155 New_Reference_To (Standard_True, Loc));
3156 Analyze_And_Resolve (N, Rtyp);
3157 Set_Is_Static_Expression (N, Static);
3158 return;
3160 -- If lower bound check succeeds and upper bound check is
3161 -- not known to succeed or fail, then replace the range check
3162 -- with a comparison against the upper bound.
3164 elsif Lcheck in Compare_GE then
3165 Rewrite (N,
3166 Make_Op_Le (Loc,
3167 Left_Opnd => Lop,
3168 Right_Opnd => High_Bound (Rop)));
3169 Analyze_And_Resolve (N, Rtyp);
3170 return;
3172 -- If upper bound check succeeds and lower bound check is
3173 -- not known to succeed or fail, then replace the range check
3174 -- with a comparison against the lower bound.
3176 elsif Ucheck in Compare_LE then
3177 Rewrite (N,
3178 Make_Op_Ge (Loc,
3179 Left_Opnd => Lop,
3180 Right_Opnd => Low_Bound (Rop)));
3181 Analyze_And_Resolve (N, Rtyp);
3182 return;
3183 end if;
3184 end;
3186 -- For all other cases of an explicit range, nothing to be done
3188 return;
3190 -- Here right operand is a subtype mark
3192 else
3193 declare
3194 Typ : Entity_Id := Etype (Rop);
3195 Is_Acc : constant Boolean := Is_Access_Type (Typ);
3196 Obj : Node_Id := Lop;
3197 Cond : Node_Id := Empty;
3199 begin
3200 Remove_Side_Effects (Obj);
3202 -- For tagged type, do tagged membership operation
3204 if Is_Tagged_Type (Typ) then
3206 -- No expansion will be performed when Java_VM, as the
3207 -- JVM back end will handle the membership tests directly
3208 -- (tags are not explicitly represented in Java objects,
3209 -- so the normal tagged membership expansion is not what
3210 -- we want).
3212 if not Java_VM then
3213 Rewrite (N, Tagged_Membership (N));
3214 Analyze_And_Resolve (N, Rtyp);
3215 end if;
3217 return;
3219 -- If type is scalar type, rewrite as x in t'first .. t'last
3220 -- This reason we do this is that the bounds may have the wrong
3221 -- type if they come from the original type definition.
3223 elsif Is_Scalar_Type (Typ) then
3224 Rewrite (Rop,
3225 Make_Range (Loc,
3226 Low_Bound =>
3227 Make_Attribute_Reference (Loc,
3228 Attribute_Name => Name_First,
3229 Prefix => New_Reference_To (Typ, Loc)),
3231 High_Bound =>
3232 Make_Attribute_Reference (Loc,
3233 Attribute_Name => Name_Last,
3234 Prefix => New_Reference_To (Typ, Loc))));
3235 Analyze_And_Resolve (N, Rtyp);
3236 return;
3238 -- Ada 2005 (AI-216): Program_Error is raised when evaluating
3239 -- a membership test if the subtype mark denotes a constrained
3240 -- Unchecked_Union subtype and the expression lacks inferable
3241 -- discriminants.
3243 elsif Is_Unchecked_Union (Base_Type (Typ))
3244 and then Is_Constrained (Typ)
3245 and then not Has_Inferable_Discriminants (Lop)
3246 then
3247 Insert_Action (N,
3248 Make_Raise_Program_Error (Loc,
3249 Reason => PE_Unchecked_Union_Restriction));
3251 -- Prevent Gigi from generating incorrect code by rewriting
3252 -- the test as a standard False.
3254 Rewrite (N,
3255 New_Occurrence_Of (Standard_False, Loc));
3257 return;
3258 end if;
3260 -- Here we have a non-scalar type
3262 if Is_Acc then
3263 Typ := Designated_Type (Typ);
3264 end if;
3266 if not Is_Constrained (Typ) then
3267 Rewrite (N,
3268 New_Reference_To (Standard_True, Loc));
3269 Analyze_And_Resolve (N, Rtyp);
3271 -- For the constrained array case, we have to check the
3272 -- subscripts for an exact match if the lengths are
3273 -- non-zero (the lengths must match in any case).
3275 elsif Is_Array_Type (Typ) then
3277 Check_Subscripts : declare
3278 function Construct_Attribute_Reference
3279 (E : Node_Id;
3280 Nam : Name_Id;
3281 Dim : Nat) return Node_Id;
3282 -- Build attribute reference E'Nam(Dim)
3284 -----------------------------------
3285 -- Construct_Attribute_Reference --
3286 -----------------------------------
3288 function Construct_Attribute_Reference
3289 (E : Node_Id;
3290 Nam : Name_Id;
3291 Dim : Nat) return Node_Id
3293 begin
3294 return
3295 Make_Attribute_Reference (Loc,
3296 Prefix => E,
3297 Attribute_Name => Nam,
3298 Expressions => New_List (
3299 Make_Integer_Literal (Loc, Dim)));
3300 end Construct_Attribute_Reference;
3302 -- Start processing for Check_Subscripts
3304 begin
3305 for J in 1 .. Number_Dimensions (Typ) loop
3306 Evolve_And_Then (Cond,
3307 Make_Op_Eq (Loc,
3308 Left_Opnd =>
3309 Construct_Attribute_Reference
3310 (Duplicate_Subexpr_No_Checks (Obj),
3311 Name_First, J),
3312 Right_Opnd =>
3313 Construct_Attribute_Reference
3314 (New_Occurrence_Of (Typ, Loc), Name_First, J)));
3316 Evolve_And_Then (Cond,
3317 Make_Op_Eq (Loc,
3318 Left_Opnd =>
3319 Construct_Attribute_Reference
3320 (Duplicate_Subexpr_No_Checks (Obj),
3321 Name_Last, J),
3322 Right_Opnd =>
3323 Construct_Attribute_Reference
3324 (New_Occurrence_Of (Typ, Loc), Name_Last, J)));
3325 end loop;
3327 if Is_Acc then
3328 Cond :=
3329 Make_Or_Else (Loc,
3330 Left_Opnd =>
3331 Make_Op_Eq (Loc,
3332 Left_Opnd => Obj,
3333 Right_Opnd => Make_Null (Loc)),
3334 Right_Opnd => Cond);
3335 end if;
3337 Rewrite (N, Cond);
3338 Analyze_And_Resolve (N, Rtyp);
3339 end Check_Subscripts;
3341 -- These are the cases where constraint checks may be
3342 -- required, e.g. records with possible discriminants
3344 else
3345 -- Expand the test into a series of discriminant comparisons.
3346 -- The expression that is built is the negation of the one
3347 -- that is used for checking discriminant constraints.
3349 Obj := Relocate_Node (Left_Opnd (N));
3351 if Has_Discriminants (Typ) then
3352 Cond := Make_Op_Not (Loc,
3353 Right_Opnd => Build_Discriminant_Checks (Obj, Typ));
3355 if Is_Acc then
3356 Cond := Make_Or_Else (Loc,
3357 Left_Opnd =>
3358 Make_Op_Eq (Loc,
3359 Left_Opnd => Obj,
3360 Right_Opnd => Make_Null (Loc)),
3361 Right_Opnd => Cond);
3362 end if;
3364 else
3365 Cond := New_Occurrence_Of (Standard_True, Loc);
3366 end if;
3368 Rewrite (N, Cond);
3369 Analyze_And_Resolve (N, Rtyp);
3370 end if;
3371 end;
3372 end if;
3373 end Expand_N_In;
3375 --------------------------------
3376 -- Expand_N_Indexed_Component --
3377 --------------------------------
3379 procedure Expand_N_Indexed_Component (N : Node_Id) is
3380 Loc : constant Source_Ptr := Sloc (N);
3381 Typ : constant Entity_Id := Etype (N);
3382 P : constant Node_Id := Prefix (N);
3383 T : constant Entity_Id := Etype (P);
3385 begin
3386 -- A special optimization, if we have an indexed component that
3387 -- is selecting from a slice, then we can eliminate the slice,
3388 -- since, for example, x (i .. j)(k) is identical to x(k). The
3389 -- only difference is the range check required by the slice. The
3390 -- range check for the slice itself has already been generated.
3391 -- The range check for the subscripting operation is ensured
3392 -- by converting the subject to the subtype of the slice.
3394 -- This optimization not only generates better code, avoiding
3395 -- slice messing especially in the packed case, but more importantly
3396 -- bypasses some problems in handling this peculiar case, for
3397 -- example, the issue of dealing specially with object renamings.
3399 if Nkind (P) = N_Slice then
3400 Rewrite (N,
3401 Make_Indexed_Component (Loc,
3402 Prefix => Prefix (P),
3403 Expressions => New_List (
3404 Convert_To
3405 (Etype (First_Index (Etype (P))),
3406 First (Expressions (N))))));
3407 Analyze_And_Resolve (N, Typ);
3408 return;
3409 end if;
3411 -- If the prefix is an access type, then we unconditionally rewrite
3412 -- if as an explicit deference. This simplifies processing for several
3413 -- cases, including packed array cases and certain cases in which
3414 -- checks must be generated. We used to try to do this only when it
3415 -- was necessary, but it cleans up the code to do it all the time.
3417 if Is_Access_Type (T) then
3418 Insert_Explicit_Dereference (P);
3419 Analyze_And_Resolve (P, Designated_Type (T));
3420 end if;
3422 -- Generate index and validity checks
3424 Generate_Index_Checks (N);
3426 if Validity_Checks_On and then Validity_Check_Subscripts then
3427 Apply_Subscript_Validity_Checks (N);
3428 end if;
3430 -- All done for the non-packed case
3432 if not Is_Packed (Etype (Prefix (N))) then
3433 return;
3434 end if;
3436 -- For packed arrays that are not bit-packed (i.e. the case of an array
3437 -- with one or more index types with a non-coniguous enumeration type),
3438 -- we can always use the normal packed element get circuit.
3440 if not Is_Bit_Packed_Array (Etype (Prefix (N))) then
3441 Expand_Packed_Element_Reference (N);
3442 return;
3443 end if;
3445 -- For a reference to a component of a bit packed array, we have to
3446 -- convert it to a reference to the corresponding Packed_Array_Type.
3447 -- We only want to do this for simple references, and not for:
3449 -- Left side of assignment, or prefix of left side of assignment,
3450 -- or prefix of the prefix, to handle packed arrays of packed arrays,
3451 -- This case is handled in Exp_Ch5.Expand_N_Assignment_Statement
3453 -- Renaming objects in renaming associations
3454 -- This case is handled when a use of the renamed variable occurs
3456 -- Actual parameters for a procedure call
3457 -- This case is handled in Exp_Ch6.Expand_Actuals
3459 -- The second expression in a 'Read attribute reference
3461 -- The prefix of an address or size attribute reference
3463 -- The following circuit detects these exceptions
3465 declare
3466 Child : Node_Id := N;
3467 Parnt : Node_Id := Parent (N);
3469 begin
3470 loop
3471 if Nkind (Parnt) = N_Unchecked_Expression then
3472 null;
3474 elsif Nkind (Parnt) = N_Object_Renaming_Declaration
3475 or else Nkind (Parnt) = N_Procedure_Call_Statement
3476 or else (Nkind (Parnt) = N_Parameter_Association
3477 and then
3478 Nkind (Parent (Parnt)) = N_Procedure_Call_Statement)
3479 then
3480 return;
3482 elsif Nkind (Parnt) = N_Attribute_Reference
3483 and then (Attribute_Name (Parnt) = Name_Address
3484 or else
3485 Attribute_Name (Parnt) = Name_Size)
3486 and then Prefix (Parnt) = Child
3487 then
3488 return;
3490 elsif Nkind (Parnt) = N_Assignment_Statement
3491 and then Name (Parnt) = Child
3492 then
3493 return;
3495 -- If the expression is an index of an indexed component,
3496 -- it must be expanded regardless of context.
3498 elsif Nkind (Parnt) = N_Indexed_Component
3499 and then Child /= Prefix (Parnt)
3500 then
3501 Expand_Packed_Element_Reference (N);
3502 return;
3504 elsif Nkind (Parent (Parnt)) = N_Assignment_Statement
3505 and then Name (Parent (Parnt)) = Parnt
3506 then
3507 return;
3509 elsif Nkind (Parnt) = N_Attribute_Reference
3510 and then Attribute_Name (Parnt) = Name_Read
3511 and then Next (First (Expressions (Parnt))) = Child
3512 then
3513 return;
3515 elsif (Nkind (Parnt) = N_Indexed_Component
3516 or else Nkind (Parnt) = N_Selected_Component)
3517 and then Prefix (Parnt) = Child
3518 then
3519 null;
3521 else
3522 Expand_Packed_Element_Reference (N);
3523 return;
3524 end if;
3526 -- Keep looking up tree for unchecked expression, or if we are
3527 -- the prefix of a possible assignment left side.
3529 Child := Parnt;
3530 Parnt := Parent (Child);
3531 end loop;
3532 end;
3534 end Expand_N_Indexed_Component;
3536 ---------------------
3537 -- Expand_N_Not_In --
3538 ---------------------
3540 -- Replace a not in b by not (a in b) so that the expansions for (a in b)
3541 -- can be done. This avoids needing to duplicate this expansion code.
3543 procedure Expand_N_Not_In (N : Node_Id) is
3544 Loc : constant Source_Ptr := Sloc (N);
3545 Typ : constant Entity_Id := Etype (N);
3546 Cfs : constant Boolean := Comes_From_Source (N);
3548 begin
3549 Rewrite (N,
3550 Make_Op_Not (Loc,
3551 Right_Opnd =>
3552 Make_In (Loc,
3553 Left_Opnd => Left_Opnd (N),
3554 Right_Opnd => Right_Opnd (N))));
3556 -- We want this tp appear as coming from source if original does (see
3557 -- tranformations in Expand_N_In).
3559 Set_Comes_From_Source (N, Cfs);
3560 Set_Comes_From_Source (Right_Opnd (N), Cfs);
3562 -- Now analyze tranformed node
3564 Analyze_And_Resolve (N, Typ);
3565 end Expand_N_Not_In;
3567 -------------------
3568 -- Expand_N_Null --
3569 -------------------
3571 -- The only replacement required is for the case of a null of type
3572 -- that is an access to protected subprogram. We represent such
3573 -- access values as a record, and so we must replace the occurrence
3574 -- of null by the equivalent record (with a null address and a null
3575 -- pointer in it), so that the backend creates the proper value.
3577 procedure Expand_N_Null (N : Node_Id) is
3578 Loc : constant Source_Ptr := Sloc (N);
3579 Typ : constant Entity_Id := Etype (N);
3580 Agg : Node_Id;
3582 begin
3583 if Ekind (Typ) = E_Access_Protected_Subprogram_Type then
3584 Agg :=
3585 Make_Aggregate (Loc,
3586 Expressions => New_List (
3587 New_Occurrence_Of (RTE (RE_Null_Address), Loc),
3588 Make_Null (Loc)));
3590 Rewrite (N, Agg);
3591 Analyze_And_Resolve (N, Equivalent_Type (Typ));
3593 -- For subsequent semantic analysis, the node must retain its
3594 -- type. Gigi in any case replaces this type by the corresponding
3595 -- record type before processing the node.
3597 Set_Etype (N, Typ);
3598 end if;
3600 exception
3601 when RE_Not_Available =>
3602 return;
3603 end Expand_N_Null;
3605 ---------------------
3606 -- Expand_N_Op_Abs --
3607 ---------------------
3609 procedure Expand_N_Op_Abs (N : Node_Id) is
3610 Loc : constant Source_Ptr := Sloc (N);
3611 Expr : constant Node_Id := Right_Opnd (N);
3613 begin
3614 Unary_Op_Validity_Checks (N);
3616 -- Deal with software overflow checking
3618 if not Backend_Overflow_Checks_On_Target
3619 and then Is_Signed_Integer_Type (Etype (N))
3620 and then Do_Overflow_Check (N)
3621 then
3622 -- The only case to worry about is when the argument is
3623 -- equal to the largest negative number, so what we do is
3624 -- to insert the check:
3626 -- [constraint_error when Expr = typ'Base'First]
3628 -- with the usual Duplicate_Subexpr use coding for expr
3630 Insert_Action (N,
3631 Make_Raise_Constraint_Error (Loc,
3632 Condition =>
3633 Make_Op_Eq (Loc,
3634 Left_Opnd => Duplicate_Subexpr (Expr),
3635 Right_Opnd =>
3636 Make_Attribute_Reference (Loc,
3637 Prefix =>
3638 New_Occurrence_Of (Base_Type (Etype (Expr)), Loc),
3639 Attribute_Name => Name_First)),
3640 Reason => CE_Overflow_Check_Failed));
3641 end if;
3643 -- Vax floating-point types case
3645 if Vax_Float (Etype (N)) then
3646 Expand_Vax_Arith (N);
3647 end if;
3648 end Expand_N_Op_Abs;
3650 ---------------------
3651 -- Expand_N_Op_Add --
3652 ---------------------
3654 procedure Expand_N_Op_Add (N : Node_Id) is
3655 Typ : constant Entity_Id := Etype (N);
3657 begin
3658 Binary_Op_Validity_Checks (N);
3660 -- N + 0 = 0 + N = N for integer types
3662 if Is_Integer_Type (Typ) then
3663 if Compile_Time_Known_Value (Right_Opnd (N))
3664 and then Expr_Value (Right_Opnd (N)) = Uint_0
3665 then
3666 Rewrite (N, Left_Opnd (N));
3667 return;
3669 elsif Compile_Time_Known_Value (Left_Opnd (N))
3670 and then Expr_Value (Left_Opnd (N)) = Uint_0
3671 then
3672 Rewrite (N, Right_Opnd (N));
3673 return;
3674 end if;
3675 end if;
3677 -- Arithmetic overflow checks for signed integer/fixed point types
3679 if Is_Signed_Integer_Type (Typ)
3680 or else Is_Fixed_Point_Type (Typ)
3681 then
3682 Apply_Arithmetic_Overflow_Check (N);
3683 return;
3685 -- Vax floating-point types case
3687 elsif Vax_Float (Typ) then
3688 Expand_Vax_Arith (N);
3689 end if;
3690 end Expand_N_Op_Add;
3692 ---------------------
3693 -- Expand_N_Op_And --
3694 ---------------------
3696 procedure Expand_N_Op_And (N : Node_Id) is
3697 Typ : constant Entity_Id := Etype (N);
3699 begin
3700 Binary_Op_Validity_Checks (N);
3702 if Is_Array_Type (Etype (N)) then
3703 Expand_Boolean_Operator (N);
3705 elsif Is_Boolean_Type (Etype (N)) then
3706 Adjust_Condition (Left_Opnd (N));
3707 Adjust_Condition (Right_Opnd (N));
3708 Set_Etype (N, Standard_Boolean);
3709 Adjust_Result_Type (N, Typ);
3710 end if;
3711 end Expand_N_Op_And;
3713 ------------------------
3714 -- Expand_N_Op_Concat --
3715 ------------------------
3717 Max_Available_String_Operands : Int := -1;
3718 -- This is initialized the first time this routine is called. It records
3719 -- a value of 0,2,3,4,5 depending on what Str_Concat_n procedures are
3720 -- available in the run-time:
3722 -- 0 None available
3723 -- 2 RE_Str_Concat available, RE_Str_Concat_3 not available
3724 -- 3 RE_Str_Concat/Concat_2 available, RE_Str_Concat_4 not available
3725 -- 4 RE_Str_Concat/Concat_2/3 available, RE_Str_Concat_5 not available
3726 -- 5 All routines including RE_Str_Concat_5 available
3728 Char_Concat_Available : Boolean;
3729 -- Records if the routines RE_Str_Concat_CC/CS/SC are available. True if
3730 -- all three are available, False if any one of these is unavailable.
3732 procedure Expand_N_Op_Concat (N : Node_Id) is
3733 Opnds : List_Id;
3734 -- List of operands to be concatenated
3736 Opnd : Node_Id;
3737 -- Single operand for concatenation
3739 Cnode : Node_Id;
3740 -- Node which is to be replaced by the result of concatenating
3741 -- the nodes in the list Opnds.
3743 Atyp : Entity_Id;
3744 -- Array type of concatenation result type
3746 Ctyp : Entity_Id;
3747 -- Component type of concatenation represented by Cnode
3749 begin
3750 -- Initialize global variables showing run-time status
3752 if Max_Available_String_Operands < 1 then
3753 if not RTE_Available (RE_Str_Concat) then
3754 Max_Available_String_Operands := 0;
3755 elsif not RTE_Available (RE_Str_Concat_3) then
3756 Max_Available_String_Operands := 2;
3757 elsif not RTE_Available (RE_Str_Concat_4) then
3758 Max_Available_String_Operands := 3;
3759 elsif not RTE_Available (RE_Str_Concat_5) then
3760 Max_Available_String_Operands := 4;
3761 else
3762 Max_Available_String_Operands := 5;
3763 end if;
3765 Char_Concat_Available :=
3766 RTE_Available (RE_Str_Concat_CC)
3767 and then
3768 RTE_Available (RE_Str_Concat_CS)
3769 and then
3770 RTE_Available (RE_Str_Concat_SC);
3771 end if;
3773 -- Ensure validity of both operands
3775 Binary_Op_Validity_Checks (N);
3777 -- If we are the left operand of a concatenation higher up the
3778 -- tree, then do nothing for now, since we want to deal with a
3779 -- series of concatenations as a unit.
3781 if Nkind (Parent (N)) = N_Op_Concat
3782 and then N = Left_Opnd (Parent (N))
3783 then
3784 return;
3785 end if;
3787 -- We get here with a concatenation whose left operand may be a
3788 -- concatenation itself with a consistent type. We need to process
3789 -- these concatenation operands from left to right, which means
3790 -- from the deepest node in the tree to the highest node.
3792 Cnode := N;
3793 while Nkind (Left_Opnd (Cnode)) = N_Op_Concat loop
3794 Cnode := Left_Opnd (Cnode);
3795 end loop;
3797 -- Now Opnd is the deepest Opnd, and its parents are the concatenation
3798 -- nodes above, so now we process bottom up, doing the operations. We
3799 -- gather a string that is as long as possible up to five operands
3801 -- The outer loop runs more than once if there are more than five
3802 -- concatenations of type Standard.String, the most we handle for
3803 -- this case, or if more than one concatenation type is involved.
3805 Outer : loop
3806 Opnds := New_List (Left_Opnd (Cnode), Right_Opnd (Cnode));
3807 Set_Parent (Opnds, N);
3809 -- The inner loop gathers concatenation operands. We gather any
3810 -- number of these in the non-string case, or if no concatenation
3811 -- routines are available for string (since in that case we will
3812 -- treat string like any other non-string case). Otherwise we only
3813 -- gather as many operands as can be handled by the available
3814 -- procedures in the run-time library (normally 5, but may be
3815 -- less for the configurable run-time case).
3817 Inner : while Cnode /= N
3818 and then (Base_Type (Etype (Cnode)) /= Standard_String
3819 or else
3820 Max_Available_String_Operands = 0
3821 or else
3822 List_Length (Opnds) <
3823 Max_Available_String_Operands)
3824 and then Base_Type (Etype (Cnode)) =
3825 Base_Type (Etype (Parent (Cnode)))
3826 loop
3827 Cnode := Parent (Cnode);
3828 Append (Right_Opnd (Cnode), Opnds);
3829 end loop Inner;
3831 -- Here we process the collected operands. First we convert
3832 -- singleton operands to singleton aggregates. This is skipped
3833 -- however for the case of two operands of type String, since
3834 -- we have special routines for these cases.
3836 Atyp := Base_Type (Etype (Cnode));
3837 Ctyp := Base_Type (Component_Type (Etype (Cnode)));
3839 if (List_Length (Opnds) > 2 or else Atyp /= Standard_String)
3840 or else not Char_Concat_Available
3841 then
3842 Opnd := First (Opnds);
3843 loop
3844 if Base_Type (Etype (Opnd)) = Ctyp then
3845 Rewrite (Opnd,
3846 Make_Aggregate (Sloc (Cnode),
3847 Expressions => New_List (Relocate_Node (Opnd))));
3848 Analyze_And_Resolve (Opnd, Atyp);
3849 end if;
3851 Next (Opnd);
3852 exit when No (Opnd);
3853 end loop;
3854 end if;
3856 -- Now call appropriate continuation routine
3858 if Atyp = Standard_String
3859 and then Max_Available_String_Operands > 0
3860 then
3861 Expand_Concatenate_String (Cnode, Opnds);
3862 else
3863 Expand_Concatenate_Other (Cnode, Opnds);
3864 end if;
3866 exit Outer when Cnode = N;
3867 Cnode := Parent (Cnode);
3868 end loop Outer;
3869 end Expand_N_Op_Concat;
3871 ------------------------
3872 -- Expand_N_Op_Divide --
3873 ------------------------
3875 procedure Expand_N_Op_Divide (N : Node_Id) is
3876 Loc : constant Source_Ptr := Sloc (N);
3877 Ltyp : constant Entity_Id := Etype (Left_Opnd (N));
3878 Rtyp : constant Entity_Id := Etype (Right_Opnd (N));
3879 Typ : Entity_Id := Etype (N);
3881 begin
3882 Binary_Op_Validity_Checks (N);
3884 -- N / 1 = N for integer types
3886 if Is_Integer_Type (Typ)
3887 and then Compile_Time_Known_Value (Right_Opnd (N))
3888 and then Expr_Value (Right_Opnd (N)) = Uint_1
3889 then
3890 Rewrite (N, Left_Opnd (N));
3891 return;
3892 end if;
3894 -- Convert x / 2 ** y to Shift_Right (x, y). Note that the fact that
3895 -- Is_Power_Of_2_For_Shift is set means that we know that our left
3896 -- operand is an unsigned integer, as required for this to work.
3898 if Nkind (Right_Opnd (N)) = N_Op_Expon
3899 and then Is_Power_Of_2_For_Shift (Right_Opnd (N))
3901 -- We cannot do this transformation in configurable run time mode if we
3902 -- have 64-bit -- integers and long shifts are not available.
3904 and then
3905 (Esize (Ltyp) <= 32
3906 or else Support_Long_Shifts_On_Target)
3907 then
3908 Rewrite (N,
3909 Make_Op_Shift_Right (Loc,
3910 Left_Opnd => Left_Opnd (N),
3911 Right_Opnd =>
3912 Convert_To (Standard_Natural, Right_Opnd (Right_Opnd (N)))));
3913 Analyze_And_Resolve (N, Typ);
3914 return;
3915 end if;
3917 -- Do required fixup of universal fixed operation
3919 if Typ = Universal_Fixed then
3920 Fixup_Universal_Fixed_Operation (N);
3921 Typ := Etype (N);
3922 end if;
3924 -- Divisions with fixed-point results
3926 if Is_Fixed_Point_Type (Typ) then
3928 -- No special processing if Treat_Fixed_As_Integer is set,
3929 -- since from a semantic point of view such operations are
3930 -- simply integer operations and will be treated that way.
3932 if not Treat_Fixed_As_Integer (N) then
3933 if Is_Integer_Type (Rtyp) then
3934 Expand_Divide_Fixed_By_Integer_Giving_Fixed (N);
3935 else
3936 Expand_Divide_Fixed_By_Fixed_Giving_Fixed (N);
3937 end if;
3938 end if;
3940 -- Other cases of division of fixed-point operands. Again we
3941 -- exclude the case where Treat_Fixed_As_Integer is set.
3943 elsif (Is_Fixed_Point_Type (Ltyp) or else
3944 Is_Fixed_Point_Type (Rtyp))
3945 and then not Treat_Fixed_As_Integer (N)
3946 then
3947 if Is_Integer_Type (Typ) then
3948 Expand_Divide_Fixed_By_Fixed_Giving_Integer (N);
3949 else
3950 pragma Assert (Is_Floating_Point_Type (Typ));
3951 Expand_Divide_Fixed_By_Fixed_Giving_Float (N);
3952 end if;
3954 -- Mixed-mode operations can appear in a non-static universal
3955 -- context, in which case the integer argument must be converted
3956 -- explicitly.
3958 elsif Typ = Universal_Real
3959 and then Is_Integer_Type (Rtyp)
3960 then
3961 Rewrite (Right_Opnd (N),
3962 Convert_To (Universal_Real, Relocate_Node (Right_Opnd (N))));
3964 Analyze_And_Resolve (Right_Opnd (N), Universal_Real);
3966 elsif Typ = Universal_Real
3967 and then Is_Integer_Type (Ltyp)
3968 then
3969 Rewrite (Left_Opnd (N),
3970 Convert_To (Universal_Real, Relocate_Node (Left_Opnd (N))));
3972 Analyze_And_Resolve (Left_Opnd (N), Universal_Real);
3974 -- Non-fixed point cases, do integer zero divide and overflow checks
3976 elsif Is_Integer_Type (Typ) then
3977 Apply_Divide_Check (N);
3979 -- Check for 64-bit division available
3981 if Esize (Ltyp) > 32
3982 and then not Support_64_Bit_Divides_On_Target
3983 then
3984 Error_Msg_CRT ("64-bit division", N);
3985 end if;
3987 -- Deal with Vax_Float
3989 elsif Vax_Float (Typ) then
3990 Expand_Vax_Arith (N);
3991 return;
3992 end if;
3993 end Expand_N_Op_Divide;
3995 --------------------
3996 -- Expand_N_Op_Eq --
3997 --------------------
3999 procedure Expand_N_Op_Eq (N : Node_Id) is
4000 Loc : constant Source_Ptr := Sloc (N);
4001 Typ : constant Entity_Id := Etype (N);
4002 Lhs : constant Node_Id := Left_Opnd (N);
4003 Rhs : constant Node_Id := Right_Opnd (N);
4004 Bodies : constant List_Id := New_List;
4005 A_Typ : constant Entity_Id := Etype (Lhs);
4007 Typl : Entity_Id := A_Typ;
4008 Op_Name : Entity_Id;
4009 Prim : Elmt_Id;
4011 procedure Build_Equality_Call (Eq : Entity_Id);
4012 -- If a constructed equality exists for the type or for its parent,
4013 -- build and analyze call, adding conversions if the operation is
4014 -- inherited.
4016 function Has_Unconstrained_UU_Component (Typ : Node_Id) return Boolean;
4017 -- Determines whether a type has a subcompoment of an unconstrained
4018 -- Unchecked_Union subtype. Typ is a record type.
4020 -------------------------
4021 -- Build_Equality_Call --
4022 -------------------------
4024 procedure Build_Equality_Call (Eq : Entity_Id) is
4025 Op_Type : constant Entity_Id := Etype (First_Formal (Eq));
4026 L_Exp : Node_Id := Relocate_Node (Lhs);
4027 R_Exp : Node_Id := Relocate_Node (Rhs);
4029 begin
4030 if Base_Type (Op_Type) /= Base_Type (A_Typ)
4031 and then not Is_Class_Wide_Type (A_Typ)
4032 then
4033 L_Exp := OK_Convert_To (Op_Type, L_Exp);
4034 R_Exp := OK_Convert_To (Op_Type, R_Exp);
4035 end if;
4037 -- If we have an Unchecked_Union, we need to add the inferred
4038 -- discriminant values as actuals in the function call. At this
4039 -- point, the expansion has determined that both operands have
4040 -- inferable discriminants.
4042 if Is_Unchecked_Union (Op_Type) then
4043 declare
4044 Lhs_Type : constant Node_Id := Etype (L_Exp);
4045 Rhs_Type : constant Node_Id := Etype (R_Exp);
4046 Lhs_Discr_Val : Node_Id;
4047 Rhs_Discr_Val : Node_Id;
4049 begin
4050 -- Per-object constrained selected components require special
4051 -- attention. If the enclosing scope of the component is an
4052 -- Unchecked_Union, we cannot reference its discriminants
4053 -- directly. This is why we use the two extra parameters of
4054 -- the equality function of the enclosing Unchecked_Union.
4056 -- type UU_Type (Discr : Integer := 0) is
4057 -- . . .
4058 -- end record;
4059 -- pragma Unchecked_Union (UU_Type);
4061 -- 1. Unchecked_Union enclosing record:
4063 -- type Enclosing_UU_Type (Discr : Integer := 0) is record
4064 -- . . .
4065 -- Comp : UU_Type (Discr);
4066 -- . . .
4067 -- end Enclosing_UU_Type;
4068 -- pragma Unchecked_Union (Enclosing_UU_Type);
4070 -- Obj1 : Enclosing_UU_Type;
4071 -- Obj2 : Enclosing_UU_Type (1);
4073 -- [. . .] Obj1 = Obj2 [. . .]
4075 -- Generated code:
4077 -- if not (uu_typeEQ (obj1.comp, obj2.comp, a, b)) then
4079 -- A and B are the formal parameters of the equality function
4080 -- of Enclosing_UU_Type. The function always has two extra
4081 -- formals to capture the inferred discriminant values.
4083 -- 2. Non-Unchecked_Union enclosing record:
4085 -- type
4086 -- Enclosing_Non_UU_Type (Discr : Integer := 0)
4087 -- is record
4088 -- . . .
4089 -- Comp : UU_Type (Discr);
4090 -- . . .
4091 -- end Enclosing_Non_UU_Type;
4093 -- Obj1 : Enclosing_Non_UU_Type;
4094 -- Obj2 : Enclosing_Non_UU_Type (1);
4096 -- ... Obj1 = Obj2 ...
4098 -- Generated code:
4100 -- if not (uu_typeEQ (obj1.comp, obj2.comp,
4101 -- obj1.discr, obj2.discr)) then
4103 -- In this case we can directly reference the discriminants of
4104 -- the enclosing record.
4106 -- Lhs of equality
4108 if Nkind (Lhs) = N_Selected_Component
4109 and then Has_Per_Object_Constraint
4110 (Entity (Selector_Name (Lhs)))
4111 then
4112 -- Enclosing record is an Unchecked_Union, use formal A
4114 if Is_Unchecked_Union (Scope
4115 (Entity (Selector_Name (Lhs))))
4116 then
4117 Lhs_Discr_Val :=
4118 Make_Identifier (Loc,
4119 Chars => Name_A);
4121 -- Enclosing record is of a non-Unchecked_Union type, it is
4122 -- possible to reference the discriminant.
4124 else
4125 Lhs_Discr_Val :=
4126 Make_Selected_Component (Loc,
4127 Prefix => Prefix (Lhs),
4128 Selector_Name =>
4129 New_Copy
4130 (Get_Discriminant_Value
4131 (First_Discriminant (Lhs_Type),
4132 Lhs_Type,
4133 Stored_Constraint (Lhs_Type))));
4134 end if;
4136 -- Comment needed here ???
4138 else
4139 -- Infer the discriminant value
4141 Lhs_Discr_Val :=
4142 New_Copy
4143 (Get_Discriminant_Value
4144 (First_Discriminant (Lhs_Type),
4145 Lhs_Type,
4146 Stored_Constraint (Lhs_Type)));
4147 end if;
4149 -- Rhs of equality
4151 if Nkind (Rhs) = N_Selected_Component
4152 and then Has_Per_Object_Constraint
4153 (Entity (Selector_Name (Rhs)))
4154 then
4155 if Is_Unchecked_Union
4156 (Scope (Entity (Selector_Name (Rhs))))
4157 then
4158 Rhs_Discr_Val :=
4159 Make_Identifier (Loc,
4160 Chars => Name_B);
4162 else
4163 Rhs_Discr_Val :=
4164 Make_Selected_Component (Loc,
4165 Prefix => Prefix (Rhs),
4166 Selector_Name =>
4167 New_Copy (Get_Discriminant_Value (
4168 First_Discriminant (Rhs_Type),
4169 Rhs_Type,
4170 Stored_Constraint (Rhs_Type))));
4172 end if;
4173 else
4174 Rhs_Discr_Val :=
4175 New_Copy (Get_Discriminant_Value (
4176 First_Discriminant (Rhs_Type),
4177 Rhs_Type,
4178 Stored_Constraint (Rhs_Type)));
4180 end if;
4182 Rewrite (N,
4183 Make_Function_Call (Loc,
4184 Name => New_Reference_To (Eq, Loc),
4185 Parameter_Associations => New_List (
4186 L_Exp,
4187 R_Exp,
4188 Lhs_Discr_Val,
4189 Rhs_Discr_Val)));
4190 end;
4192 -- Normal case, not an unchecked union
4194 else
4195 Rewrite (N,
4196 Make_Function_Call (Loc,
4197 Name => New_Reference_To (Eq, Loc),
4198 Parameter_Associations => New_List (L_Exp, R_Exp)));
4199 end if;
4201 Analyze_And_Resolve (N, Standard_Boolean, Suppress => All_Checks);
4202 end Build_Equality_Call;
4204 ------------------------------------
4205 -- Has_Unconstrained_UU_Component --
4206 ------------------------------------
4208 function Has_Unconstrained_UU_Component
4209 (Typ : Node_Id) return Boolean
4211 Tdef : constant Node_Id :=
4212 Type_Definition (Declaration_Node (Base_Type (Typ)));
4213 Clist : Node_Id;
4214 Vpart : Node_Id;
4216 function Component_Is_Unconstrained_UU
4217 (Comp : Node_Id) return Boolean;
4218 -- Determines whether the subtype of the component is an
4219 -- unconstrained Unchecked_Union.
4221 function Variant_Is_Unconstrained_UU
4222 (Variant : Node_Id) return Boolean;
4223 -- Determines whether a component of the variant has an unconstrained
4224 -- Unchecked_Union subtype.
4226 -----------------------------------
4227 -- Component_Is_Unconstrained_UU --
4228 -----------------------------------
4230 function Component_Is_Unconstrained_UU
4231 (Comp : Node_Id) return Boolean
4233 begin
4234 if Nkind (Comp) /= N_Component_Declaration then
4235 return False;
4236 end if;
4238 declare
4239 Sindic : constant Node_Id :=
4240 Subtype_Indication (Component_Definition (Comp));
4242 begin
4243 -- Unconstrained nominal type. In the case of a constraint
4244 -- present, the node kind would have been N_Subtype_Indication.
4246 if Nkind (Sindic) = N_Identifier then
4247 return Is_Unchecked_Union (Base_Type (Etype (Sindic)));
4248 end if;
4250 return False;
4251 end;
4252 end Component_Is_Unconstrained_UU;
4254 ---------------------------------
4255 -- Variant_Is_Unconstrained_UU --
4256 ---------------------------------
4258 function Variant_Is_Unconstrained_UU
4259 (Variant : Node_Id) return Boolean
4261 Clist : constant Node_Id := Component_List (Variant);
4263 begin
4264 if Is_Empty_List (Component_Items (Clist)) then
4265 return False;
4266 end if;
4268 -- We only need to test one component
4270 declare
4271 Comp : Node_Id := First (Component_Items (Clist));
4273 begin
4274 while Present (Comp) loop
4275 if Component_Is_Unconstrained_UU (Comp) then
4276 return True;
4277 end if;
4279 Next (Comp);
4280 end loop;
4281 end;
4283 -- None of the components withing the variant were of
4284 -- unconstrained Unchecked_Union type.
4286 return False;
4287 end Variant_Is_Unconstrained_UU;
4289 -- Start of processing for Has_Unconstrained_UU_Component
4291 begin
4292 if Null_Present (Tdef) then
4293 return False;
4294 end if;
4296 Clist := Component_List (Tdef);
4297 Vpart := Variant_Part (Clist);
4299 -- Inspect available components
4301 if Present (Component_Items (Clist)) then
4302 declare
4303 Comp : Node_Id := First (Component_Items (Clist));
4305 begin
4306 while Present (Comp) loop
4308 -- One component is sufficent
4310 if Component_Is_Unconstrained_UU (Comp) then
4311 return True;
4312 end if;
4314 Next (Comp);
4315 end loop;
4316 end;
4317 end if;
4319 -- Inspect available components withing variants
4321 if Present (Vpart) then
4322 declare
4323 Variant : Node_Id := First (Variants (Vpart));
4325 begin
4326 while Present (Variant) loop
4328 -- One component within a variant is sufficent
4330 if Variant_Is_Unconstrained_UU (Variant) then
4331 return True;
4332 end if;
4334 Next (Variant);
4335 end loop;
4336 end;
4337 end if;
4339 -- Neither the available components, nor the components inside the
4340 -- variant parts were of an unconstrained Unchecked_Union subtype.
4342 return False;
4343 end Has_Unconstrained_UU_Component;
4345 -- Start of processing for Expand_N_Op_Eq
4347 begin
4348 Binary_Op_Validity_Checks (N);
4350 if Ekind (Typl) = E_Private_Type then
4351 Typl := Underlying_Type (Typl);
4352 elsif Ekind (Typl) = E_Private_Subtype then
4353 Typl := Underlying_Type (Base_Type (Typl));
4354 else
4355 null;
4356 end if;
4358 -- It may happen in error situations that the underlying type is not
4359 -- set. The error will be detected later, here we just defend the
4360 -- expander code.
4362 if No (Typl) then
4363 return;
4364 end if;
4366 Typl := Base_Type (Typl);
4368 -- Boolean types (requiring handling of non-standard case)
4370 if Is_Boolean_Type (Typl) then
4371 Adjust_Condition (Left_Opnd (N));
4372 Adjust_Condition (Right_Opnd (N));
4373 Set_Etype (N, Standard_Boolean);
4374 Adjust_Result_Type (N, Typ);
4376 -- Array types
4378 elsif Is_Array_Type (Typl) then
4380 -- If we are doing full validity checking, then expand out array
4381 -- comparisons to make sure that we check the array elements.
4383 if Validity_Check_Operands then
4384 declare
4385 Save_Force_Validity_Checks : constant Boolean :=
4386 Force_Validity_Checks;
4387 begin
4388 Force_Validity_Checks := True;
4389 Rewrite (N,
4390 Expand_Array_Equality
4392 Relocate_Node (Lhs),
4393 Relocate_Node (Rhs),
4394 Bodies,
4395 Typl));
4396 Insert_Actions (N, Bodies);
4397 Analyze_And_Resolve (N, Standard_Boolean);
4398 Force_Validity_Checks := Save_Force_Validity_Checks;
4399 end;
4401 -- Packed case where both operands are known aligned
4403 elsif Is_Bit_Packed_Array (Typl)
4404 and then not Is_Possibly_Unaligned_Object (Lhs)
4405 and then not Is_Possibly_Unaligned_Object (Rhs)
4406 then
4407 Expand_Packed_Eq (N);
4409 -- Where the component type is elementary we can use a block bit
4410 -- comparison (if supported on the target) exception in the case
4411 -- of floating-point (negative zero issues require element by
4412 -- element comparison), and atomic types (where we must be sure
4413 -- to load elements independently) and possibly unaligned arrays.
4415 elsif Is_Elementary_Type (Component_Type (Typl))
4416 and then not Is_Floating_Point_Type (Component_Type (Typl))
4417 and then not Is_Atomic (Component_Type (Typl))
4418 and then not Is_Possibly_Unaligned_Object (Lhs)
4419 and then not Is_Possibly_Unaligned_Object (Rhs)
4420 and then Support_Composite_Compare_On_Target
4421 then
4422 null;
4424 -- For composite and floating-point cases, expand equality loop
4425 -- to make sure of using proper comparisons for tagged types,
4426 -- and correctly handling the floating-point case.
4428 else
4429 Rewrite (N,
4430 Expand_Array_Equality
4432 Relocate_Node (Lhs),
4433 Relocate_Node (Rhs),
4434 Bodies,
4435 Typl));
4436 Insert_Actions (N, Bodies, Suppress => All_Checks);
4437 Analyze_And_Resolve (N, Standard_Boolean, Suppress => All_Checks);
4438 end if;
4440 -- Record Types
4442 elsif Is_Record_Type (Typl) then
4444 -- For tagged types, use the primitive "="
4446 if Is_Tagged_Type (Typl) then
4448 -- If this is derived from an untagged private type completed
4449 -- with a tagged type, it does not have a full view, so we
4450 -- use the primitive operations of the private type.
4451 -- This check should no longer be necessary when these
4452 -- types receive their full views ???
4454 if Is_Private_Type (A_Typ)
4455 and then not Is_Tagged_Type (A_Typ)
4456 and then Is_Derived_Type (A_Typ)
4457 and then No (Full_View (A_Typ))
4458 then
4459 -- Search for equality operation, checking that the
4460 -- operands have the same type. Note that we must find
4461 -- a matching entry, or something is very wrong!
4463 Prim := First_Elmt (Collect_Primitive_Operations (A_Typ));
4465 while Present (Prim) loop
4466 exit when Chars (Node (Prim)) = Name_Op_Eq
4467 and then Etype (First_Formal (Node (Prim))) =
4468 Etype (Next_Formal (First_Formal (Node (Prim))))
4469 and then
4470 Base_Type (Etype (Node (Prim))) = Standard_Boolean;
4472 Next_Elmt (Prim);
4473 end loop;
4475 pragma Assert (Present (Prim));
4476 Op_Name := Node (Prim);
4478 -- Find the type's predefined equality or an overriding
4479 -- user-defined equality. The reason for not simply calling
4480 -- Find_Prim_Op here is that there may be a user-defined
4481 -- overloaded equality op that precedes the equality that
4482 -- we want, so we have to explicitly search (e.g., there
4483 -- could be an equality with two different parameter types).
4485 else
4486 if Is_Class_Wide_Type (Typl) then
4487 Typl := Root_Type (Typl);
4488 end if;
4490 Prim := First_Elmt (Primitive_Operations (Typl));
4491 while Present (Prim) loop
4492 exit when Chars (Node (Prim)) = Name_Op_Eq
4493 and then Etype (First_Formal (Node (Prim))) =
4494 Etype (Next_Formal (First_Formal (Node (Prim))))
4495 and then
4496 Base_Type (Etype (Node (Prim))) = Standard_Boolean;
4498 Next_Elmt (Prim);
4499 end loop;
4501 pragma Assert (Present (Prim));
4502 Op_Name := Node (Prim);
4503 end if;
4505 Build_Equality_Call (Op_Name);
4507 -- Ada 2005 (AI-216): Program_Error is raised when evaluating the
4508 -- predefined equality operator for a type which has a subcomponent
4509 -- of an Unchecked_Union type whose nominal subtype is unconstrained.
4511 elsif Has_Unconstrained_UU_Component (Typl) then
4512 Insert_Action (N,
4513 Make_Raise_Program_Error (Loc,
4514 Reason => PE_Unchecked_Union_Restriction));
4516 -- Prevent Gigi from generating incorrect code by rewriting the
4517 -- equality as a standard False.
4519 Rewrite (N,
4520 New_Occurrence_Of (Standard_False, Loc));
4522 elsif Is_Unchecked_Union (Typl) then
4524 -- If we can infer the discriminants of the operands, we make a
4525 -- call to the TSS equality function.
4527 if Has_Inferable_Discriminants (Lhs)
4528 and then
4529 Has_Inferable_Discriminants (Rhs)
4530 then
4531 Build_Equality_Call
4532 (TSS (Root_Type (Typl), TSS_Composite_Equality));
4534 else
4535 -- Ada 2005 (AI-216): Program_Error is raised when evaluating
4536 -- the predefined equality operator for an Unchecked_Union type
4537 -- if either of the operands lack inferable discriminants.
4539 Insert_Action (N,
4540 Make_Raise_Program_Error (Loc,
4541 Reason => PE_Unchecked_Union_Restriction));
4543 -- Prevent Gigi from generating incorrect code by rewriting
4544 -- the equality as a standard False.
4546 Rewrite (N,
4547 New_Occurrence_Of (Standard_False, Loc));
4549 end if;
4551 -- If a type support function is present (for complex cases), use it
4553 elsif Present (TSS (Root_Type (Typl), TSS_Composite_Equality)) then
4554 Build_Equality_Call
4555 (TSS (Root_Type (Typl), TSS_Composite_Equality));
4557 -- Otherwise expand the component by component equality. Note that
4558 -- we never use block-bit coparisons for records, because of the
4559 -- problems with gaps. The backend will often be able to recombine
4560 -- the separate comparisons that we generate here.
4562 else
4563 Remove_Side_Effects (Lhs);
4564 Remove_Side_Effects (Rhs);
4565 Rewrite (N,
4566 Expand_Record_Equality (N, Typl, Lhs, Rhs, Bodies));
4568 Insert_Actions (N, Bodies, Suppress => All_Checks);
4569 Analyze_And_Resolve (N, Standard_Boolean, Suppress => All_Checks);
4570 end if;
4571 end if;
4573 -- If we still have an equality comparison (i.e. it was not rewritten
4574 -- in some way), then we can test if result is known at compile time).
4576 if Nkind (N) = N_Op_Eq then
4577 Rewrite_Comparison (N);
4578 end if;
4580 -- If we still have comparison for Vax_Float, process it
4582 if Vax_Float (Typl) and then Nkind (N) in N_Op_Compare then
4583 Expand_Vax_Comparison (N);
4584 return;
4585 end if;
4586 end Expand_N_Op_Eq;
4588 -----------------------
4589 -- Expand_N_Op_Expon --
4590 -----------------------
4592 procedure Expand_N_Op_Expon (N : Node_Id) is
4593 Loc : constant Source_Ptr := Sloc (N);
4594 Typ : constant Entity_Id := Etype (N);
4595 Rtyp : constant Entity_Id := Root_Type (Typ);
4596 Base : constant Node_Id := Relocate_Node (Left_Opnd (N));
4597 Bastyp : constant Node_Id := Etype (Base);
4598 Exp : constant Node_Id := Relocate_Node (Right_Opnd (N));
4599 Exptyp : constant Entity_Id := Etype (Exp);
4600 Ovflo : constant Boolean := Do_Overflow_Check (N);
4601 Expv : Uint;
4602 Xnode : Node_Id;
4603 Temp : Node_Id;
4604 Rent : RE_Id;
4605 Ent : Entity_Id;
4606 Etyp : Entity_Id;
4608 begin
4609 Binary_Op_Validity_Checks (N);
4611 -- If either operand is of a private type, then we have the use of
4612 -- an intrinsic operator, and we get rid of the privateness, by using
4613 -- root types of underlying types for the actual operation. Otherwise
4614 -- the private types will cause trouble if we expand multiplications
4615 -- or shifts etc. We also do this transformation if the result type
4616 -- is different from the base type.
4618 if Is_Private_Type (Etype (Base))
4619 or else
4620 Is_Private_Type (Typ)
4621 or else
4622 Is_Private_Type (Exptyp)
4623 or else
4624 Rtyp /= Root_Type (Bastyp)
4625 then
4626 declare
4627 Bt : constant Entity_Id := Root_Type (Underlying_Type (Bastyp));
4628 Et : constant Entity_Id := Root_Type (Underlying_Type (Exptyp));
4630 begin
4631 Rewrite (N,
4632 Unchecked_Convert_To (Typ,
4633 Make_Op_Expon (Loc,
4634 Left_Opnd => Unchecked_Convert_To (Bt, Base),
4635 Right_Opnd => Unchecked_Convert_To (Et, Exp))));
4636 Analyze_And_Resolve (N, Typ);
4637 return;
4638 end;
4639 end if;
4641 -- Test for case of known right argument
4643 if Compile_Time_Known_Value (Exp) then
4644 Expv := Expr_Value (Exp);
4646 -- We only fold small non-negative exponents. You might think we
4647 -- could fold small negative exponents for the real case, but we
4648 -- can't because we are required to raise Constraint_Error for
4649 -- the case of 0.0 ** (negative) even if Machine_Overflows = False.
4650 -- See ACVC test C4A012B.
4652 if Expv >= 0 and then Expv <= 4 then
4654 -- X ** 0 = 1 (or 1.0)
4656 if Expv = 0 then
4657 if Ekind (Typ) in Integer_Kind then
4658 Xnode := Make_Integer_Literal (Loc, Intval => 1);
4659 else
4660 Xnode := Make_Real_Literal (Loc, Ureal_1);
4661 end if;
4663 -- X ** 1 = X
4665 elsif Expv = 1 then
4666 Xnode := Base;
4668 -- X ** 2 = X * X
4670 elsif Expv = 2 then
4671 Xnode :=
4672 Make_Op_Multiply (Loc,
4673 Left_Opnd => Duplicate_Subexpr (Base),
4674 Right_Opnd => Duplicate_Subexpr_No_Checks (Base));
4676 -- X ** 3 = X * X * X
4678 elsif Expv = 3 then
4679 Xnode :=
4680 Make_Op_Multiply (Loc,
4681 Left_Opnd =>
4682 Make_Op_Multiply (Loc,
4683 Left_Opnd => Duplicate_Subexpr (Base),
4684 Right_Opnd => Duplicate_Subexpr_No_Checks (Base)),
4685 Right_Opnd => Duplicate_Subexpr_No_Checks (Base));
4687 -- X ** 4 ->
4688 -- En : constant base'type := base * base;
4689 -- ...
4690 -- En * En
4692 else -- Expv = 4
4693 Temp :=
4694 Make_Defining_Identifier (Loc, New_Internal_Name ('E'));
4696 Insert_Actions (N, New_List (
4697 Make_Object_Declaration (Loc,
4698 Defining_Identifier => Temp,
4699 Constant_Present => True,
4700 Object_Definition => New_Reference_To (Typ, Loc),
4701 Expression =>
4702 Make_Op_Multiply (Loc,
4703 Left_Opnd => Duplicate_Subexpr (Base),
4704 Right_Opnd => Duplicate_Subexpr_No_Checks (Base)))));
4706 Xnode :=
4707 Make_Op_Multiply (Loc,
4708 Left_Opnd => New_Reference_To (Temp, Loc),
4709 Right_Opnd => New_Reference_To (Temp, Loc));
4710 end if;
4712 Rewrite (N, Xnode);
4713 Analyze_And_Resolve (N, Typ);
4714 return;
4715 end if;
4716 end if;
4718 -- Case of (2 ** expression) appearing as an argument of an integer
4719 -- multiplication, or as the right argument of a division of a non-
4720 -- negative integer. In such cases we leave the node untouched, setting
4721 -- the flag Is_Natural_Power_Of_2_for_Shift set, then the expansion
4722 -- of the higher level node converts it into a shift.
4724 if Nkind (Base) = N_Integer_Literal
4725 and then Intval (Base) = 2
4726 and then Is_Integer_Type (Root_Type (Exptyp))
4727 and then Esize (Root_Type (Exptyp)) <= Esize (Standard_Integer)
4728 and then Is_Unsigned_Type (Exptyp)
4729 and then not Ovflo
4730 and then Nkind (Parent (N)) in N_Binary_Op
4731 then
4732 declare
4733 P : constant Node_Id := Parent (N);
4734 L : constant Node_Id := Left_Opnd (P);
4735 R : constant Node_Id := Right_Opnd (P);
4737 begin
4738 if (Nkind (P) = N_Op_Multiply
4739 and then
4740 ((Is_Integer_Type (Etype (L)) and then R = N)
4741 or else
4742 (Is_Integer_Type (Etype (R)) and then L = N))
4743 and then not Do_Overflow_Check (P))
4745 or else
4746 (Nkind (P) = N_Op_Divide
4747 and then Is_Integer_Type (Etype (L))
4748 and then Is_Unsigned_Type (Etype (L))
4749 and then R = N
4750 and then not Do_Overflow_Check (P))
4751 then
4752 Set_Is_Power_Of_2_For_Shift (N);
4753 return;
4754 end if;
4755 end;
4756 end if;
4758 -- Fall through if exponentiation must be done using a runtime routine
4760 -- First deal with modular case
4762 if Is_Modular_Integer_Type (Rtyp) then
4764 -- Non-binary case, we call the special exponentiation routine for
4765 -- the non-binary case, converting the argument to Long_Long_Integer
4766 -- and passing the modulus value. Then the result is converted back
4767 -- to the base type.
4769 if Non_Binary_Modulus (Rtyp) then
4770 Rewrite (N,
4771 Convert_To (Typ,
4772 Make_Function_Call (Loc,
4773 Name => New_Reference_To (RTE (RE_Exp_Modular), Loc),
4774 Parameter_Associations => New_List (
4775 Convert_To (Standard_Integer, Base),
4776 Make_Integer_Literal (Loc, Modulus (Rtyp)),
4777 Exp))));
4779 -- Binary case, in this case, we call one of two routines, either
4780 -- the unsigned integer case, or the unsigned long long integer
4781 -- case, with a final "and" operation to do the required mod.
4783 else
4784 if UI_To_Int (Esize (Rtyp)) <= Standard_Integer_Size then
4785 Ent := RTE (RE_Exp_Unsigned);
4786 else
4787 Ent := RTE (RE_Exp_Long_Long_Unsigned);
4788 end if;
4790 Rewrite (N,
4791 Convert_To (Typ,
4792 Make_Op_And (Loc,
4793 Left_Opnd =>
4794 Make_Function_Call (Loc,
4795 Name => New_Reference_To (Ent, Loc),
4796 Parameter_Associations => New_List (
4797 Convert_To (Etype (First_Formal (Ent)), Base),
4798 Exp)),
4799 Right_Opnd =>
4800 Make_Integer_Literal (Loc, Modulus (Rtyp) - 1))));
4802 end if;
4804 -- Common exit point for modular type case
4806 Analyze_And_Resolve (N, Typ);
4807 return;
4809 -- Signed integer cases, done using either Integer or Long_Long_Integer.
4810 -- It is not worth having routines for Short_[Short_]Integer, since for
4811 -- most machines it would not help, and it would generate more code that
4812 -- might need certification in the HI-E case.
4814 -- In the integer cases, we have two routines, one for when overflow
4815 -- checks are required, and one when they are not required, since
4816 -- there is a real gain in ommitting checks on many machines.
4818 elsif Rtyp = Base_Type (Standard_Long_Long_Integer)
4819 or else (Rtyp = Base_Type (Standard_Long_Integer)
4820 and then
4821 Esize (Standard_Long_Integer) > Esize (Standard_Integer))
4822 or else (Rtyp = Universal_Integer)
4823 then
4824 Etyp := Standard_Long_Long_Integer;
4826 if Ovflo then
4827 Rent := RE_Exp_Long_Long_Integer;
4828 else
4829 Rent := RE_Exn_Long_Long_Integer;
4830 end if;
4832 elsif Is_Signed_Integer_Type (Rtyp) then
4833 Etyp := Standard_Integer;
4835 if Ovflo then
4836 Rent := RE_Exp_Integer;
4837 else
4838 Rent := RE_Exn_Integer;
4839 end if;
4841 -- Floating-point cases, always done using Long_Long_Float. We do not
4842 -- need separate routines for the overflow case here, since in the case
4843 -- of floating-point, we generate infinities anyway as a rule (either
4844 -- that or we automatically trap overflow), and if there is an infinity
4845 -- generated and a range check is required, the check will fail anyway.
4847 else
4848 pragma Assert (Is_Floating_Point_Type (Rtyp));
4849 Etyp := Standard_Long_Long_Float;
4850 Rent := RE_Exn_Long_Long_Float;
4851 end if;
4853 -- Common processing for integer cases and floating-point cases.
4854 -- If we are in the right type, we can call runtime routine directly
4856 if Typ = Etyp
4857 and then Rtyp /= Universal_Integer
4858 and then Rtyp /= Universal_Real
4859 then
4860 Rewrite (N,
4861 Make_Function_Call (Loc,
4862 Name => New_Reference_To (RTE (Rent), Loc),
4863 Parameter_Associations => New_List (Base, Exp)));
4865 -- Otherwise we have to introduce conversions (conversions are also
4866 -- required in the universal cases, since the runtime routine is
4867 -- typed using one of the standard types.
4869 else
4870 Rewrite (N,
4871 Convert_To (Typ,
4872 Make_Function_Call (Loc,
4873 Name => New_Reference_To (RTE (Rent), Loc),
4874 Parameter_Associations => New_List (
4875 Convert_To (Etyp, Base),
4876 Exp))));
4877 end if;
4879 Analyze_And_Resolve (N, Typ);
4880 return;
4882 exception
4883 when RE_Not_Available =>
4884 return;
4885 end Expand_N_Op_Expon;
4887 --------------------
4888 -- Expand_N_Op_Ge --
4889 --------------------
4891 procedure Expand_N_Op_Ge (N : Node_Id) is
4892 Typ : constant Entity_Id := Etype (N);
4893 Op1 : constant Node_Id := Left_Opnd (N);
4894 Op2 : constant Node_Id := Right_Opnd (N);
4895 Typ1 : constant Entity_Id := Base_Type (Etype (Op1));
4897 begin
4898 Binary_Op_Validity_Checks (N);
4900 if Is_Array_Type (Typ1) then
4901 Expand_Array_Comparison (N);
4902 return;
4903 end if;
4905 if Is_Boolean_Type (Typ1) then
4906 Adjust_Condition (Op1);
4907 Adjust_Condition (Op2);
4908 Set_Etype (N, Standard_Boolean);
4909 Adjust_Result_Type (N, Typ);
4910 end if;
4912 Rewrite_Comparison (N);
4914 -- If we still have comparison, and Vax_Float type, process it
4916 if Vax_Float (Typ1) and then Nkind (N) in N_Op_Compare then
4917 Expand_Vax_Comparison (N);
4918 return;
4919 end if;
4920 end Expand_N_Op_Ge;
4922 --------------------
4923 -- Expand_N_Op_Gt --
4924 --------------------
4926 procedure Expand_N_Op_Gt (N : Node_Id) is
4927 Typ : constant Entity_Id := Etype (N);
4928 Op1 : constant Node_Id := Left_Opnd (N);
4929 Op2 : constant Node_Id := Right_Opnd (N);
4930 Typ1 : constant Entity_Id := Base_Type (Etype (Op1));
4932 begin
4933 Binary_Op_Validity_Checks (N);
4935 if Is_Array_Type (Typ1) then
4936 Expand_Array_Comparison (N);
4937 return;
4938 end if;
4940 if Is_Boolean_Type (Typ1) then
4941 Adjust_Condition (Op1);
4942 Adjust_Condition (Op2);
4943 Set_Etype (N, Standard_Boolean);
4944 Adjust_Result_Type (N, Typ);
4945 end if;
4947 Rewrite_Comparison (N);
4949 -- If we still have comparison, and Vax_Float type, process it
4951 if Vax_Float (Typ1) and then Nkind (N) in N_Op_Compare then
4952 Expand_Vax_Comparison (N);
4953 return;
4954 end if;
4955 end Expand_N_Op_Gt;
4957 --------------------
4958 -- Expand_N_Op_Le --
4959 --------------------
4961 procedure Expand_N_Op_Le (N : Node_Id) is
4962 Typ : constant Entity_Id := Etype (N);
4963 Op1 : constant Node_Id := Left_Opnd (N);
4964 Op2 : constant Node_Id := Right_Opnd (N);
4965 Typ1 : constant Entity_Id := Base_Type (Etype (Op1));
4967 begin
4968 Binary_Op_Validity_Checks (N);
4970 if Is_Array_Type (Typ1) then
4971 Expand_Array_Comparison (N);
4972 return;
4973 end if;
4975 if Is_Boolean_Type (Typ1) then
4976 Adjust_Condition (Op1);
4977 Adjust_Condition (Op2);
4978 Set_Etype (N, Standard_Boolean);
4979 Adjust_Result_Type (N, Typ);
4980 end if;
4982 Rewrite_Comparison (N);
4984 -- If we still have comparison, and Vax_Float type, process it
4986 if Vax_Float (Typ1) and then Nkind (N) in N_Op_Compare then
4987 Expand_Vax_Comparison (N);
4988 return;
4989 end if;
4990 end Expand_N_Op_Le;
4992 --------------------
4993 -- Expand_N_Op_Lt --
4994 --------------------
4996 procedure Expand_N_Op_Lt (N : Node_Id) is
4997 Typ : constant Entity_Id := Etype (N);
4998 Op1 : constant Node_Id := Left_Opnd (N);
4999 Op2 : constant Node_Id := Right_Opnd (N);
5000 Typ1 : constant Entity_Id := Base_Type (Etype (Op1));
5002 begin
5003 Binary_Op_Validity_Checks (N);
5005 if Is_Array_Type (Typ1) then
5006 Expand_Array_Comparison (N);
5007 return;
5008 end if;
5010 if Is_Boolean_Type (Typ1) then
5011 Adjust_Condition (Op1);
5012 Adjust_Condition (Op2);
5013 Set_Etype (N, Standard_Boolean);
5014 Adjust_Result_Type (N, Typ);
5015 end if;
5017 Rewrite_Comparison (N);
5019 -- If we still have comparison, and Vax_Float type, process it
5021 if Vax_Float (Typ1) and then Nkind (N) in N_Op_Compare then
5022 Expand_Vax_Comparison (N);
5023 return;
5024 end if;
5025 end Expand_N_Op_Lt;
5027 -----------------------
5028 -- Expand_N_Op_Minus --
5029 -----------------------
5031 procedure Expand_N_Op_Minus (N : Node_Id) is
5032 Loc : constant Source_Ptr := Sloc (N);
5033 Typ : constant Entity_Id := Etype (N);
5035 begin
5036 Unary_Op_Validity_Checks (N);
5038 if not Backend_Overflow_Checks_On_Target
5039 and then Is_Signed_Integer_Type (Etype (N))
5040 and then Do_Overflow_Check (N)
5041 then
5042 -- Software overflow checking expands -expr into (0 - expr)
5044 Rewrite (N,
5045 Make_Op_Subtract (Loc,
5046 Left_Opnd => Make_Integer_Literal (Loc, 0),
5047 Right_Opnd => Right_Opnd (N)));
5049 Analyze_And_Resolve (N, Typ);
5051 -- Vax floating-point types case
5053 elsif Vax_Float (Etype (N)) then
5054 Expand_Vax_Arith (N);
5055 end if;
5056 end Expand_N_Op_Minus;
5058 ---------------------
5059 -- Expand_N_Op_Mod --
5060 ---------------------
5062 procedure Expand_N_Op_Mod (N : Node_Id) is
5063 Loc : constant Source_Ptr := Sloc (N);
5064 Typ : constant Entity_Id := Etype (N);
5065 Left : constant Node_Id := Left_Opnd (N);
5066 Right : constant Node_Id := Right_Opnd (N);
5067 DOC : constant Boolean := Do_Overflow_Check (N);
5068 DDC : constant Boolean := Do_Division_Check (N);
5070 LLB : Uint;
5071 Llo : Uint;
5072 Lhi : Uint;
5073 LOK : Boolean;
5074 Rlo : Uint;
5075 Rhi : Uint;
5076 ROK : Boolean;
5078 begin
5079 Binary_Op_Validity_Checks (N);
5081 Determine_Range (Right, ROK, Rlo, Rhi);
5082 Determine_Range (Left, LOK, Llo, Lhi);
5084 -- Convert mod to rem if operands are known non-negative. We do this
5085 -- since it is quite likely that this will improve the quality of code,
5086 -- (the operation now corresponds to the hardware remainder), and it
5087 -- does not seem likely that it could be harmful.
5089 if LOK and then Llo >= 0
5090 and then
5091 ROK and then Rlo >= 0
5092 then
5093 Rewrite (N,
5094 Make_Op_Rem (Sloc (N),
5095 Left_Opnd => Left_Opnd (N),
5096 Right_Opnd => Right_Opnd (N)));
5098 -- Instead of reanalyzing the node we do the analysis manually.
5099 -- This avoids anomalies when the replacement is done in an
5100 -- instance and is epsilon more efficient.
5102 Set_Entity (N, Standard_Entity (S_Op_Rem));
5103 Set_Etype (N, Typ);
5104 Set_Do_Overflow_Check (N, DOC);
5105 Set_Do_Division_Check (N, DDC);
5106 Expand_N_Op_Rem (N);
5107 Set_Analyzed (N);
5109 -- Otherwise, normal mod processing
5111 else
5112 if Is_Integer_Type (Etype (N)) then
5113 Apply_Divide_Check (N);
5114 end if;
5116 -- Apply optimization x mod 1 = 0. We don't really need that with
5117 -- gcc, but it is useful with other back ends (e.g. AAMP), and is
5118 -- certainly harmless.
5120 if Is_Integer_Type (Etype (N))
5121 and then Compile_Time_Known_Value (Right)
5122 and then Expr_Value (Right) = Uint_1
5123 then
5124 Rewrite (N, Make_Integer_Literal (Loc, 0));
5125 Analyze_And_Resolve (N, Typ);
5126 return;
5127 end if;
5129 -- Deal with annoying case of largest negative number remainder
5130 -- minus one. Gigi does not handle this case correctly, because
5131 -- it generates a divide instruction which may trap in this case.
5133 -- In fact the check is quite easy, if the right operand is -1,
5134 -- then the mod value is always 0, and we can just ignore the
5135 -- left operand completely in this case.
5137 -- The operand type may be private (e.g. in the expansion of an
5138 -- an intrinsic operation) so we must use the underlying type to
5139 -- get the bounds, and convert the literals explicitly.
5141 LLB :=
5142 Expr_Value
5143 (Type_Low_Bound (Base_Type (Underlying_Type (Etype (Left)))));
5145 if ((not ROK) or else (Rlo <= (-1) and then (-1) <= Rhi))
5146 and then
5147 ((not LOK) or else (Llo = LLB))
5148 then
5149 Rewrite (N,
5150 Make_Conditional_Expression (Loc,
5151 Expressions => New_List (
5152 Make_Op_Eq (Loc,
5153 Left_Opnd => Duplicate_Subexpr (Right),
5154 Right_Opnd =>
5155 Unchecked_Convert_To (Typ,
5156 Make_Integer_Literal (Loc, -1))),
5157 Unchecked_Convert_To (Typ,
5158 Make_Integer_Literal (Loc, Uint_0)),
5159 Relocate_Node (N))));
5161 Set_Analyzed (Next (Next (First (Expressions (N)))));
5162 Analyze_And_Resolve (N, Typ);
5163 end if;
5164 end if;
5165 end Expand_N_Op_Mod;
5167 --------------------------
5168 -- Expand_N_Op_Multiply --
5169 --------------------------
5171 procedure Expand_N_Op_Multiply (N : Node_Id) is
5172 Loc : constant Source_Ptr := Sloc (N);
5173 Lop : constant Node_Id := Left_Opnd (N);
5174 Rop : constant Node_Id := Right_Opnd (N);
5176 Lp2 : constant Boolean :=
5177 Nkind (Lop) = N_Op_Expon
5178 and then Is_Power_Of_2_For_Shift (Lop);
5180 Rp2 : constant Boolean :=
5181 Nkind (Rop) = N_Op_Expon
5182 and then Is_Power_Of_2_For_Shift (Rop);
5184 Ltyp : constant Entity_Id := Etype (Lop);
5185 Rtyp : constant Entity_Id := Etype (Rop);
5186 Typ : Entity_Id := Etype (N);
5188 begin
5189 Binary_Op_Validity_Checks (N);
5191 -- Special optimizations for integer types
5193 if Is_Integer_Type (Typ) then
5195 -- N * 0 = 0 * N = 0 for integer types
5197 if (Compile_Time_Known_Value (Rop)
5198 and then Expr_Value (Rop) = Uint_0)
5199 or else
5200 (Compile_Time_Known_Value (Lop)
5201 and then Expr_Value (Lop) = Uint_0)
5202 then
5203 Rewrite (N, Make_Integer_Literal (Loc, Uint_0));
5204 Analyze_And_Resolve (N, Typ);
5205 return;
5206 end if;
5208 -- N * 1 = 1 * N = N for integer types
5210 -- This optimisation is not done if we are going to
5211 -- rewrite the product 1 * 2 ** N to a shift.
5213 if Compile_Time_Known_Value (Rop)
5214 and then Expr_Value (Rop) = Uint_1
5215 and then not Lp2
5216 then
5217 Rewrite (N, Lop);
5218 return;
5220 elsif Compile_Time_Known_Value (Lop)
5221 and then Expr_Value (Lop) = Uint_1
5222 and then not Rp2
5223 then
5224 Rewrite (N, Rop);
5225 return;
5226 end if;
5227 end if;
5229 -- Convert x * 2 ** y to Shift_Left (x, y). Note that the fact that
5230 -- Is_Power_Of_2_For_Shift is set means that we know that our left
5231 -- operand is an integer, as required for this to work.
5233 if Rp2 then
5234 if Lp2 then
5236 -- Convert 2 ** A * 2 ** B into 2 ** (A + B)
5238 Rewrite (N,
5239 Make_Op_Expon (Loc,
5240 Left_Opnd => Make_Integer_Literal (Loc, 2),
5241 Right_Opnd =>
5242 Make_Op_Add (Loc,
5243 Left_Opnd => Right_Opnd (Lop),
5244 Right_Opnd => Right_Opnd (Rop))));
5245 Analyze_And_Resolve (N, Typ);
5246 return;
5248 else
5249 Rewrite (N,
5250 Make_Op_Shift_Left (Loc,
5251 Left_Opnd => Lop,
5252 Right_Opnd =>
5253 Convert_To (Standard_Natural, Right_Opnd (Rop))));
5254 Analyze_And_Resolve (N, Typ);
5255 return;
5256 end if;
5258 -- Same processing for the operands the other way round
5260 elsif Lp2 then
5261 Rewrite (N,
5262 Make_Op_Shift_Left (Loc,
5263 Left_Opnd => Rop,
5264 Right_Opnd =>
5265 Convert_To (Standard_Natural, Right_Opnd (Lop))));
5266 Analyze_And_Resolve (N, Typ);
5267 return;
5268 end if;
5270 -- Do required fixup of universal fixed operation
5272 if Typ = Universal_Fixed then
5273 Fixup_Universal_Fixed_Operation (N);
5274 Typ := Etype (N);
5275 end if;
5277 -- Multiplications with fixed-point results
5279 if Is_Fixed_Point_Type (Typ) then
5281 -- No special processing if Treat_Fixed_As_Integer is set,
5282 -- since from a semantic point of view such operations are
5283 -- simply integer operations and will be treated that way.
5285 if not Treat_Fixed_As_Integer (N) then
5287 -- Case of fixed * integer => fixed
5289 if Is_Integer_Type (Rtyp) then
5290 Expand_Multiply_Fixed_By_Integer_Giving_Fixed (N);
5292 -- Case of integer * fixed => fixed
5294 elsif Is_Integer_Type (Ltyp) then
5295 Expand_Multiply_Integer_By_Fixed_Giving_Fixed (N);
5297 -- Case of fixed * fixed => fixed
5299 else
5300 Expand_Multiply_Fixed_By_Fixed_Giving_Fixed (N);
5301 end if;
5302 end if;
5304 -- Other cases of multiplication of fixed-point operands. Again
5305 -- we exclude the cases where Treat_Fixed_As_Integer flag is set.
5307 elsif (Is_Fixed_Point_Type (Ltyp) or else Is_Fixed_Point_Type (Rtyp))
5308 and then not Treat_Fixed_As_Integer (N)
5309 then
5310 if Is_Integer_Type (Typ) then
5311 Expand_Multiply_Fixed_By_Fixed_Giving_Integer (N);
5312 else
5313 pragma Assert (Is_Floating_Point_Type (Typ));
5314 Expand_Multiply_Fixed_By_Fixed_Giving_Float (N);
5315 end if;
5317 -- Mixed-mode operations can appear in a non-static universal
5318 -- context, in which case the integer argument must be converted
5319 -- explicitly.
5321 elsif Typ = Universal_Real
5322 and then Is_Integer_Type (Rtyp)
5323 then
5324 Rewrite (Rop, Convert_To (Universal_Real, Relocate_Node (Rop)));
5326 Analyze_And_Resolve (Rop, Universal_Real);
5328 elsif Typ = Universal_Real
5329 and then Is_Integer_Type (Ltyp)
5330 then
5331 Rewrite (Lop, Convert_To (Universal_Real, Relocate_Node (Lop)));
5333 Analyze_And_Resolve (Lop, Universal_Real);
5335 -- Non-fixed point cases, check software overflow checking required
5337 elsif Is_Signed_Integer_Type (Etype (N)) then
5338 Apply_Arithmetic_Overflow_Check (N);
5340 -- Deal with VAX float case
5342 elsif Vax_Float (Typ) then
5343 Expand_Vax_Arith (N);
5344 return;
5345 end if;
5346 end Expand_N_Op_Multiply;
5348 --------------------
5349 -- Expand_N_Op_Ne --
5350 --------------------
5352 procedure Expand_N_Op_Ne (N : Node_Id) is
5353 Typ : constant Entity_Id := Etype (Left_Opnd (N));
5355 begin
5356 -- Case of elementary type with standard operator
5358 if Is_Elementary_Type (Typ)
5359 and then Sloc (Entity (N)) = Standard_Location
5360 then
5361 Binary_Op_Validity_Checks (N);
5363 -- Boolean types (requiring handling of non-standard case)
5365 if Is_Boolean_Type (Typ) then
5366 Adjust_Condition (Left_Opnd (N));
5367 Adjust_Condition (Right_Opnd (N));
5368 Set_Etype (N, Standard_Boolean);
5369 Adjust_Result_Type (N, Typ);
5370 end if;
5372 Rewrite_Comparison (N);
5374 -- If we still have comparison for Vax_Float, process it
5376 if Vax_Float (Typ) and then Nkind (N) in N_Op_Compare then
5377 Expand_Vax_Comparison (N);
5378 return;
5379 end if;
5381 -- For all cases other than elementary types, we rewrite node as the
5382 -- negation of an equality operation, and reanalyze. The equality to be
5383 -- used is defined in the same scope and has the same signature. This
5384 -- signature must be set explicitly since in an instance it may not have
5385 -- the same visibility as in the generic unit. This avoids duplicating
5386 -- or factoring the complex code for record/array equality tests etc.
5388 else
5389 declare
5390 Loc : constant Source_Ptr := Sloc (N);
5391 Neg : Node_Id;
5392 Ne : constant Entity_Id := Entity (N);
5394 begin
5395 Binary_Op_Validity_Checks (N);
5397 Neg :=
5398 Make_Op_Not (Loc,
5399 Right_Opnd =>
5400 Make_Op_Eq (Loc,
5401 Left_Opnd => Left_Opnd (N),
5402 Right_Opnd => Right_Opnd (N)));
5403 Set_Paren_Count (Right_Opnd (Neg), 1);
5405 if Scope (Ne) /= Standard_Standard then
5406 Set_Entity (Right_Opnd (Neg), Corresponding_Equality (Ne));
5407 end if;
5409 -- For navigation purposes, the inequality is treated as an
5410 -- implicit reference to the corresponding equality. Preserve the
5411 -- Comes_From_ source flag so that the proper Xref entry is
5412 -- generated.
5414 Preserve_Comes_From_Source (Neg, N);
5415 Preserve_Comes_From_Source (Right_Opnd (Neg), N);
5416 Rewrite (N, Neg);
5417 Analyze_And_Resolve (N, Standard_Boolean);
5418 end;
5419 end if;
5420 end Expand_N_Op_Ne;
5422 ---------------------
5423 -- Expand_N_Op_Not --
5424 ---------------------
5426 -- If the argument is other than a Boolean array type, there is no
5427 -- special expansion required.
5429 -- For the packed case, we call the special routine in Exp_Pakd, except
5430 -- that if the component size is greater than one, we use the standard
5431 -- routine generating a gruesome loop (it is so peculiar to have packed
5432 -- arrays with non-standard Boolean representations anyway, so it does
5433 -- not matter that we do not handle this case efficiently).
5435 -- For the unpacked case (and for the special packed case where we have
5436 -- non standard Booleans, as discussed above), we generate and insert
5437 -- into the tree the following function definition:
5439 -- function Nnnn (A : arr) is
5440 -- B : arr;
5441 -- begin
5442 -- for J in a'range loop
5443 -- B (J) := not A (J);
5444 -- end loop;
5445 -- return B;
5446 -- end Nnnn;
5448 -- Here arr is the actual subtype of the parameter (and hence always
5449 -- constrained). Then we replace the not with a call to this function.
5451 procedure Expand_N_Op_Not (N : Node_Id) is
5452 Loc : constant Source_Ptr := Sloc (N);
5453 Typ : constant Entity_Id := Etype (N);
5454 Opnd : Node_Id;
5455 Arr : Entity_Id;
5456 A : Entity_Id;
5457 B : Entity_Id;
5458 J : Entity_Id;
5459 A_J : Node_Id;
5460 B_J : Node_Id;
5462 Func_Name : Entity_Id;
5463 Loop_Statement : Node_Id;
5465 begin
5466 Unary_Op_Validity_Checks (N);
5468 -- For boolean operand, deal with non-standard booleans
5470 if Is_Boolean_Type (Typ) then
5471 Adjust_Condition (Right_Opnd (N));
5472 Set_Etype (N, Standard_Boolean);
5473 Adjust_Result_Type (N, Typ);
5474 return;
5475 end if;
5477 -- Only array types need any other processing
5479 if not Is_Array_Type (Typ) then
5480 return;
5481 end if;
5483 -- Case of array operand. If bit packed with a component size of 1,
5484 -- handle it in Exp_Pakd if the operand is known to be aligned.
5486 if Is_Bit_Packed_Array (Typ)
5487 and then Component_Size (Typ) = 1
5488 and then not Is_Possibly_Unaligned_Object (Right_Opnd (N))
5489 then
5490 Expand_Packed_Not (N);
5491 return;
5492 end if;
5494 -- Case of array operand which is not bit-packed. If the context is
5495 -- a safe assignment, call in-place operation, If context is a larger
5496 -- boolean expression in the context of a safe assignment, expansion is
5497 -- done by enclosing operation.
5499 Opnd := Relocate_Node (Right_Opnd (N));
5500 Convert_To_Actual_Subtype (Opnd);
5501 Arr := Etype (Opnd);
5502 Ensure_Defined (Arr, N);
5504 if Nkind (Parent (N)) = N_Assignment_Statement then
5505 if Safe_In_Place_Array_Op (Name (Parent (N)), N, Empty) then
5506 Build_Boolean_Array_Proc_Call (Parent (N), Opnd, Empty);
5507 return;
5509 -- Special case the negation of a binary operation
5511 elsif (Nkind (Opnd) = N_Op_And
5512 or else Nkind (Opnd) = N_Op_Or
5513 or else Nkind (Opnd) = N_Op_Xor)
5514 and then Safe_In_Place_Array_Op
5515 (Name (Parent (N)), Left_Opnd (Opnd), Right_Opnd (Opnd))
5516 then
5517 Build_Boolean_Array_Proc_Call (Parent (N), Opnd, Empty);
5518 return;
5519 end if;
5521 elsif Nkind (Parent (N)) in N_Binary_Op
5522 and then Nkind (Parent (Parent (N))) = N_Assignment_Statement
5523 then
5524 declare
5525 Op1 : constant Node_Id := Left_Opnd (Parent (N));
5526 Op2 : constant Node_Id := Right_Opnd (Parent (N));
5527 Lhs : constant Node_Id := Name (Parent (Parent (N)));
5529 begin
5530 if Safe_In_Place_Array_Op (Lhs, Op1, Op2) then
5531 if N = Op1
5532 and then Nkind (Op2) = N_Op_Not
5533 then
5534 -- (not A) op (not B) can be reduced to a single call
5536 return;
5538 elsif N = Op2
5539 and then Nkind (Parent (N)) = N_Op_Xor
5540 then
5541 -- A xor (not B) can also be special-cased
5543 return;
5544 end if;
5545 end if;
5546 end;
5547 end if;
5549 A := Make_Defining_Identifier (Loc, Name_uA);
5550 B := Make_Defining_Identifier (Loc, Name_uB);
5551 J := Make_Defining_Identifier (Loc, Name_uJ);
5553 A_J :=
5554 Make_Indexed_Component (Loc,
5555 Prefix => New_Reference_To (A, Loc),
5556 Expressions => New_List (New_Reference_To (J, Loc)));
5558 B_J :=
5559 Make_Indexed_Component (Loc,
5560 Prefix => New_Reference_To (B, Loc),
5561 Expressions => New_List (New_Reference_To (J, Loc)));
5563 Loop_Statement :=
5564 Make_Implicit_Loop_Statement (N,
5565 Identifier => Empty,
5567 Iteration_Scheme =>
5568 Make_Iteration_Scheme (Loc,
5569 Loop_Parameter_Specification =>
5570 Make_Loop_Parameter_Specification (Loc,
5571 Defining_Identifier => J,
5572 Discrete_Subtype_Definition =>
5573 Make_Attribute_Reference (Loc,
5574 Prefix => Make_Identifier (Loc, Chars (A)),
5575 Attribute_Name => Name_Range))),
5577 Statements => New_List (
5578 Make_Assignment_Statement (Loc,
5579 Name => B_J,
5580 Expression => Make_Op_Not (Loc, A_J))));
5582 Func_Name := Make_Defining_Identifier (Loc, New_Internal_Name ('N'));
5583 Set_Is_Inlined (Func_Name);
5585 Insert_Action (N,
5586 Make_Subprogram_Body (Loc,
5587 Specification =>
5588 Make_Function_Specification (Loc,
5589 Defining_Unit_Name => Func_Name,
5590 Parameter_Specifications => New_List (
5591 Make_Parameter_Specification (Loc,
5592 Defining_Identifier => A,
5593 Parameter_Type => New_Reference_To (Typ, Loc))),
5594 Result_Definition => New_Reference_To (Typ, Loc)),
5596 Declarations => New_List (
5597 Make_Object_Declaration (Loc,
5598 Defining_Identifier => B,
5599 Object_Definition => New_Reference_To (Arr, Loc))),
5601 Handled_Statement_Sequence =>
5602 Make_Handled_Sequence_Of_Statements (Loc,
5603 Statements => New_List (
5604 Loop_Statement,
5605 Make_Return_Statement (Loc,
5606 Expression =>
5607 Make_Identifier (Loc, Chars (B)))))));
5609 Rewrite (N,
5610 Make_Function_Call (Loc,
5611 Name => New_Reference_To (Func_Name, Loc),
5612 Parameter_Associations => New_List (Opnd)));
5614 Analyze_And_Resolve (N, Typ);
5615 end Expand_N_Op_Not;
5617 --------------------
5618 -- Expand_N_Op_Or --
5619 --------------------
5621 procedure Expand_N_Op_Or (N : Node_Id) is
5622 Typ : constant Entity_Id := Etype (N);
5624 begin
5625 Binary_Op_Validity_Checks (N);
5627 if Is_Array_Type (Etype (N)) then
5628 Expand_Boolean_Operator (N);
5630 elsif Is_Boolean_Type (Etype (N)) then
5631 Adjust_Condition (Left_Opnd (N));
5632 Adjust_Condition (Right_Opnd (N));
5633 Set_Etype (N, Standard_Boolean);
5634 Adjust_Result_Type (N, Typ);
5635 end if;
5636 end Expand_N_Op_Or;
5638 ----------------------
5639 -- Expand_N_Op_Plus --
5640 ----------------------
5642 procedure Expand_N_Op_Plus (N : Node_Id) is
5643 begin
5644 Unary_Op_Validity_Checks (N);
5645 end Expand_N_Op_Plus;
5647 ---------------------
5648 -- Expand_N_Op_Rem --
5649 ---------------------
5651 procedure Expand_N_Op_Rem (N : Node_Id) is
5652 Loc : constant Source_Ptr := Sloc (N);
5653 Typ : constant Entity_Id := Etype (N);
5655 Left : constant Node_Id := Left_Opnd (N);
5656 Right : constant Node_Id := Right_Opnd (N);
5658 LLB : Uint;
5659 Llo : Uint;
5660 Lhi : Uint;
5661 LOK : Boolean;
5662 Rlo : Uint;
5663 Rhi : Uint;
5664 ROK : Boolean;
5666 begin
5667 Binary_Op_Validity_Checks (N);
5669 if Is_Integer_Type (Etype (N)) then
5670 Apply_Divide_Check (N);
5671 end if;
5673 -- Apply optimization x rem 1 = 0. We don't really need that with
5674 -- gcc, but it is useful with other back ends (e.g. AAMP), and is
5675 -- certainly harmless.
5677 if Is_Integer_Type (Etype (N))
5678 and then Compile_Time_Known_Value (Right)
5679 and then Expr_Value (Right) = Uint_1
5680 then
5681 Rewrite (N, Make_Integer_Literal (Loc, 0));
5682 Analyze_And_Resolve (N, Typ);
5683 return;
5684 end if;
5686 -- Deal with annoying case of largest negative number remainder
5687 -- minus one. Gigi does not handle this case correctly, because
5688 -- it generates a divide instruction which may trap in this case.
5690 -- In fact the check is quite easy, if the right operand is -1,
5691 -- then the remainder is always 0, and we can just ignore the
5692 -- left operand completely in this case.
5694 Determine_Range (Right, ROK, Rlo, Rhi);
5695 Determine_Range (Left, LOK, Llo, Lhi);
5697 -- The operand type may be private (e.g. in the expansion of an
5698 -- an intrinsic operation) so we must use the underlying type to
5699 -- get the bounds, and convert the literals explicitly.
5701 LLB :=
5702 Expr_Value
5703 (Type_Low_Bound (Base_Type (Underlying_Type (Etype (Left)))));
5705 -- Now perform the test, generating code only if needed
5707 if ((not ROK) or else (Rlo <= (-1) and then (-1) <= Rhi))
5708 and then
5709 ((not LOK) or else (Llo = LLB))
5710 then
5711 Rewrite (N,
5712 Make_Conditional_Expression (Loc,
5713 Expressions => New_List (
5714 Make_Op_Eq (Loc,
5715 Left_Opnd => Duplicate_Subexpr (Right),
5716 Right_Opnd =>
5717 Unchecked_Convert_To (Typ,
5718 Make_Integer_Literal (Loc, -1))),
5720 Unchecked_Convert_To (Typ,
5721 Make_Integer_Literal (Loc, Uint_0)),
5723 Relocate_Node (N))));
5725 Set_Analyzed (Next (Next (First (Expressions (N)))));
5726 Analyze_And_Resolve (N, Typ);
5727 end if;
5728 end Expand_N_Op_Rem;
5730 -----------------------------
5731 -- Expand_N_Op_Rotate_Left --
5732 -----------------------------
5734 procedure Expand_N_Op_Rotate_Left (N : Node_Id) is
5735 begin
5736 Binary_Op_Validity_Checks (N);
5737 end Expand_N_Op_Rotate_Left;
5739 ------------------------------
5740 -- Expand_N_Op_Rotate_Right --
5741 ------------------------------
5743 procedure Expand_N_Op_Rotate_Right (N : Node_Id) is
5744 begin
5745 Binary_Op_Validity_Checks (N);
5746 end Expand_N_Op_Rotate_Right;
5748 ----------------------------
5749 -- Expand_N_Op_Shift_Left --
5750 ----------------------------
5752 procedure Expand_N_Op_Shift_Left (N : Node_Id) is
5753 begin
5754 Binary_Op_Validity_Checks (N);
5755 end Expand_N_Op_Shift_Left;
5757 -----------------------------
5758 -- Expand_N_Op_Shift_Right --
5759 -----------------------------
5761 procedure Expand_N_Op_Shift_Right (N : Node_Id) is
5762 begin
5763 Binary_Op_Validity_Checks (N);
5764 end Expand_N_Op_Shift_Right;
5766 ----------------------------------------
5767 -- Expand_N_Op_Shift_Right_Arithmetic --
5768 ----------------------------------------
5770 procedure Expand_N_Op_Shift_Right_Arithmetic (N : Node_Id) is
5771 begin
5772 Binary_Op_Validity_Checks (N);
5773 end Expand_N_Op_Shift_Right_Arithmetic;
5775 --------------------------
5776 -- Expand_N_Op_Subtract --
5777 --------------------------
5779 procedure Expand_N_Op_Subtract (N : Node_Id) is
5780 Typ : constant Entity_Id := Etype (N);
5782 begin
5783 Binary_Op_Validity_Checks (N);
5785 -- N - 0 = N for integer types
5787 if Is_Integer_Type (Typ)
5788 and then Compile_Time_Known_Value (Right_Opnd (N))
5789 and then Expr_Value (Right_Opnd (N)) = 0
5790 then
5791 Rewrite (N, Left_Opnd (N));
5792 return;
5793 end if;
5795 -- Arithemtic overflow checks for signed integer/fixed point types
5797 if Is_Signed_Integer_Type (Typ)
5798 or else Is_Fixed_Point_Type (Typ)
5799 then
5800 Apply_Arithmetic_Overflow_Check (N);
5802 -- Vax floating-point types case
5804 elsif Vax_Float (Typ) then
5805 Expand_Vax_Arith (N);
5806 end if;
5807 end Expand_N_Op_Subtract;
5809 ---------------------
5810 -- Expand_N_Op_Xor --
5811 ---------------------
5813 procedure Expand_N_Op_Xor (N : Node_Id) is
5814 Typ : constant Entity_Id := Etype (N);
5816 begin
5817 Binary_Op_Validity_Checks (N);
5819 if Is_Array_Type (Etype (N)) then
5820 Expand_Boolean_Operator (N);
5822 elsif Is_Boolean_Type (Etype (N)) then
5823 Adjust_Condition (Left_Opnd (N));
5824 Adjust_Condition (Right_Opnd (N));
5825 Set_Etype (N, Standard_Boolean);
5826 Adjust_Result_Type (N, Typ);
5827 end if;
5828 end Expand_N_Op_Xor;
5830 ----------------------
5831 -- Expand_N_Or_Else --
5832 ----------------------
5834 -- Expand into conditional expression if Actions present, and also
5835 -- deal with optimizing case of arguments being True or False.
5837 procedure Expand_N_Or_Else (N : Node_Id) is
5838 Loc : constant Source_Ptr := Sloc (N);
5839 Typ : constant Entity_Id := Etype (N);
5840 Left : constant Node_Id := Left_Opnd (N);
5841 Right : constant Node_Id := Right_Opnd (N);
5842 Actlist : List_Id;
5844 begin
5845 -- Deal with non-standard booleans
5847 if Is_Boolean_Type (Typ) then
5848 Adjust_Condition (Left);
5849 Adjust_Condition (Right);
5850 Set_Etype (N, Standard_Boolean);
5851 end if;
5853 -- Check for cases of left argument is True or False
5855 if Nkind (Left) = N_Identifier then
5857 -- If left argument is False, change (False or else Right) to Right.
5858 -- Any actions associated with Right will be executed unconditionally
5859 -- and can thus be inserted into the tree unconditionally.
5861 if Entity (Left) = Standard_False then
5862 if Present (Actions (N)) then
5863 Insert_Actions (N, Actions (N));
5864 end if;
5866 Rewrite (N, Right);
5867 Adjust_Result_Type (N, Typ);
5868 return;
5870 -- If left argument is True, change (True and then Right) to
5871 -- True. In this case we can forget the actions associated with
5872 -- Right, since they will never be executed.
5874 elsif Entity (Left) = Standard_True then
5875 Kill_Dead_Code (Right);
5876 Kill_Dead_Code (Actions (N));
5877 Rewrite (N, New_Occurrence_Of (Standard_True, Loc));
5878 Adjust_Result_Type (N, Typ);
5879 return;
5880 end if;
5881 end if;
5883 -- If Actions are present, we expand
5885 -- left or else right
5887 -- into
5889 -- if left then True else right end
5891 -- with the actions becoming the Else_Actions of the conditional
5892 -- expression. This conditional expression is then further expanded
5893 -- (and will eventually disappear)
5895 if Present (Actions (N)) then
5896 Actlist := Actions (N);
5897 Rewrite (N,
5898 Make_Conditional_Expression (Loc,
5899 Expressions => New_List (
5900 Left,
5901 New_Occurrence_Of (Standard_True, Loc),
5902 Right)));
5904 Set_Else_Actions (N, Actlist);
5905 Analyze_And_Resolve (N, Standard_Boolean);
5906 Adjust_Result_Type (N, Typ);
5907 return;
5908 end if;
5910 -- No actions present, check for cases of right argument True/False
5912 if Nkind (Right) = N_Identifier then
5914 -- Change (Left or else False) to Left. Note that we know there
5915 -- are no actions associated with the True operand, since we
5916 -- just checked for this case above.
5918 if Entity (Right) = Standard_False then
5919 Rewrite (N, Left);
5921 -- Change (Left or else True) to True, making sure to preserve
5922 -- any side effects associated with the Left operand.
5924 elsif Entity (Right) = Standard_True then
5925 Remove_Side_Effects (Left);
5926 Rewrite
5927 (N, New_Occurrence_Of (Standard_True, Loc));
5928 end if;
5929 end if;
5931 Adjust_Result_Type (N, Typ);
5932 end Expand_N_Or_Else;
5934 -----------------------------------
5935 -- Expand_N_Qualified_Expression --
5936 -----------------------------------
5938 procedure Expand_N_Qualified_Expression (N : Node_Id) is
5939 Operand : constant Node_Id := Expression (N);
5940 Target_Type : constant Entity_Id := Entity (Subtype_Mark (N));
5942 begin
5943 Apply_Constraint_Check (Operand, Target_Type, No_Sliding => True);
5944 end Expand_N_Qualified_Expression;
5946 ---------------------------------
5947 -- Expand_N_Selected_Component --
5948 ---------------------------------
5950 -- If the selector is a discriminant of a concurrent object, rewrite the
5951 -- prefix to denote the corresponding record type.
5953 procedure Expand_N_Selected_Component (N : Node_Id) is
5954 Loc : constant Source_Ptr := Sloc (N);
5955 Par : constant Node_Id := Parent (N);
5956 P : constant Node_Id := Prefix (N);
5957 Ptyp : Entity_Id := Underlying_Type (Etype (P));
5958 Disc : Entity_Id;
5959 New_N : Node_Id;
5960 Dcon : Elmt_Id;
5962 function In_Left_Hand_Side (Comp : Node_Id) return Boolean;
5963 -- Gigi needs a temporary for prefixes that depend on a discriminant,
5964 -- unless the context of an assignment can provide size information.
5965 -- Don't we have a general routine that does this???
5967 -----------------------
5968 -- In_Left_Hand_Side --
5969 -----------------------
5971 function In_Left_Hand_Side (Comp : Node_Id) return Boolean is
5972 begin
5973 return (Nkind (Parent (Comp)) = N_Assignment_Statement
5974 and then Comp = Name (Parent (Comp)))
5975 or else (Present (Parent (Comp))
5976 and then Nkind (Parent (Comp)) in N_Subexpr
5977 and then In_Left_Hand_Side (Parent (Comp)));
5978 end In_Left_Hand_Side;
5980 -- Start of processing for Expand_N_Selected_Component
5982 begin
5983 -- Insert explicit dereference if required
5985 if Is_Access_Type (Ptyp) then
5986 Insert_Explicit_Dereference (P);
5987 Analyze_And_Resolve (P, Designated_Type (Ptyp));
5989 if Ekind (Etype (P)) = E_Private_Subtype
5990 and then Is_For_Access_Subtype (Etype (P))
5991 then
5992 Set_Etype (P, Base_Type (Etype (P)));
5993 end if;
5995 Ptyp := Etype (P);
5996 end if;
5998 -- Deal with discriminant check required
6000 if Do_Discriminant_Check (N) then
6002 -- Present the discrminant checking function to the backend,
6003 -- so that it can inline the call to the function.
6005 Add_Inlined_Body
6006 (Discriminant_Checking_Func
6007 (Original_Record_Component (Entity (Selector_Name (N)))));
6009 -- Now reset the flag and generate the call
6011 Set_Do_Discriminant_Check (N, False);
6012 Generate_Discriminant_Check (N);
6013 end if;
6015 -- Gigi cannot handle unchecked conversions that are the prefix of a
6016 -- selected component with discriminants. This must be checked during
6017 -- expansion, because during analysis the type of the selector is not
6018 -- known at the point the prefix is analyzed. If the conversion is the
6019 -- target of an assignment, then we cannot force the evaluation.
6021 if Nkind (Prefix (N)) = N_Unchecked_Type_Conversion
6022 and then Has_Discriminants (Etype (N))
6023 and then not In_Left_Hand_Side (N)
6024 then
6025 Force_Evaluation (Prefix (N));
6026 end if;
6028 -- Remaining processing applies only if selector is a discriminant
6030 if Ekind (Entity (Selector_Name (N))) = E_Discriminant then
6032 -- If the selector is a discriminant of a constrained record type,
6033 -- we may be able to rewrite the expression with the actual value
6034 -- of the discriminant, a useful optimization in some cases.
6036 if Is_Record_Type (Ptyp)
6037 and then Has_Discriminants (Ptyp)
6038 and then Is_Constrained (Ptyp)
6039 then
6040 -- Do this optimization for discrete types only, and not for
6041 -- access types (access discriminants get us into trouble!)
6043 if not Is_Discrete_Type (Etype (N)) then
6044 null;
6046 -- Don't do this on the left hand of an assignment statement.
6047 -- Normally one would think that references like this would
6048 -- not occur, but they do in generated code, and mean that
6049 -- we really do want to assign the discriminant!
6051 elsif Nkind (Par) = N_Assignment_Statement
6052 and then Name (Par) = N
6053 then
6054 null;
6056 -- Don't do this optimization for the prefix of an attribute
6057 -- or the operand of an object renaming declaration since these
6058 -- are contexts where we do not want the value anyway.
6060 elsif (Nkind (Par) = N_Attribute_Reference
6061 and then Prefix (Par) = N)
6062 or else Is_Renamed_Object (N)
6063 then
6064 null;
6066 -- Don't do this optimization if we are within the code for a
6067 -- discriminant check, since the whole point of such a check may
6068 -- be to verify the condition on which the code below depends!
6070 elsif Is_In_Discriminant_Check (N) then
6071 null;
6073 -- Green light to see if we can do the optimization. There is
6074 -- still one condition that inhibits the optimization below
6075 -- but now is the time to check the particular discriminant.
6077 else
6078 -- Loop through discriminants to find the matching
6079 -- discriminant constraint to see if we can copy it.
6081 Disc := First_Discriminant (Ptyp);
6082 Dcon := First_Elmt (Discriminant_Constraint (Ptyp));
6083 Discr_Loop : while Present (Dcon) loop
6085 -- Check if this is the matching discriminant
6087 if Disc = Entity (Selector_Name (N)) then
6089 -- Here we have the matching discriminant. Check for
6090 -- the case of a discriminant of a component that is
6091 -- constrained by an outer discriminant, which cannot
6092 -- be optimized away.
6095 Denotes_Discriminant
6096 (Node (Dcon), Check_Protected => True)
6097 then
6098 exit Discr_Loop;
6100 -- In the context of a case statement, the expression
6101 -- may have the base type of the discriminant, and we
6102 -- need to preserve the constraint to avoid spurious
6103 -- errors on missing cases.
6105 elsif Nkind (Parent (N)) = N_Case_Statement
6106 and then Etype (Node (Dcon)) /= Etype (Disc)
6107 then
6108 Rewrite (N,
6109 Make_Qualified_Expression (Loc,
6110 Subtype_Mark =>
6111 New_Occurrence_Of (Etype (Disc), Loc),
6112 Expression =>
6113 New_Copy_Tree (Node (Dcon))));
6114 Analyze_And_Resolve (N, Etype (Disc));
6116 -- In case that comes out as a static expression,
6117 -- reset it (a selected component is never static).
6119 Set_Is_Static_Expression (N, False);
6120 return;
6122 -- Otherwise we can just copy the constraint, but the
6123 -- result is certainly not static! In some cases the
6124 -- discriminant constraint has been analyzed in the
6125 -- context of the original subtype indication, but for
6126 -- itypes the constraint might not have been analyzed
6127 -- yet, and this must be done now.
6129 else
6130 Rewrite (N, New_Copy_Tree (Node (Dcon)));
6131 Analyze_And_Resolve (N);
6132 Set_Is_Static_Expression (N, False);
6133 return;
6134 end if;
6135 end if;
6137 Next_Elmt (Dcon);
6138 Next_Discriminant (Disc);
6139 end loop Discr_Loop;
6141 -- Note: the above loop should always find a matching
6142 -- discriminant, but if it does not, we just missed an
6143 -- optimization due to some glitch (perhaps a previous
6144 -- error), so ignore.
6146 end if;
6147 end if;
6149 -- The only remaining processing is in the case of a discriminant of
6150 -- a concurrent object, where we rewrite the prefix to denote the
6151 -- corresponding record type. If the type is derived and has renamed
6152 -- discriminants, use corresponding discriminant, which is the one
6153 -- that appears in the corresponding record.
6155 if not Is_Concurrent_Type (Ptyp) then
6156 return;
6157 end if;
6159 Disc := Entity (Selector_Name (N));
6161 if Is_Derived_Type (Ptyp)
6162 and then Present (Corresponding_Discriminant (Disc))
6163 then
6164 Disc := Corresponding_Discriminant (Disc);
6165 end if;
6167 New_N :=
6168 Make_Selected_Component (Loc,
6169 Prefix =>
6170 Unchecked_Convert_To (Corresponding_Record_Type (Ptyp),
6171 New_Copy_Tree (P)),
6172 Selector_Name => Make_Identifier (Loc, Chars (Disc)));
6174 Rewrite (N, New_N);
6175 Analyze (N);
6176 end if;
6177 end Expand_N_Selected_Component;
6179 --------------------
6180 -- Expand_N_Slice --
6181 --------------------
6183 procedure Expand_N_Slice (N : Node_Id) is
6184 Loc : constant Source_Ptr := Sloc (N);
6185 Typ : constant Entity_Id := Etype (N);
6186 Pfx : constant Node_Id := Prefix (N);
6187 Ptp : Entity_Id := Etype (Pfx);
6189 function Is_Procedure_Actual (N : Node_Id) return Boolean;
6190 -- Check whether the argument is an actual for a procedure call,
6191 -- in which case the expansion of a bit-packed slice is deferred
6192 -- until the call itself is expanded. The reason this is required
6193 -- is that we might have an IN OUT or OUT parameter, and the copy out
6194 -- is essential, and that copy out would be missed if we created a
6195 -- temporary here in Expand_N_Slice. Note that we don't bother
6196 -- to test specifically for an IN OUT or OUT mode parameter, since it
6197 -- is a bit tricky to do, and it is harmless to defer expansion
6198 -- in the IN case, since the call processing will still generate the
6199 -- appropriate copy in operation, which will take care of the slice.
6201 procedure Make_Temporary;
6202 -- Create a named variable for the value of the slice, in
6203 -- cases where the back-end cannot handle it properly, e.g.
6204 -- when packed types or unaligned slices are involved.
6206 -------------------------
6207 -- Is_Procedure_Actual --
6208 -------------------------
6210 function Is_Procedure_Actual (N : Node_Id) return Boolean is
6211 Par : Node_Id := Parent (N);
6213 begin
6214 loop
6215 -- If our parent is a procedure call we can return
6217 if Nkind (Par) = N_Procedure_Call_Statement then
6218 return True;
6220 -- If our parent is a type conversion, keep climbing the
6221 -- tree, since a type conversion can be a procedure actual.
6222 -- Also keep climbing if parameter association or a qualified
6223 -- expression, since these are additional cases that do can
6224 -- appear on procedure actuals.
6226 elsif Nkind (Par) = N_Type_Conversion
6227 or else Nkind (Par) = N_Parameter_Association
6228 or else Nkind (Par) = N_Qualified_Expression
6229 then
6230 Par := Parent (Par);
6232 -- Any other case is not what we are looking for
6234 else
6235 return False;
6236 end if;
6237 end loop;
6238 end Is_Procedure_Actual;
6240 --------------------
6241 -- Make_Temporary --
6242 --------------------
6244 procedure Make_Temporary is
6245 Decl : Node_Id;
6246 Ent : constant Entity_Id :=
6247 Make_Defining_Identifier (Loc, New_Internal_Name ('T'));
6248 begin
6249 Decl :=
6250 Make_Object_Declaration (Loc,
6251 Defining_Identifier => Ent,
6252 Object_Definition => New_Occurrence_Of (Typ, Loc));
6254 Set_No_Initialization (Decl);
6256 Insert_Actions (N, New_List (
6257 Decl,
6258 Make_Assignment_Statement (Loc,
6259 Name => New_Occurrence_Of (Ent, Loc),
6260 Expression => Relocate_Node (N))));
6262 Rewrite (N, New_Occurrence_Of (Ent, Loc));
6263 Analyze_And_Resolve (N, Typ);
6264 end Make_Temporary;
6266 -- Start of processing for Expand_N_Slice
6268 begin
6269 -- Special handling for access types
6271 if Is_Access_Type (Ptp) then
6273 Ptp := Designated_Type (Ptp);
6275 Rewrite (Pfx,
6276 Make_Explicit_Dereference (Sloc (N),
6277 Prefix => Relocate_Node (Pfx)));
6279 Analyze_And_Resolve (Pfx, Ptp);
6280 end if;
6282 -- Range checks are potentially also needed for cases involving
6283 -- a slice indexed by a subtype indication, but Do_Range_Check
6284 -- can currently only be set for expressions ???
6286 if not Index_Checks_Suppressed (Ptp)
6287 and then (not Is_Entity_Name (Pfx)
6288 or else not Index_Checks_Suppressed (Entity (Pfx)))
6289 and then Nkind (Discrete_Range (N)) /= N_Subtype_Indication
6290 then
6291 Enable_Range_Check (Discrete_Range (N));
6292 end if;
6294 -- The remaining case to be handled is packed slices. We can leave
6295 -- packed slices as they are in the following situations:
6297 -- 1. Right or left side of an assignment (we can handle this
6298 -- situation correctly in the assignment statement expansion).
6300 -- 2. Prefix of indexed component (the slide is optimized away
6301 -- in this case, see the start of Expand_N_Slice.
6303 -- 3. Object renaming declaration, since we want the name of
6304 -- the slice, not the value.
6306 -- 4. Argument to procedure call, since copy-in/copy-out handling
6307 -- may be required, and this is handled in the expansion of
6308 -- call itself.
6310 -- 5. Prefix of an address attribute (this is an error which
6311 -- is caught elsewhere, and the expansion would intefere
6312 -- with generating the error message).
6314 if not Is_Packed (Typ) then
6316 -- Apply transformation for actuals of a function call,
6317 -- where Expand_Actuals is not used.
6319 if Nkind (Parent (N)) = N_Function_Call
6320 and then Is_Possibly_Unaligned_Slice (N)
6321 then
6322 Make_Temporary;
6323 end if;
6325 elsif Nkind (Parent (N)) = N_Assignment_Statement
6326 or else (Nkind (Parent (Parent (N))) = N_Assignment_Statement
6327 and then Parent (N) = Name (Parent (Parent (N))))
6328 then
6329 return;
6331 elsif Nkind (Parent (N)) = N_Indexed_Component
6332 or else Is_Renamed_Object (N)
6333 or else Is_Procedure_Actual (N)
6334 then
6335 return;
6337 elsif Nkind (Parent (N)) = N_Attribute_Reference
6338 and then Attribute_Name (Parent (N)) = Name_Address
6339 then
6340 return;
6342 else
6343 Make_Temporary;
6344 end if;
6345 end Expand_N_Slice;
6347 ------------------------------
6348 -- Expand_N_Type_Conversion --
6349 ------------------------------
6351 procedure Expand_N_Type_Conversion (N : Node_Id) is
6352 Loc : constant Source_Ptr := Sloc (N);
6353 Operand : constant Node_Id := Expression (N);
6354 Target_Type : constant Entity_Id := Etype (N);
6355 Operand_Type : Entity_Id := Etype (Operand);
6357 procedure Handle_Changed_Representation;
6358 -- This is called in the case of record and array type conversions
6359 -- to see if there is a change of representation to be handled.
6360 -- Change of representation is actually handled at the assignment
6361 -- statement level, and what this procedure does is rewrite node N
6362 -- conversion as an assignment to temporary. If there is no change
6363 -- of representation, then the conversion node is unchanged.
6365 procedure Real_Range_Check;
6366 -- Handles generation of range check for real target value
6368 -----------------------------------
6369 -- Handle_Changed_Representation --
6370 -----------------------------------
6372 procedure Handle_Changed_Representation is
6373 Temp : Entity_Id;
6374 Decl : Node_Id;
6375 Odef : Node_Id;
6376 Disc : Node_Id;
6377 N_Ix : Node_Id;
6378 Cons : List_Id;
6380 begin
6381 -- Nothing to do if no change of representation
6383 if Same_Representation (Operand_Type, Target_Type) then
6384 return;
6386 -- The real change of representation work is done by the assignment
6387 -- statement processing. So if this type conversion is appearing as
6388 -- the expression of an assignment statement, nothing needs to be
6389 -- done to the conversion.
6391 elsif Nkind (Parent (N)) = N_Assignment_Statement then
6392 return;
6394 -- Otherwise we need to generate a temporary variable, and do the
6395 -- change of representation assignment into that temporary variable.
6396 -- The conversion is then replaced by a reference to this variable.
6398 else
6399 Cons := No_List;
6401 -- If type is unconstrained we have to add a constraint,
6402 -- copied from the actual value of the left hand side.
6404 if not Is_Constrained (Target_Type) then
6405 if Has_Discriminants (Operand_Type) then
6406 Disc := First_Discriminant (Operand_Type);
6408 if Disc /= First_Stored_Discriminant (Operand_Type) then
6409 Disc := First_Stored_Discriminant (Operand_Type);
6410 end if;
6412 Cons := New_List;
6413 while Present (Disc) loop
6414 Append_To (Cons,
6415 Make_Selected_Component (Loc,
6416 Prefix => Duplicate_Subexpr_Move_Checks (Operand),
6417 Selector_Name =>
6418 Make_Identifier (Loc, Chars (Disc))));
6419 Next_Discriminant (Disc);
6420 end loop;
6422 elsif Is_Array_Type (Operand_Type) then
6423 N_Ix := First_Index (Target_Type);
6424 Cons := New_List;
6426 for J in 1 .. Number_Dimensions (Operand_Type) loop
6428 -- We convert the bounds explicitly. We use an unchecked
6429 -- conversion because bounds checks are done elsewhere.
6431 Append_To (Cons,
6432 Make_Range (Loc,
6433 Low_Bound =>
6434 Unchecked_Convert_To (Etype (N_Ix),
6435 Make_Attribute_Reference (Loc,
6436 Prefix =>
6437 Duplicate_Subexpr_No_Checks
6438 (Operand, Name_Req => True),
6439 Attribute_Name => Name_First,
6440 Expressions => New_List (
6441 Make_Integer_Literal (Loc, J)))),
6443 High_Bound =>
6444 Unchecked_Convert_To (Etype (N_Ix),
6445 Make_Attribute_Reference (Loc,
6446 Prefix =>
6447 Duplicate_Subexpr_No_Checks
6448 (Operand, Name_Req => True),
6449 Attribute_Name => Name_Last,
6450 Expressions => New_List (
6451 Make_Integer_Literal (Loc, J))))));
6453 Next_Index (N_Ix);
6454 end loop;
6455 end if;
6456 end if;
6458 Odef := New_Occurrence_Of (Target_Type, Loc);
6460 if Present (Cons) then
6461 Odef :=
6462 Make_Subtype_Indication (Loc,
6463 Subtype_Mark => Odef,
6464 Constraint =>
6465 Make_Index_Or_Discriminant_Constraint (Loc,
6466 Constraints => Cons));
6467 end if;
6469 Temp := Make_Defining_Identifier (Loc, New_Internal_Name ('C'));
6470 Decl :=
6471 Make_Object_Declaration (Loc,
6472 Defining_Identifier => Temp,
6473 Object_Definition => Odef);
6475 Set_No_Initialization (Decl, True);
6477 -- Insert required actions. It is essential to suppress checks
6478 -- since we have suppressed default initialization, which means
6479 -- that the variable we create may have no discriminants.
6481 Insert_Actions (N,
6482 New_List (
6483 Decl,
6484 Make_Assignment_Statement (Loc,
6485 Name => New_Occurrence_Of (Temp, Loc),
6486 Expression => Relocate_Node (N))),
6487 Suppress => All_Checks);
6489 Rewrite (N, New_Occurrence_Of (Temp, Loc));
6490 return;
6491 end if;
6492 end Handle_Changed_Representation;
6494 ----------------------
6495 -- Real_Range_Check --
6496 ----------------------
6498 -- Case of conversions to floating-point or fixed-point. If range
6499 -- checks are enabled and the target type has a range constraint,
6500 -- we convert:
6502 -- typ (x)
6504 -- to
6506 -- Tnn : typ'Base := typ'Base (x);
6507 -- [constraint_error when Tnn < typ'First or else Tnn > typ'Last]
6508 -- Tnn
6510 -- This is necessary when there is a conversion of integer to float
6511 -- or to fixed-point to ensure that the correct checks are made. It
6512 -- is not necessary for float to float where it is enough to simply
6513 -- set the Do_Range_Check flag.
6515 procedure Real_Range_Check is
6516 Btyp : constant Entity_Id := Base_Type (Target_Type);
6517 Lo : constant Node_Id := Type_Low_Bound (Target_Type);
6518 Hi : constant Node_Id := Type_High_Bound (Target_Type);
6519 Xtyp : constant Entity_Id := Etype (Operand);
6520 Conv : Node_Id;
6521 Tnn : Entity_Id;
6523 begin
6524 -- Nothing to do if conversion was rewritten
6526 if Nkind (N) /= N_Type_Conversion then
6527 return;
6528 end if;
6530 -- Nothing to do if range checks suppressed, or target has the
6531 -- same range as the base type (or is the base type).
6533 if Range_Checks_Suppressed (Target_Type)
6534 or else (Lo = Type_Low_Bound (Btyp)
6535 and then
6536 Hi = Type_High_Bound (Btyp))
6537 then
6538 return;
6539 end if;
6541 -- Nothing to do if expression is an entity on which checks
6542 -- have been suppressed.
6544 if Is_Entity_Name (Operand)
6545 and then Range_Checks_Suppressed (Entity (Operand))
6546 then
6547 return;
6548 end if;
6550 -- Nothing to do if bounds are all static and we can tell that
6551 -- the expression is within the bounds of the target. Note that
6552 -- if the operand is of an unconstrained floating-point type,
6553 -- then we do not trust it to be in range (might be infinite)
6555 declare
6556 S_Lo : constant Node_Id := Type_Low_Bound (Xtyp);
6557 S_Hi : constant Node_Id := Type_High_Bound (Xtyp);
6559 begin
6560 if (not Is_Floating_Point_Type (Xtyp)
6561 or else Is_Constrained (Xtyp))
6562 and then Compile_Time_Known_Value (S_Lo)
6563 and then Compile_Time_Known_Value (S_Hi)
6564 and then Compile_Time_Known_Value (Hi)
6565 and then Compile_Time_Known_Value (Lo)
6566 then
6567 declare
6568 D_Lov : constant Ureal := Expr_Value_R (Lo);
6569 D_Hiv : constant Ureal := Expr_Value_R (Hi);
6570 S_Lov : Ureal;
6571 S_Hiv : Ureal;
6573 begin
6574 if Is_Real_Type (Xtyp) then
6575 S_Lov := Expr_Value_R (S_Lo);
6576 S_Hiv := Expr_Value_R (S_Hi);
6577 else
6578 S_Lov := UR_From_Uint (Expr_Value (S_Lo));
6579 S_Hiv := UR_From_Uint (Expr_Value (S_Hi));
6580 end if;
6582 if D_Hiv > D_Lov
6583 and then S_Lov >= D_Lov
6584 and then S_Hiv <= D_Hiv
6585 then
6586 Set_Do_Range_Check (Operand, False);
6587 return;
6588 end if;
6589 end;
6590 end if;
6591 end;
6593 -- For float to float conversions, we are done
6595 if Is_Floating_Point_Type (Xtyp)
6596 and then
6597 Is_Floating_Point_Type (Btyp)
6598 then
6599 return;
6600 end if;
6602 -- Otherwise rewrite the conversion as described above
6604 Conv := Relocate_Node (N);
6605 Rewrite
6606 (Subtype_Mark (Conv), New_Occurrence_Of (Btyp, Loc));
6607 Set_Etype (Conv, Btyp);
6609 -- Enable overflow except for case of integer to float conversions,
6610 -- where it is never required, since we can never have overflow in
6611 -- this case.
6613 if not Is_Integer_Type (Etype (Operand)) then
6614 Enable_Overflow_Check (Conv);
6615 end if;
6617 Tnn :=
6618 Make_Defining_Identifier (Loc,
6619 Chars => New_Internal_Name ('T'));
6621 Insert_Actions (N, New_List (
6622 Make_Object_Declaration (Loc,
6623 Defining_Identifier => Tnn,
6624 Object_Definition => New_Occurrence_Of (Btyp, Loc),
6625 Expression => Conv),
6627 Make_Raise_Constraint_Error (Loc,
6628 Condition =>
6629 Make_Or_Else (Loc,
6630 Left_Opnd =>
6631 Make_Op_Lt (Loc,
6632 Left_Opnd => New_Occurrence_Of (Tnn, Loc),
6633 Right_Opnd =>
6634 Make_Attribute_Reference (Loc,
6635 Attribute_Name => Name_First,
6636 Prefix =>
6637 New_Occurrence_Of (Target_Type, Loc))),
6639 Right_Opnd =>
6640 Make_Op_Gt (Loc,
6641 Left_Opnd => New_Occurrence_Of (Tnn, Loc),
6642 Right_Opnd =>
6643 Make_Attribute_Reference (Loc,
6644 Attribute_Name => Name_Last,
6645 Prefix =>
6646 New_Occurrence_Of (Target_Type, Loc)))),
6647 Reason => CE_Range_Check_Failed)));
6649 Rewrite (N, New_Occurrence_Of (Tnn, Loc));
6650 Analyze_And_Resolve (N, Btyp);
6651 end Real_Range_Check;
6653 -- Start of processing for Expand_N_Type_Conversion
6655 begin
6656 -- Nothing at all to do if conversion is to the identical type
6657 -- so remove the conversion completely, it is useless.
6659 if Operand_Type = Target_Type then
6660 Rewrite (N, Relocate_Node (Operand));
6661 return;
6662 end if;
6664 -- Nothing to do if this is the second argument of read. This
6665 -- is a "backwards" conversion that will be handled by the
6666 -- specialized code in attribute processing.
6668 if Nkind (Parent (N)) = N_Attribute_Reference
6669 and then Attribute_Name (Parent (N)) = Name_Read
6670 and then Next (First (Expressions (Parent (N)))) = N
6671 then
6672 return;
6673 end if;
6675 -- Here if we may need to expand conversion
6677 -- Special case of converting from non-standard boolean type
6679 if Is_Boolean_Type (Operand_Type)
6680 and then (Nonzero_Is_True (Operand_Type))
6681 then
6682 Adjust_Condition (Operand);
6683 Set_Etype (Operand, Standard_Boolean);
6684 Operand_Type := Standard_Boolean;
6685 end if;
6687 -- Case of converting to an access type
6689 if Is_Access_Type (Target_Type) then
6691 -- Apply an accessibility check if the operand is an
6692 -- access parameter. Note that other checks may still
6693 -- need to be applied below (such as tagged type checks).
6695 if Is_Entity_Name (Operand)
6696 and then Ekind (Entity (Operand)) in Formal_Kind
6697 and then Ekind (Etype (Operand)) = E_Anonymous_Access_Type
6698 then
6699 Apply_Accessibility_Check (Operand, Target_Type);
6701 -- If the level of the operand type is statically deeper
6702 -- then the level of the target type, then force Program_Error.
6703 -- Note that this can only occur for cases where the attribute
6704 -- is within the body of an instantiation (otherwise the
6705 -- conversion will already have been rejected as illegal).
6706 -- Note: warnings are issued by the analyzer for the instance
6707 -- cases.
6709 elsif In_Instance_Body
6710 and then Type_Access_Level (Operand_Type) >
6711 Type_Access_Level (Target_Type)
6712 then
6713 Rewrite (N,
6714 Make_Raise_Program_Error (Sloc (N),
6715 Reason => PE_Accessibility_Check_Failed));
6716 Set_Etype (N, Target_Type);
6718 -- When the operand is a selected access discriminant
6719 -- the check needs to be made against the level of the
6720 -- object denoted by the prefix of the selected name.
6721 -- Force Program_Error for this case as well (this
6722 -- accessibility violation can only happen if within
6723 -- the body of an instantiation).
6725 elsif In_Instance_Body
6726 and then Ekind (Operand_Type) = E_Anonymous_Access_Type
6727 and then Nkind (Operand) = N_Selected_Component
6728 and then Object_Access_Level (Operand) >
6729 Type_Access_Level (Target_Type)
6730 then
6731 Rewrite (N,
6732 Make_Raise_Program_Error (Sloc (N),
6733 Reason => PE_Accessibility_Check_Failed));
6734 Set_Etype (N, Target_Type);
6735 end if;
6736 end if;
6738 -- Case of conversions of tagged types and access to tagged types
6740 -- When needed, that is to say when the expression is class-wide,
6741 -- Add runtime a tag check for (strict) downward conversion by using
6742 -- the membership test, generating:
6744 -- [constraint_error when Operand not in Target_Type'Class]
6746 -- or in the access type case
6748 -- [constraint_error
6749 -- when Operand /= null
6750 -- and then Operand.all not in
6751 -- Designated_Type (Target_Type)'Class]
6753 if (Is_Access_Type (Target_Type)
6754 and then Is_Tagged_Type (Designated_Type (Target_Type)))
6755 or else Is_Tagged_Type (Target_Type)
6756 then
6757 -- Do not do any expansion in the access type case if the
6758 -- parent is a renaming, since this is an error situation
6759 -- which will be caught by Sem_Ch8, and the expansion can
6760 -- intefere with this error check.
6762 if Is_Access_Type (Target_Type)
6763 and then Is_Renamed_Object (N)
6764 then
6765 return;
6766 end if;
6768 -- Oherwise, proceed with processing tagged conversion
6770 declare
6771 Actual_Operand_Type : Entity_Id;
6772 Actual_Target_Type : Entity_Id;
6774 Cond : Node_Id;
6776 begin
6777 if Is_Access_Type (Target_Type) then
6778 Actual_Operand_Type := Designated_Type (Operand_Type);
6779 Actual_Target_Type := Designated_Type (Target_Type);
6781 else
6782 Actual_Operand_Type := Operand_Type;
6783 Actual_Target_Type := Target_Type;
6784 end if;
6786 if Is_Class_Wide_Type (Actual_Operand_Type)
6787 and then Root_Type (Actual_Operand_Type) /= Actual_Target_Type
6788 and then Is_Ancestor
6789 (Root_Type (Actual_Operand_Type),
6790 Actual_Target_Type)
6791 and then not Tag_Checks_Suppressed (Actual_Target_Type)
6792 then
6793 -- The conversion is valid for any descendant of the
6794 -- target type
6796 Actual_Target_Type := Class_Wide_Type (Actual_Target_Type);
6798 if Is_Access_Type (Target_Type) then
6799 Cond :=
6800 Make_And_Then (Loc,
6801 Left_Opnd =>
6802 Make_Op_Ne (Loc,
6803 Left_Opnd => Duplicate_Subexpr_No_Checks (Operand),
6804 Right_Opnd => Make_Null (Loc)),
6806 Right_Opnd =>
6807 Make_Not_In (Loc,
6808 Left_Opnd =>
6809 Make_Explicit_Dereference (Loc,
6810 Prefix =>
6811 Duplicate_Subexpr_No_Checks (Operand)),
6812 Right_Opnd =>
6813 New_Reference_To (Actual_Target_Type, Loc)));
6815 else
6816 Cond :=
6817 Make_Not_In (Loc,
6818 Left_Opnd => Duplicate_Subexpr_No_Checks (Operand),
6819 Right_Opnd =>
6820 New_Reference_To (Actual_Target_Type, Loc));
6821 end if;
6823 Insert_Action (N,
6824 Make_Raise_Constraint_Error (Loc,
6825 Condition => Cond,
6826 Reason => CE_Tag_Check_Failed));
6828 declare
6829 Conv : Node_Id;
6830 begin
6831 Conv :=
6832 Make_Unchecked_Type_Conversion (Loc,
6833 Subtype_Mark => New_Occurrence_Of (Target_Type, Loc),
6834 Expression => Relocate_Node (Expression (N)));
6835 Rewrite (N, Conv);
6836 Analyze_And_Resolve (N, Target_Type);
6837 end;
6838 end if;
6839 end;
6841 -- Case of other access type conversions
6843 elsif Is_Access_Type (Target_Type) then
6844 Apply_Constraint_Check (Operand, Target_Type);
6846 -- Case of conversions from a fixed-point type
6848 -- These conversions require special expansion and processing, found
6849 -- in the Exp_Fixd package. We ignore cases where Conversion_OK is
6850 -- set, since from a semantic point of view, these are simple integer
6851 -- conversions, which do not need further processing.
6853 elsif Is_Fixed_Point_Type (Operand_Type)
6854 and then not Conversion_OK (N)
6855 then
6856 -- We should never see universal fixed at this case, since the
6857 -- expansion of the constituent divide or multiply should have
6858 -- eliminated the explicit mention of universal fixed.
6860 pragma Assert (Operand_Type /= Universal_Fixed);
6862 -- Check for special case of the conversion to universal real
6863 -- that occurs as a result of the use of a round attribute.
6864 -- In this case, the real type for the conversion is taken
6865 -- from the target type of the Round attribute and the
6866 -- result must be marked as rounded.
6868 if Target_Type = Universal_Real
6869 and then Nkind (Parent (N)) = N_Attribute_Reference
6870 and then Attribute_Name (Parent (N)) = Name_Round
6871 then
6872 Set_Rounded_Result (N);
6873 Set_Etype (N, Etype (Parent (N)));
6874 end if;
6876 -- Otherwise do correct fixed-conversion, but skip these if the
6877 -- Conversion_OK flag is set, because from a semantic point of
6878 -- view these are simple integer conversions needing no further
6879 -- processing (the backend will simply treat them as integers)
6881 if not Conversion_OK (N) then
6882 if Is_Fixed_Point_Type (Etype (N)) then
6883 Expand_Convert_Fixed_To_Fixed (N);
6884 Real_Range_Check;
6886 elsif Is_Integer_Type (Etype (N)) then
6887 Expand_Convert_Fixed_To_Integer (N);
6889 else
6890 pragma Assert (Is_Floating_Point_Type (Etype (N)));
6891 Expand_Convert_Fixed_To_Float (N);
6892 Real_Range_Check;
6893 end if;
6894 end if;
6896 -- Case of conversions to a fixed-point type
6898 -- These conversions require special expansion and processing, found
6899 -- in the Exp_Fixd package. Again, ignore cases where Conversion_OK
6900 -- is set, since from a semantic point of view, these are simple
6901 -- integer conversions, which do not need further processing.
6903 elsif Is_Fixed_Point_Type (Target_Type)
6904 and then not Conversion_OK (N)
6905 then
6906 if Is_Integer_Type (Operand_Type) then
6907 Expand_Convert_Integer_To_Fixed (N);
6908 Real_Range_Check;
6909 else
6910 pragma Assert (Is_Floating_Point_Type (Operand_Type));
6911 Expand_Convert_Float_To_Fixed (N);
6912 Real_Range_Check;
6913 end if;
6915 -- Case of float-to-integer conversions
6917 -- We also handle float-to-fixed conversions with Conversion_OK set
6918 -- since semantically the fixed-point target is treated as though it
6919 -- were an integer in such cases.
6921 elsif Is_Floating_Point_Type (Operand_Type)
6922 and then
6923 (Is_Integer_Type (Target_Type)
6924 or else
6925 (Is_Fixed_Point_Type (Target_Type) and then Conversion_OK (N)))
6926 then
6927 -- Special processing required if the conversion is the expression
6928 -- of a Truncation attribute reference. In this case we replace:
6930 -- ityp (ftyp'Truncation (x))
6932 -- by
6934 -- ityp (x)
6936 -- with the Float_Truncate flag set. This is clearly more efficient
6938 if Nkind (Operand) = N_Attribute_Reference
6939 and then Attribute_Name (Operand) = Name_Truncation
6940 then
6941 Rewrite (Operand,
6942 Relocate_Node (First (Expressions (Operand))));
6943 Set_Float_Truncate (N, True);
6944 end if;
6946 -- One more check here, gcc is still not able to do conversions of
6947 -- this type with proper overflow checking, and so gigi is doing an
6948 -- approximation of what is required by doing floating-point compares
6949 -- with the end-point. But that can lose precision in some cases, and
6950 -- give a wrong result. Converting the operand to Universal_Real is
6951 -- helpful, but still does not catch all cases with 64-bit integers
6952 -- on targets with only 64-bit floats ???
6954 if Do_Range_Check (Operand) then
6955 Rewrite (Operand,
6956 Make_Type_Conversion (Loc,
6957 Subtype_Mark =>
6958 New_Occurrence_Of (Universal_Real, Loc),
6959 Expression =>
6960 Relocate_Node (Operand)));
6962 Set_Etype (Operand, Universal_Real);
6963 Enable_Range_Check (Operand);
6964 Set_Do_Range_Check (Expression (Operand), False);
6965 end if;
6967 -- Case of array conversions
6969 -- Expansion of array conversions, add required length/range checks
6970 -- but only do this if there is no change of representation. For
6971 -- handling of this case, see Handle_Changed_Representation.
6973 elsif Is_Array_Type (Target_Type) then
6975 if Is_Constrained (Target_Type) then
6976 Apply_Length_Check (Operand, Target_Type);
6977 else
6978 Apply_Range_Check (Operand, Target_Type);
6979 end if;
6981 Handle_Changed_Representation;
6983 -- Case of conversions of discriminated types
6985 -- Add required discriminant checks if target is constrained. Again
6986 -- this change is skipped if we have a change of representation.
6988 elsif Has_Discriminants (Target_Type)
6989 and then Is_Constrained (Target_Type)
6990 then
6991 Apply_Discriminant_Check (Operand, Target_Type);
6992 Handle_Changed_Representation;
6994 -- Case of all other record conversions. The only processing required
6995 -- is to check for a change of representation requiring the special
6996 -- assignment processing.
6998 elsif Is_Record_Type (Target_Type) then
7000 -- Ada 2005 (AI-216): Program_Error is raised when converting from
7001 -- a derived Unchecked_Union type to an unconstrained non-Unchecked_
7002 -- Union type if the operand lacks inferable discriminants.
7004 if Is_Derived_Type (Operand_Type)
7005 and then Is_Unchecked_Union (Base_Type (Operand_Type))
7006 and then not Is_Constrained (Target_Type)
7007 and then not Is_Unchecked_Union (Base_Type (Target_Type))
7008 and then not Has_Inferable_Discriminants (Operand)
7009 then
7010 -- To prevent Gigi from generating illegal code, we make a
7011 -- Program_Error node, but we give it the target type of the
7012 -- conversion.
7014 declare
7015 PE : constant Node_Id := Make_Raise_Program_Error (Loc,
7016 Reason => PE_Unchecked_Union_Restriction);
7018 begin
7019 Set_Etype (PE, Target_Type);
7020 Rewrite (N, PE);
7022 end;
7023 else
7024 Handle_Changed_Representation;
7025 end if;
7027 -- Case of conversions of enumeration types
7029 elsif Is_Enumeration_Type (Target_Type) then
7031 -- Special processing is required if there is a change of
7032 -- representation (from enumeration representation clauses)
7034 if not Same_Representation (Target_Type, Operand_Type) then
7036 -- Convert: x(y) to x'val (ytyp'val (y))
7038 Rewrite (N,
7039 Make_Attribute_Reference (Loc,
7040 Prefix => New_Occurrence_Of (Target_Type, Loc),
7041 Attribute_Name => Name_Val,
7042 Expressions => New_List (
7043 Make_Attribute_Reference (Loc,
7044 Prefix => New_Occurrence_Of (Operand_Type, Loc),
7045 Attribute_Name => Name_Pos,
7046 Expressions => New_List (Operand)))));
7048 Analyze_And_Resolve (N, Target_Type);
7049 end if;
7051 -- Case of conversions to floating-point
7053 elsif Is_Floating_Point_Type (Target_Type) then
7054 Real_Range_Check;
7055 end if;
7057 -- At this stage, either the conversion node has been transformed
7058 -- into some other equivalent expression, or left as a conversion
7059 -- that can be handled by Gigi. The conversions that Gigi can handle
7060 -- are the following:
7062 -- Conversions with no change of representation or type
7064 -- Numeric conversions involving integer values, floating-point
7065 -- values, and fixed-point values. Fixed-point values are allowed
7066 -- only if Conversion_OK is set, i.e. if the fixed-point values
7067 -- are to be treated as integers.
7069 -- No other conversions should be passed to Gigi
7071 -- Check: are these rules stated in sinfo??? if so, why restate here???
7073 -- The only remaining step is to generate a range check if we still
7074 -- have a type conversion at this stage and Do_Range_Check is set.
7075 -- For now we do this only for conversions of discrete types.
7077 if Nkind (N) = N_Type_Conversion
7078 and then Is_Discrete_Type (Etype (N))
7079 then
7080 declare
7081 Expr : constant Node_Id := Expression (N);
7082 Ftyp : Entity_Id;
7083 Ityp : Entity_Id;
7085 begin
7086 if Do_Range_Check (Expr)
7087 and then Is_Discrete_Type (Etype (Expr))
7088 then
7089 Set_Do_Range_Check (Expr, False);
7091 -- Before we do a range check, we have to deal with treating
7092 -- a fixed-point operand as an integer. The way we do this
7093 -- is simply to do an unchecked conversion to an appropriate
7094 -- integer type large enough to hold the result.
7096 -- This code is not active yet, because we are only dealing
7097 -- with discrete types so far ???
7099 if Nkind (Expr) in N_Has_Treat_Fixed_As_Integer
7100 and then Treat_Fixed_As_Integer (Expr)
7101 then
7102 Ftyp := Base_Type (Etype (Expr));
7104 if Esize (Ftyp) >= Esize (Standard_Integer) then
7105 Ityp := Standard_Long_Long_Integer;
7106 else
7107 Ityp := Standard_Integer;
7108 end if;
7110 Rewrite (Expr, Unchecked_Convert_To (Ityp, Expr));
7111 end if;
7113 -- Reset overflow flag, since the range check will include
7114 -- dealing with possible overflow, and generate the check
7115 -- If Address is either source or target type, suppress
7116 -- range check to avoid typing anomalies when it is a visible
7117 -- integer type.
7119 Set_Do_Overflow_Check (N, False);
7120 if not Is_Descendent_Of_Address (Etype (Expr))
7121 and then not Is_Descendent_Of_Address (Target_Type)
7122 then
7123 Generate_Range_Check
7124 (Expr, Target_Type, CE_Range_Check_Failed);
7125 end if;
7126 end if;
7127 end;
7128 end if;
7130 -- Final step, if the result is a type conversion involving Vax_Float
7131 -- types, then it is subject for further special processing.
7133 if Nkind (N) = N_Type_Conversion
7134 and then (Vax_Float (Operand_Type) or else Vax_Float (Target_Type))
7135 then
7136 Expand_Vax_Conversion (N);
7137 return;
7138 end if;
7139 end Expand_N_Type_Conversion;
7141 -----------------------------------
7142 -- Expand_N_Unchecked_Expression --
7143 -----------------------------------
7145 -- Remove the unchecked expression node from the tree. It's job was simply
7146 -- to make sure that its constituent expression was handled with checks
7147 -- off, and now that that is done, we can remove it from the tree, and
7148 -- indeed must, since gigi does not expect to see these nodes.
7150 procedure Expand_N_Unchecked_Expression (N : Node_Id) is
7151 Exp : constant Node_Id := Expression (N);
7153 begin
7154 Set_Assignment_OK (Exp, Assignment_OK (N) or Assignment_OK (Exp));
7155 Rewrite (N, Exp);
7156 end Expand_N_Unchecked_Expression;
7158 ----------------------------------------
7159 -- Expand_N_Unchecked_Type_Conversion --
7160 ----------------------------------------
7162 -- If this cannot be handled by Gigi and we haven't already made
7163 -- a temporary for it, do it now.
7165 procedure Expand_N_Unchecked_Type_Conversion (N : Node_Id) is
7166 Target_Type : constant Entity_Id := Etype (N);
7167 Operand : constant Node_Id := Expression (N);
7168 Operand_Type : constant Entity_Id := Etype (Operand);
7170 begin
7171 -- If we have a conversion of a compile time known value to a target
7172 -- type and the value is in range of the target type, then we can simply
7173 -- replace the construct by an integer literal of the correct type. We
7174 -- only apply this to integer types being converted. Possibly it may
7175 -- apply in other cases, but it is too much trouble to worry about.
7177 -- Note that we do not do this transformation if the Kill_Range_Check
7178 -- flag is set, since then the value may be outside the expected range.
7179 -- This happens in the Normalize_Scalars case.
7181 if Is_Integer_Type (Target_Type)
7182 and then Is_Integer_Type (Operand_Type)
7183 and then Compile_Time_Known_Value (Operand)
7184 and then not Kill_Range_Check (N)
7185 then
7186 declare
7187 Val : constant Uint := Expr_Value (Operand);
7189 begin
7190 if Compile_Time_Known_Value (Type_Low_Bound (Target_Type))
7191 and then
7192 Compile_Time_Known_Value (Type_High_Bound (Target_Type))
7193 and then
7194 Val >= Expr_Value (Type_Low_Bound (Target_Type))
7195 and then
7196 Val <= Expr_Value (Type_High_Bound (Target_Type))
7197 then
7198 Rewrite (N, Make_Integer_Literal (Sloc (N), Val));
7200 -- If Address is the target type, just set the type
7201 -- to avoid a spurious type error on the literal when
7202 -- Address is a visible integer type.
7204 if Is_Descendent_Of_Address (Target_Type) then
7205 Set_Etype (N, Target_Type);
7206 else
7207 Analyze_And_Resolve (N, Target_Type);
7208 end if;
7210 return;
7211 end if;
7212 end;
7213 end if;
7215 -- Nothing to do if conversion is safe
7217 if Safe_Unchecked_Type_Conversion (N) then
7218 return;
7219 end if;
7221 -- Otherwise force evaluation unless Assignment_OK flag is set (this
7222 -- flag indicates ??? -- more comments needed here)
7224 if Assignment_OK (N) then
7225 null;
7226 else
7227 Force_Evaluation (N);
7228 end if;
7229 end Expand_N_Unchecked_Type_Conversion;
7231 ----------------------------
7232 -- Expand_Record_Equality --
7233 ----------------------------
7235 -- For non-variant records, Equality is expanded when needed into:
7237 -- and then Lhs.Discr1 = Rhs.Discr1
7238 -- and then ...
7239 -- and then Lhs.Discrn = Rhs.Discrn
7240 -- and then Lhs.Cmp1 = Rhs.Cmp1
7241 -- and then ...
7242 -- and then Lhs.Cmpn = Rhs.Cmpn
7244 -- The expression is folded by the back-end for adjacent fields. This
7245 -- function is called for tagged record in only one occasion: for imple-
7246 -- menting predefined primitive equality (see Predefined_Primitives_Bodies)
7247 -- otherwise the primitive "=" is used directly.
7249 function Expand_Record_Equality
7250 (Nod : Node_Id;
7251 Typ : Entity_Id;
7252 Lhs : Node_Id;
7253 Rhs : Node_Id;
7254 Bodies : List_Id) return Node_Id
7256 Loc : constant Source_Ptr := Sloc (Nod);
7258 Result : Node_Id;
7259 C : Entity_Id;
7261 First_Time : Boolean := True;
7263 function Suitable_Element (C : Entity_Id) return Entity_Id;
7264 -- Return the first field to compare beginning with C, skipping the
7265 -- inherited components.
7267 ----------------------
7268 -- Suitable_Element --
7269 ----------------------
7271 function Suitable_Element (C : Entity_Id) return Entity_Id is
7272 begin
7273 if No (C) then
7274 return Empty;
7276 elsif Ekind (C) /= E_Discriminant
7277 and then Ekind (C) /= E_Component
7278 then
7279 return Suitable_Element (Next_Entity (C));
7281 elsif Is_Tagged_Type (Typ)
7282 and then C /= Original_Record_Component (C)
7283 then
7284 return Suitable_Element (Next_Entity (C));
7286 elsif Chars (C) = Name_uController
7287 or else Chars (C) = Name_uTag
7288 then
7289 return Suitable_Element (Next_Entity (C));
7291 else
7292 return C;
7293 end if;
7294 end Suitable_Element;
7296 -- Start of processing for Expand_Record_Equality
7298 begin
7299 -- Generates the following code: (assuming that Typ has one Discr and
7300 -- component C2 is also a record)
7302 -- True
7303 -- and then Lhs.Discr1 = Rhs.Discr1
7304 -- and then Lhs.C1 = Rhs.C1
7305 -- and then Lhs.C2.C1=Rhs.C2.C1 and then ... Lhs.C2.Cn=Rhs.C2.Cn
7306 -- and then ...
7307 -- and then Lhs.Cmpn = Rhs.Cmpn
7309 Result := New_Reference_To (Standard_True, Loc);
7310 C := Suitable_Element (First_Entity (Typ));
7312 while Present (C) loop
7313 declare
7314 New_Lhs : Node_Id;
7315 New_Rhs : Node_Id;
7316 Check : Node_Id;
7318 begin
7319 if First_Time then
7320 First_Time := False;
7321 New_Lhs := Lhs;
7322 New_Rhs := Rhs;
7323 else
7324 New_Lhs := New_Copy_Tree (Lhs);
7325 New_Rhs := New_Copy_Tree (Rhs);
7326 end if;
7328 Check :=
7329 Expand_Composite_Equality (Nod, Etype (C),
7330 Lhs =>
7331 Make_Selected_Component (Loc,
7332 Prefix => New_Lhs,
7333 Selector_Name => New_Reference_To (C, Loc)),
7334 Rhs =>
7335 Make_Selected_Component (Loc,
7336 Prefix => New_Rhs,
7337 Selector_Name => New_Reference_To (C, Loc)),
7338 Bodies => Bodies);
7340 -- If some (sub)component is an unchecked_union, the whole
7341 -- operation will raise program error.
7343 if Nkind (Check) = N_Raise_Program_Error then
7344 Result := Check;
7345 Set_Etype (Result, Standard_Boolean);
7346 exit;
7347 else
7348 Result :=
7349 Make_And_Then (Loc,
7350 Left_Opnd => Result,
7351 Right_Opnd => Check);
7352 end if;
7353 end;
7355 C := Suitable_Element (Next_Entity (C));
7356 end loop;
7358 return Result;
7359 end Expand_Record_Equality;
7361 -------------------------------------
7362 -- Fixup_Universal_Fixed_Operation --
7363 -------------------------------------
7365 procedure Fixup_Universal_Fixed_Operation (N : Node_Id) is
7366 Conv : constant Node_Id := Parent (N);
7368 begin
7369 -- We must have a type conversion immediately above us
7371 pragma Assert (Nkind (Conv) = N_Type_Conversion);
7373 -- Normally the type conversion gives our target type. The exception
7374 -- occurs in the case of the Round attribute, where the conversion
7375 -- will be to universal real, and our real type comes from the Round
7376 -- attribute (as well as an indication that we must round the result)
7378 if Nkind (Parent (Conv)) = N_Attribute_Reference
7379 and then Attribute_Name (Parent (Conv)) = Name_Round
7380 then
7381 Set_Etype (N, Etype (Parent (Conv)));
7382 Set_Rounded_Result (N);
7384 -- Normal case where type comes from conversion above us
7386 else
7387 Set_Etype (N, Etype (Conv));
7388 end if;
7389 end Fixup_Universal_Fixed_Operation;
7391 ------------------------------
7392 -- Get_Allocator_Final_List --
7393 ------------------------------
7395 function Get_Allocator_Final_List
7396 (N : Node_Id;
7397 T : Entity_Id;
7398 PtrT : Entity_Id) return Entity_Id
7400 Loc : constant Source_Ptr := Sloc (N);
7402 Owner : Entity_Id := PtrT;
7403 -- The entity whose finalisation list must be used to attach the
7404 -- allocated object.
7406 begin
7407 if Ekind (PtrT) = E_Anonymous_Access_Type then
7408 if Nkind (Associated_Node_For_Itype (PtrT))
7409 in N_Subprogram_Specification
7410 then
7411 -- If the context is an access parameter, we need to create
7412 -- a non-anonymous access type in order to have a usable
7413 -- final list, because there is otherwise no pool to which
7414 -- the allocated object can belong. We create both the type
7415 -- and the finalization chain here, because freezing an
7416 -- internal type does not create such a chain. The Final_Chain
7417 -- that is thus created is shared by the access parameter.
7419 Owner := Make_Defining_Identifier (Loc, New_Internal_Name ('J'));
7420 Insert_Action (N,
7421 Make_Full_Type_Declaration (Loc,
7422 Defining_Identifier => Owner,
7423 Type_Definition =>
7424 Make_Access_To_Object_Definition (Loc,
7425 Subtype_Indication =>
7426 New_Occurrence_Of (T, Loc))));
7428 Build_Final_List (N, Owner);
7429 Set_Associated_Final_Chain (PtrT, Associated_Final_Chain (Owner));
7431 else
7432 -- Case of an access discriminant, or (Ada 2005) of
7433 -- an anonymous access component: find the final list
7434 -- associated with the scope of the type.
7436 Owner := Scope (PtrT);
7437 end if;
7438 end if;
7440 return Find_Final_List (Owner);
7441 end Get_Allocator_Final_List;
7443 ---------------------------------
7444 -- Has_Inferable_Discriminants --
7445 ---------------------------------
7447 function Has_Inferable_Discriminants (N : Node_Id) return Boolean is
7449 function Prefix_Is_Formal_Parameter (N : Node_Id) return Boolean;
7450 -- Determines whether the left-most prefix of a selected component is a
7451 -- formal parameter in a subprogram. Assumes N is a selected component.
7453 --------------------------------
7454 -- Prefix_Is_Formal_Parameter --
7455 --------------------------------
7457 function Prefix_Is_Formal_Parameter (N : Node_Id) return Boolean is
7458 Sel_Comp : Node_Id := N;
7460 begin
7461 -- Move to the left-most prefix by climbing up the tree
7463 while Present (Parent (Sel_Comp))
7464 and then Nkind (Parent (Sel_Comp)) = N_Selected_Component
7465 loop
7466 Sel_Comp := Parent (Sel_Comp);
7467 end loop;
7469 return Ekind (Entity (Prefix (Sel_Comp))) in Formal_Kind;
7470 end Prefix_Is_Formal_Parameter;
7472 -- Start of processing for Has_Inferable_Discriminants
7474 begin
7475 -- For identifiers and indexed components, it is sufficent to have a
7476 -- constrained Unchecked_Union nominal subtype.
7478 if Nkind (N) = N_Identifier
7479 or else
7480 Nkind (N) = N_Indexed_Component
7481 then
7482 return Is_Unchecked_Union (Base_Type (Etype (N)))
7483 and then
7484 Is_Constrained (Etype (N));
7486 -- For selected components, the subtype of the selector must be a
7487 -- constrained Unchecked_Union. If the component is subject to a
7488 -- per-object constraint, then the enclosing object must have inferable
7489 -- discriminants.
7491 elsif Nkind (N) = N_Selected_Component then
7492 if Has_Per_Object_Constraint (Entity (Selector_Name (N))) then
7494 -- A small hack. If we have a per-object constrained selected
7495 -- component of a formal parameter, return True since we do not
7496 -- know the actual parameter association yet.
7498 if Prefix_Is_Formal_Parameter (N) then
7499 return True;
7500 end if;
7502 -- Otherwise, check the enclosing object and the selector
7504 return Has_Inferable_Discriminants (Prefix (N))
7505 and then
7506 Has_Inferable_Discriminants (Selector_Name (N));
7507 end if;
7509 -- The call to Has_Inferable_Discriminants will determine whether
7510 -- the selector has a constrained Unchecked_Union nominal type.
7512 return Has_Inferable_Discriminants (Selector_Name (N));
7514 -- A qualified expression has inferable discriminants if its subtype
7515 -- mark is a constrained Unchecked_Union subtype.
7517 elsif Nkind (N) = N_Qualified_Expression then
7518 return Is_Unchecked_Union (Subtype_Mark (N))
7519 and then
7520 Is_Constrained (Subtype_Mark (N));
7522 end if;
7524 return False;
7525 end Has_Inferable_Discriminants;
7527 -------------------------------
7528 -- Insert_Dereference_Action --
7529 -------------------------------
7531 procedure Insert_Dereference_Action (N : Node_Id) is
7532 Loc : constant Source_Ptr := Sloc (N);
7533 Typ : constant Entity_Id := Etype (N);
7534 Pool : constant Entity_Id := Associated_Storage_Pool (Typ);
7535 Pnod : constant Node_Id := Parent (N);
7537 function Is_Checked_Storage_Pool (P : Entity_Id) return Boolean;
7538 -- Return true if type of P is derived from Checked_Pool;
7540 -----------------------------
7541 -- Is_Checked_Storage_Pool --
7542 -----------------------------
7544 function Is_Checked_Storage_Pool (P : Entity_Id) return Boolean is
7545 T : Entity_Id;
7547 begin
7548 if No (P) then
7549 return False;
7550 end if;
7552 T := Etype (P);
7553 while T /= Etype (T) loop
7554 if Is_RTE (T, RE_Checked_Pool) then
7555 return True;
7556 else
7557 T := Etype (T);
7558 end if;
7559 end loop;
7561 return False;
7562 end Is_Checked_Storage_Pool;
7564 -- Start of processing for Insert_Dereference_Action
7566 begin
7567 pragma Assert (Nkind (Pnod) = N_Explicit_Dereference);
7569 if not (Is_Checked_Storage_Pool (Pool)
7570 and then Comes_From_Source (Original_Node (Pnod)))
7571 then
7572 return;
7573 end if;
7575 Insert_Action (N,
7576 Make_Procedure_Call_Statement (Loc,
7577 Name => New_Reference_To (
7578 Find_Prim_Op (Etype (Pool), Name_Dereference), Loc),
7580 Parameter_Associations => New_List (
7582 -- Pool
7584 New_Reference_To (Pool, Loc),
7586 -- Storage_Address. We use the attribute Pool_Address,
7587 -- which uses the pointer itself to find the address of
7588 -- the object, and which handles unconstrained arrays
7589 -- properly by computing the address of the template.
7590 -- i.e. the correct address of the corresponding allocation.
7592 Make_Attribute_Reference (Loc,
7593 Prefix => Duplicate_Subexpr_Move_Checks (N),
7594 Attribute_Name => Name_Pool_Address),
7596 -- Size_In_Storage_Elements
7598 Make_Op_Divide (Loc,
7599 Left_Opnd =>
7600 Make_Attribute_Reference (Loc,
7601 Prefix =>
7602 Make_Explicit_Dereference (Loc,
7603 Duplicate_Subexpr_Move_Checks (N)),
7604 Attribute_Name => Name_Size),
7605 Right_Opnd =>
7606 Make_Integer_Literal (Loc, System_Storage_Unit)),
7608 -- Alignment
7610 Make_Attribute_Reference (Loc,
7611 Prefix =>
7612 Make_Explicit_Dereference (Loc,
7613 Duplicate_Subexpr_Move_Checks (N)),
7614 Attribute_Name => Name_Alignment))));
7616 exception
7617 when RE_Not_Available =>
7618 return;
7619 end Insert_Dereference_Action;
7621 ------------------------------
7622 -- Make_Array_Comparison_Op --
7623 ------------------------------
7625 -- This is a hand-coded expansion of the following generic function:
7627 -- generic
7628 -- type elem is (<>);
7629 -- type index is (<>);
7630 -- type a is array (index range <>) of elem;
7632 -- function Gnnn (X : a; Y: a) return boolean is
7633 -- J : index := Y'first;
7635 -- begin
7636 -- if X'length = 0 then
7637 -- return false;
7639 -- elsif Y'length = 0 then
7640 -- return true;
7642 -- else
7643 -- for I in X'range loop
7644 -- if X (I) = Y (J) then
7645 -- if J = Y'last then
7646 -- exit;
7647 -- else
7648 -- J := index'succ (J);
7649 -- end if;
7651 -- else
7652 -- return X (I) > Y (J);
7653 -- end if;
7654 -- end loop;
7656 -- return X'length > Y'length;
7657 -- end if;
7658 -- end Gnnn;
7660 -- Note that since we are essentially doing this expansion by hand, we
7661 -- do not need to generate an actual or formal generic part, just the
7662 -- instantiated function itself.
7664 function Make_Array_Comparison_Op
7665 (Typ : Entity_Id;
7666 Nod : Node_Id) return Node_Id
7668 Loc : constant Source_Ptr := Sloc (Nod);
7670 X : constant Entity_Id := Make_Defining_Identifier (Loc, Name_uX);
7671 Y : constant Entity_Id := Make_Defining_Identifier (Loc, Name_uY);
7672 I : constant Entity_Id := Make_Defining_Identifier (Loc, Name_uI);
7673 J : constant Entity_Id := Make_Defining_Identifier (Loc, Name_uJ);
7675 Index : constant Entity_Id := Base_Type (Etype (First_Index (Typ)));
7677 Loop_Statement : Node_Id;
7678 Loop_Body : Node_Id;
7679 If_Stat : Node_Id;
7680 Inner_If : Node_Id;
7681 Final_Expr : Node_Id;
7682 Func_Body : Node_Id;
7683 Func_Name : Entity_Id;
7684 Formals : List_Id;
7685 Length1 : Node_Id;
7686 Length2 : Node_Id;
7688 begin
7689 -- if J = Y'last then
7690 -- exit;
7691 -- else
7692 -- J := index'succ (J);
7693 -- end if;
7695 Inner_If :=
7696 Make_Implicit_If_Statement (Nod,
7697 Condition =>
7698 Make_Op_Eq (Loc,
7699 Left_Opnd => New_Reference_To (J, Loc),
7700 Right_Opnd =>
7701 Make_Attribute_Reference (Loc,
7702 Prefix => New_Reference_To (Y, Loc),
7703 Attribute_Name => Name_Last)),
7705 Then_Statements => New_List (
7706 Make_Exit_Statement (Loc)),
7708 Else_Statements =>
7709 New_List (
7710 Make_Assignment_Statement (Loc,
7711 Name => New_Reference_To (J, Loc),
7712 Expression =>
7713 Make_Attribute_Reference (Loc,
7714 Prefix => New_Reference_To (Index, Loc),
7715 Attribute_Name => Name_Succ,
7716 Expressions => New_List (New_Reference_To (J, Loc))))));
7718 -- if X (I) = Y (J) then
7719 -- if ... end if;
7720 -- else
7721 -- return X (I) > Y (J);
7722 -- end if;
7724 Loop_Body :=
7725 Make_Implicit_If_Statement (Nod,
7726 Condition =>
7727 Make_Op_Eq (Loc,
7728 Left_Opnd =>
7729 Make_Indexed_Component (Loc,
7730 Prefix => New_Reference_To (X, Loc),
7731 Expressions => New_List (New_Reference_To (I, Loc))),
7733 Right_Opnd =>
7734 Make_Indexed_Component (Loc,
7735 Prefix => New_Reference_To (Y, Loc),
7736 Expressions => New_List (New_Reference_To (J, Loc)))),
7738 Then_Statements => New_List (Inner_If),
7740 Else_Statements => New_List (
7741 Make_Return_Statement (Loc,
7742 Expression =>
7743 Make_Op_Gt (Loc,
7744 Left_Opnd =>
7745 Make_Indexed_Component (Loc,
7746 Prefix => New_Reference_To (X, Loc),
7747 Expressions => New_List (New_Reference_To (I, Loc))),
7749 Right_Opnd =>
7750 Make_Indexed_Component (Loc,
7751 Prefix => New_Reference_To (Y, Loc),
7752 Expressions => New_List (
7753 New_Reference_To (J, Loc)))))));
7755 -- for I in X'range loop
7756 -- if ... end if;
7757 -- end loop;
7759 Loop_Statement :=
7760 Make_Implicit_Loop_Statement (Nod,
7761 Identifier => Empty,
7763 Iteration_Scheme =>
7764 Make_Iteration_Scheme (Loc,
7765 Loop_Parameter_Specification =>
7766 Make_Loop_Parameter_Specification (Loc,
7767 Defining_Identifier => I,
7768 Discrete_Subtype_Definition =>
7769 Make_Attribute_Reference (Loc,
7770 Prefix => New_Reference_To (X, Loc),
7771 Attribute_Name => Name_Range))),
7773 Statements => New_List (Loop_Body));
7775 -- if X'length = 0 then
7776 -- return false;
7777 -- elsif Y'length = 0 then
7778 -- return true;
7779 -- else
7780 -- for ... loop ... end loop;
7781 -- return X'length > Y'length;
7782 -- end if;
7784 Length1 :=
7785 Make_Attribute_Reference (Loc,
7786 Prefix => New_Reference_To (X, Loc),
7787 Attribute_Name => Name_Length);
7789 Length2 :=
7790 Make_Attribute_Reference (Loc,
7791 Prefix => New_Reference_To (Y, Loc),
7792 Attribute_Name => Name_Length);
7794 Final_Expr :=
7795 Make_Op_Gt (Loc,
7796 Left_Opnd => Length1,
7797 Right_Opnd => Length2);
7799 If_Stat :=
7800 Make_Implicit_If_Statement (Nod,
7801 Condition =>
7802 Make_Op_Eq (Loc,
7803 Left_Opnd =>
7804 Make_Attribute_Reference (Loc,
7805 Prefix => New_Reference_To (X, Loc),
7806 Attribute_Name => Name_Length),
7807 Right_Opnd =>
7808 Make_Integer_Literal (Loc, 0)),
7810 Then_Statements =>
7811 New_List (
7812 Make_Return_Statement (Loc,
7813 Expression => New_Reference_To (Standard_False, Loc))),
7815 Elsif_Parts => New_List (
7816 Make_Elsif_Part (Loc,
7817 Condition =>
7818 Make_Op_Eq (Loc,
7819 Left_Opnd =>
7820 Make_Attribute_Reference (Loc,
7821 Prefix => New_Reference_To (Y, Loc),
7822 Attribute_Name => Name_Length),
7823 Right_Opnd =>
7824 Make_Integer_Literal (Loc, 0)),
7826 Then_Statements =>
7827 New_List (
7828 Make_Return_Statement (Loc,
7829 Expression => New_Reference_To (Standard_True, Loc))))),
7831 Else_Statements => New_List (
7832 Loop_Statement,
7833 Make_Return_Statement (Loc,
7834 Expression => Final_Expr)));
7836 -- (X : a; Y: a)
7838 Formals := New_List (
7839 Make_Parameter_Specification (Loc,
7840 Defining_Identifier => X,
7841 Parameter_Type => New_Reference_To (Typ, Loc)),
7843 Make_Parameter_Specification (Loc,
7844 Defining_Identifier => Y,
7845 Parameter_Type => New_Reference_To (Typ, Loc)));
7847 -- function Gnnn (...) return boolean is
7848 -- J : index := Y'first;
7849 -- begin
7850 -- if ... end if;
7851 -- end Gnnn;
7853 Func_Name := Make_Defining_Identifier (Loc, New_Internal_Name ('G'));
7855 Func_Body :=
7856 Make_Subprogram_Body (Loc,
7857 Specification =>
7858 Make_Function_Specification (Loc,
7859 Defining_Unit_Name => Func_Name,
7860 Parameter_Specifications => Formals,
7861 Result_Definition => New_Reference_To (Standard_Boolean, Loc)),
7863 Declarations => New_List (
7864 Make_Object_Declaration (Loc,
7865 Defining_Identifier => J,
7866 Object_Definition => New_Reference_To (Index, Loc),
7867 Expression =>
7868 Make_Attribute_Reference (Loc,
7869 Prefix => New_Reference_To (Y, Loc),
7870 Attribute_Name => Name_First))),
7872 Handled_Statement_Sequence =>
7873 Make_Handled_Sequence_Of_Statements (Loc,
7874 Statements => New_List (If_Stat)));
7876 return Func_Body;
7877 end Make_Array_Comparison_Op;
7879 ---------------------------
7880 -- Make_Boolean_Array_Op --
7881 ---------------------------
7883 -- For logical operations on boolean arrays, expand in line the
7884 -- following, replacing 'and' with 'or' or 'xor' where needed:
7886 -- function Annn (A : typ; B: typ) return typ is
7887 -- C : typ;
7888 -- begin
7889 -- for J in A'range loop
7890 -- C (J) := A (J) op B (J);
7891 -- end loop;
7892 -- return C;
7893 -- end Annn;
7895 -- Here typ is the boolean array type
7897 function Make_Boolean_Array_Op
7898 (Typ : Entity_Id;
7899 N : Node_Id) return Node_Id
7901 Loc : constant Source_Ptr := Sloc (N);
7903 A : constant Entity_Id := Make_Defining_Identifier (Loc, Name_uA);
7904 B : constant Entity_Id := Make_Defining_Identifier (Loc, Name_uB);
7905 C : constant Entity_Id := Make_Defining_Identifier (Loc, Name_uC);
7906 J : constant Entity_Id := Make_Defining_Identifier (Loc, Name_uJ);
7908 A_J : Node_Id;
7909 B_J : Node_Id;
7910 C_J : Node_Id;
7911 Op : Node_Id;
7913 Formals : List_Id;
7914 Func_Name : Entity_Id;
7915 Func_Body : Node_Id;
7916 Loop_Statement : Node_Id;
7918 begin
7919 A_J :=
7920 Make_Indexed_Component (Loc,
7921 Prefix => New_Reference_To (A, Loc),
7922 Expressions => New_List (New_Reference_To (J, Loc)));
7924 B_J :=
7925 Make_Indexed_Component (Loc,
7926 Prefix => New_Reference_To (B, Loc),
7927 Expressions => New_List (New_Reference_To (J, Loc)));
7929 C_J :=
7930 Make_Indexed_Component (Loc,
7931 Prefix => New_Reference_To (C, Loc),
7932 Expressions => New_List (New_Reference_To (J, Loc)));
7934 if Nkind (N) = N_Op_And then
7935 Op :=
7936 Make_Op_And (Loc,
7937 Left_Opnd => A_J,
7938 Right_Opnd => B_J);
7940 elsif Nkind (N) = N_Op_Or then
7941 Op :=
7942 Make_Op_Or (Loc,
7943 Left_Opnd => A_J,
7944 Right_Opnd => B_J);
7946 else
7947 Op :=
7948 Make_Op_Xor (Loc,
7949 Left_Opnd => A_J,
7950 Right_Opnd => B_J);
7951 end if;
7953 Loop_Statement :=
7954 Make_Implicit_Loop_Statement (N,
7955 Identifier => Empty,
7957 Iteration_Scheme =>
7958 Make_Iteration_Scheme (Loc,
7959 Loop_Parameter_Specification =>
7960 Make_Loop_Parameter_Specification (Loc,
7961 Defining_Identifier => J,
7962 Discrete_Subtype_Definition =>
7963 Make_Attribute_Reference (Loc,
7964 Prefix => New_Reference_To (A, Loc),
7965 Attribute_Name => Name_Range))),
7967 Statements => New_List (
7968 Make_Assignment_Statement (Loc,
7969 Name => C_J,
7970 Expression => Op)));
7972 Formals := New_List (
7973 Make_Parameter_Specification (Loc,
7974 Defining_Identifier => A,
7975 Parameter_Type => New_Reference_To (Typ, Loc)),
7977 Make_Parameter_Specification (Loc,
7978 Defining_Identifier => B,
7979 Parameter_Type => New_Reference_To (Typ, Loc)));
7981 Func_Name :=
7982 Make_Defining_Identifier (Loc, New_Internal_Name ('A'));
7983 Set_Is_Inlined (Func_Name);
7985 Func_Body :=
7986 Make_Subprogram_Body (Loc,
7987 Specification =>
7988 Make_Function_Specification (Loc,
7989 Defining_Unit_Name => Func_Name,
7990 Parameter_Specifications => Formals,
7991 Result_Definition => New_Reference_To (Typ, Loc)),
7993 Declarations => New_List (
7994 Make_Object_Declaration (Loc,
7995 Defining_Identifier => C,
7996 Object_Definition => New_Reference_To (Typ, Loc))),
7998 Handled_Statement_Sequence =>
7999 Make_Handled_Sequence_Of_Statements (Loc,
8000 Statements => New_List (
8001 Loop_Statement,
8002 Make_Return_Statement (Loc,
8003 Expression => New_Reference_To (C, Loc)))));
8005 return Func_Body;
8006 end Make_Boolean_Array_Op;
8008 ------------------------
8009 -- Rewrite_Comparison --
8010 ------------------------
8012 procedure Rewrite_Comparison (N : Node_Id) is
8013 Typ : constant Entity_Id := Etype (N);
8014 Op1 : constant Node_Id := Left_Opnd (N);
8015 Op2 : constant Node_Id := Right_Opnd (N);
8017 Res : constant Compare_Result := Compile_Time_Compare (Op1, Op2);
8018 -- Res indicates if compare outcome can be determined at compile time
8020 True_Result : Boolean;
8021 False_Result : Boolean;
8023 begin
8024 case N_Op_Compare (Nkind (N)) is
8025 when N_Op_Eq =>
8026 True_Result := Res = EQ;
8027 False_Result := Res = LT or else Res = GT or else Res = NE;
8029 when N_Op_Ge =>
8030 True_Result := Res in Compare_GE;
8031 False_Result := Res = LT;
8033 if Res = LE
8034 and then Constant_Condition_Warnings
8035 and then Comes_From_Source (Original_Node (N))
8036 and then Nkind (Original_Node (N)) = N_Op_Ge
8037 and then not In_Instance
8038 and then not Warnings_Off (Etype (Left_Opnd (N)))
8039 and then Is_Integer_Type (Etype (Left_Opnd (N)))
8040 then
8041 Error_Msg_N
8042 ("can never be greater than, could replace by ""'=""?", N);
8043 end if;
8045 when N_Op_Gt =>
8046 True_Result := Res = GT;
8047 False_Result := Res in Compare_LE;
8049 when N_Op_Lt =>
8050 True_Result := Res = LT;
8051 False_Result := Res in Compare_GE;
8053 when N_Op_Le =>
8054 True_Result := Res in Compare_LE;
8055 False_Result := Res = GT;
8057 if Res = GE
8058 and then Constant_Condition_Warnings
8059 and then Comes_From_Source (Original_Node (N))
8060 and then Nkind (Original_Node (N)) = N_Op_Le
8061 and then not In_Instance
8062 and then not Warnings_Off (Etype (Left_Opnd (N)))
8063 and then Is_Integer_Type (Etype (Left_Opnd (N)))
8064 then
8065 Error_Msg_N
8066 ("can never be less than, could replace by ""'=""?", N);
8067 end if;
8069 when N_Op_Ne =>
8070 True_Result := Res = NE or else Res = GT or else Res = LT;
8071 False_Result := Res = EQ;
8072 end case;
8074 if True_Result then
8075 Rewrite (N,
8076 Convert_To (Typ, New_Occurrence_Of (Standard_True, Sloc (N))));
8077 Analyze_And_Resolve (N, Typ);
8078 Warn_On_Known_Condition (N);
8080 elsif False_Result then
8081 Rewrite (N,
8082 Convert_To (Typ, New_Occurrence_Of (Standard_False, Sloc (N))));
8083 Analyze_And_Resolve (N, Typ);
8084 Warn_On_Known_Condition (N);
8085 end if;
8086 end Rewrite_Comparison;
8088 ----------------------------
8089 -- Safe_In_Place_Array_Op --
8090 ----------------------------
8092 function Safe_In_Place_Array_Op
8093 (Lhs : Node_Id;
8094 Op1 : Node_Id;
8095 Op2 : Node_Id) return Boolean
8097 Target : Entity_Id;
8099 function Is_Safe_Operand (Op : Node_Id) return Boolean;
8100 -- Operand is safe if it cannot overlap part of the target of the
8101 -- operation. If the operand and the target are identical, the operand
8102 -- is safe. The operand can be empty in the case of negation.
8104 function Is_Unaliased (N : Node_Id) return Boolean;
8105 -- Check that N is a stand-alone entity
8107 ------------------
8108 -- Is_Unaliased --
8109 ------------------
8111 function Is_Unaliased (N : Node_Id) return Boolean is
8112 begin
8113 return
8114 Is_Entity_Name (N)
8115 and then No (Address_Clause (Entity (N)))
8116 and then No (Renamed_Object (Entity (N)));
8117 end Is_Unaliased;
8119 ---------------------
8120 -- Is_Safe_Operand --
8121 ---------------------
8123 function Is_Safe_Operand (Op : Node_Id) return Boolean is
8124 begin
8125 if No (Op) then
8126 return True;
8128 elsif Is_Entity_Name (Op) then
8129 return Is_Unaliased (Op);
8131 elsif Nkind (Op) = N_Indexed_Component
8132 or else Nkind (Op) = N_Selected_Component
8133 then
8134 return Is_Unaliased (Prefix (Op));
8136 elsif Nkind (Op) = N_Slice then
8137 return
8138 Is_Unaliased (Prefix (Op))
8139 and then Entity (Prefix (Op)) /= Target;
8141 elsif Nkind (Op) = N_Op_Not then
8142 return Is_Safe_Operand (Right_Opnd (Op));
8144 else
8145 return False;
8146 end if;
8147 end Is_Safe_Operand;
8149 -- Start of processing for Is_Safe_In_Place_Array_Op
8151 begin
8152 -- We skip this processing if the component size is not the
8153 -- same as a system storage unit (since at least for NOT
8154 -- this would cause problems).
8156 if Component_Size (Etype (Lhs)) /= System_Storage_Unit then
8157 return False;
8159 -- Cannot do in place stuff on Java_VM since cannot pass addresses
8161 elsif Java_VM then
8162 return False;
8164 -- Cannot do in place stuff if non-standard Boolean representation
8166 elsif Has_Non_Standard_Rep (Component_Type (Etype (Lhs))) then
8167 return False;
8169 elsif not Is_Unaliased (Lhs) then
8170 return False;
8171 else
8172 Target := Entity (Lhs);
8174 return
8175 Is_Safe_Operand (Op1)
8176 and then Is_Safe_Operand (Op2);
8177 end if;
8178 end Safe_In_Place_Array_Op;
8180 -----------------------
8181 -- Tagged_Membership --
8182 -----------------------
8184 -- There are two different cases to consider depending on whether
8185 -- the right operand is a class-wide type or not. If not we just
8186 -- compare the actual tag of the left expr to the target type tag:
8188 -- Left_Expr.Tag = Right_Type'Tag;
8190 -- If it is a class-wide type we use the RT function CW_Membership which
8191 -- is usually implemented by looking in the ancestor tables contained in
8192 -- the dispatch table pointed by Left_Expr.Tag for Typ'Tag
8194 function Tagged_Membership (N : Node_Id) return Node_Id is
8195 Left : constant Node_Id := Left_Opnd (N);
8196 Right : constant Node_Id := Right_Opnd (N);
8197 Loc : constant Source_Ptr := Sloc (N);
8199 Left_Type : Entity_Id;
8200 Right_Type : Entity_Id;
8201 Obj_Tag : Node_Id;
8203 begin
8204 Left_Type := Etype (Left);
8205 Right_Type := Etype (Right);
8207 if Is_Class_Wide_Type (Left_Type) then
8208 Left_Type := Root_Type (Left_Type);
8209 end if;
8211 Obj_Tag :=
8212 Make_Selected_Component (Loc,
8213 Prefix => Relocate_Node (Left),
8214 Selector_Name =>
8215 New_Reference_To (First_Tag_Component (Left_Type), Loc));
8217 if Is_Class_Wide_Type (Right_Type) then
8219 -- Ada 2005 (AI-251): Class-wide applied to interfaces
8221 if Is_Interface (Etype (Class_Wide_Type (Right_Type)))
8223 -- Give support to: "Iface_CW_Typ in Typ'Class"
8225 or else Is_Interface (Left_Type)
8226 then
8227 return
8228 Make_Function_Call (Loc,
8229 Name => New_Occurrence_Of (RTE (RE_IW_Membership), Loc),
8230 Parameter_Associations => New_List (
8231 Make_Attribute_Reference (Loc,
8232 Prefix => Obj_Tag,
8233 Attribute_Name => Name_Address),
8234 New_Reference_To (
8235 Node (First_Elmt
8236 (Access_Disp_Table (Root_Type (Right_Type)))),
8237 Loc)));
8239 -- Ada 95: Normal case
8241 else
8242 return
8243 Make_Function_Call (Loc,
8244 Name => New_Occurrence_Of (RTE (RE_CW_Membership), Loc),
8245 Parameter_Associations => New_List (
8246 Obj_Tag,
8247 New_Reference_To (
8248 Node (First_Elmt
8249 (Access_Disp_Table (Root_Type (Right_Type)))),
8250 Loc)));
8251 end if;
8253 else
8254 return
8255 Make_Op_Eq (Loc,
8256 Left_Opnd => Obj_Tag,
8257 Right_Opnd =>
8258 New_Reference_To
8259 (Node (First_Elmt (Access_Disp_Table (Right_Type))), Loc));
8260 end if;
8261 end Tagged_Membership;
8263 ------------------------------
8264 -- Unary_Op_Validity_Checks --
8265 ------------------------------
8267 procedure Unary_Op_Validity_Checks (N : Node_Id) is
8268 begin
8269 if Validity_Checks_On and Validity_Check_Operands then
8270 Ensure_Valid (Right_Opnd (N));
8271 end if;
8272 end Unary_Op_Validity_Checks;
8274 end Exp_Ch4;