* c-decl.c (duplicate_decls): Conditionalize DECL_SAVED_TREE copy.
[official-gcc.git] / gcc / ada / exp_ch4.adb
blob8c299c1dc14d7ea65653be774b6dde4ef83659f5
1 ------------------------------------------------------------------------------
2 -- --
3 -- GNAT COMPILER COMPONENTS --
4 -- --
5 -- E X P _ C H 4 --
6 -- --
7 -- B o d y --
8 -- --
9 -- $Revision$
10 -- --
11 -- Copyright (C) 1992-2001, Free Software Foundation, Inc. --
12 -- --
13 -- GNAT is free software; you can redistribute it and/or modify it under --
14 -- terms of the GNU General Public License as published by the Free Soft- --
15 -- ware Foundation; either version 2, or (at your option) any later ver- --
16 -- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
17 -- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
18 -- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License --
19 -- for more details. You should have received a copy of the GNU General --
20 -- Public License distributed with GNAT; see file COPYING. If not, write --
21 -- to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, --
22 -- MA 02111-1307, USA. --
23 -- --
24 -- GNAT was originally developed by the GNAT team at New York University. --
25 -- It is now maintained by Ada Core Technologies Inc (http://www.gnat.com). --
26 -- --
27 ------------------------------------------------------------------------------
29 with Atree; use Atree;
30 with Checks; use Checks;
31 with Einfo; use Einfo;
32 with Elists; use Elists;
33 with Errout; use Errout;
34 with Exp_Aggr; use Exp_Aggr;
35 with Exp_Ch3; use Exp_Ch3;
36 with Exp_Ch7; use Exp_Ch7;
37 with Exp_Ch9; use Exp_Ch9;
38 with Exp_Disp; use Exp_Disp;
39 with Exp_Fixd; use Exp_Fixd;
40 with Exp_Pakd; use Exp_Pakd;
41 with Exp_Tss; use Exp_Tss;
42 with Exp_Util; use Exp_Util;
43 with Exp_VFpt; use Exp_VFpt;
44 with Hostparm; use Hostparm;
45 with Inline; use Inline;
46 with Nlists; use Nlists;
47 with Nmake; use Nmake;
48 with Opt; use Opt;
49 with Rtsfind; use Rtsfind;
50 with Sem; use Sem;
51 with Sem_Cat; use Sem_Cat;
52 with Sem_Ch13; use Sem_Ch13;
53 with Sem_Eval; use Sem_Eval;
54 with Sem_Res; use Sem_Res;
55 with Sem_Type; use Sem_Type;
56 with Sem_Util; use Sem_Util;
57 with Sinfo; use Sinfo;
58 with Sinfo.CN; use Sinfo.CN;
59 with Snames; use Snames;
60 with Stand; use Stand;
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 Expand_Array_Comparison (N : Node_Id);
78 -- This routine handles expansion of the comparison operators (N_Op_Lt,
79 -- N_Op_Le, N_Op_Gt, N_Op_Ge) when operating on an array type. The basic
80 -- code for these operators is similar, differing only in the details of
81 -- the actual comparison call that is made.
83 function Expand_Array_Equality
84 (Nod : Node_Id;
85 Typ : Entity_Id;
86 A_Typ : Entity_Id;
87 Lhs : Node_Id;
88 Rhs : Node_Id;
89 Bodies : List_Id)
90 return Node_Id;
91 -- Expand an array equality into a call to a function implementing this
92 -- equality, and a call to it. Loc is the location for the generated
93 -- nodes. Typ is the type of the array, and Lhs, Rhs are the array
94 -- expressions to be compared. A_Typ is the type of the arguments,
95 -- which may be a private type, in which case Typ is its full view.
96 -- Bodies is a list on which to attach bodies of local functions that
97 -- are created in the process. This is the responsability of the
98 -- caller to insert those bodies at the right place. Nod provides
99 -- the Sloc value for the generated code.
101 procedure Expand_Boolean_Operator (N : Node_Id);
102 -- Common expansion processing for Boolean operators (And, Or, Xor)
103 -- for the case of array type arguments.
105 function Expand_Composite_Equality
106 (Nod : Node_Id;
107 Typ : Entity_Id;
108 Lhs : Node_Id;
109 Rhs : Node_Id;
110 Bodies : List_Id)
111 return Node_Id;
112 -- Local recursive function used to expand equality for nested
113 -- composite types. Used by Expand_Record/Array_Equality, Bodies
114 -- is a list on which to attach bodies of local functions that are
115 -- created in the process. This is the responsability of the caller
116 -- to insert those bodies at the right place. Nod provides the Sloc
117 -- value for generated code.
119 procedure Expand_Concatenate_Other (Cnode : Node_Id; Opnds : List_Id);
120 -- This routine handles expansion of concatenation operations, where
121 -- N is the N_Op_Concat node being expanded and Operands is the list
122 -- of operands (at least two are present). The caller has dealt with
123 -- converting any singleton operands into singleton aggregates.
125 procedure Expand_Concatenate_String (Cnode : Node_Id; Opnds : List_Id);
126 -- Routine to expand concatenation of 2-5 operands (in the list Operands)
127 -- and replace node Cnode with the result of the contatenation. If there
128 -- are two operands, they can be string or character. If there are more
129 -- than two operands, then are always of type string (i.e. the caller has
130 -- already converted character operands to strings in this case).
132 procedure Fixup_Universal_Fixed_Operation (N : Node_Id);
133 -- N is either an N_Op_Divide or N_Op_Multiply node whose result is
134 -- universal fixed. We do not have such a type at runtime, so the
135 -- purpose of this routine is to find the real type by looking up
136 -- the tree. We also determine if the operation must be rounded.
138 procedure Insert_Dereference_Action (N : Node_Id);
139 -- N is an expression whose type is an access. When the type is derived
140 -- from Checked_Pool, expands a call to the primitive 'dereference'.
142 function Make_Array_Comparison_Op
143 (Typ : Entity_Id;
144 Nod : Node_Id)
145 return Node_Id;
146 -- Comparisons between arrays are expanded in line. This function
147 -- produces the body of the implementation of (a > b), where a and b
148 -- are one-dimensional arrays of some discrete type. The original
149 -- node is then expanded into the appropriate call to this function.
150 -- Nod provides the Sloc value for the generated code.
152 function Make_Boolean_Array_Op
153 (Typ : Entity_Id;
154 N : Node_Id)
155 return Node_Id;
156 -- Boolean operations on boolean arrays are expanded in line. This
157 -- function produce the body for the node N, which is (a and b),
158 -- (a or b), or (a xor b). It is used only the normal case and not
159 -- the packed case. The type involved, Typ, is the Boolean array type,
160 -- and the logical operations in the body are simple boolean operations.
161 -- Note that Typ is always a constrained type (the caller has ensured
162 -- this by using Convert_To_Actual_Subtype if necessary).
164 procedure Rewrite_Comparison (N : Node_Id);
165 -- N is the node for a compile time comparison. If this outcome of this
166 -- comparison can be determined at compile time, then the node N can be
167 -- rewritten with True or False. If the outcome cannot be determined at
168 -- compile time, the call has no effect.
170 function Tagged_Membership (N : Node_Id) return Node_Id;
171 -- Construct the expression corresponding to the tagged membership test.
172 -- Deals with a second operand being (or not) a class-wide type.
174 procedure Unary_Op_Validity_Checks (N : Node_Id);
175 pragma Inline (Unary_Op_Validity_Checks);
176 -- Performs validity checks for a unary operator
178 -------------------------------
179 -- Binary_Op_Validity_Checks --
180 -------------------------------
182 procedure Binary_Op_Validity_Checks (N : Node_Id) is
183 begin
184 if Validity_Checks_On and Validity_Check_Operands then
185 Ensure_Valid (Left_Opnd (N));
186 Ensure_Valid (Right_Opnd (N));
187 end if;
188 end Binary_Op_Validity_Checks;
190 -----------------------------
191 -- Expand_Array_Comparison --
192 -----------------------------
194 -- Expansion is only required in the case of array types. The form of
195 -- the expansion is:
197 -- [body for greater_nn; boolean_expression]
199 -- The body is built by Make_Array_Comparison_Op, and the form of the
200 -- Boolean expression depends on the operator involved.
202 procedure Expand_Array_Comparison (N : Node_Id) is
203 Loc : constant Source_Ptr := Sloc (N);
204 Op1 : Node_Id := Left_Opnd (N);
205 Op2 : Node_Id := Right_Opnd (N);
206 Typ1 : constant Entity_Id := Base_Type (Etype (Op1));
208 Expr : Node_Id;
209 Func_Body : Node_Id;
210 Func_Name : Entity_Id;
212 begin
213 -- For (a <= b) we convert to not (a > b)
215 if Chars (N) = Name_Op_Le then
216 Rewrite (N,
217 Make_Op_Not (Loc,
218 Right_Opnd =>
219 Make_Op_Gt (Loc,
220 Left_Opnd => Op1,
221 Right_Opnd => Op2)));
222 Analyze_And_Resolve (N, Standard_Boolean);
223 return;
225 -- For < the Boolean expression is
226 -- greater__nn (op2, op1)
228 elsif Chars (N) = Name_Op_Lt then
229 Func_Body := Make_Array_Comparison_Op (Typ1, N);
231 -- Switch operands
233 Op1 := Right_Opnd (N);
234 Op2 := Left_Opnd (N);
236 -- For (a >= b) we convert to not (a < b)
238 elsif Chars (N) = Name_Op_Ge then
239 Rewrite (N,
240 Make_Op_Not (Loc,
241 Right_Opnd =>
242 Make_Op_Lt (Loc,
243 Left_Opnd => Op1,
244 Right_Opnd => Op2)));
245 Analyze_And_Resolve (N, Standard_Boolean);
246 return;
248 -- For > the Boolean expression is
249 -- greater__nn (op1, op2)
251 else
252 pragma Assert (Chars (N) = Name_Op_Gt);
253 Func_Body := Make_Array_Comparison_Op (Typ1, N);
254 end if;
256 Func_Name := Defining_Unit_Name (Specification (Func_Body));
257 Expr :=
258 Make_Function_Call (Loc,
259 Name => New_Reference_To (Func_Name, Loc),
260 Parameter_Associations => New_List (Op1, Op2));
262 Insert_Action (N, Func_Body);
263 Rewrite (N, Expr);
264 Analyze_And_Resolve (N, Standard_Boolean);
266 end Expand_Array_Comparison;
268 ---------------------------
269 -- Expand_Array_Equality --
270 ---------------------------
272 -- Expand an equality function for multi-dimensional arrays. Here is
273 -- an example of such a function for Nb_Dimension = 2
275 -- function Enn (A : arr; B : arr) return boolean is
276 -- J1 : integer;
277 -- J2 : integer;
279 -- begin
280 -- if A'length (1) /= B'length (1) then
281 -- return false;
282 -- else
283 -- J1 := B'first (1);
284 -- for I1 in A'first (1) .. A'last (1) loop
285 -- if A'length (2) /= B'length (2) then
286 -- return false;
287 -- else
288 -- J2 := B'first (2);
289 -- for I2 in A'first (2) .. A'last (2) loop
290 -- if A (I1, I2) /= B (J1, J2) then
291 -- return false;
292 -- end if;
293 -- J2 := Integer'succ (J2);
294 -- end loop;
295 -- end if;
296 -- J1 := Integer'succ (J1);
297 -- end loop;
298 -- end if;
299 -- return true;
300 -- end Enn;
302 function Expand_Array_Equality
303 (Nod : Node_Id;
304 Typ : Entity_Id;
305 A_Typ : Entity_Id;
306 Lhs : Node_Id;
307 Rhs : Node_Id;
308 Bodies : List_Id)
309 return Node_Id
311 Loc : constant Source_Ptr := Sloc (Nod);
312 Actuals : List_Id;
313 Decls : List_Id := New_List;
314 Index_List1 : List_Id := New_List;
315 Index_List2 : List_Id := New_List;
316 Formals : List_Id;
317 Stats : Node_Id;
318 Func_Name : Entity_Id;
319 Func_Body : Node_Id;
321 A : constant Entity_Id := Make_Defining_Identifier (Loc, Name_uA);
322 B : constant Entity_Id := Make_Defining_Identifier (Loc, Name_uB);
324 function Component_Equality (Typ : Entity_Id) return Node_Id;
325 -- Create one statement to compare corresponding components, designated
326 -- by a full set of indices.
328 function Loop_One_Dimension
329 (N : Int;
330 Index : Node_Id)
331 return Node_Id;
332 -- Loop over the n'th dimension of the arrays. The single statement
333 -- in the body of the loop is a loop over the next dimension, or
334 -- the comparison of corresponding components.
336 ------------------------
337 -- Component_Equality --
338 ------------------------
340 function Component_Equality (Typ : Entity_Id) return Node_Id is
341 Test : Node_Id;
342 L, R : Node_Id;
344 begin
345 -- if a(i1...) /= b(j1...) then return false; end if;
347 L :=
348 Make_Indexed_Component (Loc,
349 Prefix => Make_Identifier (Loc, Chars (A)),
350 Expressions => Index_List1);
352 R :=
353 Make_Indexed_Component (Loc,
354 Prefix => Make_Identifier (Loc, Chars (B)),
355 Expressions => Index_List2);
357 Test := Expand_Composite_Equality
358 (Nod, Component_Type (Typ), L, R, Decls);
360 return
361 Make_Implicit_If_Statement (Nod,
362 Condition => Make_Op_Not (Loc, Right_Opnd => Test),
363 Then_Statements => New_List (
364 Make_Return_Statement (Loc,
365 Expression => New_Occurrence_Of (Standard_False, Loc))));
367 end Component_Equality;
369 ------------------------
370 -- Loop_One_Dimension --
371 ------------------------
373 function Loop_One_Dimension
374 (N : Int;
375 Index : Node_Id)
376 return Node_Id
378 I : constant Entity_Id := Make_Defining_Identifier (Loc,
379 New_Internal_Name ('I'));
380 J : constant Entity_Id := Make_Defining_Identifier (Loc,
381 New_Internal_Name ('J'));
382 Index_Type : Entity_Id;
383 Stats : Node_Id;
385 begin
386 if N > Number_Dimensions (Typ) then
387 return Component_Equality (Typ);
389 else
390 -- Generate the following:
392 -- j: index_type;
393 -- ...
395 -- if a'length (n) /= b'length (n) then
396 -- return false;
397 -- else
398 -- j := b'first (n);
399 -- for i in a'range (n) loop
400 -- -- loop over remaining dimensions.
401 -- j := index_type'succ (j);
402 -- end loop;
403 -- end if;
405 -- retrieve index type for current dimension.
407 Index_Type := Base_Type (Etype (Index));
408 Append (New_Reference_To (I, Loc), Index_List1);
409 Append (New_Reference_To (J, Loc), Index_List2);
411 -- Declare index for j as a local variable to the function.
412 -- Index i is a loop variable.
414 Append_To (Decls,
415 Make_Object_Declaration (Loc,
416 Defining_Identifier => J,
417 Object_Definition => New_Reference_To (Index_Type, Loc)));
419 Stats :=
420 Make_Implicit_If_Statement (Nod,
421 Condition =>
422 Make_Op_Ne (Loc,
423 Left_Opnd =>
424 Make_Attribute_Reference (Loc,
425 Prefix => New_Reference_To (A, Loc),
426 Attribute_Name => Name_Length,
427 Expressions => New_List (
428 Make_Integer_Literal (Loc, N))),
429 Right_Opnd =>
430 Make_Attribute_Reference (Loc,
431 Prefix => New_Reference_To (B, Loc),
432 Attribute_Name => Name_Length,
433 Expressions => New_List (
434 Make_Integer_Literal (Loc, N)))),
436 Then_Statements => New_List (
437 Make_Return_Statement (Loc,
438 Expression => New_Occurrence_Of (Standard_False, Loc))),
440 Else_Statements => New_List (
442 Make_Assignment_Statement (Loc,
443 Name => New_Reference_To (J, Loc),
444 Expression =>
445 Make_Attribute_Reference (Loc,
446 Prefix => New_Reference_To (B, Loc),
447 Attribute_Name => Name_First,
448 Expressions => New_List (
449 Make_Integer_Literal (Loc, N)))),
451 Make_Implicit_Loop_Statement (Nod,
452 Identifier => Empty,
453 Iteration_Scheme =>
454 Make_Iteration_Scheme (Loc,
455 Loop_Parameter_Specification =>
456 Make_Loop_Parameter_Specification (Loc,
457 Defining_Identifier => I,
458 Discrete_Subtype_Definition =>
459 Make_Attribute_Reference (Loc,
460 Prefix => New_Reference_To (A, Loc),
461 Attribute_Name => Name_Range,
462 Expressions => New_List (
463 Make_Integer_Literal (Loc, N))))),
465 Statements => New_List (
466 Loop_One_Dimension (N + 1, Next_Index (Index)),
467 Make_Assignment_Statement (Loc,
468 Name => New_Reference_To (J, Loc),
469 Expression =>
470 Make_Attribute_Reference (Loc,
471 Prefix => New_Reference_To (Index_Type, Loc),
472 Attribute_Name => Name_Succ,
473 Expressions => New_List (
474 New_Reference_To (J, Loc))))))));
476 return Stats;
477 end if;
478 end Loop_One_Dimension;
480 -- Start of processing for Expand_Array_Equality
482 begin
483 Formals := New_List (
484 Make_Parameter_Specification (Loc,
485 Defining_Identifier => A,
486 Parameter_Type => New_Reference_To (Typ, Loc)),
488 Make_Parameter_Specification (Loc,
489 Defining_Identifier => B,
490 Parameter_Type => New_Reference_To (Typ, Loc)));
492 Func_Name := Make_Defining_Identifier (Loc, New_Internal_Name ('E'));
494 Stats := Loop_One_Dimension (1, First_Index (Typ));
496 Func_Body :=
497 Make_Subprogram_Body (Loc,
498 Specification =>
499 Make_Function_Specification (Loc,
500 Defining_Unit_Name => Func_Name,
501 Parameter_Specifications => Formals,
502 Subtype_Mark => New_Reference_To (Standard_Boolean, Loc)),
503 Declarations => Decls,
504 Handled_Statement_Sequence =>
505 Make_Handled_Sequence_Of_Statements (Loc,
506 Statements => New_List (
507 Stats,
508 Make_Return_Statement (Loc,
509 Expression => New_Occurrence_Of (Standard_True, Loc)))));
511 Set_Has_Completion (Func_Name, True);
513 -- If the array type is distinct from the type of the arguments,
514 -- it is the full view of a private type. Apply an unchecked
515 -- conversion to insure that analysis of the call succeeds.
517 if Base_Type (A_Typ) /= Base_Type (Typ) then
518 Actuals := New_List (
519 OK_Convert_To (Typ, Lhs),
520 OK_Convert_To (Typ, Rhs));
521 else
522 Actuals := New_List (Lhs, Rhs);
523 end if;
525 Append_To (Bodies, Func_Body);
527 return
528 Make_Function_Call (Loc,
529 Name => New_Reference_To (Func_Name, Loc),
530 Parameter_Associations => Actuals);
531 end Expand_Array_Equality;
533 -----------------------------
534 -- Expand_Boolean_Operator --
535 -----------------------------
537 -- Note that we first get the actual subtypes of the operands,
538 -- since we always want to deal with types that have bounds.
540 procedure Expand_Boolean_Operator (N : Node_Id) is
541 Typ : constant Entity_Id := Etype (N);
543 begin
544 if Is_Bit_Packed_Array (Typ) then
545 Expand_Packed_Boolean_Operator (N);
547 else
549 -- For the normal non-packed case, the expansion is
550 -- to build a function for carrying out the comparison
551 -- (using Make_Boolean_Array_Op) and then inserting it
552 -- into the tree. The original operator node is then
553 -- rewritten as a call to this function.
555 declare
556 Loc : constant Source_Ptr := Sloc (N);
557 L : constant Node_Id := Relocate_Node (Left_Opnd (N));
558 R : constant Node_Id := Relocate_Node (Right_Opnd (N));
559 Func_Body : Node_Id;
560 Func_Name : Entity_Id;
561 begin
562 Convert_To_Actual_Subtype (L);
563 Convert_To_Actual_Subtype (R);
564 Ensure_Defined (Etype (L), N);
565 Ensure_Defined (Etype (R), N);
566 Apply_Length_Check (R, Etype (L));
568 Func_Body := Make_Boolean_Array_Op (Etype (L), N);
569 Func_Name := Defining_Unit_Name (Specification (Func_Body));
570 Insert_Action (N, Func_Body);
572 -- Now rewrite the expression with a call
574 Rewrite (N,
575 Make_Function_Call (Loc,
576 Name => New_Reference_To (Func_Name, Loc),
577 Parameter_Associations =>
578 New_List
579 (L, Make_Type_Conversion
580 (Loc, New_Reference_To (Etype (L), Loc), R))));
582 Analyze_And_Resolve (N, Typ);
583 end;
584 end if;
585 end Expand_Boolean_Operator;
587 -------------------------------
588 -- Expand_Composite_Equality --
589 -------------------------------
591 -- This function is only called for comparing internal fields of composite
592 -- types when these fields are themselves composites. This is a special
593 -- case because it is not possible to respect normal Ada visibility rules.
595 function Expand_Composite_Equality
596 (Nod : Node_Id;
597 Typ : Entity_Id;
598 Lhs : Node_Id;
599 Rhs : Node_Id;
600 Bodies : List_Id)
601 return Node_Id
603 Loc : constant Source_Ptr := Sloc (Nod);
604 Full_Type : Entity_Id;
605 Prim : Elmt_Id;
606 Eq_Op : Entity_Id;
608 begin
609 if Is_Private_Type (Typ) then
610 Full_Type := Underlying_Type (Typ);
611 else
612 Full_Type := Typ;
613 end if;
615 -- Defense against malformed private types with no completion
616 -- the error will be diagnosed later by check_completion
618 if No (Full_Type) then
619 return New_Reference_To (Standard_False, Loc);
620 end if;
622 Full_Type := Base_Type (Full_Type);
624 if Is_Array_Type (Full_Type) then
626 -- If the operand is an elementary type other than a floating-point
627 -- type, then we can simply use the built-in block bitwise equality,
628 -- since the predefined equality operators always apply and bitwise
629 -- equality is fine for all these cases.
631 if Is_Elementary_Type (Component_Type (Full_Type))
632 and then not Is_Floating_Point_Type (Component_Type (Full_Type))
633 then
634 return Make_Op_Eq (Loc, Left_Opnd => Lhs, Right_Opnd => Rhs);
636 -- For composite component types, and floating-point types, use
637 -- the expansion. This deals with tagged component types (where
638 -- we use the applicable equality routine) and floating-point,
639 -- (where we need to worry about negative zeroes), and also the
640 -- case of any composite type recursively containing such fields.
642 else
643 return Expand_Array_Equality
644 (Nod, Full_Type, Typ, Lhs, Rhs, Bodies);
645 end if;
647 elsif Is_Tagged_Type (Full_Type) then
649 -- Call the primitive operation "=" of this type
651 if Is_Class_Wide_Type (Full_Type) then
652 Full_Type := Root_Type (Full_Type);
653 end if;
655 -- If this is derived from an untagged private type completed
656 -- with a tagged type, it does not have a full view, so we
657 -- use the primitive operations of the private type.
658 -- This check should no longer be necessary when these
659 -- types receive their full views ???
661 if Is_Private_Type (Typ)
662 and then not Is_Tagged_Type (Typ)
663 and then not Is_Controlled (Typ)
664 and then Is_Derived_Type (Typ)
665 and then No (Full_View (Typ))
666 then
667 Prim := First_Elmt (Collect_Primitive_Operations (Typ));
668 else
669 Prim := First_Elmt (Primitive_Operations (Full_Type));
670 end if;
672 loop
673 Eq_Op := Node (Prim);
674 exit when Chars (Eq_Op) = Name_Op_Eq
675 and then Etype (First_Formal (Eq_Op)) =
676 Etype (Next_Formal (First_Formal (Eq_Op)));
677 Next_Elmt (Prim);
678 pragma Assert (Present (Prim));
679 end loop;
681 Eq_Op := Node (Prim);
683 return
684 Make_Function_Call (Loc,
685 Name => New_Reference_To (Eq_Op, Loc),
686 Parameter_Associations =>
687 New_List
688 (Unchecked_Convert_To (Etype (First_Formal (Eq_Op)), Lhs),
689 Unchecked_Convert_To (Etype (First_Formal (Eq_Op)), Rhs)));
691 elsif Is_Record_Type (Full_Type) then
692 Eq_Op := TSS (Full_Type, Name_uEquality);
694 if Present (Eq_Op) then
695 if Etype (First_Formal (Eq_Op)) /= Full_Type then
697 -- Inherited equality from parent type. Convert the actuals
698 -- to match signature of operation.
700 declare
701 T : Entity_Id := Etype (First_Formal (Eq_Op));
703 begin
704 return
705 Make_Function_Call (Loc,
706 Name => New_Reference_To (Eq_Op, Loc),
707 Parameter_Associations =>
708 New_List (OK_Convert_To (T, Lhs),
709 OK_Convert_To (T, Rhs)));
710 end;
712 else
713 return
714 Make_Function_Call (Loc,
715 Name => New_Reference_To (Eq_Op, Loc),
716 Parameter_Associations => New_List (Lhs, Rhs));
717 end if;
719 else
720 return Expand_Record_Equality (Nod, Full_Type, Lhs, Rhs, Bodies);
721 end if;
723 else
724 -- It can be a simple record or the full view of a scalar private
726 return Make_Op_Eq (Loc, Left_Opnd => Lhs, Right_Opnd => Rhs);
727 end if;
728 end Expand_Composite_Equality;
730 ------------------------------
731 -- Expand_Concatenate_Other --
732 ------------------------------
734 -- Let n be the number of array operands to be concatenated, Base_Typ
735 -- their base type, Ind_Typ their index type, and Arr_Typ the original
736 -- array type to which the concatenantion operator applies, then the
737 -- following subprogram is constructed:
739 -- [function Cnn (S1 : Base_Typ; ...; Sn : Base_Typ) return Base_Typ is
740 -- L : Ind_Typ;
741 -- begin
742 -- if S1'Length /= 0 then
743 -- L := XXX; --> XXX = S1'First if Arr_Typ is unconstrained
744 -- XXX = Arr_Typ'First otherwise
745 -- elsif S2'Length /= 0 then
746 -- L := YYY; --> YYY = S2'First if Arr_Typ is unconstrained
747 -- YYY = Arr_Typ'First otherwise
748 -- ...
749 -- elsif Sn-1'Length /= 0 then
750 -- L := ZZZ; --> ZZZ = Sn-1'First if Arr_Typ is unconstrained
751 -- ZZZ = Arr_Typ'First otherwise
752 -- else
753 -- return Sn;
754 -- end if;
756 -- declare
757 -- P : Ind_Typ;
758 -- H : Ind_Typ :=
759 -- Ind_Typ'Val ((((S1'Length - 1) + S2'Length) + ... + Sn'Length)
760 -- + Ind_Typ'Pos (L));
761 -- R : Base_Typ (L .. H);
762 -- begin
763 -- if S1'Length /= 0 then
764 -- P := S1'First;
765 -- loop
766 -- R (L) := S1 (P);
767 -- L := Ind_Typ'Succ (L);
768 -- exit when P = S1'Last;
769 -- P := Ind_Typ'Succ (P);
770 -- end loop;
771 -- end if;
773 -- if S2'Length /= 0 then
774 -- L := Ind_Typ'Succ (L);
775 -- loop
776 -- R (L) := S2 (P);
777 -- L := Ind_Typ'Succ (L);
778 -- exit when P = S2'Last;
779 -- P := Ind_Typ'Succ (P);
780 -- end loop;
781 -- end if;
783 -- ...
785 -- if Sn'Length /= 0 then
786 -- P := Sn'First;
787 -- loop
788 -- R (L) := Sn (P);
789 -- L := Ind_Typ'Succ (L);
790 -- exit when P = Sn'Last;
791 -- P := Ind_Typ'Succ (P);
792 -- end loop;
793 -- end if;
795 -- return R;
796 -- end;
797 -- end Cnn;]
799 procedure Expand_Concatenate_Other (Cnode : Node_Id; Opnds : List_Id) is
800 Loc : constant Source_Ptr := Sloc (Cnode);
801 Nb_Opnds : constant Nat := List_Length (Opnds);
803 Arr_Typ : constant Entity_Id := Etype (Entity (Cnode));
804 Base_Typ : constant Entity_Id := Base_Type (Etype (Cnode));
805 Ind_Typ : constant Entity_Id := Etype (First_Index (Base_Typ));
807 Func_Id : Node_Id;
808 Func_Spec : Node_Id;
809 Param_Specs : List_Id;
811 Func_Body : Node_Id;
812 Func_Decls : List_Id;
813 Func_Stmts : List_Id;
815 L_Decl : Node_Id;
817 If_Stmt : Node_Id;
818 Elsif_List : List_Id;
820 Declare_Block : Node_Id;
821 Declare_Decls : List_Id;
822 Declare_Stmts : List_Id;
824 H_Decl : Node_Id;
825 H_Init : Node_Id;
826 P_Decl : Node_Id;
827 R_Decl : Node_Id;
828 R_Constr : Node_Id;
829 R_Range : Node_Id;
831 Params : List_Id;
832 Operand : Node_Id;
834 function Copy_Into_R_S (I : Nat) return List_Id;
835 -- Builds the sequence of statement:
836 -- P := Si'First;
837 -- loop
838 -- R (L) := Si (P);
839 -- L := Ind_Typ'Succ (L);
840 -- exit when P = Si'Last;
841 -- P := Ind_Typ'Succ (P);
842 -- end loop;
844 -- where i is the input parameter I given.
846 function Init_L (I : Nat) return Node_Id;
847 -- Builds the statement:
848 -- L := Arr_Typ'First; If Arr_Typ is constrained
849 -- L := Si'First; otherwise (where I is the input param given)
851 function H return Node_Id;
852 -- Builds reference to identifier H.
854 function Ind_Val (E : Node_Id) return Node_Id;
855 -- Builds expression Ind_Typ'Val (E);
857 function L return Node_Id;
858 -- Builds reference to identifier L.
860 function L_Pos return Node_Id;
861 -- Builds expression Ind_Typ'Pos (L).
863 function L_Succ return Node_Id;
864 -- Builds expression Ind_Typ'Succ (L).
866 function One return Node_Id;
867 -- Builds integer literal one.
869 function P return Node_Id;
870 -- Builds reference to identifier P.
872 function P_Succ return Node_Id;
873 -- Builds expression Ind_Typ'Succ (P).
875 function R return Node_Id;
876 -- Builds reference to identifier R.
878 function S (I : Nat) return Node_Id;
879 -- Builds reference to identifier Si, where I is the value given.
881 function S_First (I : Nat) return Node_Id;
882 -- Builds expression Si'First, where I is the value given.
884 function S_Last (I : Nat) return Node_Id;
885 -- Builds expression Si'Last, where I is the value given.
887 function S_Length (I : Nat) return Node_Id;
888 -- Builds expression Si'Length, where I is the value given.
890 function S_Length_Test (I : Nat) return Node_Id;
891 -- Builds expression Si'Length /= 0, where I is the value given.
893 -------------------
894 -- Copy_Into_R_S --
895 -------------------
897 function Copy_Into_R_S (I : Nat) return List_Id is
898 Stmts : List_Id := New_List;
899 P_Start : Node_Id;
900 Loop_Stmt : Node_Id;
901 R_Copy : Node_Id;
902 Exit_Stmt : Node_Id;
903 L_Inc : Node_Id;
904 P_Inc : Node_Id;
906 begin
907 -- First construct the initializations
909 P_Start := Make_Assignment_Statement (Loc,
910 Name => P,
911 Expression => S_First (I));
912 Append_To (Stmts, P_Start);
914 -- Then build the loop
916 R_Copy := Make_Assignment_Statement (Loc,
917 Name => Make_Indexed_Component (Loc,
918 Prefix => R,
919 Expressions => New_List (L)),
920 Expression => Make_Indexed_Component (Loc,
921 Prefix => S (I),
922 Expressions => New_List (P)));
924 L_Inc := Make_Assignment_Statement (Loc,
925 Name => L,
926 Expression => L_Succ);
928 Exit_Stmt := Make_Exit_Statement (Loc,
929 Condition => Make_Op_Eq (Loc, P, S_Last (I)));
931 P_Inc := Make_Assignment_Statement (Loc,
932 Name => P,
933 Expression => P_Succ);
935 Loop_Stmt :=
936 Make_Implicit_Loop_Statement (Cnode,
937 Statements => New_List (R_Copy, L_Inc, Exit_Stmt, P_Inc));
939 Append_To (Stmts, Loop_Stmt);
941 return Stmts;
942 end Copy_Into_R_S;
944 -------
945 -- H --
946 -------
948 function H return Node_Id is
949 begin
950 return Make_Identifier (Loc, Name_uH);
951 end H;
953 -------------
954 -- Ind_Val --
955 -------------
957 function Ind_Val (E : Node_Id) return Node_Id is
958 begin
959 return
960 Make_Attribute_Reference (Loc,
961 Prefix => New_Reference_To (Ind_Typ, Loc),
962 Attribute_Name => Name_Val,
963 Expressions => New_List (E));
964 end Ind_Val;
966 ------------
967 -- Init_L --
968 ------------
970 function Init_L (I : Nat) return Node_Id is
971 E : Node_Id;
973 begin
974 if Is_Constrained (Arr_Typ) then
975 E := Make_Attribute_Reference (Loc,
976 Prefix => New_Reference_To (Arr_Typ, Loc),
977 Attribute_Name => Name_First);
979 else
980 E := S_First (I);
981 end if;
983 return Make_Assignment_Statement (Loc, Name => L, Expression => E);
984 end Init_L;
986 -------
987 -- L --
988 -------
990 function L return Node_Id is
991 begin
992 return Make_Identifier (Loc, Name_uL);
993 end L;
995 -----------
996 -- L_Pos --
997 -----------
999 function L_Pos return Node_Id is
1000 begin
1001 return
1002 Make_Attribute_Reference (Loc,
1003 Prefix => New_Reference_To (Ind_Typ, Loc),
1004 Attribute_Name => Name_Pos,
1005 Expressions => New_List (L));
1006 end L_Pos;
1008 ------------
1009 -- L_Succ --
1010 ------------
1012 function L_Succ return Node_Id is
1013 begin
1014 return
1015 Make_Attribute_Reference (Loc,
1016 Prefix => New_Reference_To (Ind_Typ, Loc),
1017 Attribute_Name => Name_Succ,
1018 Expressions => New_List (L));
1019 end L_Succ;
1021 ---------
1022 -- One --
1023 ---------
1025 function One return Node_Id is
1026 begin
1027 return Make_Integer_Literal (Loc, 1);
1028 end One;
1030 -------
1031 -- P --
1032 -------
1034 function P return Node_Id is
1035 begin
1036 return Make_Identifier (Loc, Name_uP);
1037 end P;
1039 ------------
1040 -- P_Succ --
1041 ------------
1043 function P_Succ return Node_Id is
1044 begin
1045 return
1046 Make_Attribute_Reference (Loc,
1047 Prefix => New_Reference_To (Ind_Typ, Loc),
1048 Attribute_Name => Name_Succ,
1049 Expressions => New_List (P));
1050 end P_Succ;
1052 -------
1053 -- R --
1054 -------
1056 function R return Node_Id is
1057 begin
1058 return Make_Identifier (Loc, Name_uR);
1059 end R;
1061 -------
1062 -- S --
1063 -------
1065 function S (I : Nat) return Node_Id is
1066 begin
1067 return Make_Identifier (Loc, New_External_Name ('S', I));
1068 end S;
1070 -------------
1071 -- S_First --
1072 -------------
1074 function S_First (I : Nat) return Node_Id is
1075 begin
1076 return Make_Attribute_Reference (Loc,
1077 Prefix => S (I),
1078 Attribute_Name => Name_First);
1079 end S_First;
1081 ------------
1082 -- S_Last --
1083 ------------
1085 function S_Last (I : Nat) return Node_Id is
1086 begin
1087 return Make_Attribute_Reference (Loc,
1088 Prefix => S (I),
1089 Attribute_Name => Name_Last);
1090 end S_Last;
1092 --------------
1093 -- S_Length --
1094 --------------
1096 function S_Length (I : Nat) return Node_Id is
1097 begin
1098 return Make_Attribute_Reference (Loc,
1099 Prefix => S (I),
1100 Attribute_Name => Name_Length);
1101 end S_Length;
1103 -------------------
1104 -- S_Length_Test --
1105 -------------------
1107 function S_Length_Test (I : Nat) return Node_Id is
1108 begin
1109 return
1110 Make_Op_Ne (Loc,
1111 Left_Opnd => S_Length (I),
1112 Right_Opnd => Make_Integer_Literal (Loc, 0));
1113 end S_Length_Test;
1115 -- Start of processing for Expand_Concatenate_Other
1117 begin
1118 -- Construct the parameter specs and the overall function spec
1120 Param_Specs := New_List;
1121 for I in 1 .. Nb_Opnds loop
1122 Append_To
1123 (Param_Specs,
1124 Make_Parameter_Specification (Loc,
1125 Defining_Identifier =>
1126 Make_Defining_Identifier (Loc, New_External_Name ('S', I)),
1127 Parameter_Type => New_Reference_To (Base_Typ, Loc)));
1128 end loop;
1130 Func_Id := Make_Defining_Identifier (Loc, New_Internal_Name ('C'));
1131 Func_Spec :=
1132 Make_Function_Specification (Loc,
1133 Defining_Unit_Name => Func_Id,
1134 Parameter_Specifications => Param_Specs,
1135 Subtype_Mark => New_Reference_To (Base_Typ, Loc));
1137 -- Construct L's object declaration
1139 L_Decl :=
1140 Make_Object_Declaration (Loc,
1141 Defining_Identifier => Make_Defining_Identifier (Loc, Name_uL),
1142 Object_Definition => New_Reference_To (Ind_Typ, Loc));
1144 Func_Decls := New_List (L_Decl);
1146 -- Construct the if-then-elsif statements
1148 Elsif_List := New_List;
1149 for I in 2 .. Nb_Opnds - 1 loop
1150 Append_To (Elsif_List, Make_Elsif_Part (Loc,
1151 Condition => S_Length_Test (I),
1152 Then_Statements => New_List (Init_L (I))));
1153 end loop;
1155 If_Stmt :=
1156 Make_Implicit_If_Statement (Cnode,
1157 Condition => S_Length_Test (1),
1158 Then_Statements => New_List (Init_L (1)),
1159 Elsif_Parts => Elsif_List,
1160 Else_Statements => New_List (Make_Return_Statement (Loc,
1161 Expression => S (Nb_Opnds))));
1163 -- Construct the declaration for H
1165 P_Decl :=
1166 Make_Object_Declaration (Loc,
1167 Defining_Identifier => Make_Defining_Identifier (Loc, Name_uP),
1168 Object_Definition => New_Reference_To (Ind_Typ, Loc));
1170 H_Init := Make_Op_Subtract (Loc, S_Length (1), One);
1171 for I in 2 .. Nb_Opnds loop
1172 H_Init := Make_Op_Add (Loc, H_Init, S_Length (I));
1173 end loop;
1174 H_Init := Ind_Val (Make_Op_Add (Loc, H_Init, L_Pos));
1176 H_Decl :=
1177 Make_Object_Declaration (Loc,
1178 Defining_Identifier => Make_Defining_Identifier (Loc, Name_uH),
1179 Object_Definition => New_Reference_To (Ind_Typ, Loc),
1180 Expression => H_Init);
1182 -- Construct the declaration for R
1184 R_Range := Make_Range (Loc, Low_Bound => L, High_Bound => H);
1185 R_Constr :=
1186 Make_Index_Or_Discriminant_Constraint (Loc,
1187 Constraints => New_List (R_Range));
1189 R_Decl :=
1190 Make_Object_Declaration (Loc,
1191 Defining_Identifier => Make_Defining_Identifier (Loc, Name_uR),
1192 Object_Definition =>
1193 Make_Subtype_Indication (Loc,
1194 Subtype_Mark => New_Reference_To (Base_Typ, Loc),
1195 Constraint => R_Constr));
1197 -- Construct the declarations for the declare block
1199 Declare_Decls := New_List (P_Decl, H_Decl, R_Decl);
1201 -- Construct list of statements for the declare block
1203 Declare_Stmts := New_List;
1204 for I in 1 .. Nb_Opnds loop
1205 Append_To (Declare_Stmts,
1206 Make_Implicit_If_Statement (Cnode,
1207 Condition => S_Length_Test (I),
1208 Then_Statements => Copy_Into_R_S (I)));
1209 end loop;
1211 Append_To (Declare_Stmts, Make_Return_Statement (Loc, Expression => R));
1213 -- Construct the declare block
1215 Declare_Block := Make_Block_Statement (Loc,
1216 Declarations => Declare_Decls,
1217 Handled_Statement_Sequence =>
1218 Make_Handled_Sequence_Of_Statements (Loc, Declare_Stmts));
1220 -- Construct the list of function statements
1222 Func_Stmts := New_List (If_Stmt, Declare_Block);
1224 -- Construct the function body
1226 Func_Body :=
1227 Make_Subprogram_Body (Loc,
1228 Specification => Func_Spec,
1229 Declarations => Func_Decls,
1230 Handled_Statement_Sequence =>
1231 Make_Handled_Sequence_Of_Statements (Loc, Func_Stmts));
1233 -- Insert the newly generated function in the code. This is analyzed
1234 -- with all checks off, since we have completed all the checks.
1236 -- Note that this does *not* fix the array concatenation bug when the
1237 -- low bound is Integer'first sibce that bug comes from the pointer
1238 -- derefencing an unconstrained array. An there we need a constraint
1239 -- check to make sure the length of the concatenated array is ok. ???
1241 Insert_Action (Cnode, Func_Body, Suppress => All_Checks);
1243 -- Construct list of arguments for the function call
1245 Params := New_List;
1246 Operand := First (Opnds);
1247 for I in 1 .. Nb_Opnds loop
1248 Append_To (Params, Relocate_Node (Operand));
1249 Next (Operand);
1250 end loop;
1252 -- Insert the function call
1254 Rewrite
1255 (Cnode,
1256 Make_Function_Call (Loc, New_Reference_To (Func_Id, Loc), Params));
1258 Analyze_And_Resolve (Cnode, Base_Typ);
1259 Set_Is_Inlined (Func_Id);
1260 end Expand_Concatenate_Other;
1262 -------------------------------
1263 -- Expand_Concatenate_String --
1264 -------------------------------
1266 procedure Expand_Concatenate_String (Cnode : Node_Id; Opnds : List_Id) is
1267 Loc : constant Source_Ptr := Sloc (Cnode);
1268 Opnd1 : constant Node_Id := First (Opnds);
1269 Opnd2 : constant Node_Id := Next (Opnd1);
1270 Typ1 : constant Entity_Id := Base_Type (Etype (Opnd1));
1271 Typ2 : constant Entity_Id := Base_Type (Etype (Opnd2));
1273 R : RE_Id;
1274 -- RE_Id value for function to be called
1276 begin
1277 -- In all cases, we build a call to a routine giving the list of
1278 -- arguments as the parameter list to the routine.
1280 case List_Length (Opnds) is
1281 when 2 =>
1282 if Typ1 = Standard_Character then
1283 if Typ2 = Standard_Character then
1284 R := RE_Str_Concat_CC;
1286 else
1287 pragma Assert (Typ2 = Standard_String);
1288 R := RE_Str_Concat_CS;
1289 end if;
1291 elsif Typ1 = Standard_String then
1292 if Typ2 = Standard_Character then
1293 R := RE_Str_Concat_SC;
1295 else
1296 pragma Assert (Typ2 = Standard_String);
1297 R := RE_Str_Concat;
1298 end if;
1300 -- If we have anything other than Standard_Character or
1301 -- Standard_String, then we must have had an error earlier.
1302 -- So we just abandon the attempt at expansion.
1304 else
1305 pragma Assert (Errors_Detected > 0);
1306 return;
1307 end if;
1309 when 3 =>
1310 R := RE_Str_Concat_3;
1312 when 4 =>
1313 R := RE_Str_Concat_4;
1315 when 5 =>
1316 R := RE_Str_Concat_5;
1318 when others =>
1319 R := RE_Null;
1320 raise Program_Error;
1321 end case;
1323 -- Now generate the appropriate call
1325 Rewrite (Cnode,
1326 Make_Function_Call (Sloc (Cnode),
1327 Name => New_Occurrence_Of (RTE (R), Loc),
1328 Parameter_Associations => Opnds));
1330 Analyze_And_Resolve (Cnode, Standard_String);
1331 end Expand_Concatenate_String;
1333 ------------------------
1334 -- Expand_N_Allocator --
1335 ------------------------
1337 procedure Expand_N_Allocator (N : Node_Id) is
1338 PtrT : constant Entity_Id := Etype (N);
1339 Desig : Entity_Id;
1340 Loc : constant Source_Ptr := Sloc (N);
1341 Temp : Entity_Id;
1342 Node : Node_Id;
1344 begin
1345 -- RM E.2.3(22). We enforce that the expected type of an allocator
1346 -- shall not be a remote access-to-class-wide-limited-private type
1348 -- Why is this being done at expansion time, seems clearly wrong ???
1350 Validate_Remote_Access_To_Class_Wide_Type (N);
1352 -- Set the Storage Pool
1354 Set_Storage_Pool (N, Associated_Storage_Pool (Root_Type (PtrT)));
1356 if Present (Storage_Pool (N)) then
1357 if Is_RTE (Storage_Pool (N), RE_SS_Pool) then
1358 if not Java_VM then
1359 Set_Procedure_To_Call (N, RTE (RE_SS_Allocate));
1360 end if;
1361 else
1362 Set_Procedure_To_Call (N,
1363 Find_Prim_Op (Etype (Storage_Pool (N)), Name_Allocate));
1364 end if;
1365 end if;
1367 -- Under certain circumstances we can replace an allocator by an
1368 -- access to statically allocated storage. The conditions, as noted
1369 -- in AARM 3.10 (10c) are as follows:
1371 -- Size and initial value is known at compile time
1372 -- Access type is access-to-constant
1374 if Is_Access_Constant (PtrT)
1375 and then Nkind (Expression (N)) = N_Qualified_Expression
1376 and then Compile_Time_Known_Value (Expression (Expression (N)))
1377 and then Size_Known_At_Compile_Time (Etype (Expression
1378 (Expression (N))))
1379 then
1380 -- Here we can do the optimization. For the allocator
1382 -- new x'(y)
1384 -- We insert an object declaration
1386 -- Tnn : aliased x := y;
1388 -- and replace the allocator by Tnn'Unrestricted_Access.
1389 -- Tnn is marked as requiring static allocation.
1391 Temp :=
1392 Make_Defining_Identifier (Loc, New_Internal_Name ('T'));
1394 Desig := Subtype_Mark (Expression (N));
1396 -- If context is constrained, use constrained subtype directly,
1397 -- so that the constant is not labelled as having a nomimally
1398 -- unconstrained subtype.
1400 if Entity (Desig) = Base_Type (Designated_Type (PtrT)) then
1401 Desig := New_Occurrence_Of (Designated_Type (PtrT), Loc);
1402 end if;
1404 Insert_Action (N,
1405 Make_Object_Declaration (Loc,
1406 Defining_Identifier => Temp,
1407 Aliased_Present => True,
1408 Constant_Present => Is_Access_Constant (PtrT),
1409 Object_Definition => Desig,
1410 Expression => Expression (Expression (N))));
1412 Rewrite (N,
1413 Make_Attribute_Reference (Loc,
1414 Prefix => New_Occurrence_Of (Temp, Loc),
1415 Attribute_Name => Name_Unrestricted_Access));
1417 Analyze_And_Resolve (N, PtrT);
1419 -- We set the variable as statically allocated, since we don't
1420 -- want it going on the stack of the current procedure!
1422 Set_Is_Statically_Allocated (Temp);
1423 return;
1424 end if;
1426 -- If the allocator is for a type which requires initialization, and
1427 -- there is no initial value (i.e. the operand is a subtype indication
1428 -- rather than a qualifed expression), then we must generate a call to
1429 -- the initialization routine. This is done using an expression actions
1430 -- node:
1432 -- [Pnnn : constant ptr_T := new (T); Init (Pnnn.all,...); Pnnn]
1434 -- Here ptr_T is the pointer type for the allocator, and T is the
1435 -- subtype of the allocator. A special case arises if the designated
1436 -- type of the access type is a task or contains tasks. In this case
1437 -- the call to Init (Temp.all ...) is replaced by code that ensures
1438 -- that the tasks get activated (see Exp_Ch9.Build_Task_Allocate_Block
1439 -- for details). In addition, if the type T is a task T, then the first
1440 -- argument to Init must be converted to the task record type.
1442 if Nkind (Expression (N)) = N_Qualified_Expression then
1443 declare
1444 Indic : constant Node_Id := Subtype_Mark (Expression (N));
1445 T : constant Entity_Id := Entity (Indic);
1446 Exp : constant Node_Id := Expression (Expression (N));
1448 Aggr_In_Place : constant Boolean := Is_Delayed_Aggregate (Exp);
1450 Tag_Assign : Node_Id;
1451 Tmp_Node : Node_Id;
1453 begin
1454 if Is_Tagged_Type (T) or else Controlled_Type (T) then
1456 -- Actions inserted before:
1457 -- Temp : constant ptr_T := new T'(Expression);
1458 -- <no CW> Temp._tag := T'tag;
1459 -- <CTRL> Adjust (Finalizable (Temp.all));
1460 -- <CTRL> Attach_To_Final_List (Finalizable (Temp.all));
1462 -- We analyze by hand the new internal allocator to avoid
1463 -- any recursion and inappropriate call to Initialize
1464 if not Aggr_In_Place then
1465 Remove_Side_Effects (Exp);
1466 end if;
1468 Temp :=
1469 Make_Defining_Identifier (Loc, New_Internal_Name ('P'));
1471 -- For a class wide allocation generate the following code:
1473 -- type Equiv_Record is record ... end record;
1474 -- implicit subtype CW is <Class_Wide_Subytpe>;
1475 -- temp : PtrT := new CW'(CW!(expr));
1477 if Is_Class_Wide_Type (T) then
1478 Expand_Subtype_From_Expr (Empty, T, Indic, Exp);
1480 Set_Expression (Expression (N),
1481 Unchecked_Convert_To (Entity (Indic), Exp));
1483 Analyze_And_Resolve (Expression (N), Entity (Indic));
1484 end if;
1486 if Aggr_In_Place then
1487 Tmp_Node :=
1488 Make_Object_Declaration (Loc,
1489 Defining_Identifier => Temp,
1490 Object_Definition => New_Reference_To (PtrT, Loc),
1491 Expression => Make_Allocator (Loc,
1492 New_Reference_To (Etype (Exp), Loc)));
1494 Set_No_Initialization (Expression (Tmp_Node));
1495 Insert_Action (N, Tmp_Node);
1496 Convert_Aggr_In_Allocator (Tmp_Node, Exp);
1497 else
1498 Node := Relocate_Node (N);
1499 Set_Analyzed (Node);
1500 Insert_Action (N,
1501 Make_Object_Declaration (Loc,
1502 Defining_Identifier => Temp,
1503 Constant_Present => True,
1504 Object_Definition => New_Reference_To (PtrT, Loc),
1505 Expression => Node));
1506 end if;
1508 -- Suppress the tag assignment when Java_VM because JVM tags
1509 -- are represented implicitly in objects.
1511 if Is_Tagged_Type (T)
1512 and then not Is_Class_Wide_Type (T)
1513 and then not Java_VM
1514 then
1515 Tag_Assign :=
1516 Make_Assignment_Statement (Loc,
1517 Name =>
1518 Make_Selected_Component (Loc,
1519 Prefix => New_Reference_To (Temp, Loc),
1520 Selector_Name =>
1521 New_Reference_To (Tag_Component (T), Loc)),
1523 Expression =>
1524 Unchecked_Convert_To (RTE (RE_Tag),
1525 New_Reference_To (Access_Disp_Table (T), Loc)));
1527 -- The previous assignment has to be done in any case
1529 Set_Assignment_OK (Name (Tag_Assign));
1530 Insert_Action (N, Tag_Assign);
1532 elsif Is_Private_Type (T)
1533 and then Is_Tagged_Type (Underlying_Type (T))
1534 and then not Java_VM
1535 then
1536 declare
1537 Utyp : constant Entity_Id := Underlying_Type (T);
1538 Ref : constant Node_Id :=
1539 Unchecked_Convert_To (Utyp,
1540 Make_Explicit_Dereference (Loc,
1541 New_Reference_To (Temp, Loc)));
1543 begin
1544 Tag_Assign :=
1545 Make_Assignment_Statement (Loc,
1546 Name =>
1547 Make_Selected_Component (Loc,
1548 Prefix => Ref,
1549 Selector_Name =>
1550 New_Reference_To (Tag_Component (Utyp), Loc)),
1552 Expression =>
1553 Unchecked_Convert_To (RTE (RE_Tag),
1554 New_Reference_To (
1555 Access_Disp_Table (Utyp), Loc)));
1557 Set_Assignment_OK (Name (Tag_Assign));
1558 Insert_Action (N, Tag_Assign);
1559 end;
1560 end if;
1562 if Controlled_Type (Designated_Type (PtrT))
1563 and then Controlled_Type (T)
1564 then
1565 declare
1566 Flist : Node_Id;
1567 Attach : Node_Id;
1568 Apool : constant Entity_Id :=
1569 Associated_Storage_Pool (PtrT);
1571 begin
1572 -- If it is an allocation on the secondary stack
1573 -- (i.e. a value returned from a function), the object
1574 -- is attached on the caller side as soon as the call
1575 -- is completed (see Expand_Ctrl_Function_Call)
1577 if Is_RTE (Apool, RE_SS_Pool) then
1578 declare
1579 F : constant Entity_Id :=
1580 Make_Defining_Identifier (Loc,
1581 New_Internal_Name ('F'));
1582 begin
1583 Insert_Action (N,
1584 Make_Object_Declaration (Loc,
1585 Defining_Identifier => F,
1586 Object_Definition => New_Reference_To (RTE
1587 (RE_Finalizable_Ptr), Loc)));
1589 Flist := New_Reference_To (F, Loc);
1590 Attach := Make_Integer_Literal (Loc, 1);
1591 end;
1593 -- Normal case, not a secondary stack allocation
1595 else
1596 Flist := Find_Final_List (PtrT);
1597 Attach := Make_Integer_Literal (Loc, 2);
1598 end if;
1600 if not Aggr_In_Place then
1601 Insert_Actions (N,
1602 Make_Adjust_Call (
1603 Ref =>
1605 -- An unchecked conversion is needed in the
1606 -- classwide case because the designated type
1607 -- can be an ancestor of the subtype mark of
1608 -- the allocator.
1610 Unchecked_Convert_To (T,
1611 Make_Explicit_Dereference (Loc,
1612 New_Reference_To (Temp, Loc))),
1614 Typ => T,
1615 Flist_Ref => Flist,
1616 With_Attach => Attach));
1617 end if;
1618 end;
1619 end if;
1621 Rewrite (N, New_Reference_To (Temp, Loc));
1622 Analyze_And_Resolve (N, PtrT);
1624 elsif Aggr_In_Place then
1625 Temp :=
1626 Make_Defining_Identifier (Loc, New_Internal_Name ('P'));
1627 Tmp_Node :=
1628 Make_Object_Declaration (Loc,
1629 Defining_Identifier => Temp,
1630 Object_Definition => New_Reference_To (PtrT, Loc),
1631 Expression => Make_Allocator (Loc,
1632 New_Reference_To (Etype (Exp), Loc)));
1634 Set_No_Initialization (Expression (Tmp_Node));
1635 Insert_Action (N, Tmp_Node);
1636 Convert_Aggr_In_Allocator (Tmp_Node, Exp);
1637 Rewrite (N, New_Reference_To (Temp, Loc));
1638 Analyze_And_Resolve (N, PtrT);
1640 elsif Is_Access_Type (Designated_Type (PtrT))
1641 and then Nkind (Exp) = N_Allocator
1642 and then Nkind (Expression (Exp)) /= N_Qualified_Expression
1643 then
1644 -- Apply constraint to designated subtype indication.
1646 Apply_Constraint_Check (Expression (Exp),
1647 Designated_Type (Designated_Type (PtrT)),
1648 No_Sliding => True);
1650 if Nkind (Expression (Exp)) = N_Raise_Constraint_Error then
1652 -- Propagate constraint_error to enclosing allocator.
1654 Rewrite
1655 (Exp, New_Copy (Expression (Exp)));
1656 end if;
1657 else
1658 -- First check against the type of the qualified expression
1660 -- NOTE: The commented call should be correct, but for
1661 -- some reason causes the compiler to bomb (sigsegv) on
1662 -- ACVC test c34007g, so for now we just perform the old
1663 -- (incorrect) test against the designated subtype with
1664 -- no sliding in the else part of the if statement below.
1665 -- ???
1667 -- Apply_Constraint_Check (Exp, T, No_Sliding => True);
1669 -- A check is also needed in cases where the designated
1670 -- subtype is constrained and differs from the subtype
1671 -- given in the qualified expression. Note that the check
1672 -- on the qualified expression does not allow sliding,
1673 -- but this check does (a relaxation from Ada 83).
1675 if Is_Constrained (Designated_Type (PtrT))
1676 and then not Subtypes_Statically_Match
1677 (T, Designated_Type (PtrT))
1678 then
1679 Apply_Constraint_Check
1680 (Exp, Designated_Type (PtrT), No_Sliding => False);
1682 -- The nonsliding check should really be performed
1683 -- (unconditionally) against the subtype of the
1684 -- qualified expression, but that causes a problem
1685 -- with c34007g (see above), so for now we retain this.
1687 else
1688 Apply_Constraint_Check
1689 (Exp, Designated_Type (PtrT), No_Sliding => True);
1690 end if;
1691 end if;
1692 end;
1694 -- Here if not qualified expression case.
1695 -- In this case, an initialization routine may be required
1697 else
1698 declare
1699 T : constant Entity_Id := Entity (Expression (N));
1700 Init : Entity_Id;
1701 Arg1 : Node_Id;
1702 Args : List_Id;
1703 Decls : List_Id;
1704 Decl : Node_Id;
1705 Discr : Elmt_Id;
1706 Flist : Node_Id;
1707 Temp_Decl : Node_Id;
1708 Temp_Type : Entity_Id;
1710 begin
1712 if No_Initialization (N) then
1713 null;
1715 -- Case of no initialization procedure present
1717 elsif not Has_Non_Null_Base_Init_Proc (T) then
1719 -- Case of simple initialization required
1721 if Needs_Simple_Initialization (T) then
1722 Rewrite (Expression (N),
1723 Make_Qualified_Expression (Loc,
1724 Subtype_Mark => New_Occurrence_Of (T, Loc),
1725 Expression => Get_Simple_Init_Val (T, Loc)));
1727 Analyze_And_Resolve (Expression (Expression (N)), T);
1728 Analyze_And_Resolve (Expression (N), T);
1729 Set_Paren_Count (Expression (Expression (N)), 1);
1730 Expand_N_Allocator (N);
1732 -- No initialization required
1734 else
1735 null;
1736 end if;
1738 -- Case of initialization procedure present, must be called
1740 else
1741 Init := Base_Init_Proc (T);
1742 Node := N;
1743 Temp :=
1744 Make_Defining_Identifier (Loc, New_Internal_Name ('P'));
1746 -- Construct argument list for the initialization routine call
1747 -- The CPP constructor needs the address directly
1749 if Is_CPP_Class (T) then
1750 Arg1 := New_Reference_To (Temp, Loc);
1751 Temp_Type := T;
1753 else
1754 Arg1 :=
1755 Make_Explicit_Dereference (Loc,
1756 Prefix => New_Reference_To (Temp, Loc));
1757 Set_Assignment_OK (Arg1);
1758 Temp_Type := PtrT;
1760 -- The initialization procedure expects a specific type.
1761 -- if the context is access to class wide, indicate that
1762 -- the object being allocated has the right specific type.
1764 if Is_Class_Wide_Type (Designated_Type (PtrT)) then
1765 Arg1 := Unchecked_Convert_To (T, Arg1);
1766 end if;
1767 end if;
1769 -- If designated type is a concurrent type or if it is a
1770 -- private type whose definition is a concurrent type,
1771 -- the first argument in the Init routine has to be
1772 -- unchecked conversion to the corresponding record type.
1773 -- If the designated type is a derived type, we also
1774 -- convert the argument to its root type.
1776 if Is_Concurrent_Type (T) then
1777 Arg1 :=
1778 Unchecked_Convert_To (Corresponding_Record_Type (T), Arg1);
1780 elsif Is_Private_Type (T)
1781 and then Present (Full_View (T))
1782 and then Is_Concurrent_Type (Full_View (T))
1783 then
1784 Arg1 :=
1785 Unchecked_Convert_To
1786 (Corresponding_Record_Type (Full_View (T)), Arg1);
1788 elsif Etype (First_Formal (Init)) /= Base_Type (T) then
1790 declare
1791 Ftyp : constant Entity_Id := Etype (First_Formal (Init));
1793 begin
1794 Arg1 := OK_Convert_To (Etype (Ftyp), Arg1);
1795 Set_Etype (Arg1, Ftyp);
1796 end;
1797 end if;
1799 Args := New_List (Arg1);
1801 -- For the task case, pass the Master_Id of the access type
1802 -- as the value of the _Master parameter, and _Chain as the
1803 -- value of the _Chain parameter (_Chain will be defined as
1804 -- part of the generated code for the allocator).
1806 if Has_Task (T) then
1808 if No (Master_Id (Base_Type (PtrT))) then
1810 -- The designated type was an incomplete type, and
1811 -- the access type did not get expanded. Salvage
1812 -- it now.
1814 Expand_N_Full_Type_Declaration
1815 (Parent (Base_Type (PtrT)));
1816 end if;
1818 -- If the context of the allocator is a declaration or
1819 -- an assignment, we can generate a meaningful image for
1820 -- it, even though subsequent assignments might remove
1821 -- the connection between task and entity. We build this
1822 -- image when the left-hand side is a simple variable,
1823 -- a simple indexed assignment or a simple selected
1824 -- component.
1826 if Nkind (Parent (N)) = N_Assignment_Statement then
1827 declare
1828 Nam : constant Node_Id := Name (Parent (N));
1830 begin
1831 if Is_Entity_Name (Nam) then
1832 Decls :=
1833 Build_Task_Image_Decls (
1834 Loc,
1835 New_Occurrence_Of
1836 (Entity (Nam), Sloc (Nam)), T);
1838 elsif (Nkind (Nam) = N_Indexed_Component
1839 or else Nkind (Nam) = N_Selected_Component)
1840 and then Is_Entity_Name (Prefix (Nam))
1841 then
1842 Decls :=
1843 Build_Task_Image_Decls
1844 (Loc, Nam, Etype (Prefix (Nam)));
1845 else
1846 Decls := Build_Task_Image_Decls (Loc, T, T);
1847 end if;
1848 end;
1850 elsif Nkind (Parent (N)) = N_Object_Declaration then
1851 Decls :=
1852 Build_Task_Image_Decls (
1853 Loc, Defining_Identifier (Parent (N)), T);
1855 else
1856 Decls := Build_Task_Image_Decls (Loc, T, T);
1857 end if;
1859 Append_To (Args,
1860 New_Reference_To
1861 (Master_Id (Base_Type (Root_Type (PtrT))), Loc));
1862 Append_To (Args, Make_Identifier (Loc, Name_uChain));
1864 Decl := Last (Decls);
1865 Append_To (Args,
1866 New_Occurrence_Of (Defining_Identifier (Decl), Loc));
1868 -- Has_Task is false, Decls not used
1870 else
1871 Decls := No_List;
1872 end if;
1874 -- Add discriminants if discriminated type
1876 if Has_Discriminants (T) then
1877 Discr := First_Elmt (Discriminant_Constraint (T));
1879 while Present (Discr) loop
1880 Append (New_Copy (Elists.Node (Discr)), Args);
1881 Next_Elmt (Discr);
1882 end loop;
1884 elsif Is_Private_Type (T)
1885 and then Present (Full_View (T))
1886 and then Has_Discriminants (Full_View (T))
1887 then
1888 Discr :=
1889 First_Elmt (Discriminant_Constraint (Full_View (T)));
1891 while Present (Discr) loop
1892 Append (New_Copy (Elists.Node (Discr)), Args);
1893 Next_Elmt (Discr);
1894 end loop;
1895 end if;
1897 -- We set the allocator as analyzed so that when we analyze the
1898 -- expression actions node, we do not get an unwanted recursive
1899 -- expansion of the allocator expression.
1901 Set_Analyzed (N, True);
1902 Node := Relocate_Node (N);
1904 -- Here is the transformation:
1905 -- input: new T
1906 -- output: Temp : constant ptr_T := new T;
1907 -- Init (Temp.all, ...);
1908 -- <CTRL> Attach_To_Final_List (Finalizable (Temp.all));
1909 -- <CTRL> Initialize (Finalizable (Temp.all));
1911 -- Here ptr_T is the pointer type for the allocator, and T
1912 -- is the subtype of the allocator.
1914 Temp_Decl :=
1915 Make_Object_Declaration (Loc,
1916 Defining_Identifier => Temp,
1917 Constant_Present => True,
1918 Object_Definition => New_Reference_To (Temp_Type, Loc),
1919 Expression => Node);
1921 Set_Assignment_OK (Temp_Decl);
1923 if Is_CPP_Class (T) then
1924 Set_Aliased_Present (Temp_Decl);
1925 end if;
1927 Insert_Action (N, Temp_Decl, Suppress => All_Checks);
1929 -- Case of designated type is task or contains task
1930 -- Create block to activate created tasks, and insert
1931 -- declaration for Task_Image variable ahead of call.
1933 if Has_Task (T) then
1934 declare
1935 L : List_Id := New_List;
1936 Blk : Node_Id;
1938 begin
1939 Build_Task_Allocate_Block (L, Node, Args);
1940 Blk := Last (L);
1942 Insert_List_Before (First (Declarations (Blk)), Decls);
1943 Insert_Actions (N, L);
1944 end;
1946 else
1947 Insert_Action (N,
1948 Make_Procedure_Call_Statement (Loc,
1949 Name => New_Reference_To (Init, Loc),
1950 Parameter_Associations => Args));
1951 end if;
1953 if Controlled_Type (T) then
1955 -- If the context is an access parameter, we need to create
1956 -- a non-anonymous access type in order to have a usable
1957 -- final list, because there is otherwise no pool to which
1958 -- the allocated object can belong. We create both the type
1959 -- and the finalization chain here, because freezing an
1960 -- internal type does not create such a chain.
1962 if Ekind (PtrT) = E_Anonymous_Access_Type then
1963 declare
1964 Acc : Entity_Id :=
1965 Make_Defining_Identifier (Loc,
1966 New_Internal_Name ('I'));
1967 begin
1968 Insert_Action (N,
1969 Make_Full_Type_Declaration (Loc,
1970 Defining_Identifier => Acc,
1971 Type_Definition =>
1972 Make_Access_To_Object_Definition (Loc,
1973 Subtype_Indication =>
1974 New_Occurrence_Of (T, Loc))));
1976 Build_Final_List (N, Acc);
1977 Flist := Find_Final_List (Acc);
1978 end;
1980 else
1981 Flist := Find_Final_List (PtrT);
1982 end if;
1984 Insert_Actions (N,
1985 Make_Init_Call (
1986 Ref => New_Copy_Tree (Arg1),
1987 Typ => T,
1988 Flist_Ref => Flist,
1989 With_Attach => Make_Integer_Literal (Loc, 2)));
1990 end if;
1992 if Is_CPP_Class (T) then
1993 Rewrite (N,
1994 Make_Attribute_Reference (Loc,
1995 Prefix => New_Reference_To (Temp, Loc),
1996 Attribute_Name => Name_Unchecked_Access));
1997 else
1998 Rewrite (N, New_Reference_To (Temp, Loc));
1999 end if;
2001 Analyze_And_Resolve (N, PtrT);
2002 end if;
2003 end;
2004 end if;
2005 end Expand_N_Allocator;
2007 -----------------------
2008 -- Expand_N_And_Then --
2009 -----------------------
2011 -- Expand into conditional expression if Actions present, and also
2012 -- deal with optimizing case of arguments being True or False.
2014 procedure Expand_N_And_Then (N : Node_Id) is
2015 Loc : constant Source_Ptr := Sloc (N);
2016 Typ : constant Entity_Id := Etype (N);
2017 Left : constant Node_Id := Left_Opnd (N);
2018 Right : constant Node_Id := Right_Opnd (N);
2019 Actlist : List_Id;
2021 begin
2022 -- Deal with non-standard booleans
2024 if Is_Boolean_Type (Typ) then
2025 Adjust_Condition (Left);
2026 Adjust_Condition (Right);
2027 Set_Etype (N, Standard_Boolean);
2028 end if;
2030 -- Check for cases of left argument is True or False
2032 if Nkind (Left) = N_Identifier then
2034 -- If left argument is True, change (True and then Right) to Right.
2035 -- Any actions associated with Right will be executed unconditionally
2036 -- and can thus be inserted into the tree unconditionally.
2038 if Entity (Left) = Standard_True then
2039 if Present (Actions (N)) then
2040 Insert_Actions (N, Actions (N));
2041 end if;
2043 Rewrite (N, Right);
2044 Adjust_Result_Type (N, Typ);
2045 return;
2047 -- If left argument is False, change (False and then Right) to
2048 -- False. In this case we can forget the actions associated with
2049 -- Right, since they will never be executed.
2051 elsif Entity (Left) = Standard_False then
2052 Kill_Dead_Code (Right);
2053 Kill_Dead_Code (Actions (N));
2054 Rewrite (N, New_Occurrence_Of (Standard_False, Loc));
2055 Adjust_Result_Type (N, Typ);
2056 return;
2057 end if;
2058 end if;
2060 -- If Actions are present, we expand
2062 -- left and then right
2064 -- into
2066 -- if left then right else false end
2068 -- with the actions becoming the Then_Actions of the conditional
2069 -- expression. This conditional expression is then further expanded
2070 -- (and will eventually disappear)
2072 if Present (Actions (N)) then
2073 Actlist := Actions (N);
2074 Rewrite (N,
2075 Make_Conditional_Expression (Loc,
2076 Expressions => New_List (
2077 Left,
2078 Right,
2079 New_Occurrence_Of (Standard_False, Loc))));
2081 Set_Then_Actions (N, Actlist);
2082 Analyze_And_Resolve (N, Standard_Boolean);
2083 Adjust_Result_Type (N, Typ);
2084 return;
2085 end if;
2087 -- No actions present, check for cases of right argument True/False
2089 if Nkind (Right) = N_Identifier then
2091 -- Change (Left and then True) to Left. Note that we know there
2092 -- are no actions associated with the True operand, since we
2093 -- just checked for this case above.
2095 if Entity (Right) = Standard_True then
2096 Rewrite (N, Left);
2098 -- Change (Left and then False) to False, making sure to preserve
2099 -- any side effects associated with the Left operand.
2101 elsif Entity (Right) = Standard_False then
2102 Remove_Side_Effects (Left);
2103 Rewrite
2104 (N, New_Occurrence_Of (Standard_False, Loc));
2105 end if;
2106 end if;
2108 Adjust_Result_Type (N, Typ);
2109 end Expand_N_And_Then;
2111 -------------------------------------
2112 -- Expand_N_Conditional_Expression --
2113 -------------------------------------
2115 -- Expand into expression actions if then/else actions present
2117 procedure Expand_N_Conditional_Expression (N : Node_Id) is
2118 Loc : constant Source_Ptr := Sloc (N);
2119 Cond : constant Node_Id := First (Expressions (N));
2120 Thenx : constant Node_Id := Next (Cond);
2121 Elsex : constant Node_Id := Next (Thenx);
2122 Typ : constant Entity_Id := Etype (N);
2123 Cnn : Entity_Id;
2124 New_If : Node_Id;
2126 begin
2127 -- If either then or else actions are present, then given:
2129 -- if cond then then-expr else else-expr end
2131 -- we insert the following sequence of actions (using Insert_Actions):
2133 -- Cnn : typ;
2134 -- if cond then
2135 -- <<then actions>>
2136 -- Cnn := then-expr;
2137 -- else
2138 -- <<else actions>>
2139 -- Cnn := else-expr
2140 -- end if;
2142 -- and replace the conditional expression by a reference to Cnn.
2144 if Present (Then_Actions (N)) or else Present (Else_Actions (N)) then
2145 Cnn := Make_Defining_Identifier (Loc, New_Internal_Name ('C'));
2147 New_If :=
2148 Make_Implicit_If_Statement (N,
2149 Condition => Relocate_Node (Cond),
2151 Then_Statements => New_List (
2152 Make_Assignment_Statement (Sloc (Thenx),
2153 Name => New_Occurrence_Of (Cnn, Sloc (Thenx)),
2154 Expression => Relocate_Node (Thenx))),
2156 Else_Statements => New_List (
2157 Make_Assignment_Statement (Sloc (Elsex),
2158 Name => New_Occurrence_Of (Cnn, Sloc (Elsex)),
2159 Expression => Relocate_Node (Elsex))));
2161 if Present (Then_Actions (N)) then
2162 Insert_List_Before
2163 (First (Then_Statements (New_If)), Then_Actions (N));
2164 end if;
2166 if Present (Else_Actions (N)) then
2167 Insert_List_Before
2168 (First (Else_Statements (New_If)), Else_Actions (N));
2169 end if;
2171 Rewrite (N, New_Occurrence_Of (Cnn, Loc));
2173 Insert_Action (N,
2174 Make_Object_Declaration (Loc,
2175 Defining_Identifier => Cnn,
2176 Object_Definition => New_Occurrence_Of (Typ, Loc)));
2178 Insert_Action (N, New_If);
2179 Analyze_And_Resolve (N, Typ);
2180 end if;
2181 end Expand_N_Conditional_Expression;
2183 -----------------------------------
2184 -- Expand_N_Explicit_Dereference --
2185 -----------------------------------
2187 procedure Expand_N_Explicit_Dereference (N : Node_Id) is
2188 begin
2189 -- The only processing required is an insertion of an explicit
2190 -- dereference call for the checked storage pool case.
2192 Insert_Dereference_Action (Prefix (N));
2193 end Expand_N_Explicit_Dereference;
2195 -----------------
2196 -- Expand_N_In --
2197 -----------------
2199 procedure Expand_N_In (N : Node_Id) is
2200 Loc : constant Source_Ptr := Sloc (N);
2201 Rtyp : constant Entity_Id := Etype (N);
2203 begin
2204 -- No expansion is required if we have an explicit range
2206 if Nkind (Right_Opnd (N)) = N_Range then
2207 return;
2209 -- Here right operand is a subtype mark
2211 else
2212 declare
2213 Typ : Entity_Id := Etype (Right_Opnd (N));
2214 Obj : Node_Id := Left_Opnd (N);
2215 Cond : Node_Id := Empty;
2216 Is_Acc : Boolean := Is_Access_Type (Typ);
2218 begin
2219 Remove_Side_Effects (Obj);
2221 -- For tagged type, do tagged membership operation
2223 if Is_Tagged_Type (Typ) then
2224 -- No expansion will be performed when Java_VM, as the
2225 -- JVM back end will handle the membership tests directly
2226 -- (tags are not explicitly represented in Java objects,
2227 -- so the normal tagged membership expansion is not what
2228 -- we want).
2230 if not Java_VM then
2231 Rewrite (N, Tagged_Membership (N));
2232 Analyze_And_Resolve (N, Rtyp);
2233 end if;
2235 return;
2237 -- If type is scalar type, rewrite as x in t'first .. t'last
2238 -- This reason we do this is that the bounds may have the wrong
2239 -- type if they come from the original type definition.
2241 elsif Is_Scalar_Type (Typ) then
2242 Rewrite (Right_Opnd (N),
2243 Make_Range (Loc,
2244 Low_Bound =>
2245 Make_Attribute_Reference (Loc,
2246 Attribute_Name => Name_First,
2247 Prefix => New_Reference_To (Typ, Loc)),
2249 High_Bound =>
2250 Make_Attribute_Reference (Loc,
2251 Attribute_Name => Name_Last,
2252 Prefix => New_Reference_To (Typ, Loc))));
2253 Analyze_And_Resolve (N, Rtyp);
2254 return;
2255 end if;
2257 if Is_Acc then
2258 Typ := Designated_Type (Typ);
2259 end if;
2261 if not Is_Constrained (Typ) then
2262 Rewrite (N,
2263 New_Reference_To (Standard_True, Loc));
2264 Analyze_And_Resolve (N, Rtyp);
2266 -- For the constrained array case, we have to check the
2267 -- subscripts for an exact match if the lengths are
2268 -- non-zero (the lengths must match in any case).
2270 elsif Is_Array_Type (Typ) then
2272 declare
2273 function Construct_Attribute_Reference
2274 (E : Node_Id;
2275 Nam : Name_Id;
2276 Dim : Nat)
2277 return Node_Id;
2278 -- Build attribute reference E'Nam(Dim)
2280 function Construct_Attribute_Reference
2281 (E : Node_Id;
2282 Nam : Name_Id;
2283 Dim : Nat)
2284 return Node_Id
2286 begin
2287 return
2288 Make_Attribute_Reference (Loc,
2289 Prefix => E,
2290 Attribute_Name => Nam,
2291 Expressions => New_List (
2292 Make_Integer_Literal (Loc, Dim)));
2293 end Construct_Attribute_Reference;
2295 begin
2296 for J in 1 .. Number_Dimensions (Typ) loop
2297 Evolve_And_Then (Cond,
2298 Make_Op_Eq (Loc,
2299 Left_Opnd =>
2300 Construct_Attribute_Reference
2301 (Duplicate_Subexpr (Obj), Name_First, J),
2302 Right_Opnd =>
2303 Construct_Attribute_Reference
2304 (New_Occurrence_Of (Typ, Loc), Name_First, J)));
2306 Evolve_And_Then (Cond,
2307 Make_Op_Eq (Loc,
2308 Left_Opnd =>
2309 Construct_Attribute_Reference
2310 (Duplicate_Subexpr (Obj), Name_Last, J),
2311 Right_Opnd =>
2312 Construct_Attribute_Reference
2313 (New_Occurrence_Of (Typ, Loc), Name_Last, J)));
2314 end loop;
2316 if Is_Acc then
2317 Cond := Make_Or_Else (Loc,
2318 Left_Opnd =>
2319 Make_Op_Eq (Loc,
2320 Left_Opnd => Obj,
2321 Right_Opnd => Make_Null (Loc)),
2322 Right_Opnd => Cond);
2323 end if;
2325 Rewrite (N, Cond);
2326 Analyze_And_Resolve (N, Rtyp);
2327 end;
2329 -- These are the cases where constraint checks may be
2330 -- required, e.g. records with possible discriminants
2332 else
2333 -- Expand the test into a series of discriminant comparisons.
2334 -- The expression that is built is the negation of the one
2335 -- that is used for checking discriminant constraints.
2337 Obj := Relocate_Node (Left_Opnd (N));
2339 if Has_Discriminants (Typ) then
2340 Cond := Make_Op_Not (Loc,
2341 Right_Opnd => Build_Discriminant_Checks (Obj, Typ));
2343 if Is_Acc then
2344 Cond := Make_Or_Else (Loc,
2345 Left_Opnd =>
2346 Make_Op_Eq (Loc,
2347 Left_Opnd => Obj,
2348 Right_Opnd => Make_Null (Loc)),
2349 Right_Opnd => Cond);
2350 end if;
2352 else
2353 Cond := New_Occurrence_Of (Standard_True, Loc);
2354 end if;
2356 Rewrite (N, Cond);
2357 Analyze_And_Resolve (N, Rtyp);
2358 end if;
2359 end;
2360 end if;
2361 end Expand_N_In;
2363 --------------------------------
2364 -- Expand_N_Indexed_Component --
2365 --------------------------------
2367 procedure Expand_N_Indexed_Component (N : Node_Id) is
2368 Loc : constant Source_Ptr := Sloc (N);
2369 Typ : constant Entity_Id := Etype (N);
2370 P : constant Node_Id := Prefix (N);
2371 T : constant Entity_Id := Etype (P);
2373 begin
2374 -- A special optimization, if we have an indexed component that
2375 -- is selecting from a slice, then we can eliminate the slice,
2376 -- since, for example, x (i .. j)(k) is identical to x(k). The
2377 -- only difference is the range check required by the slice. The
2378 -- range check for the slice itself has already been generated.
2379 -- The range check for the subscripting operation is ensured
2380 -- by converting the subject to the subtype of the slice.
2382 -- This optimization not only generates better code, avoiding
2383 -- slice messing especially in the packed case, but more importantly
2384 -- bypasses some problems in handling this peculiar case, for
2385 -- example, the issue of dealing specially with object renamings.
2387 if Nkind (P) = N_Slice then
2388 Rewrite (N,
2389 Make_Indexed_Component (Loc,
2390 Prefix => Prefix (P),
2391 Expressions => New_List (
2392 Convert_To
2393 (Etype (First_Index (Etype (P))),
2394 First (Expressions (N))))));
2395 Analyze_And_Resolve (N, Typ);
2396 return;
2397 end if;
2399 -- If the prefix is an access type, then we unconditionally rewrite
2400 -- if as an explicit deference. This simplifies processing for several
2401 -- cases, including packed array cases and certain cases in which
2402 -- checks must be generated. We used to try to do this only when it
2403 -- was necessary, but it cleans up the code to do it all the time.
2405 if Is_Access_Type (T) then
2406 Rewrite (P,
2407 Make_Explicit_Dereference (Sloc (N),
2408 Prefix => Relocate_Node (P)));
2409 Analyze_And_Resolve (P, Designated_Type (T));
2410 end if;
2412 if Validity_Checks_On and then Validity_Check_Subscripts then
2413 Apply_Subscript_Validity_Checks (N);
2414 end if;
2416 -- All done for the non-packed case
2418 if not Is_Packed (Etype (Prefix (N))) then
2419 return;
2420 end if;
2422 -- For packed arrays that are not bit-packed (i.e. the case of an array
2423 -- with one or more index types with a non-coniguous enumeration type),
2424 -- we can always use the normal packed element get circuit.
2426 if not Is_Bit_Packed_Array (Etype (Prefix (N))) then
2427 Expand_Packed_Element_Reference (N);
2428 return;
2429 end if;
2431 -- For a reference to a component of a bit packed array, we have to
2432 -- convert it to a reference to the corresponding Packed_Array_Type.
2433 -- We only want to do this for simple references, and not for:
2435 -- Left side of assignment (or prefix of left side of assignment)
2436 -- This case is handled in Exp_Ch5.Expand_N_Assignment_Statement
2438 -- Renaming objects in renaming associations
2439 -- This case is handled when a use of the renamed variable occurs
2441 -- Actual parameters for a procedure call
2442 -- This case is handled in Exp_Ch6.Expand_Actuals
2444 -- The second expression in a 'Read attribute reference
2446 -- The prefix of an address or size attribute reference
2448 -- The following circuit detects these exceptions
2450 declare
2451 Child : Node_Id := N;
2452 Parnt : Node_Id := Parent (N);
2454 begin
2455 loop
2456 if Nkind (Parnt) = N_Unchecked_Expression then
2457 null;
2459 elsif Nkind (Parnt) = N_Object_Renaming_Declaration
2460 or else Nkind (Parnt) = N_Procedure_Call_Statement
2461 or else (Nkind (Parnt) = N_Parameter_Association
2462 and then
2463 Nkind (Parent (Parnt)) = N_Procedure_Call_Statement)
2464 then
2465 return;
2467 elsif Nkind (Parnt) = N_Attribute_Reference
2468 and then (Attribute_Name (Parnt) = Name_Address
2469 or else
2470 Attribute_Name (Parnt) = Name_Size)
2471 and then Prefix (Parnt) = Child
2472 then
2473 return;
2475 elsif Nkind (Parnt) = N_Assignment_Statement
2476 and then Name (Parnt) = Child
2477 then
2478 return;
2480 elsif Nkind (Parnt) = N_Attribute_Reference
2481 and then Attribute_Name (Parnt) = Name_Read
2482 and then Next (First (Expressions (Parnt))) = Child
2483 then
2484 return;
2486 elsif (Nkind (Parnt) = N_Indexed_Component
2487 or else Nkind (Parnt) = N_Selected_Component)
2488 and then Prefix (Parnt) = Child
2489 then
2490 null;
2492 else
2493 Expand_Packed_Element_Reference (N);
2494 return;
2495 end if;
2497 -- Keep looking up tree for unchecked expression, or if we are
2498 -- the prefix of a possible assignment left side.
2500 Child := Parnt;
2501 Parnt := Parent (Child);
2502 end loop;
2503 end;
2505 end Expand_N_Indexed_Component;
2507 ---------------------
2508 -- Expand_N_Not_In --
2509 ---------------------
2511 -- Replace a not in b by not (a in b) so that the expansions for (a in b)
2512 -- can be done. This avoids needing to duplicate this expansion code.
2514 procedure Expand_N_Not_In (N : Node_Id) is
2515 Loc : constant Source_Ptr := Sloc (N);
2516 Typ : constant Entity_Id := Etype (N);
2518 begin
2519 Rewrite (N,
2520 Make_Op_Not (Loc,
2521 Right_Opnd =>
2522 Make_In (Loc,
2523 Left_Opnd => Left_Opnd (N),
2524 Right_Opnd => Right_Opnd (N))));
2525 Analyze_And_Resolve (N, Typ);
2526 end Expand_N_Not_In;
2528 -------------------
2529 -- Expand_N_Null --
2530 -------------------
2532 -- The only replacement required is for the case of a null of type
2533 -- that is an access to protected subprogram. We represent such
2534 -- access values as a record, and so we must replace the occurrence
2535 -- of null by the equivalent record (with a null address and a null
2536 -- pointer in it), so that the backend creates the proper value.
2538 procedure Expand_N_Null (N : Node_Id) is
2539 Loc : constant Source_Ptr := Sloc (N);
2540 Typ : constant Entity_Id := Etype (N);
2541 Agg : Node_Id;
2543 begin
2544 if Ekind (Typ) = E_Access_Protected_Subprogram_Type then
2545 Agg :=
2546 Make_Aggregate (Loc,
2547 Expressions => New_List (
2548 New_Occurrence_Of (RTE (RE_Null_Address), Loc),
2549 Make_Null (Loc)));
2551 Rewrite (N, Agg);
2552 Analyze_And_Resolve (N, Equivalent_Type (Typ));
2554 -- For subsequent semantic analysis, the node must retain its
2555 -- type. Gigi in any case replaces this type by the corresponding
2556 -- record type before processing the node.
2558 Set_Etype (N, Typ);
2559 end if;
2560 end Expand_N_Null;
2562 ---------------------
2563 -- Expand_N_Op_Abs --
2564 ---------------------
2566 procedure Expand_N_Op_Abs (N : Node_Id) is
2567 Loc : constant Source_Ptr := Sloc (N);
2568 Expr : constant Node_Id := Right_Opnd (N);
2570 begin
2571 Unary_Op_Validity_Checks (N);
2573 -- Deal with software overflow checking
2575 if Software_Overflow_Checking
2576 and then Is_Signed_Integer_Type (Etype (N))
2577 and then Do_Overflow_Check (N)
2578 then
2579 -- Software overflow checking expands abs (expr) into
2581 -- (if expr >= 0 then expr else -expr)
2583 -- with the usual Duplicate_Subexpr use coding for expr
2585 Rewrite (N,
2586 Make_Conditional_Expression (Loc,
2587 Expressions => New_List (
2588 Make_Op_Ge (Loc,
2589 Left_Opnd => Duplicate_Subexpr (Expr),
2590 Right_Opnd => Make_Integer_Literal (Loc, 0)),
2592 Duplicate_Subexpr (Expr),
2594 Make_Op_Minus (Loc,
2595 Right_Opnd => Duplicate_Subexpr (Expr)))));
2597 Analyze_And_Resolve (N);
2599 -- Vax floating-point types case
2601 elsif Vax_Float (Etype (N)) then
2602 Expand_Vax_Arith (N);
2603 end if;
2604 end Expand_N_Op_Abs;
2606 ---------------------
2607 -- Expand_N_Op_Add --
2608 ---------------------
2610 procedure Expand_N_Op_Add (N : Node_Id) is
2611 Typ : constant Entity_Id := Etype (N);
2613 begin
2614 Binary_Op_Validity_Checks (N);
2616 -- N + 0 = 0 + N = N for integer types
2618 if Is_Integer_Type (Typ) then
2619 if Compile_Time_Known_Value (Right_Opnd (N))
2620 and then Expr_Value (Right_Opnd (N)) = Uint_0
2621 then
2622 Rewrite (N, Left_Opnd (N));
2623 return;
2625 elsif Compile_Time_Known_Value (Left_Opnd (N))
2626 and then Expr_Value (Left_Opnd (N)) = Uint_0
2627 then
2628 Rewrite (N, Right_Opnd (N));
2629 return;
2630 end if;
2631 end if;
2633 -- Arithemtic overflow checks for signed integer/fixed point types
2635 if Is_Signed_Integer_Type (Typ)
2636 or else Is_Fixed_Point_Type (Typ)
2637 then
2638 Apply_Arithmetic_Overflow_Check (N);
2639 return;
2641 -- Vax floating-point types case
2643 elsif Vax_Float (Typ) then
2644 Expand_Vax_Arith (N);
2645 end if;
2646 end Expand_N_Op_Add;
2648 ---------------------
2649 -- Expand_N_Op_And --
2650 ---------------------
2652 procedure Expand_N_Op_And (N : Node_Id) is
2653 Typ : constant Entity_Id := Etype (N);
2655 begin
2656 Binary_Op_Validity_Checks (N);
2658 if Is_Array_Type (Etype (N)) then
2659 Expand_Boolean_Operator (N);
2661 elsif Is_Boolean_Type (Etype (N)) then
2662 Adjust_Condition (Left_Opnd (N));
2663 Adjust_Condition (Right_Opnd (N));
2664 Set_Etype (N, Standard_Boolean);
2665 Adjust_Result_Type (N, Typ);
2666 end if;
2667 end Expand_N_Op_And;
2669 ------------------------
2670 -- Expand_N_Op_Concat --
2671 ------------------------
2673 procedure Expand_N_Op_Concat (N : Node_Id) is
2675 Opnds : List_Id;
2676 -- List of operands to be concatenated
2678 Opnd : Node_Id;
2679 -- Single operand for concatenation
2681 Cnode : Node_Id;
2682 -- Node which is to be replaced by the result of concatenating
2683 -- the nodes in the list Opnds.
2685 Atyp : Entity_Id;
2686 -- Array type of concatenation result type
2688 Ctyp : Entity_Id;
2689 -- Component type of concatenation represented by Cnode
2691 begin
2692 Binary_Op_Validity_Checks (N);
2694 -- If we are the left operand of a concatenation higher up the
2695 -- tree, then do nothing for now, since we want to deal with a
2696 -- series of concatenations as a unit.
2698 if Nkind (Parent (N)) = N_Op_Concat
2699 and then N = Left_Opnd (Parent (N))
2700 then
2701 return;
2702 end if;
2704 -- We get here with a concatenation whose left operand may be a
2705 -- concatenation itself with a consistent type. We need to process
2706 -- these concatenation operands from left to right, which means
2707 -- from the deepest node in the tree to the highest node.
2709 Cnode := N;
2710 while Nkind (Left_Opnd (Cnode)) = N_Op_Concat loop
2711 Cnode := Left_Opnd (Cnode);
2712 end loop;
2714 -- Now Opnd is the deepest Opnd, and its parents are the concatenation
2715 -- nodes above, so now we process bottom up, doing the operations. We
2716 -- gather a string that is as long as possible up to five operands
2718 -- The outer loop runs more than once if there are more than five
2719 -- concatenations of type Standard.String, the most we handle for
2720 -- this case, or if more than one concatenation type is involved.
2722 Outer : loop
2723 Opnds := New_List (Left_Opnd (Cnode), Right_Opnd (Cnode));
2724 Set_Parent (Opnds, N);
2726 -- The inner loop gathers concatenation operands
2728 Inner : while Cnode /= N
2729 and then (Base_Type (Etype (Cnode)) /= Standard_String
2730 or else
2731 List_Length (Opnds) < 5)
2732 and then Base_Type (Etype (Cnode)) =
2733 Base_Type (Etype (Parent (Cnode)))
2734 loop
2735 Cnode := Parent (Cnode);
2736 Append (Right_Opnd (Cnode), Opnds);
2737 end loop Inner;
2739 -- Here we process the collected operands. First we convert
2740 -- singleton operands to singleton aggregates. This is skipped
2741 -- however for the case of two operands of type String, since
2742 -- we have special routines for these cases.
2744 Atyp := Base_Type (Etype (Cnode));
2745 Ctyp := Base_Type (Component_Type (Etype (Cnode)));
2747 if List_Length (Opnds) > 2 or else Atyp /= Standard_String then
2748 Opnd := First (Opnds);
2749 loop
2750 if Base_Type (Etype (Opnd)) = Ctyp then
2751 Rewrite (Opnd,
2752 Make_Aggregate (Sloc (Cnode),
2753 Expressions => New_List (Relocate_Node (Opnd))));
2754 Analyze_And_Resolve (Opnd, Atyp);
2755 end if;
2757 Next (Opnd);
2758 exit when No (Opnd);
2759 end loop;
2760 end if;
2762 -- Now call appropriate continuation routine
2764 if Atyp = Standard_String then
2765 Expand_Concatenate_String (Cnode, Opnds);
2766 else
2767 Expand_Concatenate_Other (Cnode, Opnds);
2768 end if;
2770 exit Outer when Cnode = N;
2771 Cnode := Parent (Cnode);
2772 end loop Outer;
2773 end Expand_N_Op_Concat;
2775 ------------------------
2776 -- Expand_N_Op_Divide --
2777 ------------------------
2779 procedure Expand_N_Op_Divide (N : Node_Id) is
2780 Loc : constant Source_Ptr := Sloc (N);
2781 Ltyp : constant Entity_Id := Etype (Left_Opnd (N));
2782 Rtyp : constant Entity_Id := Etype (Right_Opnd (N));
2783 Typ : Entity_Id := Etype (N);
2785 begin
2786 Binary_Op_Validity_Checks (N);
2788 -- Vax_Float is a special case
2790 if Vax_Float (Typ) then
2791 Expand_Vax_Arith (N);
2792 return;
2793 end if;
2795 -- N / 1 = N for integer types
2797 if Is_Integer_Type (Typ)
2798 and then Compile_Time_Known_Value (Right_Opnd (N))
2799 and then Expr_Value (Right_Opnd (N)) = Uint_1
2800 then
2801 Rewrite (N, Left_Opnd (N));
2802 return;
2803 end if;
2805 -- Convert x / 2 ** y to Shift_Right (x, y). Note that the fact that
2806 -- Is_Power_Of_2_For_Shift is set means that we know that our left
2807 -- operand is an unsigned integer, as required for this to work.
2809 if Nkind (Right_Opnd (N)) = N_Op_Expon
2810 and then Is_Power_Of_2_For_Shift (Right_Opnd (N))
2811 then
2812 Rewrite (N,
2813 Make_Op_Shift_Right (Loc,
2814 Left_Opnd => Left_Opnd (N),
2815 Right_Opnd =>
2816 Convert_To (Standard_Natural, Right_Opnd (Right_Opnd (N)))));
2817 Analyze_And_Resolve (N, Typ);
2818 return;
2819 end if;
2821 -- Do required fixup of universal fixed operation
2823 if Typ = Universal_Fixed then
2824 Fixup_Universal_Fixed_Operation (N);
2825 Typ := Etype (N);
2826 end if;
2828 -- Divisions with fixed-point results
2830 if Is_Fixed_Point_Type (Typ) then
2832 -- No special processing if Treat_Fixed_As_Integer is set,
2833 -- since from a semantic point of view such operations are
2834 -- simply integer operations and will be treated that way.
2836 if not Treat_Fixed_As_Integer (N) then
2837 if Is_Integer_Type (Rtyp) then
2838 Expand_Divide_Fixed_By_Integer_Giving_Fixed (N);
2839 else
2840 Expand_Divide_Fixed_By_Fixed_Giving_Fixed (N);
2841 end if;
2842 end if;
2844 -- Other cases of division of fixed-point operands. Again we
2845 -- exclude the case where Treat_Fixed_As_Integer is set.
2847 elsif (Is_Fixed_Point_Type (Ltyp) or else
2848 Is_Fixed_Point_Type (Rtyp))
2849 and then not Treat_Fixed_As_Integer (N)
2850 then
2851 if Is_Integer_Type (Typ) then
2852 Expand_Divide_Fixed_By_Fixed_Giving_Integer (N);
2853 else
2854 pragma Assert (Is_Floating_Point_Type (Typ));
2855 Expand_Divide_Fixed_By_Fixed_Giving_Float (N);
2856 end if;
2858 -- Mixed-mode operations can appear in a non-static universal
2859 -- context, in which case the integer argument must be converted
2860 -- explicitly.
2862 elsif Typ = Universal_Real
2863 and then Is_Integer_Type (Rtyp)
2864 then
2865 Rewrite (Right_Opnd (N),
2866 Convert_To (Universal_Real, Relocate_Node (Right_Opnd (N))));
2868 Analyze_And_Resolve (Right_Opnd (N), Universal_Real);
2870 elsif Typ = Universal_Real
2871 and then Is_Integer_Type (Ltyp)
2872 then
2873 Rewrite (Left_Opnd (N),
2874 Convert_To (Universal_Real, Relocate_Node (Left_Opnd (N))));
2876 Analyze_And_Resolve (Left_Opnd (N), Universal_Real);
2878 -- Non-fixed point cases, do zero divide and overflow checks
2880 elsif Is_Integer_Type (Typ) then
2881 Apply_Divide_Check (N);
2882 end if;
2883 end Expand_N_Op_Divide;
2885 --------------------
2886 -- Expand_N_Op_Eq --
2887 --------------------
2889 procedure Expand_N_Op_Eq (N : Node_Id) is
2890 Loc : constant Source_Ptr := Sloc (N);
2891 Typ : constant Entity_Id := Etype (N);
2892 Lhs : constant Node_Id := Left_Opnd (N);
2893 Rhs : constant Node_Id := Right_Opnd (N);
2894 A_Typ : Entity_Id := Etype (Lhs);
2895 Typl : Entity_Id := A_Typ;
2896 Op_Name : Entity_Id;
2897 Prim : Elmt_Id;
2898 Bodies : List_Id := New_List;
2900 procedure Build_Equality_Call (Eq : Entity_Id);
2901 -- If a constructed equality exists for the type or for its parent,
2902 -- build and analyze call, adding conversions if the operation is
2903 -- inherited.
2905 -------------------------
2906 -- Build_Equality_Call --
2907 -------------------------
2909 procedure Build_Equality_Call (Eq : Entity_Id) is
2910 Op_Type : constant Entity_Id := Etype (First_Formal (Eq));
2911 L_Exp : Node_Id := Relocate_Node (Lhs);
2912 R_Exp : Node_Id := Relocate_Node (Rhs);
2914 begin
2915 if Base_Type (Op_Type) /= Base_Type (A_Typ)
2916 and then not Is_Class_Wide_Type (A_Typ)
2917 then
2918 L_Exp := OK_Convert_To (Op_Type, L_Exp);
2919 R_Exp := OK_Convert_To (Op_Type, R_Exp);
2920 end if;
2922 Rewrite (N,
2923 Make_Function_Call (Loc,
2924 Name => New_Reference_To (Eq, Loc),
2925 Parameter_Associations => New_List (L_Exp, R_Exp)));
2927 Analyze_And_Resolve (N, Standard_Boolean, Suppress => All_Checks);
2928 end Build_Equality_Call;
2930 -- Start of processing for Expand_N_Op_Eq
2932 begin
2933 Binary_Op_Validity_Checks (N);
2935 if Ekind (Typl) = E_Private_Type then
2936 Typl := Underlying_Type (Typl);
2938 elsif Ekind (Typl) = E_Private_Subtype then
2939 Typl := Underlying_Type (Base_Type (Typl));
2940 end if;
2942 -- It may happen in error situations that the underlying type is not
2943 -- set. The error will be detected later, here we just defend the
2944 -- expander code.
2946 if No (Typl) then
2947 return;
2948 end if;
2950 Typl := Base_Type (Typl);
2952 -- Vax float types
2954 if Vax_Float (Typl) then
2955 Expand_Vax_Comparison (N);
2956 return;
2958 -- Boolean types (requiring handling of non-standard case)
2960 elsif Is_Boolean_Type (Typl) then
2961 Adjust_Condition (Left_Opnd (N));
2962 Adjust_Condition (Right_Opnd (N));
2963 Set_Etype (N, Standard_Boolean);
2964 Adjust_Result_Type (N, Typ);
2966 -- Array types
2968 elsif Is_Array_Type (Typl) then
2970 -- Packed case
2972 if Is_Bit_Packed_Array (Typl) then
2973 Expand_Packed_Eq (N);
2975 -- For non-floating-point elementary types, the primitive equality
2976 -- always applies, and block-bit comparison is fine. Floating-point
2977 -- is an exception because of negative zeroes.
2979 -- However, we never use block bit comparison in No_Run_Time mode,
2980 -- since this may result in a call to a run time routine
2982 elsif Is_Elementary_Type (Component_Type (Typl))
2983 and then not Is_Floating_Point_Type (Component_Type (Typl))
2984 and then not No_Run_Time
2985 then
2986 null;
2988 -- For composite and floating-point cases, expand equality loop
2989 -- to make sure of using proper comparisons for tagged types,
2990 -- and correctly handling the floating-point case.
2992 else
2993 Rewrite (N,
2994 Expand_Array_Equality (N, Typl, A_Typ,
2995 Relocate_Node (Lhs), Relocate_Node (Rhs), Bodies));
2997 Insert_Actions (N, Bodies, Suppress => All_Checks);
2998 Analyze_And_Resolve (N, Standard_Boolean, Suppress => All_Checks);
2999 end if;
3001 -- Record Types
3003 elsif Is_Record_Type (Typl) then
3005 -- For tagged types, use the primitive "="
3007 if Is_Tagged_Type (Typl) then
3009 -- If this is derived from an untagged private type completed
3010 -- with a tagged type, it does not have a full view, so we
3011 -- use the primitive operations of the private type.
3012 -- This check should no longer be necessary when these
3013 -- types receive their full views ???
3015 if Is_Private_Type (A_Typ)
3016 and then not Is_Tagged_Type (A_Typ)
3017 and then Is_Derived_Type (A_Typ)
3018 and then No (Full_View (A_Typ))
3019 then
3020 Prim := First_Elmt (Collect_Primitive_Operations (A_Typ));
3022 while Chars (Node (Prim)) /= Name_Op_Eq loop
3023 Next_Elmt (Prim);
3024 pragma Assert (Present (Prim));
3025 end loop;
3027 Op_Name := Node (Prim);
3028 else
3029 Op_Name := Find_Prim_Op (Typl, Name_Op_Eq);
3030 end if;
3032 Build_Equality_Call (Op_Name);
3034 -- If a type support function is present (for complex cases), use it
3036 elsif Present (TSS (Root_Type (Typl), Name_uEquality)) then
3037 Build_Equality_Call (TSS (Root_Type (Typl), Name_uEquality));
3039 -- Otherwise expand the component by component equality. Note that
3040 -- we never use block-bit coparisons for records, because of the
3041 -- problems with gaps. The backend will often be able to recombine
3042 -- the separate comparisons that we generate here.
3044 else
3045 Remove_Side_Effects (Lhs);
3046 Remove_Side_Effects (Rhs);
3047 Rewrite (N,
3048 Expand_Record_Equality (N, Typl, Lhs, Rhs, Bodies));
3050 Insert_Actions (N, Bodies, Suppress => All_Checks);
3051 Analyze_And_Resolve (N, Standard_Boolean, Suppress => All_Checks);
3052 end if;
3053 end if;
3055 -- If we still have an equality comparison (i.e. it was not rewritten
3056 -- in some way), then we can test if result is needed at compile time).
3058 if Nkind (N) = N_Op_Eq then
3059 Rewrite_Comparison (N);
3060 end if;
3061 end Expand_N_Op_Eq;
3063 -----------------------
3064 -- Expand_N_Op_Expon --
3065 -----------------------
3067 procedure Expand_N_Op_Expon (N : Node_Id) is
3068 Loc : constant Source_Ptr := Sloc (N);
3069 Typ : constant Entity_Id := Etype (N);
3070 Rtyp : constant Entity_Id := Root_Type (Typ);
3071 Base : constant Node_Id := Relocate_Node (Left_Opnd (N));
3072 Exp : constant Node_Id := Relocate_Node (Right_Opnd (N));
3073 Exptyp : constant Entity_Id := Etype (Exp);
3074 Ovflo : constant Boolean := Do_Overflow_Check (N);
3075 Expv : Uint;
3076 Xnode : Node_Id;
3077 Temp : Node_Id;
3078 Rent : RE_Id;
3079 Ent : Entity_Id;
3081 begin
3082 Binary_Op_Validity_Checks (N);
3084 -- At this point the exponentiation must be dynamic since the static
3085 -- case has already been folded after Resolve by Eval_Op_Expon.
3087 -- Test for case of literal right argument
3089 if Compile_Time_Known_Value (Exp) then
3090 Expv := Expr_Value (Exp);
3092 -- We only fold small non-negative exponents. You might think we
3093 -- could fold small negative exponents for the real case, but we
3094 -- can't because we are required to raise Constraint_Error for
3095 -- the case of 0.0 ** (negative) even if Machine_Overflows = False.
3096 -- See ACVC test C4A012B.
3098 if Expv >= 0 and then Expv <= 4 then
3100 -- X ** 0 = 1 (or 1.0)
3102 if Expv = 0 then
3103 if Ekind (Typ) in Integer_Kind then
3104 Xnode := Make_Integer_Literal (Loc, Intval => 1);
3105 else
3106 Xnode := Make_Real_Literal (Loc, Ureal_1);
3107 end if;
3109 -- X ** 1 = X
3111 elsif Expv = 1 then
3112 Xnode := Base;
3114 -- X ** 2 = X * X
3116 elsif Expv = 2 then
3117 Xnode :=
3118 Make_Op_Multiply (Loc,
3119 Left_Opnd => Duplicate_Subexpr (Base),
3120 Right_Opnd => Duplicate_Subexpr (Base));
3122 -- X ** 3 = X * X * X
3124 elsif Expv = 3 then
3125 Xnode :=
3126 Make_Op_Multiply (Loc,
3127 Left_Opnd =>
3128 Make_Op_Multiply (Loc,
3129 Left_Opnd => Duplicate_Subexpr (Base),
3130 Right_Opnd => Duplicate_Subexpr (Base)),
3131 Right_Opnd => Duplicate_Subexpr (Base));
3133 -- X ** 4 ->
3134 -- En : constant base'type := base * base;
3135 -- ...
3136 -- En * En
3138 else -- Expv = 4
3139 Temp :=
3140 Make_Defining_Identifier (Loc, New_Internal_Name ('E'));
3142 Insert_Actions (N, New_List (
3143 Make_Object_Declaration (Loc,
3144 Defining_Identifier => Temp,
3145 Constant_Present => True,
3146 Object_Definition => New_Reference_To (Typ, Loc),
3147 Expression =>
3148 Make_Op_Multiply (Loc,
3149 Left_Opnd => Duplicate_Subexpr (Base),
3150 Right_Opnd => Duplicate_Subexpr (Base)))));
3152 Xnode :=
3153 Make_Op_Multiply (Loc,
3154 Left_Opnd => New_Reference_To (Temp, Loc),
3155 Right_Opnd => New_Reference_To (Temp, Loc));
3156 end if;
3158 Rewrite (N, Xnode);
3159 Analyze_And_Resolve (N, Typ);
3160 return;
3161 end if;
3162 end if;
3164 -- Case of (2 ** expression) appearing as an argument of an integer
3165 -- multiplication, or as the right argument of a division of a non-
3166 -- negative integer. In such cases we lave the node untouched, setting
3167 -- the flag Is_Natural_Power_Of_2_for_Shift set, then the expansion
3168 -- of the higher level node converts it into a shift.
3170 if Nkind (Base) = N_Integer_Literal
3171 and then Intval (Base) = 2
3172 and then Is_Integer_Type (Root_Type (Exptyp))
3173 and then Esize (Root_Type (Exptyp)) <= Esize (Standard_Integer)
3174 and then Is_Unsigned_Type (Exptyp)
3175 and then not Ovflo
3176 and then Nkind (Parent (N)) in N_Binary_Op
3177 then
3178 declare
3179 P : constant Node_Id := Parent (N);
3180 L : constant Node_Id := Left_Opnd (P);
3181 R : constant Node_Id := Right_Opnd (P);
3183 begin
3184 if (Nkind (P) = N_Op_Multiply
3185 and then
3186 ((Is_Integer_Type (Etype (L)) and then R = N)
3187 or else
3188 (Is_Integer_Type (Etype (R)) and then L = N))
3189 and then not Do_Overflow_Check (P))
3191 or else
3192 (Nkind (P) = N_Op_Divide
3193 and then Is_Integer_Type (Etype (L))
3194 and then Is_Unsigned_Type (Etype (L))
3195 and then R = N
3196 and then not Do_Overflow_Check (P))
3197 then
3198 Set_Is_Power_Of_2_For_Shift (N);
3199 return;
3200 end if;
3201 end;
3202 end if;
3204 -- Fall through if exponentiation must be done using a runtime routine.
3206 -- First deal with modular case.
3208 if Is_Modular_Integer_Type (Rtyp) then
3210 -- Non-binary case, we call the special exponentiation routine for
3211 -- the non-binary case, converting the argument to Long_Long_Integer
3212 -- and passing the modulus value. Then the result is converted back
3213 -- to the base type.
3215 if Non_Binary_Modulus (Rtyp) then
3217 Rewrite (N,
3218 Convert_To (Typ,
3219 Make_Function_Call (Loc,
3220 Name => New_Reference_To (RTE (RE_Exp_Modular), Loc),
3221 Parameter_Associations => New_List (
3222 Convert_To (Standard_Integer, Base),
3223 Make_Integer_Literal (Loc, Modulus (Rtyp)),
3224 Exp))));
3226 -- Binary case, in this case, we call one of two routines, either
3227 -- the unsigned integer case, or the unsigned long long integer
3228 -- case, with a final "and" operation to do the required mod.
3230 else
3231 if UI_To_Int (Esize (Rtyp)) <= Standard_Integer_Size then
3232 Ent := RTE (RE_Exp_Unsigned);
3233 else
3234 Ent := RTE (RE_Exp_Long_Long_Unsigned);
3235 end if;
3237 Rewrite (N,
3238 Convert_To (Typ,
3239 Make_Op_And (Loc,
3240 Left_Opnd =>
3241 Make_Function_Call (Loc,
3242 Name => New_Reference_To (Ent, Loc),
3243 Parameter_Associations => New_List (
3244 Convert_To (Etype (First_Formal (Ent)), Base),
3245 Exp)),
3246 Right_Opnd =>
3247 Make_Integer_Literal (Loc, Modulus (Rtyp) - 1))));
3249 end if;
3251 -- Common exit point for modular type case
3253 Analyze_And_Resolve (N, Typ);
3254 return;
3256 -- Signed integer cases
3258 elsif Rtyp = Base_Type (Standard_Integer) then
3259 if Ovflo then
3260 Rent := RE_Exp_Integer;
3261 else
3262 Rent := RE_Exn_Integer;
3263 end if;
3265 elsif Rtyp = Base_Type (Standard_Short_Integer) then
3266 if Ovflo then
3267 Rent := RE_Exp_Short_Integer;
3268 else
3269 Rent := RE_Exn_Short_Integer;
3270 end if;
3272 elsif Rtyp = Base_Type (Standard_Short_Short_Integer) then
3273 if Ovflo then
3274 Rent := RE_Exp_Short_Short_Integer;
3275 else
3276 Rent := RE_Exn_Short_Short_Integer;
3277 end if;
3279 elsif Rtyp = Base_Type (Standard_Long_Integer) then
3280 if Ovflo then
3281 Rent := RE_Exp_Long_Integer;
3282 else
3283 Rent := RE_Exn_Long_Integer;
3284 end if;
3286 elsif (Rtyp = Base_Type (Standard_Long_Long_Integer)
3287 or else Rtyp = Universal_Integer)
3288 then
3289 if Ovflo then
3290 Rent := RE_Exp_Long_Long_Integer;
3291 else
3292 Rent := RE_Exn_Long_Long_Integer;
3293 end if;
3295 -- Floating-point cases
3297 elsif Rtyp = Standard_Float then
3298 if Ovflo then
3299 Rent := RE_Exp_Float;
3300 else
3301 Rent := RE_Exn_Float;
3302 end if;
3304 elsif Rtyp = Standard_Short_Float then
3305 if Ovflo then
3306 Rent := RE_Exp_Short_Float;
3307 else
3308 Rent := RE_Exn_Short_Float;
3309 end if;
3311 elsif Rtyp = Standard_Long_Float then
3312 if Ovflo then
3313 Rent := RE_Exp_Long_Float;
3314 else
3315 Rent := RE_Exn_Long_Float;
3316 end if;
3318 else
3319 pragma Assert
3320 (Rtyp = Standard_Long_Long_Float or else Rtyp = Universal_Real);
3322 if Ovflo then
3323 Rent := RE_Exp_Long_Long_Float;
3324 else
3325 Rent := RE_Exn_Long_Long_Float;
3326 end if;
3327 end if;
3329 -- Common processing for integer cases and floating-point cases.
3330 -- If we are in the base type, we can call runtime routine directly
3332 if Typ = Rtyp
3333 and then Rtyp /= Universal_Integer
3334 and then Rtyp /= Universal_Real
3335 then
3336 Rewrite (N,
3337 Make_Function_Call (Loc,
3338 Name => New_Reference_To (RTE (Rent), Loc),
3339 Parameter_Associations => New_List (Base, Exp)));
3341 -- Otherwise we have to introduce conversions (conversions are also
3342 -- required in the universal cases, since the runtime routine was
3343 -- typed using the largest integer or real case.
3345 else
3346 Rewrite (N,
3347 Convert_To (Typ,
3348 Make_Function_Call (Loc,
3349 Name => New_Reference_To (RTE (Rent), Loc),
3350 Parameter_Associations => New_List (
3351 Convert_To (Rtyp, Base),
3352 Exp))));
3353 end if;
3355 Analyze_And_Resolve (N, Typ);
3356 return;
3358 end Expand_N_Op_Expon;
3360 --------------------
3361 -- Expand_N_Op_Ge --
3362 --------------------
3364 procedure Expand_N_Op_Ge (N : Node_Id) is
3365 Typ : constant Entity_Id := Etype (N);
3366 Op1 : constant Node_Id := Left_Opnd (N);
3367 Op2 : constant Node_Id := Right_Opnd (N);
3368 Typ1 : constant Entity_Id := Base_Type (Etype (Op1));
3370 begin
3371 Binary_Op_Validity_Checks (N);
3373 if Vax_Float (Typ1) then
3374 Expand_Vax_Comparison (N);
3375 return;
3377 elsif Is_Array_Type (Typ1) then
3378 Expand_Array_Comparison (N);
3379 return;
3380 end if;
3382 if Is_Boolean_Type (Typ1) then
3383 Adjust_Condition (Op1);
3384 Adjust_Condition (Op2);
3385 Set_Etype (N, Standard_Boolean);
3386 Adjust_Result_Type (N, Typ);
3387 end if;
3389 Rewrite_Comparison (N);
3390 end Expand_N_Op_Ge;
3392 --------------------
3393 -- Expand_N_Op_Gt --
3394 --------------------
3396 procedure Expand_N_Op_Gt (N : Node_Id) is
3397 Typ : constant Entity_Id := Etype (N);
3398 Op1 : constant Node_Id := Left_Opnd (N);
3399 Op2 : constant Node_Id := Right_Opnd (N);
3400 Typ1 : constant Entity_Id := Base_Type (Etype (Op1));
3402 begin
3403 Binary_Op_Validity_Checks (N);
3405 if Vax_Float (Typ1) then
3406 Expand_Vax_Comparison (N);
3407 return;
3409 elsif Is_Array_Type (Typ1) then
3410 Expand_Array_Comparison (N);
3411 return;
3412 end if;
3414 if Is_Boolean_Type (Typ1) then
3415 Adjust_Condition (Op1);
3416 Adjust_Condition (Op2);
3417 Set_Etype (N, Standard_Boolean);
3418 Adjust_Result_Type (N, Typ);
3419 end if;
3421 Rewrite_Comparison (N);
3422 end Expand_N_Op_Gt;
3424 --------------------
3425 -- Expand_N_Op_Le --
3426 --------------------
3428 procedure Expand_N_Op_Le (N : Node_Id) is
3429 Typ : constant Entity_Id := Etype (N);
3430 Op1 : constant Node_Id := Left_Opnd (N);
3431 Op2 : constant Node_Id := Right_Opnd (N);
3432 Typ1 : constant Entity_Id := Base_Type (Etype (Op1));
3434 begin
3435 Binary_Op_Validity_Checks (N);
3437 if Vax_Float (Typ1) then
3438 Expand_Vax_Comparison (N);
3439 return;
3441 elsif Is_Array_Type (Typ1) then
3442 Expand_Array_Comparison (N);
3443 return;
3444 end if;
3446 if Is_Boolean_Type (Typ1) then
3447 Adjust_Condition (Op1);
3448 Adjust_Condition (Op2);
3449 Set_Etype (N, Standard_Boolean);
3450 Adjust_Result_Type (N, Typ);
3451 end if;
3453 Rewrite_Comparison (N);
3454 end Expand_N_Op_Le;
3456 --------------------
3457 -- Expand_N_Op_Lt --
3458 --------------------
3460 procedure Expand_N_Op_Lt (N : Node_Id) is
3461 Typ : constant Entity_Id := Etype (N);
3462 Op1 : constant Node_Id := Left_Opnd (N);
3463 Op2 : constant Node_Id := Right_Opnd (N);
3464 Typ1 : constant Entity_Id := Base_Type (Etype (Op1));
3466 begin
3467 Binary_Op_Validity_Checks (N);
3469 if Vax_Float (Typ1) then
3470 Expand_Vax_Comparison (N);
3471 return;
3473 elsif Is_Array_Type (Typ1) then
3474 Expand_Array_Comparison (N);
3475 return;
3476 end if;
3478 if Is_Boolean_Type (Typ1) then
3479 Adjust_Condition (Op1);
3480 Adjust_Condition (Op2);
3481 Set_Etype (N, Standard_Boolean);
3482 Adjust_Result_Type (N, Typ);
3483 end if;
3485 Rewrite_Comparison (N);
3486 end Expand_N_Op_Lt;
3488 -----------------------
3489 -- Expand_N_Op_Minus --
3490 -----------------------
3492 procedure Expand_N_Op_Minus (N : Node_Id) is
3493 Loc : constant Source_Ptr := Sloc (N);
3494 Typ : constant Entity_Id := Etype (N);
3496 begin
3497 Unary_Op_Validity_Checks (N);
3499 if Software_Overflow_Checking
3500 and then Is_Signed_Integer_Type (Etype (N))
3501 and then Do_Overflow_Check (N)
3502 then
3503 -- Software overflow checking expands -expr into (0 - expr)
3505 Rewrite (N,
3506 Make_Op_Subtract (Loc,
3507 Left_Opnd => Make_Integer_Literal (Loc, 0),
3508 Right_Opnd => Right_Opnd (N)));
3510 Analyze_And_Resolve (N, Typ);
3512 -- Vax floating-point types case
3514 elsif Vax_Float (Etype (N)) then
3515 Expand_Vax_Arith (N);
3516 end if;
3517 end Expand_N_Op_Minus;
3519 ---------------------
3520 -- Expand_N_Op_Mod --
3521 ---------------------
3523 procedure Expand_N_Op_Mod (N : Node_Id) is
3524 Loc : constant Source_Ptr := Sloc (N);
3525 T : constant Entity_Id := Etype (N);
3526 Left : constant Node_Id := Left_Opnd (N);
3527 Right : constant Node_Id := Right_Opnd (N);
3528 DOC : constant Boolean := Do_Overflow_Check (N);
3529 DDC : constant Boolean := Do_Division_Check (N);
3531 LLB : Uint;
3532 Llo : Uint;
3533 Lhi : Uint;
3534 LOK : Boolean;
3535 Rlo : Uint;
3536 Rhi : Uint;
3537 ROK : Boolean;
3539 begin
3540 Binary_Op_Validity_Checks (N);
3542 Determine_Range (Right, ROK, Rlo, Rhi);
3543 Determine_Range (Left, LOK, Llo, Lhi);
3545 -- Convert mod to rem if operands are known non-negative. We do this
3546 -- since it is quite likely that this will improve the quality of code,
3547 -- (the operation now corresponds to the hardware remainder), and it
3548 -- does not seem likely that it could be harmful.
3550 if LOK and then Llo >= 0
3551 and then
3552 ROK and then Rlo >= 0
3553 then
3554 Rewrite (N,
3555 Make_Op_Rem (Sloc (N),
3556 Left_Opnd => Left_Opnd (N),
3557 Right_Opnd => Right_Opnd (N)));
3559 -- Instead of reanalyzing the node we do the analysis manually.
3560 -- This avoids anomalies when the replacement is done in an
3561 -- instance and is epsilon more efficient.
3563 Set_Entity (N, Standard_Entity (S_Op_Rem));
3564 Set_Etype (N, T);
3565 Set_Do_Overflow_Check (N, DOC);
3566 Set_Do_Division_Check (N, DDC);
3567 Expand_N_Op_Rem (N);
3568 Set_Analyzed (N);
3570 -- Otherwise, normal mod processing
3572 else
3573 if Is_Integer_Type (Etype (N)) then
3574 Apply_Divide_Check (N);
3575 end if;
3577 -- Deal with annoying case of largest negative number remainder
3578 -- minus one. Gigi does not handle this case correctly, because
3579 -- it generates a divide instruction which may trap in this case.
3581 -- In fact the check is quite easy, if the right operand is -1,
3582 -- then the mod value is always 0, and we can just ignore the
3583 -- left operand completely in this case.
3585 LLB := Expr_Value (Type_Low_Bound (Base_Type (Etype (Left))));
3587 if ((not ROK) or else (Rlo <= (-1) and then (-1) <= Rhi))
3588 and then
3589 ((not LOK) or else (Llo = LLB))
3590 then
3591 Rewrite (N,
3592 Make_Conditional_Expression (Loc,
3593 Expressions => New_List (
3594 Make_Op_Eq (Loc,
3595 Left_Opnd => Duplicate_Subexpr (Right),
3596 Right_Opnd =>
3597 Make_Integer_Literal (Loc, -1)),
3598 Make_Integer_Literal (Loc, Uint_0),
3599 Relocate_Node (N))));
3601 Set_Analyzed (Next (Next (First (Expressions (N)))));
3602 Analyze_And_Resolve (N, T);
3603 end if;
3604 end if;
3605 end Expand_N_Op_Mod;
3607 --------------------------
3608 -- Expand_N_Op_Multiply --
3609 --------------------------
3611 procedure Expand_N_Op_Multiply (N : Node_Id) is
3612 Loc : constant Source_Ptr := Sloc (N);
3613 Lop : constant Node_Id := Left_Opnd (N);
3614 Rop : constant Node_Id := Right_Opnd (N);
3615 Ltyp : constant Entity_Id := Etype (Lop);
3616 Rtyp : constant Entity_Id := Etype (Rop);
3617 Typ : Entity_Id := Etype (N);
3619 begin
3620 Binary_Op_Validity_Checks (N);
3622 -- Special optimizations for integer types
3624 if Is_Integer_Type (Typ) then
3626 -- N * 0 = 0 * N = 0 for integer types
3628 if (Compile_Time_Known_Value (Right_Opnd (N))
3629 and then Expr_Value (Right_Opnd (N)) = Uint_0)
3630 or else
3631 (Compile_Time_Known_Value (Left_Opnd (N))
3632 and then Expr_Value (Left_Opnd (N)) = Uint_0)
3633 then
3634 Rewrite (N, Make_Integer_Literal (Loc, Uint_0));
3635 Analyze_And_Resolve (N, Typ);
3636 return;
3637 end if;
3639 -- N * 1 = 1 * N = N for integer types
3641 if Compile_Time_Known_Value (Right_Opnd (N))
3642 and then Expr_Value (Right_Opnd (N)) = Uint_1
3643 then
3644 Rewrite (N, Left_Opnd (N));
3645 return;
3647 elsif Compile_Time_Known_Value (Left_Opnd (N))
3648 and then Expr_Value (Left_Opnd (N)) = Uint_1
3649 then
3650 Rewrite (N, Right_Opnd (N));
3651 return;
3652 end if;
3653 end if;
3655 -- Deal with VAX float case
3657 if Vax_Float (Typ) then
3658 Expand_Vax_Arith (N);
3659 return;
3660 end if;
3662 -- Convert x * 2 ** y to Shift_Left (x, y). Note that the fact that
3663 -- Is_Power_Of_2_For_Shift is set means that we know that our left
3664 -- operand is an integer, as required for this to work.
3666 if Nkind (Rop) = N_Op_Expon
3667 and then Is_Power_Of_2_For_Shift (Rop)
3668 then
3669 if Nkind (Lop) = N_Op_Expon
3670 and then Is_Power_Of_2_For_Shift (Lop)
3671 then
3673 -- convert 2 ** A * 2 ** B into 2 ** (A + B)
3675 Rewrite (N,
3676 Make_Op_Expon (Loc,
3677 Left_Opnd => Make_Integer_Literal (Loc, 2),
3678 Right_Opnd =>
3679 Make_Op_Add (Loc,
3680 Left_Opnd => Right_Opnd (Lop),
3681 Right_Opnd => Right_Opnd (Rop))));
3682 Analyze_And_Resolve (N, Typ);
3683 return;
3685 else
3686 Rewrite (N,
3687 Make_Op_Shift_Left (Loc,
3688 Left_Opnd => Lop,
3689 Right_Opnd =>
3690 Convert_To (Standard_Natural, Right_Opnd (Rop))));
3691 Analyze_And_Resolve (N, Typ);
3692 return;
3693 end if;
3695 -- Same processing for the operands the other way round
3697 elsif Nkind (Lop) = N_Op_Expon
3698 and then Is_Power_Of_2_For_Shift (Lop)
3699 then
3700 Rewrite (N,
3701 Make_Op_Shift_Left (Loc,
3702 Left_Opnd => Rop,
3703 Right_Opnd =>
3704 Convert_To (Standard_Natural, Right_Opnd (Lop))));
3705 Analyze_And_Resolve (N, Typ);
3706 return;
3707 end if;
3709 -- Do required fixup of universal fixed operation
3711 if Typ = Universal_Fixed then
3712 Fixup_Universal_Fixed_Operation (N);
3713 Typ := Etype (N);
3714 end if;
3716 -- Multiplications with fixed-point results
3718 if Is_Fixed_Point_Type (Typ) then
3720 -- No special processing if Treat_Fixed_As_Integer is set,
3721 -- since from a semantic point of view such operations are
3722 -- simply integer operations and will be treated that way.
3724 if not Treat_Fixed_As_Integer (N) then
3726 -- Case of fixed * integer => fixed
3728 if Is_Integer_Type (Rtyp) then
3729 Expand_Multiply_Fixed_By_Integer_Giving_Fixed (N);
3731 -- Case of integer * fixed => fixed
3733 elsif Is_Integer_Type (Ltyp) then
3734 Expand_Multiply_Integer_By_Fixed_Giving_Fixed (N);
3736 -- Case of fixed * fixed => fixed
3738 else
3739 Expand_Multiply_Fixed_By_Fixed_Giving_Fixed (N);
3740 end if;
3741 end if;
3743 -- Other cases of multiplication of fixed-point operands. Again
3744 -- we exclude the cases where Treat_Fixed_As_Integer flag is set.
3746 elsif (Is_Fixed_Point_Type (Ltyp) or else Is_Fixed_Point_Type (Rtyp))
3747 and then not Treat_Fixed_As_Integer (N)
3748 then
3749 if Is_Integer_Type (Typ) then
3750 Expand_Multiply_Fixed_By_Fixed_Giving_Integer (N);
3751 else
3752 pragma Assert (Is_Floating_Point_Type (Typ));
3753 Expand_Multiply_Fixed_By_Fixed_Giving_Float (N);
3754 end if;
3756 -- Mixed-mode operations can appear in a non-static universal
3757 -- context, in which case the integer argument must be converted
3758 -- explicitly.
3760 elsif Typ = Universal_Real
3761 and then Is_Integer_Type (Rtyp)
3762 then
3763 Rewrite (Rop, Convert_To (Universal_Real, Relocate_Node (Rop)));
3765 Analyze_And_Resolve (Rop, Universal_Real);
3767 elsif Typ = Universal_Real
3768 and then Is_Integer_Type (Ltyp)
3769 then
3770 Rewrite (Lop, Convert_To (Universal_Real, Relocate_Node (Lop)));
3772 Analyze_And_Resolve (Lop, Universal_Real);
3774 -- Non-fixed point cases, check software overflow checking required
3776 elsif Is_Signed_Integer_Type (Etype (N)) then
3777 Apply_Arithmetic_Overflow_Check (N);
3778 end if;
3779 end Expand_N_Op_Multiply;
3781 --------------------
3782 -- Expand_N_Op_Ne --
3783 --------------------
3785 -- Rewrite node as the negation of an equality operation, and reanalyze.
3786 -- The equality to be used is defined in the same scope and has the same
3787 -- signature. It must be set explicitly because in an instance it may not
3788 -- have the same visibility as in the generic unit.
3790 procedure Expand_N_Op_Ne (N : Node_Id) is
3791 Loc : constant Source_Ptr := Sloc (N);
3792 Neg : Node_Id;
3793 Ne : constant Entity_Id := Entity (N);
3795 begin
3796 Binary_Op_Validity_Checks (N);
3798 Neg :=
3799 Make_Op_Not (Loc,
3800 Right_Opnd =>
3801 Make_Op_Eq (Loc,
3802 Left_Opnd => Left_Opnd (N),
3803 Right_Opnd => Right_Opnd (N)));
3804 Set_Paren_Count (Right_Opnd (Neg), 1);
3806 if Scope (Ne) /= Standard_Standard then
3807 Set_Entity (Right_Opnd (Neg), Corresponding_Equality (Ne));
3808 end if;
3810 Rewrite (N, Neg);
3811 Analyze_And_Resolve (N, Standard_Boolean);
3812 end Expand_N_Op_Ne;
3814 ---------------------
3815 -- Expand_N_Op_Not --
3816 ---------------------
3818 -- If the argument is other than a Boolean array type, there is no
3819 -- special expansion required.
3821 -- For the packed case, we call the special routine in Exp_Pakd, except
3822 -- that if the component size is greater than one, we use the standard
3823 -- routine generating a gruesome loop (it is so peculiar to have packed
3824 -- arrays with non-standard Boolean representations anyway, so it does
3825 -- not matter that we do not handle this case efficiently).
3827 -- For the unpacked case (and for the special packed case where we have
3828 -- non standard Booleans, as discussed above), we generate and insert
3829 -- into the tree the following function definition:
3831 -- function Nnnn (A : arr) is
3832 -- B : arr;
3833 -- begin
3834 -- for J in a'range loop
3835 -- B (J) := not A (J);
3836 -- end loop;
3837 -- return B;
3838 -- end Nnnn;
3840 -- Here arr is the actual subtype of the parameter (and hence always
3841 -- constrained). Then we replace the not with a call to this function.
3843 procedure Expand_N_Op_Not (N : Node_Id) is
3844 Loc : constant Source_Ptr := Sloc (N);
3845 Typ : constant Entity_Id := Etype (N);
3846 Opnd : Node_Id;
3847 Arr : Entity_Id;
3848 A : Entity_Id;
3849 B : Entity_Id;
3850 J : Entity_Id;
3851 A_J : Node_Id;
3852 B_J : Node_Id;
3854 Func_Name : Entity_Id;
3855 Loop_Statement : Node_Id;
3857 begin
3858 Unary_Op_Validity_Checks (N);
3860 -- For boolean operand, deal with non-standard booleans
3862 if Is_Boolean_Type (Typ) then
3863 Adjust_Condition (Right_Opnd (N));
3864 Set_Etype (N, Standard_Boolean);
3865 Adjust_Result_Type (N, Typ);
3866 return;
3867 end if;
3869 -- Only array types need any other processing
3871 if not Is_Array_Type (Typ) then
3872 return;
3873 end if;
3875 -- Case of array operand. If bit packed, handle it in Exp_Pakd
3877 if Is_Bit_Packed_Array (Typ) and then Component_Size (Typ) = 1 then
3878 Expand_Packed_Not (N);
3879 return;
3880 end if;
3882 -- Case of array operand which is not bit-packed
3884 Opnd := Relocate_Node (Right_Opnd (N));
3885 Convert_To_Actual_Subtype (Opnd);
3886 Arr := Etype (Opnd);
3887 Ensure_Defined (Arr, N);
3889 A := Make_Defining_Identifier (Loc, Name_uA);
3890 B := Make_Defining_Identifier (Loc, Name_uB);
3891 J := Make_Defining_Identifier (Loc, Name_uJ);
3893 A_J :=
3894 Make_Indexed_Component (Loc,
3895 Prefix => New_Reference_To (A, Loc),
3896 Expressions => New_List (New_Reference_To (J, Loc)));
3898 B_J :=
3899 Make_Indexed_Component (Loc,
3900 Prefix => New_Reference_To (B, Loc),
3901 Expressions => New_List (New_Reference_To (J, Loc)));
3903 Loop_Statement :=
3904 Make_Implicit_Loop_Statement (N,
3905 Identifier => Empty,
3907 Iteration_Scheme =>
3908 Make_Iteration_Scheme (Loc,
3909 Loop_Parameter_Specification =>
3910 Make_Loop_Parameter_Specification (Loc,
3911 Defining_Identifier => J,
3912 Discrete_Subtype_Definition =>
3913 Make_Attribute_Reference (Loc,
3914 Prefix => Make_Identifier (Loc, Chars (A)),
3915 Attribute_Name => Name_Range))),
3917 Statements => New_List (
3918 Make_Assignment_Statement (Loc,
3919 Name => B_J,
3920 Expression => Make_Op_Not (Loc, A_J))));
3922 Func_Name := Make_Defining_Identifier (Loc, New_Internal_Name ('N'));
3923 Set_Is_Inlined (Func_Name);
3925 Insert_Action (N,
3926 Make_Subprogram_Body (Loc,
3927 Specification =>
3928 Make_Function_Specification (Loc,
3929 Defining_Unit_Name => Func_Name,
3930 Parameter_Specifications => New_List (
3931 Make_Parameter_Specification (Loc,
3932 Defining_Identifier => A,
3933 Parameter_Type => New_Reference_To (Typ, Loc))),
3934 Subtype_Mark => New_Reference_To (Typ, Loc)),
3936 Declarations => New_List (
3937 Make_Object_Declaration (Loc,
3938 Defining_Identifier => B,
3939 Object_Definition => New_Reference_To (Arr, Loc))),
3941 Handled_Statement_Sequence =>
3942 Make_Handled_Sequence_Of_Statements (Loc,
3943 Statements => New_List (
3944 Loop_Statement,
3945 Make_Return_Statement (Loc,
3946 Expression =>
3947 Make_Identifier (Loc, Chars (B)))))));
3949 Rewrite (N,
3950 Make_Function_Call (Loc,
3951 Name => New_Reference_To (Func_Name, Loc),
3952 Parameter_Associations => New_List (Opnd)));
3954 Analyze_And_Resolve (N, Typ);
3955 end Expand_N_Op_Not;
3957 --------------------
3958 -- Expand_N_Op_Or --
3959 --------------------
3961 procedure Expand_N_Op_Or (N : Node_Id) is
3962 Typ : constant Entity_Id := Etype (N);
3964 begin
3965 Binary_Op_Validity_Checks (N);
3967 if Is_Array_Type (Etype (N)) then
3968 Expand_Boolean_Operator (N);
3970 elsif Is_Boolean_Type (Etype (N)) then
3971 Adjust_Condition (Left_Opnd (N));
3972 Adjust_Condition (Right_Opnd (N));
3973 Set_Etype (N, Standard_Boolean);
3974 Adjust_Result_Type (N, Typ);
3975 end if;
3976 end Expand_N_Op_Or;
3978 ----------------------
3979 -- Expand_N_Op_Plus --
3980 ----------------------
3982 procedure Expand_N_Op_Plus (N : Node_Id) is
3983 begin
3984 Unary_Op_Validity_Checks (N);
3985 end Expand_N_Op_Plus;
3987 ---------------------
3988 -- Expand_N_Op_Rem --
3989 ---------------------
3991 procedure Expand_N_Op_Rem (N : Node_Id) is
3992 Loc : constant Source_Ptr := Sloc (N);
3994 Left : constant Node_Id := Left_Opnd (N);
3995 Right : constant Node_Id := Right_Opnd (N);
3997 LLB : Uint;
3998 Llo : Uint;
3999 Lhi : Uint;
4000 LOK : Boolean;
4001 Rlo : Uint;
4002 Rhi : Uint;
4003 ROK : Boolean;
4004 Typ : Entity_Id;
4006 begin
4007 Binary_Op_Validity_Checks (N);
4009 if Is_Integer_Type (Etype (N)) then
4010 Apply_Divide_Check (N);
4011 end if;
4013 -- Deal with annoying case of largest negative number remainder
4014 -- minus one. Gigi does not handle this case correctly, because
4015 -- it generates a divide instruction which may trap in this case.
4017 -- In fact the check is quite easy, if the right operand is -1,
4018 -- then the remainder is always 0, and we can just ignore the
4019 -- left operand completely in this case.
4021 Determine_Range (Right, ROK, Rlo, Rhi);
4022 Determine_Range (Left, LOK, Llo, Lhi);
4023 LLB := Expr_Value (Type_Low_Bound (Base_Type (Etype (Left))));
4024 Typ := Etype (N);
4026 if ((not ROK) or else (Rlo <= (-1) and then (-1) <= Rhi))
4027 and then
4028 ((not LOK) or else (Llo = LLB))
4029 then
4030 Rewrite (N,
4031 Make_Conditional_Expression (Loc,
4032 Expressions => New_List (
4033 Make_Op_Eq (Loc,
4034 Left_Opnd => Duplicate_Subexpr (Right),
4035 Right_Opnd =>
4036 Make_Integer_Literal (Loc, -1)),
4038 Make_Integer_Literal (Loc, Uint_0),
4040 Relocate_Node (N))));
4042 Set_Analyzed (Next (Next (First (Expressions (N)))));
4043 Analyze_And_Resolve (N, Typ);
4044 end if;
4045 end Expand_N_Op_Rem;
4047 -----------------------------
4048 -- Expand_N_Op_Rotate_Left --
4049 -----------------------------
4051 procedure Expand_N_Op_Rotate_Left (N : Node_Id) is
4052 begin
4053 Binary_Op_Validity_Checks (N);
4054 end Expand_N_Op_Rotate_Left;
4056 ------------------------------
4057 -- Expand_N_Op_Rotate_Right --
4058 ------------------------------
4060 procedure Expand_N_Op_Rotate_Right (N : Node_Id) is
4061 begin
4062 Binary_Op_Validity_Checks (N);
4063 end Expand_N_Op_Rotate_Right;
4065 ----------------------------
4066 -- Expand_N_Op_Shift_Left --
4067 ----------------------------
4069 procedure Expand_N_Op_Shift_Left (N : Node_Id) is
4070 begin
4071 Binary_Op_Validity_Checks (N);
4072 end Expand_N_Op_Shift_Left;
4074 -----------------------------
4075 -- Expand_N_Op_Shift_Right --
4076 -----------------------------
4078 procedure Expand_N_Op_Shift_Right (N : Node_Id) is
4079 begin
4080 Binary_Op_Validity_Checks (N);
4081 end Expand_N_Op_Shift_Right;
4083 ----------------------------------------
4084 -- Expand_N_Op_Shift_Right_Arithmetic --
4085 ----------------------------------------
4087 procedure Expand_N_Op_Shift_Right_Arithmetic (N : Node_Id) is
4088 begin
4089 Binary_Op_Validity_Checks (N);
4090 end Expand_N_Op_Shift_Right_Arithmetic;
4092 --------------------------
4093 -- Expand_N_Op_Subtract --
4094 --------------------------
4096 procedure Expand_N_Op_Subtract (N : Node_Id) is
4097 Typ : constant Entity_Id := Etype (N);
4099 begin
4100 Binary_Op_Validity_Checks (N);
4102 -- N - 0 = N for integer types
4104 if Is_Integer_Type (Typ)
4105 and then Compile_Time_Known_Value (Right_Opnd (N))
4106 and then Expr_Value (Right_Opnd (N)) = 0
4107 then
4108 Rewrite (N, Left_Opnd (N));
4109 return;
4110 end if;
4112 -- Arithemtic overflow checks for signed integer/fixed point types
4114 if Is_Signed_Integer_Type (Typ)
4115 or else Is_Fixed_Point_Type (Typ)
4116 then
4117 Apply_Arithmetic_Overflow_Check (N);
4119 -- Vax floating-point types case
4121 elsif Vax_Float (Typ) then
4122 Expand_Vax_Arith (N);
4123 end if;
4124 end Expand_N_Op_Subtract;
4126 ---------------------
4127 -- Expand_N_Op_Xor --
4128 ---------------------
4130 procedure Expand_N_Op_Xor (N : Node_Id) is
4131 Typ : constant Entity_Id := Etype (N);
4133 begin
4134 Binary_Op_Validity_Checks (N);
4136 if Is_Array_Type (Etype (N)) then
4137 Expand_Boolean_Operator (N);
4139 elsif Is_Boolean_Type (Etype (N)) then
4140 Adjust_Condition (Left_Opnd (N));
4141 Adjust_Condition (Right_Opnd (N));
4142 Set_Etype (N, Standard_Boolean);
4143 Adjust_Result_Type (N, Typ);
4144 end if;
4145 end Expand_N_Op_Xor;
4147 ----------------------
4148 -- Expand_N_Or_Else --
4149 ----------------------
4151 -- Expand into conditional expression if Actions present, and also
4152 -- deal with optimizing case of arguments being True or False.
4154 procedure Expand_N_Or_Else (N : Node_Id) is
4155 Loc : constant Source_Ptr := Sloc (N);
4156 Typ : constant Entity_Id := Etype (N);
4157 Left : constant Node_Id := Left_Opnd (N);
4158 Right : constant Node_Id := Right_Opnd (N);
4159 Actlist : List_Id;
4161 begin
4162 -- Deal with non-standard booleans
4164 if Is_Boolean_Type (Typ) then
4165 Adjust_Condition (Left);
4166 Adjust_Condition (Right);
4167 Set_Etype (N, Standard_Boolean);
4169 -- Check for cases of left argument is True or False
4171 elsif Nkind (Left) = N_Identifier then
4173 -- If left argument is False, change (False or else Right) to Right.
4174 -- Any actions associated with Right will be executed unconditionally
4175 -- and can thus be inserted into the tree unconditionally.
4177 if Entity (Left) = Standard_False then
4178 if Present (Actions (N)) then
4179 Insert_Actions (N, Actions (N));
4180 end if;
4182 Rewrite (N, Right);
4183 Adjust_Result_Type (N, Typ);
4184 return;
4186 -- If left argument is True, change (True and then Right) to
4187 -- True. In this case we can forget the actions associated with
4188 -- Right, since they will never be executed.
4190 elsif Entity (Left) = Standard_True then
4191 Kill_Dead_Code (Right);
4192 Kill_Dead_Code (Actions (N));
4193 Rewrite (N, New_Occurrence_Of (Standard_True, Loc));
4194 Adjust_Result_Type (N, Typ);
4195 return;
4196 end if;
4197 end if;
4199 -- If Actions are present, we expand
4201 -- left or else right
4203 -- into
4205 -- if left then True else right end
4207 -- with the actions becoming the Else_Actions of the conditional
4208 -- expression. This conditional expression is then further expanded
4209 -- (and will eventually disappear)
4211 if Present (Actions (N)) then
4212 Actlist := Actions (N);
4213 Rewrite (N,
4214 Make_Conditional_Expression (Loc,
4215 Expressions => New_List (
4216 Left,
4217 New_Occurrence_Of (Standard_True, Loc),
4218 Right)));
4220 Set_Else_Actions (N, Actlist);
4221 Analyze_And_Resolve (N, Standard_Boolean);
4222 Adjust_Result_Type (N, Typ);
4223 return;
4224 end if;
4226 -- No actions present, check for cases of right argument True/False
4228 if Nkind (Right) = N_Identifier then
4230 -- Change (Left or else False) to Left. Note that we know there
4231 -- are no actions associated with the True operand, since we
4232 -- just checked for this case above.
4234 if Entity (Right) = Standard_False then
4235 Rewrite (N, Left);
4237 -- Change (Left or else True) to True, making sure to preserve
4238 -- any side effects associated with the Left operand.
4240 elsif Entity (Right) = Standard_True then
4241 Remove_Side_Effects (Left);
4242 Rewrite
4243 (N, New_Occurrence_Of (Standard_True, Loc));
4244 end if;
4245 end if;
4247 Adjust_Result_Type (N, Typ);
4248 end Expand_N_Or_Else;
4250 -----------------------------------
4251 -- Expand_N_Qualified_Expression --
4252 -----------------------------------
4254 procedure Expand_N_Qualified_Expression (N : Node_Id) is
4255 Operand : constant Node_Id := Expression (N);
4256 Target_Type : constant Entity_Id := Entity (Subtype_Mark (N));
4258 begin
4259 Apply_Constraint_Check (Operand, Target_Type, No_Sliding => True);
4260 end Expand_N_Qualified_Expression;
4262 ---------------------------------
4263 -- Expand_N_Selected_Component --
4264 ---------------------------------
4266 -- If the selector is a discriminant of a concurrent object, rewrite the
4267 -- prefix to denote the corresponding record type.
4269 procedure Expand_N_Selected_Component (N : Node_Id) is
4270 Loc : constant Source_Ptr := Sloc (N);
4271 Par : constant Node_Id := Parent (N);
4272 P : constant Node_Id := Prefix (N);
4273 Disc : Entity_Id;
4274 Ptyp : Entity_Id := Underlying_Type (Etype (P));
4275 New_N : Node_Id;
4277 function In_Left_Hand_Side (Comp : Node_Id) return Boolean;
4278 -- Gigi needs a temporary for prefixes that depend on a discriminant,
4279 -- unless the context of an assignment can provide size information.
4281 function In_Left_Hand_Side (Comp : Node_Id) return Boolean is
4282 begin
4283 return
4284 (Nkind (Parent (Comp)) = N_Assignment_Statement
4285 and then Comp = Name (Parent (Comp)))
4286 or else
4287 (Present (Parent (Comp))
4288 and then Nkind (Parent (Comp)) in N_Subexpr
4289 and then In_Left_Hand_Side (Parent (Comp)));
4290 end In_Left_Hand_Side;
4292 begin
4293 if Do_Discriminant_Check (N) then
4295 -- Present the discrminant checking function to the backend,
4296 -- so that it can inline the call to the function.
4298 Add_Inlined_Body
4299 (Discriminant_Checking_Func
4300 (Original_Record_Component (Entity (Selector_Name (N)))));
4301 end if;
4303 -- Insert explicit dereference call for the checked storage pool case
4305 if Is_Access_Type (Ptyp) then
4306 Insert_Dereference_Action (P);
4307 return;
4308 end if;
4310 -- Gigi cannot handle unchecked conversions that are the prefix of
4311 -- a selected component with discriminants. This must be checked
4312 -- during expansion, because during analysis the type of the selector
4313 -- is not known at the point the prefix is analyzed. If the conversion
4314 -- is the target of an assignment, we cannot force the evaluation, of
4315 -- course.
4317 if Nkind (Prefix (N)) = N_Unchecked_Type_Conversion
4318 and then Has_Discriminants (Etype (N))
4319 and then not In_Left_Hand_Side (N)
4320 then
4321 Force_Evaluation (Prefix (N));
4322 end if;
4324 -- Remaining processing applies only if selector is a discriminant
4326 if Ekind (Entity (Selector_Name (N))) = E_Discriminant then
4328 -- If the selector is a discriminant of a constrained record type,
4329 -- rewrite the expression with the actual value of the discriminant.
4330 -- Don't do this on the left hand of an assignment statement (this
4331 -- happens in generated code, and means we really want to set it!)
4332 -- We also only do this optimization for discrete types, and not
4333 -- for access types (access discriminants get us into trouble!)
4334 -- We also do not expand the prefix of an attribute or the
4335 -- operand of an object renaming declaration.
4337 if Is_Record_Type (Ptyp)
4338 and then Has_Discriminants (Ptyp)
4339 and then Is_Constrained (Ptyp)
4340 and then Is_Discrete_Type (Etype (N))
4341 and then (Nkind (Par) /= N_Assignment_Statement
4342 or else Name (Par) /= N)
4343 and then (Nkind (Par) /= N_Attribute_Reference
4344 or else Prefix (Par) /= N)
4345 and then not Is_Renamed_Object (N)
4346 then
4347 declare
4348 D : Entity_Id;
4349 E : Elmt_Id;
4351 begin
4352 D := First_Discriminant (Ptyp);
4353 E := First_Elmt (Discriminant_Constraint (Ptyp));
4355 while Present (E) loop
4356 if D = Entity (Selector_Name (N)) then
4358 -- In the context of a case statement, the expression
4359 -- may have the base type of the discriminant, and we
4360 -- need to preserve the constraint to avoid spurious
4361 -- errors on missing cases.
4363 if Nkind (Parent (N)) = N_Case_Statement
4364 and then Etype (Node (E)) /= Etype (D)
4365 then
4366 Rewrite (N,
4367 Make_Qualified_Expression (Loc,
4368 Subtype_Mark => New_Occurrence_Of (Etype (D), Loc),
4369 Expression => New_Copy (Node (E))));
4370 Analyze (N);
4371 else
4372 Rewrite (N, New_Copy (Node (E)));
4373 end if;
4375 Set_Is_Static_Expression (N, False);
4376 return;
4377 end if;
4379 Next_Elmt (E);
4380 Next_Discriminant (D);
4381 end loop;
4383 -- Note: the above loop should always terminate, but if
4384 -- it does not, we just missed an optimization due to
4385 -- some glitch (perhaps a previous error), so ignore!
4386 end;
4387 end if;
4389 -- The only remaining processing is in the case of a discriminant of
4390 -- a concurrent object, where we rewrite the prefix to denote the
4391 -- corresponding record type. If the type is derived and has renamed
4392 -- discriminants, use corresponding discriminant, which is the one
4393 -- that appears in the corresponding record.
4395 if not Is_Concurrent_Type (Ptyp) then
4396 return;
4397 end if;
4399 Disc := Entity (Selector_Name (N));
4401 if Is_Derived_Type (Ptyp)
4402 and then Present (Corresponding_Discriminant (Disc))
4403 then
4404 Disc := Corresponding_Discriminant (Disc);
4405 end if;
4407 New_N :=
4408 Make_Selected_Component (Loc,
4409 Prefix =>
4410 Unchecked_Convert_To (Corresponding_Record_Type (Ptyp),
4411 New_Copy_Tree (P)),
4412 Selector_Name => Make_Identifier (Loc, Chars (Disc)));
4414 Rewrite (N, New_N);
4415 Analyze (N);
4416 end if;
4418 end Expand_N_Selected_Component;
4420 --------------------
4421 -- Expand_N_Slice --
4422 --------------------
4424 procedure Expand_N_Slice (N : Node_Id) is
4425 Loc : constant Source_Ptr := Sloc (N);
4426 Typ : constant Entity_Id := Etype (N);
4427 Pfx : constant Node_Id := Prefix (N);
4428 Ptp : Entity_Id := Etype (Pfx);
4429 Ent : Entity_Id;
4430 Decl : Node_Id;
4432 begin
4433 -- Special handling for access types
4435 if Is_Access_Type (Ptp) then
4437 -- Check for explicit dereference required for checked pool
4439 Insert_Dereference_Action (Pfx);
4441 -- If we have an access to a packed array type, then put in an
4442 -- explicit dereference. We do this in case the slice must be
4443 -- expanded, and we want to make sure we get an access check.
4445 Ptp := Designated_Type (Ptp);
4447 if Is_Array_Type (Ptp) and then Is_Packed (Ptp) then
4448 Rewrite (Pfx,
4449 Make_Explicit_Dereference (Sloc (N),
4450 Prefix => Relocate_Node (Pfx)));
4452 Analyze_And_Resolve (Pfx, Ptp);
4454 -- The prefix will now carry the Access_Check flag for the back
4455 -- end, remove it from slice itself.
4457 Set_Do_Access_Check (N, False);
4458 end if;
4459 end if;
4461 -- Range checks are potentially also needed for cases involving
4462 -- a slice indexed by a subtype indication, but Do_Range_Check
4463 -- can currently only be set for expressions ???
4465 if not Index_Checks_Suppressed (Ptp)
4466 and then (not Is_Entity_Name (Pfx)
4467 or else not Index_Checks_Suppressed (Entity (Pfx)))
4468 and then Nkind (Discrete_Range (N)) /= N_Subtype_Indication
4469 then
4470 Enable_Range_Check (Discrete_Range (N));
4471 end if;
4473 -- The remaining case to be handled is packed slices. We can leave
4474 -- packed slices as they are in the following situations:
4476 -- 1. Right or left side of an assignment (we can handle this
4477 -- situation correctly in the assignment statement expansion).
4479 -- 2. Prefix of indexed component (the slide is optimized away
4480 -- in this case, see the start of Expand_N_Slice.
4482 -- 3. Object renaming declaration, since we want the name of
4483 -- the slice, not the value.
4485 -- 4. Argument to procedure call, since copy-in/copy-out handling
4486 -- may be required, and this is handled in the expansion of
4487 -- call itself.
4489 -- 5. Prefix of an address attribute (this is an error which
4490 -- is caught elsewhere, and the expansion would intefere
4491 -- with generating the error message).
4493 if Is_Packed (Typ)
4494 and then Nkind (Parent (N)) /= N_Assignment_Statement
4495 and then Nkind (Parent (N)) /= N_Indexed_Component
4496 and then not Is_Renamed_Object (N)
4497 and then Nkind (Parent (N)) /= N_Procedure_Call_Statement
4498 and then (Nkind (Parent (N)) /= N_Attribute_Reference
4499 or else
4500 Attribute_Name (Parent (N)) /= Name_Address)
4501 then
4502 Ent :=
4503 Make_Defining_Identifier (Loc, New_Internal_Name ('T'));
4505 Decl :=
4506 Make_Object_Declaration (Loc,
4507 Defining_Identifier => Ent,
4508 Object_Definition => New_Occurrence_Of (Typ, Loc));
4510 Set_No_Initialization (Decl);
4512 Insert_Actions (N, New_List (
4513 Decl,
4514 Make_Assignment_Statement (Loc,
4515 Name => New_Occurrence_Of (Ent, Loc),
4516 Expression => Relocate_Node (N))));
4518 Rewrite (N, New_Occurrence_Of (Ent, Loc));
4519 Analyze_And_Resolve (N, Typ);
4520 end if;
4521 end Expand_N_Slice;
4523 ------------------------------
4524 -- Expand_N_Type_Conversion --
4525 ------------------------------
4527 procedure Expand_N_Type_Conversion (N : Node_Id) is
4528 Loc : constant Source_Ptr := Sloc (N);
4529 Operand : constant Node_Id := Expression (N);
4530 Target_Type : constant Entity_Id := Etype (N);
4531 Operand_Type : Entity_Id := Etype (Operand);
4533 procedure Handle_Changed_Representation;
4534 -- This is called in the case of record and array type conversions
4535 -- to see if there is a change of representation to be handled.
4536 -- Change of representation is actually handled at the assignment
4537 -- statement level, and what this procedure does is rewrite node N
4538 -- conversion as an assignment to temporary. If there is no change
4539 -- of representation, then the conversion node is unchanged.
4541 procedure Real_Range_Check;
4542 -- Handles generation of range check for real target value
4544 -----------------------------------
4545 -- Handle_Changed_Representation --
4546 -----------------------------------
4548 procedure Handle_Changed_Representation is
4549 Temp : Entity_Id;
4550 Decl : Node_Id;
4551 Odef : Node_Id;
4552 Disc : Node_Id;
4553 N_Ix : Node_Id;
4554 Cons : List_Id;
4556 begin
4557 -- Nothing to do if no change of representation
4559 if Same_Representation (Operand_Type, Target_Type) then
4560 return;
4562 -- The real change of representation work is done by the assignment
4563 -- statement processing. So if this type conversion is appearing as
4564 -- the expression of an assignment statement, nothing needs to be
4565 -- done to the conversion.
4567 elsif Nkind (Parent (N)) = N_Assignment_Statement then
4568 return;
4570 -- Otherwise we need to generate a temporary variable, and do the
4571 -- change of representation assignment into that temporary variable.
4572 -- The conversion is then replaced by a reference to this variable.
4574 else
4575 Cons := No_List;
4577 -- If type is unconstrained we have to add a constraint,
4578 -- copied from the actual value of the left hand side.
4580 if not Is_Constrained (Target_Type) then
4581 if Has_Discriminants (Operand_Type) then
4582 Disc := First_Discriminant (Operand_Type);
4583 Cons := New_List;
4584 while Present (Disc) loop
4585 Append_To (Cons,
4586 Make_Selected_Component (Loc,
4587 Prefix => Duplicate_Subexpr (Operand),
4588 Selector_Name =>
4589 Make_Identifier (Loc, Chars (Disc))));
4590 Next_Discriminant (Disc);
4591 end loop;
4593 elsif Is_Array_Type (Operand_Type) then
4594 N_Ix := First_Index (Target_Type);
4595 Cons := New_List;
4597 for J in 1 .. Number_Dimensions (Operand_Type) loop
4599 -- We convert the bounds explicitly. We use an unchecked
4600 -- conversion because bounds checks are done elsewhere.
4602 Append_To (Cons,
4603 Make_Range (Loc,
4604 Low_Bound =>
4605 Unchecked_Convert_To (Etype (N_Ix),
4606 Make_Attribute_Reference (Loc,
4607 Prefix =>
4608 Duplicate_Subexpr
4609 (Operand, Name_Req => True),
4610 Attribute_Name => Name_First,
4611 Expressions => New_List (
4612 Make_Integer_Literal (Loc, J)))),
4614 High_Bound =>
4615 Unchecked_Convert_To (Etype (N_Ix),
4616 Make_Attribute_Reference (Loc,
4617 Prefix =>
4618 Duplicate_Subexpr
4619 (Operand, Name_Req => True),
4620 Attribute_Name => Name_Last,
4621 Expressions => New_List (
4622 Make_Integer_Literal (Loc, J))))));
4624 Next_Index (N_Ix);
4625 end loop;
4626 end if;
4627 end if;
4629 Odef := New_Occurrence_Of (Target_Type, Loc);
4631 if Present (Cons) then
4632 Odef :=
4633 Make_Subtype_Indication (Loc,
4634 Subtype_Mark => Odef,
4635 Constraint =>
4636 Make_Index_Or_Discriminant_Constraint (Loc,
4637 Constraints => Cons));
4638 end if;
4640 Temp := Make_Defining_Identifier (Loc, New_Internal_Name ('C'));
4641 Decl :=
4642 Make_Object_Declaration (Loc,
4643 Defining_Identifier => Temp,
4644 Object_Definition => Odef);
4646 Set_No_Initialization (Decl, True);
4648 -- Insert required actions. It is essential to suppress checks
4649 -- since we have suppressed default initialization, which means
4650 -- that the variable we create may have no discriminants.
4652 Insert_Actions (N,
4653 New_List (
4654 Decl,
4655 Make_Assignment_Statement (Loc,
4656 Name => New_Occurrence_Of (Temp, Loc),
4657 Expression => Relocate_Node (N))),
4658 Suppress => All_Checks);
4660 Rewrite (N, New_Occurrence_Of (Temp, Loc));
4661 return;
4662 end if;
4663 end Handle_Changed_Representation;
4665 ----------------------
4666 -- Real_Range_Check --
4667 ----------------------
4669 -- Case of conversions to floating-point or fixed-point. If range
4670 -- checks are enabled and the target type has a range constraint,
4671 -- we convert:
4673 -- typ (x)
4675 -- to
4677 -- Tnn : typ'Base := typ'Base (x);
4678 -- [constraint_error when Tnn < typ'First or else Tnn > typ'Last]
4679 -- Tnn
4681 procedure Real_Range_Check is
4682 Btyp : constant Entity_Id := Base_Type (Target_Type);
4683 Lo : constant Node_Id := Type_Low_Bound (Target_Type);
4684 Hi : constant Node_Id := Type_High_Bound (Target_Type);
4685 Conv : Node_Id;
4686 Tnn : Entity_Id;
4688 begin
4689 -- Nothing to do if conversion was rewritten
4691 if Nkind (N) /= N_Type_Conversion then
4692 return;
4693 end if;
4695 -- Nothing to do if range checks suppressed, or target has the
4696 -- same range as the base type (or is the base type).
4698 if Range_Checks_Suppressed (Target_Type)
4699 or else (Lo = Type_Low_Bound (Btyp)
4700 and then
4701 Hi = Type_High_Bound (Btyp))
4702 then
4703 return;
4704 end if;
4706 -- Nothing to do if expression is an entity on which checks
4707 -- have been suppressed.
4709 if Is_Entity_Name (Expression (N))
4710 and then Range_Checks_Suppressed (Entity (Expression (N)))
4711 then
4712 return;
4713 end if;
4715 -- Here we rewrite the conversion as described above
4717 Conv := Relocate_Node (N);
4718 Rewrite
4719 (Subtype_Mark (Conv), New_Occurrence_Of (Btyp, Loc));
4720 Set_Etype (Conv, Btyp);
4722 -- Skip overflow check for integer to float conversions,
4723 -- since it is not needed, and in any case gigi generates
4724 -- incorrect code for such overflow checks ???
4726 if not Is_Integer_Type (Etype (Expression (N))) then
4727 Set_Do_Overflow_Check (Conv, True);
4728 end if;
4730 Tnn :=
4731 Make_Defining_Identifier (Loc,
4732 Chars => New_Internal_Name ('T'));
4734 Insert_Actions (N, New_List (
4735 Make_Object_Declaration (Loc,
4736 Defining_Identifier => Tnn,
4737 Object_Definition => New_Occurrence_Of (Btyp, Loc),
4738 Expression => Conv),
4740 Make_Raise_Constraint_Error (Loc,
4741 Condition =>
4742 Make_Or_Else (Loc,
4743 Left_Opnd =>
4744 Make_Op_Lt (Loc,
4745 Left_Opnd => New_Occurrence_Of (Tnn, Loc),
4746 Right_Opnd =>
4747 Make_Attribute_Reference (Loc,
4748 Attribute_Name => Name_First,
4749 Prefix =>
4750 New_Occurrence_Of (Target_Type, Loc))),
4752 Right_Opnd =>
4753 Make_Op_Gt (Loc,
4754 Left_Opnd => New_Occurrence_Of (Tnn, Loc),
4755 Right_Opnd =>
4756 Make_Attribute_Reference (Loc,
4757 Attribute_Name => Name_Last,
4758 Prefix =>
4759 New_Occurrence_Of (Target_Type, Loc)))))));
4761 Rewrite (N, New_Occurrence_Of (Tnn, Loc));
4762 Analyze_And_Resolve (N, Btyp);
4763 end Real_Range_Check;
4765 -- Start of processing for Expand_N_Type_Conversion
4767 begin
4768 -- Nothing at all to do if conversion is to the identical type
4769 -- so remove the conversion completely, it is useless.
4771 if Operand_Type = Target_Type then
4772 Rewrite (N, Relocate_Node (Expression (N)));
4773 return;
4774 end if;
4776 -- Deal with Vax floating-point cases
4778 if Vax_Float (Operand_Type) or else Vax_Float (Target_Type) then
4779 Expand_Vax_Conversion (N);
4780 return;
4781 end if;
4783 -- Nothing to do if this is the second argument of read. This
4784 -- is a "backwards" conversion that will be handled by the
4785 -- specialized code in attribute processing.
4787 if Nkind (Parent (N)) = N_Attribute_Reference
4788 and then Attribute_Name (Parent (N)) = Name_Read
4789 and then Next (First (Expressions (Parent (N)))) = N
4790 then
4791 return;
4792 end if;
4794 -- Here if we may need to expand conversion
4796 -- Special case of converting from non-standard boolean type
4798 if Is_Boolean_Type (Operand_Type)
4799 and then (Nonzero_Is_True (Operand_Type))
4800 then
4801 Adjust_Condition (Operand);
4802 Set_Etype (Operand, Standard_Boolean);
4803 Operand_Type := Standard_Boolean;
4804 end if;
4806 -- Case of converting to an access type
4808 if Is_Access_Type (Target_Type) then
4810 -- Apply an accessibility check if the operand is an
4811 -- access parameter. Note that other checks may still
4812 -- need to be applied below (such as tagged type checks).
4814 if Is_Entity_Name (Operand)
4815 and then Ekind (Entity (Operand)) in Formal_Kind
4816 and then Ekind (Etype (Operand)) = E_Anonymous_Access_Type
4817 then
4818 Apply_Accessibility_Check (Operand, Target_Type);
4820 -- If the level of the operand type is statically deeper
4821 -- then the level of the target type, then force Program_Error.
4822 -- Note that this can only occur for cases where the attribute
4823 -- is within the body of an instantiation (otherwise the
4824 -- conversion will already have been rejected as illegal).
4825 -- Note: warnings are issued by the analyzer for the instance
4826 -- cases.
4828 elsif In_Instance_Body
4829 and then Type_Access_Level (Operand_Type)
4830 > Type_Access_Level (Target_Type)
4831 then
4832 Rewrite (N, Make_Raise_Program_Error (Sloc (N)));
4833 Set_Etype (N, Target_Type);
4835 -- When the operand is a selected access discriminant
4836 -- the check needs to be made against the level of the
4837 -- object denoted by the prefix of the selected name.
4838 -- Force Program_Error for this case as well (this
4839 -- accessibility violation can only happen if within
4840 -- the body of an instantiation).
4842 elsif In_Instance_Body
4843 and then Ekind (Operand_Type) = E_Anonymous_Access_Type
4844 and then Nkind (Operand) = N_Selected_Component
4845 and then Object_Access_Level (Operand) >
4846 Type_Access_Level (Target_Type)
4847 then
4848 Rewrite (N, Make_Raise_Program_Error (Sloc (N)));
4849 Set_Etype (N, Target_Type);
4850 end if;
4851 end if;
4853 -- Case of conversions of tagged types and access to tagged types
4855 -- When needed, that is to say when the expression is class-wide,
4856 -- Add runtime a tag check for (strict) downward conversion by using
4857 -- the membership test, generating:
4859 -- [constraint_error when Operand not in Target_Type'Class]
4861 -- or in the access type case
4863 -- [constraint_error
4864 -- when Operand /= null
4865 -- and then Operand.all not in
4866 -- Designated_Type (Target_Type)'Class]
4868 if (Is_Access_Type (Target_Type)
4869 and then Is_Tagged_Type (Designated_Type (Target_Type)))
4870 or else Is_Tagged_Type (Target_Type)
4871 then
4872 -- Do not do any expansion in the access type case if the
4873 -- parent is a renaming, since this is an error situation
4874 -- which will be caught by Sem_Ch8, and the expansion can
4875 -- intefere with this error check.
4877 if Is_Access_Type (Target_Type)
4878 and then Is_Renamed_Object (N)
4879 then
4880 return;
4881 end if;
4883 -- Oherwise, proceed with processing tagged conversion
4885 declare
4886 Actual_Operand_Type : Entity_Id;
4887 Actual_Target_Type : Entity_Id;
4889 Cond : Node_Id;
4891 begin
4892 if Is_Access_Type (Target_Type) then
4893 Actual_Operand_Type := Designated_Type (Operand_Type);
4894 Actual_Target_Type := Designated_Type (Target_Type);
4896 else
4897 Actual_Operand_Type := Operand_Type;
4898 Actual_Target_Type := Target_Type;
4899 end if;
4901 if Is_Class_Wide_Type (Actual_Operand_Type)
4902 and then Root_Type (Actual_Operand_Type) /= Actual_Target_Type
4903 and then Is_Ancestor
4904 (Root_Type (Actual_Operand_Type),
4905 Actual_Target_Type)
4906 and then not Tag_Checks_Suppressed (Actual_Target_Type)
4907 then
4908 -- The conversion is valid for any descendant of the
4909 -- target type
4911 Actual_Target_Type := Class_Wide_Type (Actual_Target_Type);
4913 if Is_Access_Type (Target_Type) then
4914 Cond :=
4915 Make_And_Then (Loc,
4916 Left_Opnd =>
4917 Make_Op_Ne (Loc,
4918 Left_Opnd => Duplicate_Subexpr (Operand),
4919 Right_Opnd => Make_Null (Loc)),
4921 Right_Opnd =>
4922 Make_Not_In (Loc,
4923 Left_Opnd =>
4924 Make_Explicit_Dereference (Loc,
4925 Prefix => Duplicate_Subexpr (Operand)),
4926 Right_Opnd =>
4927 New_Reference_To (Actual_Target_Type, Loc)));
4929 else
4930 Cond :=
4931 Make_Not_In (Loc,
4932 Left_Opnd => Duplicate_Subexpr (Operand),
4933 Right_Opnd =>
4934 New_Reference_To (Actual_Target_Type, Loc));
4935 end if;
4937 Insert_Action (N,
4938 Make_Raise_Constraint_Error (Loc,
4939 Condition => Cond));
4941 Change_Conversion_To_Unchecked (N);
4942 Analyze_And_Resolve (N, Target_Type);
4943 end if;
4944 end;
4946 -- Case of other access type conversions
4948 elsif Is_Access_Type (Target_Type) then
4949 Apply_Constraint_Check (Operand, Target_Type);
4951 -- Case of conversions from a fixed-point type
4953 -- These conversions require special expansion and processing, found
4954 -- in the Exp_Fixd package. We ignore cases where Conversion_OK is
4955 -- set, since from a semantic point of view, these are simple integer
4956 -- conversions, which do not need further processing.
4958 elsif Is_Fixed_Point_Type (Operand_Type)
4959 and then not Conversion_OK (N)
4960 then
4961 -- We should never see universal fixed at this case, since the
4962 -- expansion of the constituent divide or multiply should have
4963 -- eliminated the explicit mention of universal fixed.
4965 pragma Assert (Operand_Type /= Universal_Fixed);
4967 -- Check for special case of the conversion to universal real
4968 -- that occurs as a result of the use of a round attribute.
4969 -- In this case, the real type for the conversion is taken
4970 -- from the target type of the Round attribute and the
4971 -- result must be marked as rounded.
4973 if Target_Type = Universal_Real
4974 and then Nkind (Parent (N)) = N_Attribute_Reference
4975 and then Attribute_Name (Parent (N)) = Name_Round
4976 then
4977 Set_Rounded_Result (N);
4978 Set_Etype (N, Etype (Parent (N)));
4979 end if;
4981 -- Otherwise do correct fixed-conversion, but skip these if the
4982 -- Conversion_OK flag is set, because from a semantic point of
4983 -- view these are simple integer conversions needing no further
4984 -- processing (the backend will simply treat them as integers)
4986 if not Conversion_OK (N) then
4987 if Is_Fixed_Point_Type (Etype (N)) then
4988 Expand_Convert_Fixed_To_Fixed (N);
4989 Real_Range_Check;
4991 elsif Is_Integer_Type (Etype (N)) then
4992 Expand_Convert_Fixed_To_Integer (N);
4994 else
4995 pragma Assert (Is_Floating_Point_Type (Etype (N)));
4996 Expand_Convert_Fixed_To_Float (N);
4997 Real_Range_Check;
4998 end if;
4999 end if;
5001 -- Case of conversions to a fixed-point type
5003 -- These conversions require special expansion and processing, found
5004 -- in the Exp_Fixd package. Again, ignore cases where Conversion_OK
5005 -- is set, since from a semantic point of view, these are simple
5006 -- integer conversions, which do not need further processing.
5008 elsif Is_Fixed_Point_Type (Target_Type)
5009 and then not Conversion_OK (N)
5010 then
5011 if Is_Integer_Type (Operand_Type) then
5012 Expand_Convert_Integer_To_Fixed (N);
5013 Real_Range_Check;
5014 else
5015 pragma Assert (Is_Floating_Point_Type (Operand_Type));
5016 Expand_Convert_Float_To_Fixed (N);
5017 Real_Range_Check;
5018 end if;
5020 -- Case of float-to-integer conversions
5022 -- We also handle float-to-fixed conversions with Conversion_OK set
5023 -- since semantically the fixed-point target is treated as though it
5024 -- were an integer in such cases.
5026 elsif Is_Floating_Point_Type (Operand_Type)
5027 and then
5028 (Is_Integer_Type (Target_Type)
5029 or else
5030 (Is_Fixed_Point_Type (Target_Type) and then Conversion_OK (N)))
5031 then
5032 -- Special processing required if the conversion is the expression
5033 -- of a Truncation attribute reference. In this case we replace:
5035 -- ityp (ftyp'Truncation (x))
5037 -- by
5039 -- ityp (x)
5041 -- with the Float_Truncate flag set. This is clearly more efficient.
5043 if Nkind (Operand) = N_Attribute_Reference
5044 and then Attribute_Name (Operand) = Name_Truncation
5045 then
5046 Rewrite (Operand,
5047 Relocate_Node (First (Expressions (Operand))));
5048 Set_Float_Truncate (N, True);
5049 end if;
5051 -- One more check here, gcc is still not able to do conversions of
5052 -- this type with proper overflow checking, and so gigi is doing an
5053 -- approximation of what is required by doing floating-point compares
5054 -- with the end-point. But that can lose precision in some cases, and
5055 -- give a wrong result. Converting the operand to Long_Long_Float is
5056 -- helpful, but still does not catch all cases with 64-bit integers
5057 -- on targets with only 64-bit floats ???
5059 if Do_Range_Check (Expression (N)) then
5060 Rewrite (Expression (N),
5061 Make_Type_Conversion (Loc,
5062 Subtype_Mark =>
5063 New_Occurrence_Of (Standard_Long_Long_Float, Loc),
5064 Expression =>
5065 Relocate_Node (Expression (N))));
5067 Set_Etype (Expression (N), Standard_Long_Long_Float);
5068 Enable_Range_Check (Expression (N));
5069 Set_Do_Range_Check (Expression (Expression (N)), False);
5070 end if;
5072 -- Case of array conversions
5074 -- Expansion of array conversions, add required length/range checks
5075 -- but only do this if there is no change of representation. For
5076 -- handling of this case, see Handle_Changed_Representation.
5078 elsif Is_Array_Type (Target_Type) then
5080 if Is_Constrained (Target_Type) then
5081 Apply_Length_Check (Operand, Target_Type);
5082 else
5083 Apply_Range_Check (Operand, Target_Type);
5084 end if;
5086 Handle_Changed_Representation;
5088 -- Case of conversions of discriminated types
5090 -- Add required discriminant checks if target is constrained. Again
5091 -- this change is skipped if we have a change of representation.
5093 elsif Has_Discriminants (Target_Type)
5094 and then Is_Constrained (Target_Type)
5095 then
5096 Apply_Discriminant_Check (Operand, Target_Type);
5097 Handle_Changed_Representation;
5099 -- Case of all other record conversions. The only processing required
5100 -- is to check for a change of representation requiring the special
5101 -- assignment processing.
5103 elsif Is_Record_Type (Target_Type) then
5104 Handle_Changed_Representation;
5106 -- Case of conversions of enumeration types
5108 elsif Is_Enumeration_Type (Target_Type) then
5110 -- Special processing is required if there is a change of
5111 -- representation (from enumeration representation clauses)
5113 if not Same_Representation (Target_Type, Operand_Type) then
5115 -- Convert: x(y) to x'val (ytyp'val (y))
5117 Rewrite (N,
5118 Make_Attribute_Reference (Loc,
5119 Prefix => New_Occurrence_Of (Target_Type, Loc),
5120 Attribute_Name => Name_Val,
5121 Expressions => New_List (
5122 Make_Attribute_Reference (Loc,
5123 Prefix => New_Occurrence_Of (Operand_Type, Loc),
5124 Attribute_Name => Name_Pos,
5125 Expressions => New_List (Operand)))));
5127 Analyze_And_Resolve (N, Target_Type);
5128 end if;
5130 -- Case of conversions to floating-point
5132 elsif Is_Floating_Point_Type (Target_Type) then
5133 Real_Range_Check;
5135 -- The remaining cases require no front end processing
5137 else
5138 null;
5139 end if;
5141 -- At this stage, either the conversion node has been transformed
5142 -- into some other equivalent expression, or left as a conversion
5143 -- that can be handled by Gigi. The conversions that Gigi can handle
5144 -- are the following:
5146 -- Conversions with no change of representation or type
5148 -- Numeric conversions involving integer values, floating-point
5149 -- values, and fixed-point values. Fixed-point values are allowed
5150 -- only if Conversion_OK is set, i.e. if the fixed-point values
5151 -- are to be treated as integers.
5153 -- No other conversions should be passed to Gigi.
5155 end Expand_N_Type_Conversion;
5157 -----------------------------------
5158 -- Expand_N_Unchecked_Expression --
5159 -----------------------------------
5161 -- Remove the unchecked expression node from the tree. It's job was simply
5162 -- to make sure that its constituent expression was handled with checks
5163 -- off, and now that that is done, we can remove it from the tree, and
5164 -- indeed must, since gigi does not expect to see these nodes.
5166 procedure Expand_N_Unchecked_Expression (N : Node_Id) is
5167 Exp : constant Node_Id := Expression (N);
5169 begin
5170 Set_Assignment_OK (Exp, Assignment_OK (N) or Assignment_OK (Exp));
5171 Rewrite (N, Exp);
5172 end Expand_N_Unchecked_Expression;
5174 ----------------------------------------
5175 -- Expand_N_Unchecked_Type_Conversion --
5176 ----------------------------------------
5178 -- If this cannot be handled by Gigi and we haven't already made
5179 -- a temporary for it, do it now.
5181 procedure Expand_N_Unchecked_Type_Conversion (N : Node_Id) is
5182 Target_Type : constant Entity_Id := Etype (N);
5183 Operand : constant Node_Id := Expression (N);
5184 Operand_Type : constant Entity_Id := Etype (Operand);
5186 begin
5187 -- If we have a conversion of a compile time known value to a target
5188 -- type and the value is in range of the target type, then we can simply
5189 -- replace the construct by an integer literal of the correct type. We
5190 -- only apply this to integer types being converted. Possibly it may
5191 -- apply in other cases, but it is too much trouble to worry about.
5193 -- Note that we do not do this transformation if the Kill_Range_Check
5194 -- flag is set, since then the value may be outside the expected range.
5195 -- This happens in the Normalize_Scalars case.
5197 if Is_Integer_Type (Target_Type)
5198 and then Is_Integer_Type (Operand_Type)
5199 and then Compile_Time_Known_Value (Operand)
5200 and then not Kill_Range_Check (N)
5201 then
5202 declare
5203 Val : constant Uint := Expr_Value (Operand);
5205 begin
5206 if Compile_Time_Known_Value (Type_Low_Bound (Target_Type))
5207 and then
5208 Compile_Time_Known_Value (Type_High_Bound (Target_Type))
5209 and then
5210 Val >= Expr_Value (Type_Low_Bound (Target_Type))
5211 and then
5212 Val <= Expr_Value (Type_High_Bound (Target_Type))
5213 then
5214 Rewrite (N, Make_Integer_Literal (Sloc (N), Val));
5215 Analyze_And_Resolve (N, Target_Type);
5216 return;
5217 end if;
5218 end;
5219 end if;
5221 -- Nothing to do if conversion is safe
5223 if Safe_Unchecked_Type_Conversion (N) then
5224 return;
5225 end if;
5227 -- Otherwise force evaluation unless Assignment_OK flag is set (this
5228 -- flag indicates ??? -- more comments needed here)
5230 if Assignment_OK (N) then
5231 null;
5232 else
5233 Force_Evaluation (N);
5234 end if;
5235 end Expand_N_Unchecked_Type_Conversion;
5237 ----------------------------
5238 -- Expand_Record_Equality --
5239 ----------------------------
5241 -- For non-variant records, Equality is expanded when needed into:
5243 -- and then Lhs.Discr1 = Rhs.Discr1
5244 -- and then ...
5245 -- and then Lhs.Discrn = Rhs.Discrn
5246 -- and then Lhs.Cmp1 = Rhs.Cmp1
5247 -- and then ...
5248 -- and then Lhs.Cmpn = Rhs.Cmpn
5250 -- The expression is folded by the back-end for adjacent fields. This
5251 -- function is called for tagged record in only one occasion: for imple-
5252 -- menting predefined primitive equality (see Predefined_Primitives_Bodies)
5253 -- otherwise the primitive "=" is used directly.
5255 function Expand_Record_Equality
5256 (Nod : Node_Id;
5257 Typ : Entity_Id;
5258 Lhs : Node_Id;
5259 Rhs : Node_Id;
5260 Bodies : List_Id)
5261 return Node_Id
5263 Loc : constant Source_Ptr := Sloc (Nod);
5265 function Suitable_Element (C : Entity_Id) return Entity_Id;
5266 -- Return the first field to compare beginning with C, skipping the
5267 -- inherited components
5269 function Suitable_Element (C : Entity_Id) return Entity_Id is
5270 begin
5271 if No (C) then
5272 return Empty;
5274 elsif Ekind (C) /= E_Discriminant
5275 and then Ekind (C) /= E_Component
5276 then
5277 return Suitable_Element (Next_Entity (C));
5279 elsif Is_Tagged_Type (Typ)
5280 and then C /= Original_Record_Component (C)
5281 then
5282 return Suitable_Element (Next_Entity (C));
5284 elsif Chars (C) = Name_uController
5285 or else Chars (C) = Name_uTag
5286 then
5287 return Suitable_Element (Next_Entity (C));
5289 else
5290 return C;
5291 end if;
5292 end Suitable_Element;
5294 Result : Node_Id;
5295 C : Entity_Id;
5297 First_Time : Boolean := True;
5299 -- Start of processing for Expand_Record_Equality
5301 begin
5302 -- Special processing for the unchecked union case, which will occur
5303 -- only in the context of tagged types and dynamic dispatching, since
5304 -- other cases are handled statically. We return True, but insert a
5305 -- raise Program_Error statement.
5307 if Is_Unchecked_Union (Typ) then
5309 -- If this is a component of an enclosing record, return the Raise
5310 -- statement directly.
5312 if No (Parent (Lhs)) then
5313 Result := Make_Raise_Program_Error (Loc);
5314 Set_Etype (Result, Standard_Boolean);
5315 return Result;
5317 else
5318 Insert_Action (Lhs,
5319 Make_Raise_Program_Error (Loc));
5320 return New_Occurrence_Of (Standard_True, Loc);
5321 end if;
5322 end if;
5324 -- Generates the following code: (assuming that Typ has one Discr and
5325 -- component C2 is also a record)
5327 -- True
5328 -- and then Lhs.Discr1 = Rhs.Discr1
5329 -- and then Lhs.C1 = Rhs.C1
5330 -- and then Lhs.C2.C1=Rhs.C2.C1 and then ... Lhs.C2.Cn=Rhs.C2.Cn
5331 -- and then ...
5332 -- and then Lhs.Cmpn = Rhs.Cmpn
5334 Result := New_Reference_To (Standard_True, Loc);
5335 C := Suitable_Element (First_Entity (Typ));
5337 while Present (C) loop
5339 declare
5340 New_Lhs : Node_Id;
5341 New_Rhs : Node_Id;
5343 begin
5344 if First_Time then
5345 First_Time := False;
5346 New_Lhs := Lhs;
5347 New_Rhs := Rhs;
5349 else
5350 New_Lhs := New_Copy_Tree (Lhs);
5351 New_Rhs := New_Copy_Tree (Rhs);
5352 end if;
5354 Result :=
5355 Make_And_Then (Loc,
5356 Left_Opnd => Result,
5357 Right_Opnd =>
5358 Expand_Composite_Equality (Nod, Etype (C),
5359 Lhs =>
5360 Make_Selected_Component (Loc,
5361 Prefix => New_Lhs,
5362 Selector_Name => New_Reference_To (C, Loc)),
5363 Rhs =>
5364 Make_Selected_Component (Loc,
5365 Prefix => New_Rhs,
5366 Selector_Name => New_Reference_To (C, Loc)),
5367 Bodies => Bodies));
5368 end;
5370 C := Suitable_Element (Next_Entity (C));
5371 end loop;
5373 return Result;
5374 end Expand_Record_Equality;
5376 -------------------------------------
5377 -- Fixup_Universal_Fixed_Operation --
5378 -------------------------------------
5380 procedure Fixup_Universal_Fixed_Operation (N : Node_Id) is
5381 Conv : constant Node_Id := Parent (N);
5383 begin
5384 -- We must have a type conversion immediately above us
5386 pragma Assert (Nkind (Conv) = N_Type_Conversion);
5388 -- Normally the type conversion gives our target type. The exception
5389 -- occurs in the case of the Round attribute, where the conversion
5390 -- will be to universal real, and our real type comes from the Round
5391 -- attribute (as well as an indication that we must round the result)
5393 if Nkind (Parent (Conv)) = N_Attribute_Reference
5394 and then Attribute_Name (Parent (Conv)) = Name_Round
5395 then
5396 Set_Etype (N, Etype (Parent (Conv)));
5397 Set_Rounded_Result (N);
5399 -- Normal case where type comes from conversion above us
5401 else
5402 Set_Etype (N, Etype (Conv));
5403 end if;
5404 end Fixup_Universal_Fixed_Operation;
5406 -------------------------------
5407 -- Insert_Dereference_Action --
5408 -------------------------------
5410 procedure Insert_Dereference_Action (N : Node_Id) is
5411 Loc : constant Source_Ptr := Sloc (N);
5412 Typ : constant Entity_Id := Etype (N);
5413 Pool : constant Entity_Id := Associated_Storage_Pool (Typ);
5415 function Is_Checked_Storage_Pool (P : Entity_Id) return Boolean;
5416 -- return true if type of P is derived from Checked_Pool;
5418 function Is_Checked_Storage_Pool (P : Entity_Id) return Boolean is
5419 T : Entity_Id;
5421 begin
5422 if No (P) then
5423 return False;
5424 end if;
5426 T := Etype (P);
5427 while T /= Etype (T) loop
5428 if Is_RTE (T, RE_Checked_Pool) then
5429 return True;
5430 else
5431 T := Etype (T);
5432 end if;
5433 end loop;
5435 return False;
5436 end Is_Checked_Storage_Pool;
5438 -- Start of processing for Insert_Dereference_Action
5440 begin
5441 if not Comes_From_Source (Parent (N)) then
5442 return;
5444 elsif not Is_Checked_Storage_Pool (Pool) then
5445 return;
5446 end if;
5448 Insert_Action (N,
5449 Make_Procedure_Call_Statement (Loc,
5450 Name => New_Reference_To (
5451 Find_Prim_Op (Etype (Pool), Name_Dereference), Loc),
5453 Parameter_Associations => New_List (
5455 -- Pool
5457 New_Reference_To (Pool, Loc),
5459 -- Storage_Address
5461 Make_Attribute_Reference (Loc,
5462 Prefix =>
5463 Make_Explicit_Dereference (Loc, Duplicate_Subexpr (N)),
5464 Attribute_Name => Name_Address),
5466 -- Size_In_Storage_Elements
5468 Make_Op_Divide (Loc,
5469 Left_Opnd =>
5470 Make_Attribute_Reference (Loc,
5471 Prefix =>
5472 Make_Explicit_Dereference (Loc, Duplicate_Subexpr (N)),
5473 Attribute_Name => Name_Size),
5474 Right_Opnd =>
5475 Make_Integer_Literal (Loc, System_Storage_Unit)),
5477 -- Alignment
5479 Make_Attribute_Reference (Loc,
5480 Prefix =>
5481 Make_Explicit_Dereference (Loc, Duplicate_Subexpr (N)),
5482 Attribute_Name => Name_Alignment))));
5484 end Insert_Dereference_Action;
5486 ------------------------------
5487 -- Make_Array_Comparison_Op --
5488 ------------------------------
5490 -- This is a hand-coded expansion of the following generic function:
5492 -- generic
5493 -- type elem is (<>);
5494 -- type index is (<>);
5495 -- type a is array (index range <>) of elem;
5497 -- function Gnnn (X : a; Y: a) return boolean is
5498 -- J : index := Y'first;
5500 -- begin
5501 -- if X'length = 0 then
5502 -- return false;
5504 -- elsif Y'length = 0 then
5505 -- return true;
5507 -- else
5508 -- for I in X'range loop
5509 -- if X (I) = Y (J) then
5510 -- if J = Y'last then
5511 -- exit;
5512 -- else
5513 -- J := index'succ (J);
5514 -- end if;
5516 -- else
5517 -- return X (I) > Y (J);
5518 -- end if;
5519 -- end loop;
5521 -- return X'length > Y'length;
5522 -- end if;
5523 -- end Gnnn;
5525 -- Note that since we are essentially doing this expansion by hand, we
5526 -- do not need to generate an actual or formal generic part, just the
5527 -- instantiated function itself.
5529 function Make_Array_Comparison_Op
5530 (Typ : Entity_Id;
5531 Nod : Node_Id)
5532 return Node_Id
5534 Loc : constant Source_Ptr := Sloc (Nod);
5536 X : constant Entity_Id := Make_Defining_Identifier (Loc, Name_uX);
5537 Y : constant Entity_Id := Make_Defining_Identifier (Loc, Name_uY);
5538 I : constant Entity_Id := Make_Defining_Identifier (Loc, Name_uI);
5539 J : constant Entity_Id := Make_Defining_Identifier (Loc, Name_uJ);
5541 Index : constant Entity_Id := Base_Type (Etype (First_Index (Typ)));
5543 Loop_Statement : Node_Id;
5544 Loop_Body : Node_Id;
5545 If_Stat : Node_Id;
5546 Inner_If : Node_Id;
5547 Final_Expr : Node_Id;
5548 Func_Body : Node_Id;
5549 Func_Name : Entity_Id;
5550 Formals : List_Id;
5551 Length1 : Node_Id;
5552 Length2 : Node_Id;
5554 begin
5555 -- if J = Y'last then
5556 -- exit;
5557 -- else
5558 -- J := index'succ (J);
5559 -- end if;
5561 Inner_If :=
5562 Make_Implicit_If_Statement (Nod,
5563 Condition =>
5564 Make_Op_Eq (Loc,
5565 Left_Opnd => New_Reference_To (J, Loc),
5566 Right_Opnd =>
5567 Make_Attribute_Reference (Loc,
5568 Prefix => New_Reference_To (Y, Loc),
5569 Attribute_Name => Name_Last)),
5571 Then_Statements => New_List (
5572 Make_Exit_Statement (Loc)),
5574 Else_Statements =>
5575 New_List (
5576 Make_Assignment_Statement (Loc,
5577 Name => New_Reference_To (J, Loc),
5578 Expression =>
5579 Make_Attribute_Reference (Loc,
5580 Prefix => New_Reference_To (Index, Loc),
5581 Attribute_Name => Name_Succ,
5582 Expressions => New_List (New_Reference_To (J, Loc))))));
5584 -- if X (I) = Y (J) then
5585 -- if ... end if;
5586 -- else
5587 -- return X (I) > Y (J);
5588 -- end if;
5590 Loop_Body :=
5591 Make_Implicit_If_Statement (Nod,
5592 Condition =>
5593 Make_Op_Eq (Loc,
5594 Left_Opnd =>
5595 Make_Indexed_Component (Loc,
5596 Prefix => New_Reference_To (X, Loc),
5597 Expressions => New_List (New_Reference_To (I, Loc))),
5599 Right_Opnd =>
5600 Make_Indexed_Component (Loc,
5601 Prefix => New_Reference_To (Y, Loc),
5602 Expressions => New_List (New_Reference_To (J, Loc)))),
5604 Then_Statements => New_List (Inner_If),
5606 Else_Statements => New_List (
5607 Make_Return_Statement (Loc,
5608 Expression =>
5609 Make_Op_Gt (Loc,
5610 Left_Opnd =>
5611 Make_Indexed_Component (Loc,
5612 Prefix => New_Reference_To (X, Loc),
5613 Expressions => New_List (New_Reference_To (I, Loc))),
5615 Right_Opnd =>
5616 Make_Indexed_Component (Loc,
5617 Prefix => New_Reference_To (Y, Loc),
5618 Expressions => New_List (
5619 New_Reference_To (J, Loc)))))));
5621 -- for I in X'range loop
5622 -- if ... end if;
5623 -- end loop;
5625 Loop_Statement :=
5626 Make_Implicit_Loop_Statement (Nod,
5627 Identifier => Empty,
5629 Iteration_Scheme =>
5630 Make_Iteration_Scheme (Loc,
5631 Loop_Parameter_Specification =>
5632 Make_Loop_Parameter_Specification (Loc,
5633 Defining_Identifier => I,
5634 Discrete_Subtype_Definition =>
5635 Make_Attribute_Reference (Loc,
5636 Prefix => New_Reference_To (X, Loc),
5637 Attribute_Name => Name_Range))),
5639 Statements => New_List (Loop_Body));
5641 -- if X'length = 0 then
5642 -- return false;
5643 -- elsif Y'length = 0 then
5644 -- return true;
5645 -- else
5646 -- for ... loop ... end loop;
5647 -- return X'length > Y'length;
5648 -- end if;
5650 Length1 :=
5651 Make_Attribute_Reference (Loc,
5652 Prefix => New_Reference_To (X, Loc),
5653 Attribute_Name => Name_Length);
5655 Length2 :=
5656 Make_Attribute_Reference (Loc,
5657 Prefix => New_Reference_To (Y, Loc),
5658 Attribute_Name => Name_Length);
5660 Final_Expr :=
5661 Make_Op_Gt (Loc,
5662 Left_Opnd => Length1,
5663 Right_Opnd => Length2);
5665 If_Stat :=
5666 Make_Implicit_If_Statement (Nod,
5667 Condition =>
5668 Make_Op_Eq (Loc,
5669 Left_Opnd =>
5670 Make_Attribute_Reference (Loc,
5671 Prefix => New_Reference_To (X, Loc),
5672 Attribute_Name => Name_Length),
5673 Right_Opnd =>
5674 Make_Integer_Literal (Loc, 0)),
5676 Then_Statements =>
5677 New_List (
5678 Make_Return_Statement (Loc,
5679 Expression => New_Reference_To (Standard_False, Loc))),
5681 Elsif_Parts => New_List (
5682 Make_Elsif_Part (Loc,
5683 Condition =>
5684 Make_Op_Eq (Loc,
5685 Left_Opnd =>
5686 Make_Attribute_Reference (Loc,
5687 Prefix => New_Reference_To (Y, Loc),
5688 Attribute_Name => Name_Length),
5689 Right_Opnd =>
5690 Make_Integer_Literal (Loc, 0)),
5692 Then_Statements =>
5693 New_List (
5694 Make_Return_Statement (Loc,
5695 Expression => New_Reference_To (Standard_True, Loc))))),
5697 Else_Statements => New_List (
5698 Loop_Statement,
5699 Make_Return_Statement (Loc,
5700 Expression => Final_Expr)));
5702 -- (X : a; Y: a)
5704 Formals := New_List (
5705 Make_Parameter_Specification (Loc,
5706 Defining_Identifier => X,
5707 Parameter_Type => New_Reference_To (Typ, Loc)),
5709 Make_Parameter_Specification (Loc,
5710 Defining_Identifier => Y,
5711 Parameter_Type => New_Reference_To (Typ, Loc)));
5713 -- function Gnnn (...) return boolean is
5714 -- J : index := Y'first;
5715 -- begin
5716 -- if ... end if;
5717 -- end Gnnn;
5719 Func_Name := Make_Defining_Identifier (Loc, New_Internal_Name ('G'));
5721 Func_Body :=
5722 Make_Subprogram_Body (Loc,
5723 Specification =>
5724 Make_Function_Specification (Loc,
5725 Defining_Unit_Name => Func_Name,
5726 Parameter_Specifications => Formals,
5727 Subtype_Mark => New_Reference_To (Standard_Boolean, Loc)),
5729 Declarations => New_List (
5730 Make_Object_Declaration (Loc,
5731 Defining_Identifier => J,
5732 Object_Definition => New_Reference_To (Index, Loc),
5733 Expression =>
5734 Make_Attribute_Reference (Loc,
5735 Prefix => New_Reference_To (Y, Loc),
5736 Attribute_Name => Name_First))),
5738 Handled_Statement_Sequence =>
5739 Make_Handled_Sequence_Of_Statements (Loc,
5740 Statements => New_List (If_Stat)));
5742 return Func_Body;
5744 end Make_Array_Comparison_Op;
5746 ---------------------------
5747 -- Make_Boolean_Array_Op --
5748 ---------------------------
5750 -- For logical operations on boolean arrays, expand in line the
5751 -- following, replacing 'and' with 'or' or 'xor' where needed:
5753 -- function Annn (A : typ; B: typ) return typ is
5754 -- C : typ;
5755 -- begin
5756 -- for J in A'range loop
5757 -- C (J) := A (J) op B (J);
5758 -- end loop;
5759 -- return C;
5760 -- end Annn;
5762 -- Here typ is the boolean array type
5764 function Make_Boolean_Array_Op
5765 (Typ : Entity_Id;
5766 N : Node_Id)
5767 return Node_Id
5769 Loc : constant Source_Ptr := Sloc (N);
5771 A : constant Entity_Id := Make_Defining_Identifier (Loc, Name_uA);
5772 B : constant Entity_Id := Make_Defining_Identifier (Loc, Name_uB);
5773 C : constant Entity_Id := Make_Defining_Identifier (Loc, Name_uC);
5774 J : constant Entity_Id := Make_Defining_Identifier (Loc, Name_uJ);
5776 A_J : Node_Id;
5777 B_J : Node_Id;
5778 C_J : Node_Id;
5779 Op : Node_Id;
5781 Formals : List_Id;
5782 Func_Name : Entity_Id;
5783 Func_Body : Node_Id;
5784 Loop_Statement : Node_Id;
5786 begin
5787 A_J :=
5788 Make_Indexed_Component (Loc,
5789 Prefix => New_Reference_To (A, Loc),
5790 Expressions => New_List (New_Reference_To (J, Loc)));
5792 B_J :=
5793 Make_Indexed_Component (Loc,
5794 Prefix => New_Reference_To (B, Loc),
5795 Expressions => New_List (New_Reference_To (J, Loc)));
5797 C_J :=
5798 Make_Indexed_Component (Loc,
5799 Prefix => New_Reference_To (C, Loc),
5800 Expressions => New_List (New_Reference_To (J, Loc)));
5802 if Nkind (N) = N_Op_And then
5803 Op :=
5804 Make_Op_And (Loc,
5805 Left_Opnd => A_J,
5806 Right_Opnd => B_J);
5808 elsif Nkind (N) = N_Op_Or then
5809 Op :=
5810 Make_Op_Or (Loc,
5811 Left_Opnd => A_J,
5812 Right_Opnd => B_J);
5814 else
5815 Op :=
5816 Make_Op_Xor (Loc,
5817 Left_Opnd => A_J,
5818 Right_Opnd => B_J);
5819 end if;
5821 Loop_Statement :=
5822 Make_Implicit_Loop_Statement (N,
5823 Identifier => Empty,
5825 Iteration_Scheme =>
5826 Make_Iteration_Scheme (Loc,
5827 Loop_Parameter_Specification =>
5828 Make_Loop_Parameter_Specification (Loc,
5829 Defining_Identifier => J,
5830 Discrete_Subtype_Definition =>
5831 Make_Attribute_Reference (Loc,
5832 Prefix => New_Reference_To (A, Loc),
5833 Attribute_Name => Name_Range))),
5835 Statements => New_List (
5836 Make_Assignment_Statement (Loc,
5837 Name => C_J,
5838 Expression => Op)));
5840 Formals := New_List (
5841 Make_Parameter_Specification (Loc,
5842 Defining_Identifier => A,
5843 Parameter_Type => New_Reference_To (Typ, Loc)),
5845 Make_Parameter_Specification (Loc,
5846 Defining_Identifier => B,
5847 Parameter_Type => New_Reference_To (Typ, Loc)));
5849 Func_Name :=
5850 Make_Defining_Identifier (Loc, New_Internal_Name ('A'));
5851 Set_Is_Inlined (Func_Name);
5853 Func_Body :=
5854 Make_Subprogram_Body (Loc,
5855 Specification =>
5856 Make_Function_Specification (Loc,
5857 Defining_Unit_Name => Func_Name,
5858 Parameter_Specifications => Formals,
5859 Subtype_Mark => New_Reference_To (Typ, Loc)),
5861 Declarations => New_List (
5862 Make_Object_Declaration (Loc,
5863 Defining_Identifier => C,
5864 Object_Definition => New_Reference_To (Typ, Loc))),
5866 Handled_Statement_Sequence =>
5867 Make_Handled_Sequence_Of_Statements (Loc,
5868 Statements => New_List (
5869 Loop_Statement,
5870 Make_Return_Statement (Loc,
5871 Expression => New_Reference_To (C, Loc)))));
5873 return Func_Body;
5874 end Make_Boolean_Array_Op;
5876 ------------------------
5877 -- Rewrite_Comparison --
5878 ------------------------
5880 procedure Rewrite_Comparison (N : Node_Id) is
5881 Typ : constant Entity_Id := Etype (N);
5882 Op1 : constant Node_Id := Left_Opnd (N);
5883 Op2 : constant Node_Id := Right_Opnd (N);
5885 Res : constant Compare_Result := Compile_Time_Compare (Op1, Op2);
5886 -- Res indicates if compare outcome can be determined at compile time
5888 True_Result : Boolean;
5889 False_Result : Boolean;
5891 begin
5892 case N_Op_Compare (Nkind (N)) is
5893 when N_Op_Eq =>
5894 True_Result := Res = EQ;
5895 False_Result := Res = LT or else Res = GT or else Res = NE;
5897 when N_Op_Ge =>
5898 True_Result := Res in Compare_GE;
5899 False_Result := Res = LT;
5901 when N_Op_Gt =>
5902 True_Result := Res = GT;
5903 False_Result := Res in Compare_LE;
5905 when N_Op_Lt =>
5906 True_Result := Res = LT;
5907 False_Result := Res in Compare_GE;
5909 when N_Op_Le =>
5910 True_Result := Res in Compare_LE;
5911 False_Result := Res = GT;
5913 when N_Op_Ne =>
5914 True_Result := Res = NE;
5915 False_Result := Res = LT or else Res = GT or else Res = EQ;
5916 end case;
5918 if True_Result then
5919 Rewrite (N,
5920 Convert_To (Typ, New_Occurrence_Of (Standard_True, Sloc (N))));
5921 Analyze_And_Resolve (N, Typ);
5923 elsif False_Result then
5924 Rewrite (N,
5925 Convert_To (Typ, New_Occurrence_Of (Standard_False, Sloc (N))));
5926 Analyze_And_Resolve (N, Typ);
5927 end if;
5928 end Rewrite_Comparison;
5930 -----------------------
5931 -- Tagged_Membership --
5932 -----------------------
5934 -- There are two different cases to consider depending on whether
5935 -- the right operand is a class-wide type or not. If not we just
5936 -- compare the actual tag of the left expr to the target type tag:
5938 -- Left_Expr.Tag = Right_Type'Tag;
5940 -- If it is a class-wide type we use the RT function CW_Membership which
5941 -- is usually implemented by looking in the ancestor tables contained in
5942 -- the dispatch table pointed by Left_Expr.Tag for Typ'Tag
5944 function Tagged_Membership (N : Node_Id) return Node_Id is
5945 Left : constant Node_Id := Left_Opnd (N);
5946 Right : constant Node_Id := Right_Opnd (N);
5947 Loc : constant Source_Ptr := Sloc (N);
5949 Left_Type : Entity_Id;
5950 Right_Type : Entity_Id;
5951 Obj_Tag : Node_Id;
5953 begin
5954 Left_Type := Etype (Left);
5955 Right_Type := Etype (Right);
5957 if Is_Class_Wide_Type (Left_Type) then
5958 Left_Type := Root_Type (Left_Type);
5959 end if;
5961 Obj_Tag :=
5962 Make_Selected_Component (Loc,
5963 Prefix => Relocate_Node (Left),
5964 Selector_Name => New_Reference_To (Tag_Component (Left_Type), Loc));
5966 if Is_Class_Wide_Type (Right_Type) then
5967 return
5968 Make_DT_Access_Action (Left_Type,
5969 Action => CW_Membership,
5970 Args => New_List (
5971 Obj_Tag,
5972 New_Reference_To (
5973 Access_Disp_Table (Root_Type (Right_Type)), Loc)));
5974 else
5975 return
5976 Make_Op_Eq (Loc,
5977 Left_Opnd => Obj_Tag,
5978 Right_Opnd =>
5979 New_Reference_To (Access_Disp_Table (Right_Type), Loc));
5980 end if;
5982 end Tagged_Membership;
5984 ------------------------------
5985 -- Unary_Op_Validity_Checks --
5986 ------------------------------
5988 procedure Unary_Op_Validity_Checks (N : Node_Id) is
5989 begin
5990 if Validity_Checks_On and Validity_Check_Operands then
5991 Ensure_Valid (Right_Opnd (N));
5992 end if;
5993 end Unary_Op_Validity_Checks;
5995 end Exp_Ch4;