]> gcc.gnu.org Git - gcc.git/blame - gcc/ada/exp_ch4.adb
1aexcept.adb, [...]: Merge header, formatting and other trivial changes from ACT.
[gcc.git] / gcc / ada / exp_ch4.adb
CommitLineData
70482933
RK
1------------------------------------------------------------------------------
2-- --
3-- GNAT COMPILER COMPONENTS --
4-- --
5-- E X P _ C H 4 --
6-- --
7-- B o d y --
8-- --
07fc65c4 9-- Copyright (C) 1992-2002, Free Software Foundation, Inc. --
70482933
RK
10-- --
11-- GNAT is free software; you can redistribute it and/or modify it under --
12-- terms of the GNU General Public License as published by the Free Soft- --
13-- ware Foundation; either version 2, or (at your option) any later ver- --
14-- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
15-- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
16-- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License --
17-- for more details. You should have received a copy of the GNU General --
18-- Public License distributed with GNAT; see file COPYING. If not, write --
19-- to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, --
20-- MA 02111-1307, USA. --
21-- --
22-- GNAT was originally developed by the GNAT team at New York University. --
71ff80dc 23-- Extensive contributions were provided by Ada Core Technologies Inc. --
70482933
RK
24-- --
25------------------------------------------------------------------------------
26
27with Atree; use Atree;
28with Checks; use Checks;
29with Einfo; use Einfo;
30with Elists; use Elists;
31with Errout; use Errout;
32with Exp_Aggr; use Exp_Aggr;
33with Exp_Ch3; use Exp_Ch3;
34with Exp_Ch7; use Exp_Ch7;
35with Exp_Ch9; use Exp_Ch9;
36with Exp_Disp; use Exp_Disp;
37with Exp_Fixd; use Exp_Fixd;
38with Exp_Pakd; use Exp_Pakd;
39with Exp_Tss; use Exp_Tss;
40with Exp_Util; use Exp_Util;
41with Exp_VFpt; use Exp_VFpt;
42with Hostparm; use Hostparm;
43with Inline; use Inline;
44with Nlists; use Nlists;
45with Nmake; use Nmake;
46with Opt; use Opt;
07fc65c4 47with Restrict; use Restrict;
70482933
RK
48with Rtsfind; use Rtsfind;
49with Sem; use Sem;
50with Sem_Cat; use Sem_Cat;
51with Sem_Ch13; use Sem_Ch13;
52with Sem_Eval; use Sem_Eval;
53with Sem_Res; use Sem_Res;
54with Sem_Type; use Sem_Type;
55with Sem_Util; use Sem_Util;
07fc65c4 56with Sem_Warn; use Sem_Warn;
70482933
RK
57with Sinfo; use Sinfo;
58with Sinfo.CN; use Sinfo.CN;
59with Snames; use Snames;
60with Stand; use Stand;
07fc65c4 61with Targparm; use Targparm;
70482933
RK
62with Tbuild; use Tbuild;
63with Ttypes; use Ttypes;
64with Uintp; use Uintp;
65with Urealp; use Urealp;
66with Validsw; use Validsw;
67
68package body Exp_Ch4 is
69
70 ------------------------
71 -- Local Subprograms --
72 ------------------------
73
74 procedure Binary_Op_Validity_Checks (N : Node_Id);
75 pragma Inline (Binary_Op_Validity_Checks);
76 -- Performs validity checks for a binary operator
77
78 procedure Expand_Array_Comparison (N : Node_Id);
79 -- This routine handles expansion of the comparison operators (N_Op_Lt,
80 -- N_Op_Le, N_Op_Gt, N_Op_Ge) when operating on an array type. The basic
81 -- code for these operators is similar, differing only in the details of
82 -- the actual comparison call that is made.
83
84 function Expand_Array_Equality
85 (Nod : Node_Id;
86 Typ : Entity_Id;
87 A_Typ : Entity_Id;
88 Lhs : Node_Id;
89 Rhs : Node_Id;
90 Bodies : List_Id)
91 return Node_Id;
92 -- Expand an array equality into a call to a function implementing this
93 -- equality, and a call to it. Loc is the location for the generated
94 -- nodes. Typ is the type of the array, and Lhs, Rhs are the array
95 -- expressions to be compared. A_Typ is the type of the arguments,
96 -- which may be a private type, in which case Typ is its full view.
97 -- Bodies is a list on which to attach bodies of local functions that
98 -- are created in the process. This is the responsability of the
99 -- caller to insert those bodies at the right place. Nod provides
100 -- the Sloc value for the generated code.
101
102 procedure Expand_Boolean_Operator (N : Node_Id);
103 -- Common expansion processing for Boolean operators (And, Or, Xor)
104 -- for the case of array type arguments.
105
106 function Expand_Composite_Equality
107 (Nod : Node_Id;
108 Typ : Entity_Id;
109 Lhs : Node_Id;
110 Rhs : Node_Id;
111 Bodies : List_Id)
112 return Node_Id;
113 -- Local recursive function used to expand equality for nested
114 -- composite types. Used by Expand_Record/Array_Equality, Bodies
115 -- is a list on which to attach bodies of local functions that are
116 -- created in the process. This is the responsability of the caller
117 -- to insert those bodies at the right place. Nod provides the Sloc
118 -- value for generated code.
119
120 procedure Expand_Concatenate_Other (Cnode : Node_Id; Opnds : List_Id);
121 -- This routine handles expansion of concatenation operations, where
122 -- N is the N_Op_Concat node being expanded and Operands is the list
123 -- of operands (at least two are present). The caller has dealt with
124 -- converting any singleton operands into singleton aggregates.
125
126 procedure Expand_Concatenate_String (Cnode : Node_Id; Opnds : List_Id);
127 -- Routine to expand concatenation of 2-5 operands (in the list Operands)
128 -- and replace node Cnode with the result of the contatenation. If there
129 -- are two operands, they can be string or character. If there are more
130 -- than two operands, then are always of type string (i.e. the caller has
131 -- already converted character operands to strings in this case).
132
133 procedure Fixup_Universal_Fixed_Operation (N : Node_Id);
134 -- N is either an N_Op_Divide or N_Op_Multiply node whose result is
135 -- universal fixed. We do not have such a type at runtime, so the
136 -- purpose of this routine is to find the real type by looking up
137 -- the tree. We also determine if the operation must be rounded.
138
139 procedure Insert_Dereference_Action (N : Node_Id);
140 -- N is an expression whose type is an access. When the type is derived
141 -- from Checked_Pool, expands a call to the primitive 'dereference'.
142
143 function Make_Array_Comparison_Op
144 (Typ : Entity_Id;
145 Nod : Node_Id)
146 return Node_Id;
147 -- Comparisons between arrays are expanded in line. This function
148 -- produces the body of the implementation of (a > b), where a and b
149 -- are one-dimensional arrays of some discrete type. The original
150 -- node is then expanded into the appropriate call to this function.
151 -- Nod provides the Sloc value for the generated code.
152
153 function Make_Boolean_Array_Op
154 (Typ : Entity_Id;
155 N : Node_Id)
156 return Node_Id;
157 -- Boolean operations on boolean arrays are expanded in line. This
158 -- function produce the body for the node N, which is (a and b),
159 -- (a or b), or (a xor b). It is used only the normal case and not
160 -- the packed case. The type involved, Typ, is the Boolean array type,
161 -- and the logical operations in the body are simple boolean operations.
162 -- Note that Typ is always a constrained type (the caller has ensured
163 -- this by using Convert_To_Actual_Subtype if necessary).
164
165 procedure Rewrite_Comparison (N : Node_Id);
166 -- N is the node for a compile time comparison. If this outcome of this
167 -- comparison can be determined at compile time, then the node N can be
168 -- rewritten with True or False. If the outcome cannot be determined at
169 -- compile time, the call has no effect.
170
171 function Tagged_Membership (N : Node_Id) return Node_Id;
172 -- Construct the expression corresponding to the tagged membership test.
173 -- Deals with a second operand being (or not) a class-wide type.
174
175 procedure Unary_Op_Validity_Checks (N : Node_Id);
176 pragma Inline (Unary_Op_Validity_Checks);
177 -- Performs validity checks for a unary operator
178
179 -------------------------------
180 -- Binary_Op_Validity_Checks --
181 -------------------------------
182
183 procedure Binary_Op_Validity_Checks (N : Node_Id) is
184 begin
185 if Validity_Checks_On and Validity_Check_Operands then
186 Ensure_Valid (Left_Opnd (N));
187 Ensure_Valid (Right_Opnd (N));
188 end if;
189 end Binary_Op_Validity_Checks;
190
191 -----------------------------
192 -- Expand_Array_Comparison --
193 -----------------------------
194
195 -- Expansion is only required in the case of array types. The form of
196 -- the expansion is:
197
198 -- [body for greater_nn; boolean_expression]
199
200 -- The body is built by Make_Array_Comparison_Op, and the form of the
201 -- Boolean expression depends on the operator involved.
202
203 procedure Expand_Array_Comparison (N : Node_Id) is
204 Loc : constant Source_Ptr := Sloc (N);
205 Op1 : Node_Id := Left_Opnd (N);
206 Op2 : Node_Id := Right_Opnd (N);
207 Typ1 : constant Entity_Id := Base_Type (Etype (Op1));
208
209 Expr : Node_Id;
210 Func_Body : Node_Id;
211 Func_Name : Entity_Id;
212
213 begin
214 -- For (a <= b) we convert to not (a > b)
215
216 if Chars (N) = Name_Op_Le then
217 Rewrite (N,
218 Make_Op_Not (Loc,
219 Right_Opnd =>
220 Make_Op_Gt (Loc,
221 Left_Opnd => Op1,
222 Right_Opnd => Op2)));
223 Analyze_And_Resolve (N, Standard_Boolean);
224 return;
225
226 -- For < the Boolean expression is
227 -- greater__nn (op2, op1)
228
229 elsif Chars (N) = Name_Op_Lt then
230 Func_Body := Make_Array_Comparison_Op (Typ1, N);
231
232 -- Switch operands
233
234 Op1 := Right_Opnd (N);
235 Op2 := Left_Opnd (N);
236
237 -- For (a >= b) we convert to not (a < b)
238
239 elsif Chars (N) = Name_Op_Ge then
240 Rewrite (N,
241 Make_Op_Not (Loc,
242 Right_Opnd =>
243 Make_Op_Lt (Loc,
244 Left_Opnd => Op1,
245 Right_Opnd => Op2)));
246 Analyze_And_Resolve (N, Standard_Boolean);
247 return;
248
249 -- For > the Boolean expression is
250 -- greater__nn (op1, op2)
251
252 else
253 pragma Assert (Chars (N) = Name_Op_Gt);
254 Func_Body := Make_Array_Comparison_Op (Typ1, N);
255 end if;
256
257 Func_Name := Defining_Unit_Name (Specification (Func_Body));
258 Expr :=
259 Make_Function_Call (Loc,
260 Name => New_Reference_To (Func_Name, Loc),
261 Parameter_Associations => New_List (Op1, Op2));
262
263 Insert_Action (N, Func_Body);
264 Rewrite (N, Expr);
265 Analyze_And_Resolve (N, Standard_Boolean);
266
267 end Expand_Array_Comparison;
268
269 ---------------------------
270 -- Expand_Array_Equality --
271 ---------------------------
272
273 -- Expand an equality function for multi-dimensional arrays. Here is
274 -- an example of such a function for Nb_Dimension = 2
275
276 -- function Enn (A : arr; B : arr) return boolean is
277 -- J1 : integer;
278 -- J2 : integer;
279 --
280 -- begin
281 -- if A'length (1) /= B'length (1) then
282 -- return false;
283 -- else
284 -- J1 := B'first (1);
285 -- for I1 in A'first (1) .. A'last (1) loop
286 -- if A'length (2) /= B'length (2) then
287 -- return false;
288 -- else
289 -- J2 := B'first (2);
290 -- for I2 in A'first (2) .. A'last (2) loop
291 -- if A (I1, I2) /= B (J1, J2) then
292 -- return false;
293 -- end if;
294 -- J2 := Integer'succ (J2);
295 -- end loop;
296 -- end if;
297 -- J1 := Integer'succ (J1);
298 -- end loop;
299 -- end if;
300 -- return true;
301 -- end Enn;
302
303 function Expand_Array_Equality
304 (Nod : Node_Id;
305 Typ : Entity_Id;
306 A_Typ : Entity_Id;
307 Lhs : Node_Id;
308 Rhs : Node_Id;
309 Bodies : List_Id)
310 return Node_Id
311 is
312 Loc : constant Source_Ptr := Sloc (Nod);
313 Actuals : List_Id;
314 Decls : List_Id := New_List;
315 Index_List1 : List_Id := New_List;
316 Index_List2 : List_Id := New_List;
317 Formals : List_Id;
318 Stats : Node_Id;
319 Func_Name : Entity_Id;
320 Func_Body : Node_Id;
321
322 A : constant Entity_Id := Make_Defining_Identifier (Loc, Name_uA);
323 B : constant Entity_Id := Make_Defining_Identifier (Loc, Name_uB);
324
325 function Component_Equality (Typ : Entity_Id) return Node_Id;
326 -- Create one statement to compare corresponding components, designated
327 -- by a full set of indices.
328
329 function Loop_One_Dimension
330 (N : Int;
331 Index : Node_Id)
332 return Node_Id;
333 -- Loop over the n'th dimension of the arrays. The single statement
334 -- in the body of the loop is a loop over the next dimension, or
335 -- the comparison of corresponding components.
336
337 ------------------------
338 -- Component_Equality --
339 ------------------------
340
341 function Component_Equality (Typ : Entity_Id) return Node_Id is
342 Test : Node_Id;
343 L, R : Node_Id;
344
345 begin
346 -- if a(i1...) /= b(j1...) then return false; end if;
347
348 L :=
349 Make_Indexed_Component (Loc,
350 Prefix => Make_Identifier (Loc, Chars (A)),
351 Expressions => Index_List1);
352
353 R :=
354 Make_Indexed_Component (Loc,
355 Prefix => Make_Identifier (Loc, Chars (B)),
356 Expressions => Index_List2);
357
358 Test := Expand_Composite_Equality
359 (Nod, Component_Type (Typ), L, R, Decls);
360
361 return
362 Make_Implicit_If_Statement (Nod,
363 Condition => Make_Op_Not (Loc, Right_Opnd => Test),
364 Then_Statements => New_List (
365 Make_Return_Statement (Loc,
366 Expression => New_Occurrence_Of (Standard_False, Loc))));
367
368 end Component_Equality;
369
370 ------------------------
371 -- Loop_One_Dimension --
372 ------------------------
373
374 function Loop_One_Dimension
375 (N : Int;
376 Index : Node_Id)
377 return Node_Id
378 is
379 I : constant Entity_Id := Make_Defining_Identifier (Loc,
380 New_Internal_Name ('I'));
381 J : constant Entity_Id := Make_Defining_Identifier (Loc,
382 New_Internal_Name ('J'));
383 Index_Type : Entity_Id;
384 Stats : Node_Id;
385
386 begin
387 if N > Number_Dimensions (Typ) then
388 return Component_Equality (Typ);
389
390 else
391 -- Generate the following:
392
393 -- j: index_type;
394 -- ...
395
396 -- if a'length (n) /= b'length (n) then
397 -- return false;
398 -- else
399 -- j := b'first (n);
400 -- for i in a'range (n) loop
401 -- -- loop over remaining dimensions.
402 -- j := index_type'succ (j);
403 -- end loop;
404 -- end if;
405
406 -- retrieve index type for current dimension.
407
408 Index_Type := Base_Type (Etype (Index));
409 Append (New_Reference_To (I, Loc), Index_List1);
410 Append (New_Reference_To (J, Loc), Index_List2);
411
412 -- Declare index for j as a local variable to the function.
413 -- Index i is a loop variable.
414
415 Append_To (Decls,
416 Make_Object_Declaration (Loc,
417 Defining_Identifier => J,
418 Object_Definition => New_Reference_To (Index_Type, Loc)));
419
420 Stats :=
421 Make_Implicit_If_Statement (Nod,
422 Condition =>
423 Make_Op_Ne (Loc,
424 Left_Opnd =>
425 Make_Attribute_Reference (Loc,
426 Prefix => New_Reference_To (A, Loc),
427 Attribute_Name => Name_Length,
428 Expressions => New_List (
429 Make_Integer_Literal (Loc, N))),
430 Right_Opnd =>
431 Make_Attribute_Reference (Loc,
432 Prefix => New_Reference_To (B, Loc),
433 Attribute_Name => Name_Length,
434 Expressions => New_List (
435 Make_Integer_Literal (Loc, N)))),
436
437 Then_Statements => New_List (
438 Make_Return_Statement (Loc,
439 Expression => New_Occurrence_Of (Standard_False, Loc))),
440
441 Else_Statements => New_List (
442
443 Make_Assignment_Statement (Loc,
444 Name => New_Reference_To (J, Loc),
445 Expression =>
446 Make_Attribute_Reference (Loc,
447 Prefix => New_Reference_To (B, Loc),
448 Attribute_Name => Name_First,
449 Expressions => New_List (
450 Make_Integer_Literal (Loc, N)))),
451
452 Make_Implicit_Loop_Statement (Nod,
453 Identifier => Empty,
454 Iteration_Scheme =>
455 Make_Iteration_Scheme (Loc,
456 Loop_Parameter_Specification =>
457 Make_Loop_Parameter_Specification (Loc,
458 Defining_Identifier => I,
459 Discrete_Subtype_Definition =>
460 Make_Attribute_Reference (Loc,
461 Prefix => New_Reference_To (A, Loc),
462 Attribute_Name => Name_Range,
463 Expressions => New_List (
464 Make_Integer_Literal (Loc, N))))),
465
466 Statements => New_List (
467 Loop_One_Dimension (N + 1, Next_Index (Index)),
468 Make_Assignment_Statement (Loc,
469 Name => New_Reference_To (J, Loc),
470 Expression =>
471 Make_Attribute_Reference (Loc,
472 Prefix => New_Reference_To (Index_Type, Loc),
473 Attribute_Name => Name_Succ,
474 Expressions => New_List (
475 New_Reference_To (J, Loc))))))));
476
477 return Stats;
478 end if;
479 end Loop_One_Dimension;
480
481 -- Start of processing for Expand_Array_Equality
482
483 begin
484 Formals := New_List (
485 Make_Parameter_Specification (Loc,
486 Defining_Identifier => A,
487 Parameter_Type => New_Reference_To (Typ, Loc)),
488
489 Make_Parameter_Specification (Loc,
490 Defining_Identifier => B,
491 Parameter_Type => New_Reference_To (Typ, Loc)));
492
493 Func_Name := Make_Defining_Identifier (Loc, New_Internal_Name ('E'));
494
495 Stats := Loop_One_Dimension (1, First_Index (Typ));
496
497 Func_Body :=
498 Make_Subprogram_Body (Loc,
499 Specification =>
500 Make_Function_Specification (Loc,
501 Defining_Unit_Name => Func_Name,
502 Parameter_Specifications => Formals,
503 Subtype_Mark => New_Reference_To (Standard_Boolean, Loc)),
504 Declarations => Decls,
505 Handled_Statement_Sequence =>
506 Make_Handled_Sequence_Of_Statements (Loc,
507 Statements => New_List (
508 Stats,
509 Make_Return_Statement (Loc,
510 Expression => New_Occurrence_Of (Standard_True, Loc)))));
511
512 Set_Has_Completion (Func_Name, True);
513
514 -- If the array type is distinct from the type of the arguments,
515 -- it is the full view of a private type. Apply an unchecked
516 -- conversion to insure that analysis of the call succeeds.
517
518 if Base_Type (A_Typ) /= Base_Type (Typ) then
519 Actuals := New_List (
520 OK_Convert_To (Typ, Lhs),
521 OK_Convert_To (Typ, Rhs));
522 else
523 Actuals := New_List (Lhs, Rhs);
524 end if;
525
526 Append_To (Bodies, Func_Body);
527
528 return
529 Make_Function_Call (Loc,
530 Name => New_Reference_To (Func_Name, Loc),
531 Parameter_Associations => Actuals);
532 end Expand_Array_Equality;
533
534 -----------------------------
535 -- Expand_Boolean_Operator --
536 -----------------------------
537
538 -- Note that we first get the actual subtypes of the operands,
539 -- since we always want to deal with types that have bounds.
540
541 procedure Expand_Boolean_Operator (N : Node_Id) is
542 Typ : constant Entity_Id := Etype (N);
543
544 begin
545 if Is_Bit_Packed_Array (Typ) then
546 Expand_Packed_Boolean_Operator (N);
547
548 else
549
550 -- For the normal non-packed case, the expansion is
551 -- to build a function for carrying out the comparison
552 -- (using Make_Boolean_Array_Op) and then inserting it
553 -- into the tree. The original operator node is then
554 -- rewritten as a call to this function.
555
556 declare
557 Loc : constant Source_Ptr := Sloc (N);
558 L : constant Node_Id := Relocate_Node (Left_Opnd (N));
559 R : constant Node_Id := Relocate_Node (Right_Opnd (N));
560 Func_Body : Node_Id;
561 Func_Name : Entity_Id;
562 begin
563 Convert_To_Actual_Subtype (L);
564 Convert_To_Actual_Subtype (R);
565 Ensure_Defined (Etype (L), N);
566 Ensure_Defined (Etype (R), N);
567 Apply_Length_Check (R, Etype (L));
568
569 Func_Body := Make_Boolean_Array_Op (Etype (L), N);
570 Func_Name := Defining_Unit_Name (Specification (Func_Body));
571 Insert_Action (N, Func_Body);
572
573 -- Now rewrite the expression with a call
574
575 Rewrite (N,
576 Make_Function_Call (Loc,
577 Name => New_Reference_To (Func_Name, Loc),
578 Parameter_Associations =>
579 New_List
580 (L, Make_Type_Conversion
581 (Loc, New_Reference_To (Etype (L), Loc), R))));
582
583 Analyze_And_Resolve (N, Typ);
584 end;
585 end if;
586 end Expand_Boolean_Operator;
587
588 -------------------------------
589 -- Expand_Composite_Equality --
590 -------------------------------
591
592 -- This function is only called for comparing internal fields of composite
593 -- types when these fields are themselves composites. This is a special
594 -- case because it is not possible to respect normal Ada visibility rules.
595
596 function Expand_Composite_Equality
597 (Nod : Node_Id;
598 Typ : Entity_Id;
599 Lhs : Node_Id;
600 Rhs : Node_Id;
601 Bodies : List_Id)
602 return Node_Id
603 is
604 Loc : constant Source_Ptr := Sloc (Nod);
605 Full_Type : Entity_Id;
606 Prim : Elmt_Id;
607 Eq_Op : Entity_Id;
608
609 begin
610 if Is_Private_Type (Typ) then
611 Full_Type := Underlying_Type (Typ);
612 else
613 Full_Type := Typ;
614 end if;
615
616 -- Defense against malformed private types with no completion
617 -- the error will be diagnosed later by check_completion
618
619 if No (Full_Type) then
620 return New_Reference_To (Standard_False, Loc);
621 end if;
622
623 Full_Type := Base_Type (Full_Type);
624
625 if Is_Array_Type (Full_Type) then
626
627 -- If the operand is an elementary type other than a floating-point
628 -- type, then we can simply use the built-in block bitwise equality,
629 -- since the predefined equality operators always apply and bitwise
630 -- equality is fine for all these cases.
631
632 if Is_Elementary_Type (Component_Type (Full_Type))
633 and then not Is_Floating_Point_Type (Component_Type (Full_Type))
634 then
635 return Make_Op_Eq (Loc, Left_Opnd => Lhs, Right_Opnd => Rhs);
636
637 -- For composite component types, and floating-point types, use
638 -- the expansion. This deals with tagged component types (where
639 -- we use the applicable equality routine) and floating-point,
640 -- (where we need to worry about negative zeroes), and also the
641 -- case of any composite type recursively containing such fields.
642
643 else
644 return Expand_Array_Equality
645 (Nod, Full_Type, Typ, Lhs, Rhs, Bodies);
646 end if;
647
648 elsif Is_Tagged_Type (Full_Type) then
649
650 -- Call the primitive operation "=" of this type
651
652 if Is_Class_Wide_Type (Full_Type) then
653 Full_Type := Root_Type (Full_Type);
654 end if;
655
656 -- If this is derived from an untagged private type completed
657 -- with a tagged type, it does not have a full view, so we
658 -- use the primitive operations of the private type.
659 -- This check should no longer be necessary when these
660 -- types receive their full views ???
661
662 if Is_Private_Type (Typ)
663 and then not Is_Tagged_Type (Typ)
664 and then not Is_Controlled (Typ)
665 and then Is_Derived_Type (Typ)
666 and then No (Full_View (Typ))
667 then
668 Prim := First_Elmt (Collect_Primitive_Operations (Typ));
669 else
670 Prim := First_Elmt (Primitive_Operations (Full_Type));
671 end if;
672
673 loop
674 Eq_Op := Node (Prim);
675 exit when Chars (Eq_Op) = Name_Op_Eq
676 and then Etype (First_Formal (Eq_Op)) =
677 Etype (Next_Formal (First_Formal (Eq_Op)));
678 Next_Elmt (Prim);
679 pragma Assert (Present (Prim));
680 end loop;
681
682 Eq_Op := Node (Prim);
683
684 return
685 Make_Function_Call (Loc,
686 Name => New_Reference_To (Eq_Op, Loc),
687 Parameter_Associations =>
688 New_List
689 (Unchecked_Convert_To (Etype (First_Formal (Eq_Op)), Lhs),
690 Unchecked_Convert_To (Etype (First_Formal (Eq_Op)), Rhs)));
691
692 elsif Is_Record_Type (Full_Type) then
693 Eq_Op := TSS (Full_Type, Name_uEquality);
694
695 if Present (Eq_Op) then
696 if Etype (First_Formal (Eq_Op)) /= Full_Type then
697
698 -- Inherited equality from parent type. Convert the actuals
699 -- to match signature of operation.
700
701 declare
702 T : Entity_Id := Etype (First_Formal (Eq_Op));
703
704 begin
705 return
706 Make_Function_Call (Loc,
707 Name => New_Reference_To (Eq_Op, Loc),
708 Parameter_Associations =>
709 New_List (OK_Convert_To (T, Lhs),
710 OK_Convert_To (T, Rhs)));
711 end;
712
713 else
714 return
715 Make_Function_Call (Loc,
716 Name => New_Reference_To (Eq_Op, Loc),
717 Parameter_Associations => New_List (Lhs, Rhs));
718 end if;
719
720 else
721 return Expand_Record_Equality (Nod, Full_Type, Lhs, Rhs, Bodies);
722 end if;
723
724 else
725 -- It can be a simple record or the full view of a scalar private
726
727 return Make_Op_Eq (Loc, Left_Opnd => Lhs, Right_Opnd => Rhs);
728 end if;
729 end Expand_Composite_Equality;
730
731 ------------------------------
732 -- Expand_Concatenate_Other --
733 ------------------------------
734
735 -- Let n be the number of array operands to be concatenated, Base_Typ
736 -- their base type, Ind_Typ their index type, and Arr_Typ the original
737 -- array type to which the concatenantion operator applies, then the
738 -- following subprogram is constructed:
739 --
740 -- [function Cnn (S1 : Base_Typ; ...; Sn : Base_Typ) return Base_Typ is
741 -- L : Ind_Typ;
742 -- begin
743 -- if S1'Length /= 0 then
744 -- L := XXX; --> XXX = S1'First if Arr_Typ is unconstrained
745 -- XXX = Arr_Typ'First otherwise
746 -- elsif S2'Length /= 0 then
747 -- L := YYY; --> YYY = S2'First if Arr_Typ is unconstrained
748 -- YYY = Arr_Typ'First otherwise
749 -- ...
750 -- elsif Sn-1'Length /= 0 then
751 -- L := ZZZ; --> ZZZ = Sn-1'First if Arr_Typ is unconstrained
752 -- ZZZ = Arr_Typ'First otherwise
753 -- else
754 -- return Sn;
755 -- end if;
756 --
757 -- declare
758 -- P : Ind_Typ;
759 -- H : Ind_Typ :=
760 -- Ind_Typ'Val ((((S1'Length - 1) + S2'Length) + ... + Sn'Length)
761 -- + Ind_Typ'Pos (L));
762 -- R : Base_Typ (L .. H);
763 -- begin
764 -- if S1'Length /= 0 then
765 -- P := S1'First;
766 -- loop
767 -- R (L) := S1 (P);
768 -- L := Ind_Typ'Succ (L);
769 -- exit when P = S1'Last;
770 -- P := Ind_Typ'Succ (P);
771 -- end loop;
772 -- end if;
773 --
774 -- if S2'Length /= 0 then
775 -- L := Ind_Typ'Succ (L);
776 -- loop
777 -- R (L) := S2 (P);
778 -- L := Ind_Typ'Succ (L);
779 -- exit when P = S2'Last;
780 -- P := Ind_Typ'Succ (P);
781 -- end loop;
782 -- end if;
783 --
784 -- ...
785 --
786 -- if Sn'Length /= 0 then
787 -- P := Sn'First;
788 -- loop
789 -- R (L) := Sn (P);
790 -- L := Ind_Typ'Succ (L);
791 -- exit when P = Sn'Last;
792 -- P := Ind_Typ'Succ (P);
793 -- end loop;
794 -- end if;
795 --
796 -- return R;
797 -- end;
798 -- end Cnn;]
799
800 procedure Expand_Concatenate_Other (Cnode : Node_Id; Opnds : List_Id) is
801 Loc : constant Source_Ptr := Sloc (Cnode);
802 Nb_Opnds : constant Nat := List_Length (Opnds);
803
804 Arr_Typ : constant Entity_Id := Etype (Entity (Cnode));
805 Base_Typ : constant Entity_Id := Base_Type (Etype (Cnode));
806 Ind_Typ : constant Entity_Id := Etype (First_Index (Base_Typ));
807
808 Func_Id : Node_Id;
809 Func_Spec : Node_Id;
810 Param_Specs : List_Id;
811
812 Func_Body : Node_Id;
813 Func_Decls : List_Id;
814 Func_Stmts : List_Id;
815
816 L_Decl : Node_Id;
817
818 If_Stmt : Node_Id;
819 Elsif_List : List_Id;
820
821 Declare_Block : Node_Id;
822 Declare_Decls : List_Id;
823 Declare_Stmts : List_Id;
824
825 H_Decl : Node_Id;
826 H_Init : Node_Id;
827 P_Decl : Node_Id;
828 R_Decl : Node_Id;
829 R_Constr : Node_Id;
830 R_Range : Node_Id;
831
832 Params : List_Id;
833 Operand : Node_Id;
834
835 function Copy_Into_R_S (I : Nat) return List_Id;
836 -- Builds the sequence of statement:
837 -- P := Si'First;
838 -- loop
839 -- R (L) := Si (P);
840 -- L := Ind_Typ'Succ (L);
841 -- exit when P = Si'Last;
842 -- P := Ind_Typ'Succ (P);
843 -- end loop;
844 --
845 -- where i is the input parameter I given.
846
847 function Init_L (I : Nat) return Node_Id;
848 -- Builds the statement:
849 -- L := Arr_Typ'First; If Arr_Typ is constrained
850 -- L := Si'First; otherwise (where I is the input param given)
851
852 function H return Node_Id;
853 -- Builds reference to identifier H.
854
855 function Ind_Val (E : Node_Id) return Node_Id;
856 -- Builds expression Ind_Typ'Val (E);
857
858 function L return Node_Id;
859 -- Builds reference to identifier L.
860
861 function L_Pos return Node_Id;
862 -- Builds expression Ind_Typ'Pos (L).
863
864 function L_Succ return Node_Id;
865 -- Builds expression Ind_Typ'Succ (L).
866
867 function One return Node_Id;
868 -- Builds integer literal one.
869
870 function P return Node_Id;
871 -- Builds reference to identifier P.
872
873 function P_Succ return Node_Id;
874 -- Builds expression Ind_Typ'Succ (P).
875
876 function R return Node_Id;
877 -- Builds reference to identifier R.
878
879 function S (I : Nat) return Node_Id;
880 -- Builds reference to identifier Si, where I is the value given.
881
882 function S_First (I : Nat) return Node_Id;
883 -- Builds expression Si'First, where I is the value given.
884
885 function S_Last (I : Nat) return Node_Id;
886 -- Builds expression Si'Last, where I is the value given.
887
888 function S_Length (I : Nat) return Node_Id;
889 -- Builds expression Si'Length, where I is the value given.
890
891 function S_Length_Test (I : Nat) return Node_Id;
892 -- Builds expression Si'Length /= 0, where I is the value given.
893
894 -------------------
895 -- Copy_Into_R_S --
896 -------------------
897
898 function Copy_Into_R_S (I : Nat) return List_Id is
899 Stmts : List_Id := New_List;
900 P_Start : Node_Id;
901 Loop_Stmt : Node_Id;
902 R_Copy : Node_Id;
903 Exit_Stmt : Node_Id;
904 L_Inc : Node_Id;
905 P_Inc : Node_Id;
906
907 begin
908 -- First construct the initializations
909
910 P_Start := Make_Assignment_Statement (Loc,
911 Name => P,
912 Expression => S_First (I));
913 Append_To (Stmts, P_Start);
914
915 -- Then build the loop
916
917 R_Copy := Make_Assignment_Statement (Loc,
918 Name => Make_Indexed_Component (Loc,
919 Prefix => R,
920 Expressions => New_List (L)),
921 Expression => Make_Indexed_Component (Loc,
922 Prefix => S (I),
923 Expressions => New_List (P)));
924
925 L_Inc := Make_Assignment_Statement (Loc,
926 Name => L,
927 Expression => L_Succ);
928
929 Exit_Stmt := Make_Exit_Statement (Loc,
930 Condition => Make_Op_Eq (Loc, P, S_Last (I)));
931
932 P_Inc := Make_Assignment_Statement (Loc,
933 Name => P,
934 Expression => P_Succ);
935
936 Loop_Stmt :=
937 Make_Implicit_Loop_Statement (Cnode,
938 Statements => New_List (R_Copy, L_Inc, Exit_Stmt, P_Inc));
939
940 Append_To (Stmts, Loop_Stmt);
941
942 return Stmts;
943 end Copy_Into_R_S;
944
945 -------
946 -- H --
947 -------
948
949 function H return Node_Id is
950 begin
951 return Make_Identifier (Loc, Name_uH);
952 end H;
953
954 -------------
955 -- Ind_Val --
956 -------------
957
958 function Ind_Val (E : Node_Id) return Node_Id is
959 begin
960 return
961 Make_Attribute_Reference (Loc,
962 Prefix => New_Reference_To (Ind_Typ, Loc),
963 Attribute_Name => Name_Val,
964 Expressions => New_List (E));
965 end Ind_Val;
966
967 ------------
968 -- Init_L --
969 ------------
970
971 function Init_L (I : Nat) return Node_Id is
972 E : Node_Id;
973
974 begin
975 if Is_Constrained (Arr_Typ) then
976 E := Make_Attribute_Reference (Loc,
977 Prefix => New_Reference_To (Arr_Typ, Loc),
978 Attribute_Name => Name_First);
979
980 else
981 E := S_First (I);
982 end if;
983
984 return Make_Assignment_Statement (Loc, Name => L, Expression => E);
985 end Init_L;
986
987 -------
988 -- L --
989 -------
990
991 function L return Node_Id is
992 begin
993 return Make_Identifier (Loc, Name_uL);
994 end L;
995
996 -----------
997 -- L_Pos --
998 -----------
999
1000 function L_Pos return Node_Id is
1001 begin
1002 return
1003 Make_Attribute_Reference (Loc,
1004 Prefix => New_Reference_To (Ind_Typ, Loc),
1005 Attribute_Name => Name_Pos,
1006 Expressions => New_List (L));
1007 end L_Pos;
1008
1009 ------------
1010 -- L_Succ --
1011 ------------
1012
1013 function L_Succ return Node_Id is
1014 begin
1015 return
1016 Make_Attribute_Reference (Loc,
1017 Prefix => New_Reference_To (Ind_Typ, Loc),
1018 Attribute_Name => Name_Succ,
1019 Expressions => New_List (L));
1020 end L_Succ;
1021
1022 ---------
1023 -- One --
1024 ---------
1025
1026 function One return Node_Id is
1027 begin
1028 return Make_Integer_Literal (Loc, 1);
1029 end One;
1030
1031 -------
1032 -- P --
1033 -------
1034
1035 function P return Node_Id is
1036 begin
1037 return Make_Identifier (Loc, Name_uP);
1038 end P;
1039
1040 ------------
1041 -- P_Succ --
1042 ------------
1043
1044 function P_Succ return Node_Id is
1045 begin
1046 return
1047 Make_Attribute_Reference (Loc,
1048 Prefix => New_Reference_To (Ind_Typ, Loc),
1049 Attribute_Name => Name_Succ,
1050 Expressions => New_List (P));
1051 end P_Succ;
1052
1053 -------
1054 -- R --
1055 -------
1056
1057 function R return Node_Id is
1058 begin
1059 return Make_Identifier (Loc, Name_uR);
1060 end R;
1061
1062 -------
1063 -- S --
1064 -------
1065
1066 function S (I : Nat) return Node_Id is
1067 begin
1068 return Make_Identifier (Loc, New_External_Name ('S', I));
1069 end S;
1070
1071 -------------
1072 -- S_First --
1073 -------------
1074
1075 function S_First (I : Nat) return Node_Id is
1076 begin
1077 return Make_Attribute_Reference (Loc,
1078 Prefix => S (I),
1079 Attribute_Name => Name_First);
1080 end S_First;
1081
1082 ------------
1083 -- S_Last --
1084 ------------
1085
1086 function S_Last (I : Nat) return Node_Id is
1087 begin
1088 return Make_Attribute_Reference (Loc,
1089 Prefix => S (I),
1090 Attribute_Name => Name_Last);
1091 end S_Last;
1092
1093 --------------
1094 -- S_Length --
1095 --------------
1096
1097 function S_Length (I : Nat) return Node_Id is
1098 begin
1099 return Make_Attribute_Reference (Loc,
1100 Prefix => S (I),
1101 Attribute_Name => Name_Length);
1102 end S_Length;
1103
1104 -------------------
1105 -- S_Length_Test --
1106 -------------------
1107
1108 function S_Length_Test (I : Nat) return Node_Id is
1109 begin
1110 return
1111 Make_Op_Ne (Loc,
1112 Left_Opnd => S_Length (I),
1113 Right_Opnd => Make_Integer_Literal (Loc, 0));
1114 end S_Length_Test;
1115
1116 -- Start of processing for Expand_Concatenate_Other
1117
1118 begin
1119 -- Construct the parameter specs and the overall function spec
1120
1121 Param_Specs := New_List;
1122 for I in 1 .. Nb_Opnds loop
1123 Append_To
1124 (Param_Specs,
1125 Make_Parameter_Specification (Loc,
1126 Defining_Identifier =>
1127 Make_Defining_Identifier (Loc, New_External_Name ('S', I)),
1128 Parameter_Type => New_Reference_To (Base_Typ, Loc)));
1129 end loop;
1130
1131 Func_Id := Make_Defining_Identifier (Loc, New_Internal_Name ('C'));
1132 Func_Spec :=
1133 Make_Function_Specification (Loc,
1134 Defining_Unit_Name => Func_Id,
1135 Parameter_Specifications => Param_Specs,
1136 Subtype_Mark => New_Reference_To (Base_Typ, Loc));
1137
1138 -- Construct L's object declaration
1139
1140 L_Decl :=
1141 Make_Object_Declaration (Loc,
1142 Defining_Identifier => Make_Defining_Identifier (Loc, Name_uL),
1143 Object_Definition => New_Reference_To (Ind_Typ, Loc));
1144
1145 Func_Decls := New_List (L_Decl);
1146
1147 -- Construct the if-then-elsif statements
1148
1149 Elsif_List := New_List;
1150 for I in 2 .. Nb_Opnds - 1 loop
1151 Append_To (Elsif_List, Make_Elsif_Part (Loc,
1152 Condition => S_Length_Test (I),
1153 Then_Statements => New_List (Init_L (I))));
1154 end loop;
1155
1156 If_Stmt :=
1157 Make_Implicit_If_Statement (Cnode,
1158 Condition => S_Length_Test (1),
1159 Then_Statements => New_List (Init_L (1)),
1160 Elsif_Parts => Elsif_List,
1161 Else_Statements => New_List (Make_Return_Statement (Loc,
1162 Expression => S (Nb_Opnds))));
1163
1164 -- Construct the declaration for H
1165
1166 P_Decl :=
1167 Make_Object_Declaration (Loc,
1168 Defining_Identifier => Make_Defining_Identifier (Loc, Name_uP),
1169 Object_Definition => New_Reference_To (Ind_Typ, Loc));
1170
1171 H_Init := Make_Op_Subtract (Loc, S_Length (1), One);
1172 for I in 2 .. Nb_Opnds loop
1173 H_Init := Make_Op_Add (Loc, H_Init, S_Length (I));
1174 end loop;
1175 H_Init := Ind_Val (Make_Op_Add (Loc, H_Init, L_Pos));
1176
1177 H_Decl :=
1178 Make_Object_Declaration (Loc,
1179 Defining_Identifier => Make_Defining_Identifier (Loc, Name_uH),
1180 Object_Definition => New_Reference_To (Ind_Typ, Loc),
1181 Expression => H_Init);
1182
1183 -- Construct the declaration for R
1184
1185 R_Range := Make_Range (Loc, Low_Bound => L, High_Bound => H);
1186 R_Constr :=
1187 Make_Index_Or_Discriminant_Constraint (Loc,
1188 Constraints => New_List (R_Range));
1189
1190 R_Decl :=
1191 Make_Object_Declaration (Loc,
1192 Defining_Identifier => Make_Defining_Identifier (Loc, Name_uR),
1193 Object_Definition =>
1194 Make_Subtype_Indication (Loc,
1195 Subtype_Mark => New_Reference_To (Base_Typ, Loc),
1196 Constraint => R_Constr));
1197
1198 -- Construct the declarations for the declare block
1199
1200 Declare_Decls := New_List (P_Decl, H_Decl, R_Decl);
1201
1202 -- Construct list of statements for the declare block
1203
1204 Declare_Stmts := New_List;
1205 for I in 1 .. Nb_Opnds loop
1206 Append_To (Declare_Stmts,
1207 Make_Implicit_If_Statement (Cnode,
1208 Condition => S_Length_Test (I),
1209 Then_Statements => Copy_Into_R_S (I)));
1210 end loop;
1211
1212 Append_To (Declare_Stmts, Make_Return_Statement (Loc, Expression => R));
1213
1214 -- Construct the declare block
1215
1216 Declare_Block := Make_Block_Statement (Loc,
1217 Declarations => Declare_Decls,
1218 Handled_Statement_Sequence =>
1219 Make_Handled_Sequence_Of_Statements (Loc, Declare_Stmts));
1220
1221 -- Construct the list of function statements
1222
1223 Func_Stmts := New_List (If_Stmt, Declare_Block);
1224
1225 -- Construct the function body
1226
1227 Func_Body :=
1228 Make_Subprogram_Body (Loc,
1229 Specification => Func_Spec,
1230 Declarations => Func_Decls,
1231 Handled_Statement_Sequence =>
1232 Make_Handled_Sequence_Of_Statements (Loc, Func_Stmts));
1233
1234 -- Insert the newly generated function in the code. This is analyzed
1235 -- with all checks off, since we have completed all the checks.
1236
1237 -- Note that this does *not* fix the array concatenation bug when the
1238 -- low bound is Integer'first sibce that bug comes from the pointer
44d6a706 1239 -- dereferencing an unconstrained array. An there we need a constraint
70482933
RK
1240 -- check to make sure the length of the concatenated array is ok. ???
1241
1242 Insert_Action (Cnode, Func_Body, Suppress => All_Checks);
1243
1244 -- Construct list of arguments for the function call
1245
1246 Params := New_List;
1247 Operand := First (Opnds);
1248 for I in 1 .. Nb_Opnds loop
1249 Append_To (Params, Relocate_Node (Operand));
1250 Next (Operand);
1251 end loop;
1252
1253 -- Insert the function call
1254
1255 Rewrite
1256 (Cnode,
1257 Make_Function_Call (Loc, New_Reference_To (Func_Id, Loc), Params));
1258
1259 Analyze_And_Resolve (Cnode, Base_Typ);
1260 Set_Is_Inlined (Func_Id);
1261 end Expand_Concatenate_Other;
1262
1263 -------------------------------
1264 -- Expand_Concatenate_String --
1265 -------------------------------
1266
1267 procedure Expand_Concatenate_String (Cnode : Node_Id; Opnds : List_Id) is
1268 Loc : constant Source_Ptr := Sloc (Cnode);
1269 Opnd1 : constant Node_Id := First (Opnds);
1270 Opnd2 : constant Node_Id := Next (Opnd1);
1271 Typ1 : constant Entity_Id := Base_Type (Etype (Opnd1));
1272 Typ2 : constant Entity_Id := Base_Type (Etype (Opnd2));
1273
1274 R : RE_Id;
1275 -- RE_Id value for function to be called
1276
1277 begin
1278 -- In all cases, we build a call to a routine giving the list of
1279 -- arguments as the parameter list to the routine.
1280
1281 case List_Length (Opnds) is
1282 when 2 =>
1283 if Typ1 = Standard_Character then
1284 if Typ2 = Standard_Character then
1285 R := RE_Str_Concat_CC;
1286
1287 else
1288 pragma Assert (Typ2 = Standard_String);
1289 R := RE_Str_Concat_CS;
1290 end if;
1291
1292 elsif Typ1 = Standard_String then
1293 if Typ2 = Standard_Character then
1294 R := RE_Str_Concat_SC;
1295
1296 else
1297 pragma Assert (Typ2 = Standard_String);
1298 R := RE_Str_Concat;
1299 end if;
1300
1301 -- If we have anything other than Standard_Character or
07fc65c4
GB
1302 -- Standard_String, then we must have had a serious error
1303 -- earlier, so we just abandon the attempt at expansion.
70482933
RK
1304
1305 else
07fc65c4 1306 pragma Assert (Serious_Errors_Detected > 0);
70482933
RK
1307 return;
1308 end if;
1309
1310 when 3 =>
1311 R := RE_Str_Concat_3;
1312
1313 when 4 =>
1314 R := RE_Str_Concat_4;
1315
1316 when 5 =>
1317 R := RE_Str_Concat_5;
1318
1319 when others =>
1320 R := RE_Null;
1321 raise Program_Error;
1322 end case;
1323
1324 -- Now generate the appropriate call
1325
1326 Rewrite (Cnode,
1327 Make_Function_Call (Sloc (Cnode),
1328 Name => New_Occurrence_Of (RTE (R), Loc),
1329 Parameter_Associations => Opnds));
1330
1331 Analyze_And_Resolve (Cnode, Standard_String);
1332 end Expand_Concatenate_String;
1333
1334 ------------------------
1335 -- Expand_N_Allocator --
1336 ------------------------
1337
1338 procedure Expand_N_Allocator (N : Node_Id) is
1339 PtrT : constant Entity_Id := Etype (N);
1340 Desig : Entity_Id;
1341 Loc : constant Source_Ptr := Sloc (N);
1342 Temp : Entity_Id;
1343 Node : Node_Id;
1344
1345 begin
1346 -- RM E.2.3(22). We enforce that the expected type of an allocator
1347 -- shall not be a remote access-to-class-wide-limited-private type
1348
1349 -- Why is this being done at expansion time, seems clearly wrong ???
1350
1351 Validate_Remote_Access_To_Class_Wide_Type (N);
1352
1353 -- Set the Storage Pool
1354
1355 Set_Storage_Pool (N, Associated_Storage_Pool (Root_Type (PtrT)));
1356
1357 if Present (Storage_Pool (N)) then
1358 if Is_RTE (Storage_Pool (N), RE_SS_Pool) then
1359 if not Java_VM then
1360 Set_Procedure_To_Call (N, RTE (RE_SS_Allocate));
1361 end if;
1362 else
1363 Set_Procedure_To_Call (N,
1364 Find_Prim_Op (Etype (Storage_Pool (N)), Name_Allocate));
1365 end if;
1366 end if;
1367
1368 -- Under certain circumstances we can replace an allocator by an
1369 -- access to statically allocated storage. The conditions, as noted
1370 -- in AARM 3.10 (10c) are as follows:
1371
1372 -- Size and initial value is known at compile time
1373 -- Access type is access-to-constant
1374
1375 if Is_Access_Constant (PtrT)
1376 and then Nkind (Expression (N)) = N_Qualified_Expression
1377 and then Compile_Time_Known_Value (Expression (Expression (N)))
1378 and then Size_Known_At_Compile_Time (Etype (Expression
1379 (Expression (N))))
1380 then
1381 -- Here we can do the optimization. For the allocator
1382
1383 -- new x'(y)
1384
1385 -- We insert an object declaration
1386
1387 -- Tnn : aliased x := y;
1388
1389 -- and replace the allocator by Tnn'Unrestricted_Access.
1390 -- Tnn is marked as requiring static allocation.
1391
1392 Temp :=
1393 Make_Defining_Identifier (Loc, New_Internal_Name ('T'));
1394
1395 Desig := Subtype_Mark (Expression (N));
1396
1397 -- If context is constrained, use constrained subtype directly,
1398 -- so that the constant is not labelled as having a nomimally
1399 -- unconstrained subtype.
1400
1401 if Entity (Desig) = Base_Type (Designated_Type (PtrT)) then
1402 Desig := New_Occurrence_Of (Designated_Type (PtrT), Loc);
1403 end if;
1404
1405 Insert_Action (N,
1406 Make_Object_Declaration (Loc,
1407 Defining_Identifier => Temp,
1408 Aliased_Present => True,
1409 Constant_Present => Is_Access_Constant (PtrT),
1410 Object_Definition => Desig,
1411 Expression => Expression (Expression (N))));
1412
1413 Rewrite (N,
1414 Make_Attribute_Reference (Loc,
1415 Prefix => New_Occurrence_Of (Temp, Loc),
1416 Attribute_Name => Name_Unrestricted_Access));
1417
1418 Analyze_And_Resolve (N, PtrT);
1419
1420 -- We set the variable as statically allocated, since we don't
1421 -- want it going on the stack of the current procedure!
1422
1423 Set_Is_Statically_Allocated (Temp);
1424 return;
1425 end if;
1426
1427 -- If the allocator is for a type which requires initialization, and
1428 -- there is no initial value (i.e. the operand is a subtype indication
1429 -- rather than a qualifed expression), then we must generate a call to
1430 -- the initialization routine. This is done using an expression actions
1431 -- node:
1432 --
1433 -- [Pnnn : constant ptr_T := new (T); Init (Pnnn.all,...); Pnnn]
1434 --
1435 -- Here ptr_T is the pointer type for the allocator, and T is the
1436 -- subtype of the allocator. A special case arises if the designated
1437 -- type of the access type is a task or contains tasks. In this case
1438 -- the call to Init (Temp.all ...) is replaced by code that ensures
1439 -- that the tasks get activated (see Exp_Ch9.Build_Task_Allocate_Block
1440 -- for details). In addition, if the type T is a task T, then the first
1441 -- argument to Init must be converted to the task record type.
1442
1443 if Nkind (Expression (N)) = N_Qualified_Expression then
1444 declare
1445 Indic : constant Node_Id := Subtype_Mark (Expression (N));
1446 T : constant Entity_Id := Entity (Indic);
1447 Exp : constant Node_Id := Expression (Expression (N));
1448
1449 Aggr_In_Place : constant Boolean := Is_Delayed_Aggregate (Exp);
1450
1451 Tag_Assign : Node_Id;
1452 Tmp_Node : Node_Id;
1453
1454 begin
1455 if Is_Tagged_Type (T) or else Controlled_Type (T) then
1456
1457 -- Actions inserted before:
1458 -- Temp : constant ptr_T := new T'(Expression);
1459 -- <no CW> Temp._tag := T'tag;
1460 -- <CTRL> Adjust (Finalizable (Temp.all));
1461 -- <CTRL> Attach_To_Final_List (Finalizable (Temp.all));
1462
1463 -- We analyze by hand the new internal allocator to avoid
1464 -- any recursion and inappropriate call to Initialize
1465 if not Aggr_In_Place then
1466 Remove_Side_Effects (Exp);
1467 end if;
1468
1469 Temp :=
1470 Make_Defining_Identifier (Loc, New_Internal_Name ('P'));
1471
1472 -- For a class wide allocation generate the following code:
1473
1474 -- type Equiv_Record is record ... end record;
1475 -- implicit subtype CW is <Class_Wide_Subytpe>;
1476 -- temp : PtrT := new CW'(CW!(expr));
1477
1478 if Is_Class_Wide_Type (T) then
1479 Expand_Subtype_From_Expr (Empty, T, Indic, Exp);
1480
1481 Set_Expression (Expression (N),
1482 Unchecked_Convert_To (Entity (Indic), Exp));
1483
1484 Analyze_And_Resolve (Expression (N), Entity (Indic));
1485 end if;
1486
1487 if Aggr_In_Place then
1488 Tmp_Node :=
1489 Make_Object_Declaration (Loc,
1490 Defining_Identifier => Temp,
1491 Object_Definition => New_Reference_To (PtrT, Loc),
1492 Expression => Make_Allocator (Loc,
1493 New_Reference_To (Etype (Exp), Loc)));
1494
1495 Set_No_Initialization (Expression (Tmp_Node));
1496 Insert_Action (N, Tmp_Node);
1497 Convert_Aggr_In_Allocator (Tmp_Node, Exp);
1498 else
1499 Node := Relocate_Node (N);
1500 Set_Analyzed (Node);
1501 Insert_Action (N,
1502 Make_Object_Declaration (Loc,
1503 Defining_Identifier => Temp,
1504 Constant_Present => True,
1505 Object_Definition => New_Reference_To (PtrT, Loc),
1506 Expression => Node));
1507 end if;
1508
1509 -- Suppress the tag assignment when Java_VM because JVM tags
1510 -- are represented implicitly in objects.
1511
1512 if Is_Tagged_Type (T)
1513 and then not Is_Class_Wide_Type (T)
1514 and then not Java_VM
1515 then
1516 Tag_Assign :=
1517 Make_Assignment_Statement (Loc,
1518 Name =>
1519 Make_Selected_Component (Loc,
1520 Prefix => New_Reference_To (Temp, Loc),
1521 Selector_Name =>
1522 New_Reference_To (Tag_Component (T), Loc)),
1523
1524 Expression =>
1525 Unchecked_Convert_To (RTE (RE_Tag),
1526 New_Reference_To (Access_Disp_Table (T), Loc)));
1527
1528 -- The previous assignment has to be done in any case
1529
1530 Set_Assignment_OK (Name (Tag_Assign));
1531 Insert_Action (N, Tag_Assign);
1532
1533 elsif Is_Private_Type (T)
1534 and then Is_Tagged_Type (Underlying_Type (T))
1535 and then not Java_VM
1536 then
1537 declare
1538 Utyp : constant Entity_Id := Underlying_Type (T);
1539 Ref : constant Node_Id :=
1540 Unchecked_Convert_To (Utyp,
1541 Make_Explicit_Dereference (Loc,
1542 New_Reference_To (Temp, Loc)));
1543
1544 begin
1545 Tag_Assign :=
1546 Make_Assignment_Statement (Loc,
1547 Name =>
1548 Make_Selected_Component (Loc,
1549 Prefix => Ref,
1550 Selector_Name =>
1551 New_Reference_To (Tag_Component (Utyp), Loc)),
1552
1553 Expression =>
1554 Unchecked_Convert_To (RTE (RE_Tag),
1555 New_Reference_To (
1556 Access_Disp_Table (Utyp), Loc)));
1557
1558 Set_Assignment_OK (Name (Tag_Assign));
1559 Insert_Action (N, Tag_Assign);
1560 end;
1561 end if;
1562
1563 if Controlled_Type (Designated_Type (PtrT))
1564 and then Controlled_Type (T)
1565 then
1566 declare
1567 Flist : Node_Id;
1568 Attach : Node_Id;
1569 Apool : constant Entity_Id :=
1570 Associated_Storage_Pool (PtrT);
1571
1572 begin
1573 -- If it is an allocation on the secondary stack
1574 -- (i.e. a value returned from a function), the object
1575 -- is attached on the caller side as soon as the call
1576 -- is completed (see Expand_Ctrl_Function_Call)
1577
1578 if Is_RTE (Apool, RE_SS_Pool) then
1579 declare
1580 F : constant Entity_Id :=
1581 Make_Defining_Identifier (Loc,
1582 New_Internal_Name ('F'));
1583 begin
1584 Insert_Action (N,
1585 Make_Object_Declaration (Loc,
1586 Defining_Identifier => F,
1587 Object_Definition => New_Reference_To (RTE
1588 (RE_Finalizable_Ptr), Loc)));
1589
1590 Flist := New_Reference_To (F, Loc);
1591 Attach := Make_Integer_Literal (Loc, 1);
1592 end;
1593
1594 -- Normal case, not a secondary stack allocation
1595
1596 else
1597 Flist := Find_Final_List (PtrT);
1598 Attach := Make_Integer_Literal (Loc, 2);
1599 end if;
1600
1601 if not Aggr_In_Place then
1602 Insert_Actions (N,
1603 Make_Adjust_Call (
1604 Ref =>
1605
1606 -- An unchecked conversion is needed in the
1607 -- classwide case because the designated type
1608 -- can be an ancestor of the subtype mark of
1609 -- the allocator.
1610
1611 Unchecked_Convert_To (T,
1612 Make_Explicit_Dereference (Loc,
1613 New_Reference_To (Temp, Loc))),
1614
1615 Typ => T,
1616 Flist_Ref => Flist,
1617 With_Attach => Attach));
1618 end if;
1619 end;
1620 end if;
1621
1622 Rewrite (N, New_Reference_To (Temp, Loc));
1623 Analyze_And_Resolve (N, PtrT);
1624
1625 elsif Aggr_In_Place then
1626 Temp :=
1627 Make_Defining_Identifier (Loc, New_Internal_Name ('P'));
1628 Tmp_Node :=
1629 Make_Object_Declaration (Loc,
1630 Defining_Identifier => Temp,
1631 Object_Definition => New_Reference_To (PtrT, Loc),
1632 Expression => Make_Allocator (Loc,
1633 New_Reference_To (Etype (Exp), Loc)));
1634
1635 Set_No_Initialization (Expression (Tmp_Node));
1636 Insert_Action (N, Tmp_Node);
1637 Convert_Aggr_In_Allocator (Tmp_Node, Exp);
1638 Rewrite (N, New_Reference_To (Temp, Loc));
1639 Analyze_And_Resolve (N, PtrT);
1640
1641 elsif Is_Access_Type (Designated_Type (PtrT))
1642 and then Nkind (Exp) = N_Allocator
1643 and then Nkind (Expression (Exp)) /= N_Qualified_Expression
1644 then
1645 -- Apply constraint to designated subtype indication.
1646
1647 Apply_Constraint_Check (Expression (Exp),
1648 Designated_Type (Designated_Type (PtrT)),
1649 No_Sliding => True);
1650
1651 if Nkind (Expression (Exp)) = N_Raise_Constraint_Error then
1652
07fc65c4 1653 -- Propagate constraint_error to enclosing allocator
70482933 1654
07fc65c4 1655 Rewrite (Exp, New_Copy (Expression (Exp)));
70482933
RK
1656 end if;
1657 else
1658 -- First check against the type of the qualified expression
1659 --
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 -- ???
1666 --
1667 -- Apply_Constraint_Check (Exp, T, No_Sliding => True);
1668
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).
1674
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);
1681
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.
1686
1687 else
1688 Apply_Constraint_Check
1689 (Exp, Designated_Type (PtrT), No_Sliding => True);
1690 end if;
1691 end if;
1692 end;
1693
1694 -- Here if not qualified expression case.
1695 -- In this case, an initialization routine may be required
1696
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;
1709
1710 begin
1711
1712 if No_Initialization (N) then
1713 null;
1714
1715 -- Case of no initialization procedure present
1716
1717 elsif not Has_Non_Null_Base_Init_Proc (T) then
1718
1719 -- Case of simple initialization required
1720
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)));
1726
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);
1731
1732 -- No initialization required
1733
1734 else
1735 null;
1736 end if;
1737
1738 -- Case of initialization procedure present, must be called
1739
1740 else
1741 Init := Base_Init_Proc (T);
1742 Node := N;
1743 Temp :=
1744 Make_Defining_Identifier (Loc, New_Internal_Name ('P'));
1745
1746 -- Construct argument list for the initialization routine call
1747 -- The CPP constructor needs the address directly
1748
1749 if Is_CPP_Class (T) then
1750 Arg1 := New_Reference_To (Temp, Loc);
1751 Temp_Type := T;
1752
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;
1759
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.
1763
1764 if Is_Class_Wide_Type (Designated_Type (PtrT)) then
1765 Arg1 := Unchecked_Convert_To (T, Arg1);
1766 end if;
1767 end if;
1768
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.
1775
1776 if Is_Concurrent_Type (T) then
1777 Arg1 :=
1778 Unchecked_Convert_To (Corresponding_Record_Type (T), Arg1);
1779
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);
1787
1788 elsif Etype (First_Formal (Init)) /= Base_Type (T) then
1789
1790 declare
1791 Ftyp : constant Entity_Id := Etype (First_Formal (Init));
1792
1793 begin
1794 Arg1 := OK_Convert_To (Etype (Ftyp), Arg1);
1795 Set_Etype (Arg1, Ftyp);
1796 end;
1797 end if;
1798
1799 Args := New_List (Arg1);
1800
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).
1805
1806 if Has_Task (T) then
1807
1808 if No (Master_Id (Base_Type (PtrT))) then
1809
1810 -- The designated type was an incomplete type, and
1811 -- the access type did not get expanded. Salvage
1812 -- it now.
1813
1814 Expand_N_Full_Type_Declaration
1815 (Parent (Base_Type (PtrT)));
1816 end if;
1817
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
7bc1c7df
ES
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.
70482933
RK
1825
1826 if Nkind (Parent (N)) = N_Assignment_Statement then
1827 declare
1828 Nam : constant Node_Id := Name (Parent (N));
1829
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);
1837
7bc1c7df
ES
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 :=
316ad9c5
RD
1843 Build_Task_Image_Decls
1844 (Loc, Nam, Etype (Prefix (Nam)));
70482933
RK
1845 else
1846 Decls := Build_Task_Image_Decls (Loc, T, T);
1847 end if;
1848 end;
1849
1850 elsif Nkind (Parent (N)) = N_Object_Declaration then
1851 Decls :=
1852 Build_Task_Image_Decls (
1853 Loc, Defining_Identifier (Parent (N)), T);
1854
1855 else
1856 Decls := Build_Task_Image_Decls (Loc, T, T);
1857 end if;
1858
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));
1863
1864 Decl := Last (Decls);
1865 Append_To (Args,
1866 New_Occurrence_Of (Defining_Identifier (Decl), Loc));
1867
1868 -- Has_Task is false, Decls not used
1869
1870 else
1871 Decls := No_List;
1872 end if;
1873
1874 -- Add discriminants if discriminated type
1875
1876 if Has_Discriminants (T) then
1877 Discr := First_Elmt (Discriminant_Constraint (T));
1878
1879 while Present (Discr) loop
1880 Append (New_Copy (Elists.Node (Discr)), Args);
1881 Next_Elmt (Discr);
1882 end loop;
1883
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)));
1890
1891 while Present (Discr) loop
1892 Append (New_Copy (Elists.Node (Discr)), Args);
1893 Next_Elmt (Discr);
1894 end loop;
1895 end if;
1896
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.
1900
1901 Set_Analyzed (N, True);
1902 Node := Relocate_Node (N);
1903
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));
1910
1911 -- Here ptr_T is the pointer type for the allocator, and T
1912 -- is the subtype of the allocator.
1913
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);
1920
1921 Set_Assignment_OK (Temp_Decl);
1922
1923 if Is_CPP_Class (T) then
1924 Set_Aliased_Present (Temp_Decl);
1925 end if;
1926
1927 Insert_Action (N, Temp_Decl, Suppress => All_Checks);
1928
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.
1932
1933 if Has_Task (T) then
1934 declare
1935 L : List_Id := New_List;
1936 Blk : Node_Id;
1937
1938 begin
1939 Build_Task_Allocate_Block (L, Node, Args);
1940 Blk := Last (L);
1941
1942 Insert_List_Before (First (Declarations (Blk)), Decls);
1943 Insert_Actions (N, L);
1944 end;
1945
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;
1952
1953 if Controlled_Type (T) then
1954
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.
1961
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))));
1975
1976 Build_Final_List (N, Acc);
1977 Flist := Find_Final_List (Acc);
1978 end;
1979
1980 else
1981 Flist := Find_Final_List (PtrT);
1982 end if;
1983
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;
1991
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;
2000
2001 Analyze_And_Resolve (N, PtrT);
2002 end if;
2003 end;
2004 end if;
2005 end Expand_N_Allocator;
2006
2007 -----------------------
2008 -- Expand_N_And_Then --
2009 -----------------------
2010
2011 -- Expand into conditional expression if Actions present, and also
2012 -- deal with optimizing case of arguments being True or False.
2013
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;
2020
2021 begin
2022 -- Deal with non-standard booleans
2023
2024 if Is_Boolean_Type (Typ) then
2025 Adjust_Condition (Left);
2026 Adjust_Condition (Right);
2027 Set_Etype (N, Standard_Boolean);
2028 end if;
2029
2030 -- Check for cases of left argument is True or False
2031
2032 if Nkind (Left) = N_Identifier then
2033
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.
2037
2038 if Entity (Left) = Standard_True then
2039 if Present (Actions (N)) then
2040 Insert_Actions (N, Actions (N));
2041 end if;
2042
2043 Rewrite (N, Right);
2044 Adjust_Result_Type (N, Typ);
2045 return;
2046
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.
2050
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;
2059
2060 -- If Actions are present, we expand
2061
2062 -- left and then right
2063
2064 -- into
2065
2066 -- if left then right else false end
2067
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)
2071
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))));
2080
2081 Set_Then_Actions (N, Actlist);
2082 Analyze_And_Resolve (N, Standard_Boolean);
2083 Adjust_Result_Type (N, Typ);
2084 return;
2085 end if;
2086
2087 -- No actions present, check for cases of right argument True/False
2088
2089 if Nkind (Right) = N_Identifier then
2090
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.
2094
2095 if Entity (Right) = Standard_True then
2096 Rewrite (N, Left);
2097
2098 -- Change (Left and then False) to False, making sure to preserve
2099 -- any side effects associated with the Left operand.
2100
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;
2107
2108 Adjust_Result_Type (N, Typ);
2109 end Expand_N_And_Then;
2110
2111 -------------------------------------
2112 -- Expand_N_Conditional_Expression --
2113 -------------------------------------
2114
2115 -- Expand into expression actions if then/else actions present
2116
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;
2125
2126 begin
2127 -- If either then or else actions are present, then given:
2128
2129 -- if cond then then-expr else else-expr end
2130
2131 -- we insert the following sequence of actions (using Insert_Actions):
2132
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;
2141
2142 -- and replace the conditional expression by a reference to Cnn.
2143
2144 if Present (Then_Actions (N)) or else Present (Else_Actions (N)) then
2145 Cnn := Make_Defining_Identifier (Loc, New_Internal_Name ('C'));
2146
2147 New_If :=
2148 Make_Implicit_If_Statement (N,
2149 Condition => Relocate_Node (Cond),
2150
2151 Then_Statements => New_List (
2152 Make_Assignment_Statement (Sloc (Thenx),
2153 Name => New_Occurrence_Of (Cnn, Sloc (Thenx)),
2154 Expression => Relocate_Node (Thenx))),
2155
2156 Else_Statements => New_List (
2157 Make_Assignment_Statement (Sloc (Elsex),
2158 Name => New_Occurrence_Of (Cnn, Sloc (Elsex)),
2159 Expression => Relocate_Node (Elsex))));
2160
2161 if Present (Then_Actions (N)) then
2162 Insert_List_Before
2163 (First (Then_Statements (New_If)), Then_Actions (N));
2164 end if;
2165
2166 if Present (Else_Actions (N)) then
2167 Insert_List_Before
2168 (First (Else_Statements (New_If)), Else_Actions (N));
2169 end if;
2170
2171 Rewrite (N, New_Occurrence_Of (Cnn, Loc));
2172
2173 Insert_Action (N,
2174 Make_Object_Declaration (Loc,
2175 Defining_Identifier => Cnn,
2176 Object_Definition => New_Occurrence_Of (Typ, Loc)));
2177
2178 Insert_Action (N, New_If);
2179 Analyze_And_Resolve (N, Typ);
2180 end if;
2181 end Expand_N_Conditional_Expression;
2182
2183 -----------------------------------
2184 -- Expand_N_Explicit_Dereference --
2185 -----------------------------------
2186
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.
2191
2192 Insert_Dereference_Action (Prefix (N));
2193 end Expand_N_Explicit_Dereference;
2194
2195 -----------------
2196 -- Expand_N_In --
2197 -----------------
2198
2199 procedure Expand_N_In (N : Node_Id) is
2200 Loc : constant Source_Ptr := Sloc (N);
2201 Rtyp : constant Entity_Id := Etype (N);
2202
2203 begin
2204 -- No expansion is required if we have an explicit range
2205
2206 if Nkind (Right_Opnd (N)) = N_Range then
2207 return;
2208
2209 -- Here right operand is a subtype mark
2210
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);
2217
2218 begin
2219 Remove_Side_Effects (Obj);
2220
2221 -- For tagged type, do tagged membership operation
2222
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).
2229
2230 if not Java_VM then
2231 Rewrite (N, Tagged_Membership (N));
2232 Analyze_And_Resolve (N, Rtyp);
2233 end if;
2234
2235 return;
2236
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.
2240
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)),
2248
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;
2256
2257 if Is_Acc then
2258 Typ := Designated_Type (Typ);
2259 end if;
2260
2261 if not Is_Constrained (Typ) then
2262 Rewrite (N,
2263 New_Reference_To (Standard_True, Loc));
2264 Analyze_And_Resolve (N, Rtyp);
2265
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).
2269
2270 elsif Is_Array_Type (Typ) then
2271
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)
2279
2280 function Construct_Attribute_Reference
2281 (E : Node_Id;
2282 Nam : Name_Id;
2283 Dim : Nat)
2284 return Node_Id
2285 is
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;
2294
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)));
2305
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;
2315
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;
2324
2325 Rewrite (N, Cond);
2326 Analyze_And_Resolve (N, Rtyp);
2327 end;
2328
2329 -- These are the cases where constraint checks may be
2330 -- required, e.g. records with possible discriminants
2331
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.
2336
2337 Obj := Relocate_Node (Left_Opnd (N));
2338
2339 if Has_Discriminants (Typ) then
2340 Cond := Make_Op_Not (Loc,
2341 Right_Opnd => Build_Discriminant_Checks (Obj, Typ));
2342
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;
2351
2352 else
2353 Cond := New_Occurrence_Of (Standard_True, Loc);
2354 end if;
2355
2356 Rewrite (N, Cond);
2357 Analyze_And_Resolve (N, Rtyp);
2358 end if;
2359 end;
2360 end if;
2361 end Expand_N_In;
2362
2363 --------------------------------
2364 -- Expand_N_Indexed_Component --
2365 --------------------------------
2366
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);
2372
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.
2381
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.
2386
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;
2398
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.
2404
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;
2411
2412 if Validity_Checks_On and then Validity_Check_Subscripts then
2413 Apply_Subscript_Validity_Checks (N);
2414 end if;
2415
2416 -- All done for the non-packed case
2417
2418 if not Is_Packed (Etype (Prefix (N))) then
2419 return;
2420 end if;
2421
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.
2425
2426 if not Is_Bit_Packed_Array (Etype (Prefix (N))) then
2427 Expand_Packed_Element_Reference (N);
2428 return;
2429 end if;
2430
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:
2434
2435 -- Left side of assignment (or prefix of left side of assignment)
2436 -- This case is handled in Exp_Ch5.Expand_N_Assignment_Statement
2437
2438 -- Renaming objects in renaming associations
2439 -- This case is handled when a use of the renamed variable occurs
2440
2441 -- Actual parameters for a procedure call
2442 -- This case is handled in Exp_Ch6.Expand_Actuals
2443
2444 -- The second expression in a 'Read attribute reference
2445
2446 -- The prefix of an address or size attribute reference
2447
2448 -- The following circuit detects these exceptions
2449
2450 declare
2451 Child : Node_Id := N;
2452 Parnt : Node_Id := Parent (N);
2453
2454 begin
2455 loop
2456 if Nkind (Parnt) = N_Unchecked_Expression then
2457 null;
2458
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;
2466
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;
2474
2475 elsif Nkind (Parnt) = N_Assignment_Statement
2476 and then Name (Parnt) = Child
2477 then
2478 return;
2479
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;
2485
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;
2491
2492 else
2493 Expand_Packed_Element_Reference (N);
2494 return;
2495 end if;
2496
2497 -- Keep looking up tree for unchecked expression, or if we are
2498 -- the prefix of a possible assignment left side.
2499
2500 Child := Parnt;
2501 Parnt := Parent (Child);
2502 end loop;
2503 end;
2504
2505 end Expand_N_Indexed_Component;
2506
2507 ---------------------
2508 -- Expand_N_Not_In --
2509 ---------------------
2510
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.
2513
2514 procedure Expand_N_Not_In (N : Node_Id) is
2515 Loc : constant Source_Ptr := Sloc (N);
2516 Typ : constant Entity_Id := Etype (N);
2517
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;
2527
2528 -------------------
2529 -- Expand_N_Null --
2530 -------------------
2531
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.
2537
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;
2542
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)));
2550
2551 Rewrite (N, Agg);
2552 Analyze_And_Resolve (N, Equivalent_Type (Typ));
2553
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.
2557
2558 Set_Etype (N, Typ);
2559 end if;
2560 end Expand_N_Null;
2561
2562 ---------------------
2563 -- Expand_N_Op_Abs --
2564 ---------------------
2565
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);
2569
2570 begin
2571 Unary_Op_Validity_Checks (N);
2572
2573 -- Deal with software overflow checking
2574
07fc65c4 2575 if not Backend_Overflow_Checks_On_Target
70482933
RK
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
2580
2581 -- (if expr >= 0 then expr else -expr)
2582
2583 -- with the usual Duplicate_Subexpr use coding for expr
2584
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)),
2591
2592 Duplicate_Subexpr (Expr),
2593
2594 Make_Op_Minus (Loc,
2595 Right_Opnd => Duplicate_Subexpr (Expr)))));
2596
2597 Analyze_And_Resolve (N);
2598
2599 -- Vax floating-point types case
2600
2601 elsif Vax_Float (Etype (N)) then
2602 Expand_Vax_Arith (N);
2603 end if;
2604 end Expand_N_Op_Abs;
2605
2606 ---------------------
2607 -- Expand_N_Op_Add --
2608 ---------------------
2609
2610 procedure Expand_N_Op_Add (N : Node_Id) is
2611 Typ : constant Entity_Id := Etype (N);
2612
2613 begin
2614 Binary_Op_Validity_Checks (N);
2615
2616 -- N + 0 = 0 + N = N for integer types
2617
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;
2624
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;
2632
2633 -- Arithemtic overflow checks for signed integer/fixed point types
2634
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;
2640
2641 -- Vax floating-point types case
2642
2643 elsif Vax_Float (Typ) then
2644 Expand_Vax_Arith (N);
2645 end if;
2646 end Expand_N_Op_Add;
2647
2648 ---------------------
2649 -- Expand_N_Op_And --
2650 ---------------------
2651
2652 procedure Expand_N_Op_And (N : Node_Id) is
2653 Typ : constant Entity_Id := Etype (N);
2654
2655 begin
2656 Binary_Op_Validity_Checks (N);
2657
2658 if Is_Array_Type (Etype (N)) then
2659 Expand_Boolean_Operator (N);
2660
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;
2668
2669 ------------------------
2670 -- Expand_N_Op_Concat --
2671 ------------------------
2672
2673 procedure Expand_N_Op_Concat (N : Node_Id) is
2674
2675 Opnds : List_Id;
2676 -- List of operands to be concatenated
2677
2678 Opnd : Node_Id;
2679 -- Single operand for concatenation
2680
2681 Cnode : Node_Id;
2682 -- Node which is to be replaced by the result of concatenating
2683 -- the nodes in the list Opnds.
2684
2685 Atyp : Entity_Id;
2686 -- Array type of concatenation result type
2687
2688 Ctyp : Entity_Id;
2689 -- Component type of concatenation represented by Cnode
2690
2691 begin
2692 Binary_Op_Validity_Checks (N);
2693
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.
2697
2698 if Nkind (Parent (N)) = N_Op_Concat
2699 and then N = Left_Opnd (Parent (N))
2700 then
2701 return;
2702 end if;
2703
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.
2708
2709 Cnode := N;
2710 while Nkind (Left_Opnd (Cnode)) = N_Op_Concat loop
2711 Cnode := Left_Opnd (Cnode);
2712 end loop;
2713
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
2717
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.
2721
2722 Outer : loop
2723 Opnds := New_List (Left_Opnd (Cnode), Right_Opnd (Cnode));
2724 Set_Parent (Opnds, N);
2725
2726 -- The inner loop gathers concatenation operands
2727
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;
2738
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.
2743
2744 Atyp := Base_Type (Etype (Cnode));
2745 Ctyp := Base_Type (Component_Type (Etype (Cnode)));
2746
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;
2756
2757 Next (Opnd);
2758 exit when No (Opnd);
2759 end loop;
2760 end if;
2761
2762 -- Now call appropriate continuation routine
2763
2764 if Atyp = Standard_String then
2765 Expand_Concatenate_String (Cnode, Opnds);
2766 else
2767 Expand_Concatenate_Other (Cnode, Opnds);
2768 end if;
2769
2770 exit Outer when Cnode = N;
2771 Cnode := Parent (Cnode);
2772 end loop Outer;
2773 end Expand_N_Op_Concat;
2774
2775 ------------------------
2776 -- Expand_N_Op_Divide --
2777 ------------------------
2778
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);
2784
2785 begin
2786 Binary_Op_Validity_Checks (N);
2787
2788 -- Vax_Float is a special case
2789
2790 if Vax_Float (Typ) then
2791 Expand_Vax_Arith (N);
2792 return;
2793 end if;
2794
2795 -- N / 1 = N for integer types
2796
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;
2804
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.
2808
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;
2820
2821 -- Do required fixup of universal fixed operation
2822
2823 if Typ = Universal_Fixed then
2824 Fixup_Universal_Fixed_Operation (N);
2825 Typ := Etype (N);
2826 end if;
2827
2828 -- Divisions with fixed-point results
2829
2830 if Is_Fixed_Point_Type (Typ) then
2831
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.
2835
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;
2843
2844 -- Other cases of division of fixed-point operands. Again we
2845 -- exclude the case where Treat_Fixed_As_Integer is set.
2846
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;
2857
2858 -- Mixed-mode operations can appear in a non-static universal
2859 -- context, in which case the integer argument must be converted
2860 -- explicitly.
2861
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))));
2867
2868 Analyze_And_Resolve (Right_Opnd (N), Universal_Real);
2869
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))));
2875
2876 Analyze_And_Resolve (Left_Opnd (N), Universal_Real);
2877
2878 -- Non-fixed point cases, do zero divide and overflow checks
2879
2880 elsif Is_Integer_Type (Typ) then
2881 Apply_Divide_Check (N);
2882 end if;
2883 end Expand_N_Op_Divide;
2884
2885 --------------------
2886 -- Expand_N_Op_Eq --
2887 --------------------
2888
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;
2899
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.
2904
2905 -------------------------
2906 -- Build_Equality_Call --
2907 -------------------------
2908
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);
2913
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;
2921
2922 Rewrite (N,
2923 Make_Function_Call (Loc,
2924 Name => New_Reference_To (Eq, Loc),
2925 Parameter_Associations => New_List (L_Exp, R_Exp)));
2926
2927 Analyze_And_Resolve (N, Standard_Boolean, Suppress => All_Checks);
2928 end Build_Equality_Call;
2929
2930 -- Start of processing for Expand_N_Op_Eq
2931
2932 begin
2933 Binary_Op_Validity_Checks (N);
2934
2935 if Ekind (Typl) = E_Private_Type then
2936 Typl := Underlying_Type (Typl);
2937
2938 elsif Ekind (Typl) = E_Private_Subtype then
2939 Typl := Underlying_Type (Base_Type (Typl));
2940 end if;
2941
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.
2945
2946 if No (Typl) then
2947 return;
2948 end if;
2949
2950 Typl := Base_Type (Typl);
2951
2952 -- Vax float types
2953
2954 if Vax_Float (Typl) then
2955 Expand_Vax_Comparison (N);
2956 return;
2957
2958 -- Boolean types (requiring handling of non-standard case)
2959
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);
2965
2966 -- Array types
2967
2968 elsif Is_Array_Type (Typl) then
2969
2970 -- Packed case
2971
2972 if Is_Bit_Packed_Array (Typl) then
2973 Expand_Packed_Eq (N);
2974
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.
2978
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
2981
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;
2987
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.
2991
2992 else
2993 Rewrite (N,
2994 Expand_Array_Equality (N, Typl, A_Typ,
2995 Relocate_Node (Lhs), Relocate_Node (Rhs), Bodies));
2996
2997 Insert_Actions (N, Bodies, Suppress => All_Checks);
2998 Analyze_And_Resolve (N, Standard_Boolean, Suppress => All_Checks);
2999 end if;
3000
3001 -- Record Types
3002
3003 elsif Is_Record_Type (Typl) then
3004
3005 -- For tagged types, use the primitive "="
3006
3007 if Is_Tagged_Type (Typl) then
3008
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 ???
3014
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));
3021
3022 while Chars (Node (Prim)) /= Name_Op_Eq loop
3023 Next_Elmt (Prim);
3024 pragma Assert (Present (Prim));
3025 end loop;
3026
3027 Op_Name := Node (Prim);
3028 else
3029 Op_Name := Find_Prim_Op (Typl, Name_Op_Eq);
3030 end if;
3031
3032 Build_Equality_Call (Op_Name);
3033
3034 -- If a type support function is present (for complex cases), use it
3035
3036 elsif Present (TSS (Root_Type (Typl), Name_uEquality)) then
3037 Build_Equality_Call (TSS (Root_Type (Typl), Name_uEquality));
3038
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.
3043
3044 else
3045 Remove_Side_Effects (Lhs);
3046 Remove_Side_Effects (Rhs);
3047 Rewrite (N,
3048 Expand_Record_Equality (N, Typl, Lhs, Rhs, Bodies));
3049
3050 Insert_Actions (N, Bodies, Suppress => All_Checks);
3051 Analyze_And_Resolve (N, Standard_Boolean, Suppress => All_Checks);
3052 end if;
3053 end if;
3054
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).
3057
3058 if Nkind (N) = N_Op_Eq then
3059 Rewrite_Comparison (N);
3060 end if;
3061 end Expand_N_Op_Eq;
3062
3063 -----------------------
3064 -- Expand_N_Op_Expon --
3065 -----------------------
3066
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));
07fc65c4 3072 Bastyp : constant Node_Id := Etype (Base);
70482933
RK
3073 Exp : constant Node_Id := Relocate_Node (Right_Opnd (N));
3074 Exptyp : constant Entity_Id := Etype (Exp);
3075 Ovflo : constant Boolean := Do_Overflow_Check (N);
3076 Expv : Uint;
3077 Xnode : Node_Id;
3078 Temp : Node_Id;
3079 Rent : RE_Id;
3080 Ent : Entity_Id;
3081
3082 begin
3083 Binary_Op_Validity_Checks (N);
3084
07fc65c4
GB
3085 -- If either operand is of a private type, then we have the use of
3086 -- an intrinsic operator, and we get rid of the privateness, by using
3087 -- root types of underlying types for the actual operation. Otherwise
3088 -- the private types will cause trouble if we expand multiplications
3089 -- or shifts etc. We also do this transformation if the result type
3090 -- is different from the base type.
3091
3092 if Is_Private_Type (Etype (Base))
3093 or else
3094 Is_Private_Type (Typ)
3095 or else
3096 Is_Private_Type (Exptyp)
3097 or else
3098 Rtyp /= Root_Type (Bastyp)
3099 then
3100 declare
3101 Bt : constant Entity_Id := Root_Type (Underlying_Type (Bastyp));
3102 Et : constant Entity_Id := Root_Type (Underlying_Type (Exptyp));
3103
3104 begin
3105 Rewrite (N,
3106 Unchecked_Convert_To (Typ,
3107 Make_Op_Expon (Loc,
3108 Left_Opnd => Unchecked_Convert_To (Bt, Base),
3109 Right_Opnd => Unchecked_Convert_To (Et, Exp))));
3110 Analyze_And_Resolve (N, Typ);
3111 return;
3112 end;
3113 end if;
3114
70482933
RK
3115 -- At this point the exponentiation must be dynamic since the static
3116 -- case has already been folded after Resolve by Eval_Op_Expon.
3117
3118 -- Test for case of literal right argument
3119
3120 if Compile_Time_Known_Value (Exp) then
3121 Expv := Expr_Value (Exp);
3122
3123 -- We only fold small non-negative exponents. You might think we
3124 -- could fold small negative exponents for the real case, but we
3125 -- can't because we are required to raise Constraint_Error for
3126 -- the case of 0.0 ** (negative) even if Machine_Overflows = False.
3127 -- See ACVC test C4A012B.
3128
3129 if Expv >= 0 and then Expv <= 4 then
3130
3131 -- X ** 0 = 1 (or 1.0)
3132
3133 if Expv = 0 then
3134 if Ekind (Typ) in Integer_Kind then
3135 Xnode := Make_Integer_Literal (Loc, Intval => 1);
3136 else
3137 Xnode := Make_Real_Literal (Loc, Ureal_1);
3138 end if;
3139
3140 -- X ** 1 = X
3141
3142 elsif Expv = 1 then
3143 Xnode := Base;
3144
3145 -- X ** 2 = X * X
3146
3147 elsif Expv = 2 then
3148 Xnode :=
3149 Make_Op_Multiply (Loc,
3150 Left_Opnd => Duplicate_Subexpr (Base),
3151 Right_Opnd => Duplicate_Subexpr (Base));
3152
3153 -- X ** 3 = X * X * X
3154
3155 elsif Expv = 3 then
3156 Xnode :=
3157 Make_Op_Multiply (Loc,
3158 Left_Opnd =>
3159 Make_Op_Multiply (Loc,
3160 Left_Opnd => Duplicate_Subexpr (Base),
3161 Right_Opnd => Duplicate_Subexpr (Base)),
3162 Right_Opnd => Duplicate_Subexpr (Base));
3163
3164 -- X ** 4 ->
3165 -- En : constant base'type := base * base;
3166 -- ...
3167 -- En * En
3168
3169 else -- Expv = 4
3170 Temp :=
3171 Make_Defining_Identifier (Loc, New_Internal_Name ('E'));
3172
3173 Insert_Actions (N, New_List (
3174 Make_Object_Declaration (Loc,
3175 Defining_Identifier => Temp,
3176 Constant_Present => True,
3177 Object_Definition => New_Reference_To (Typ, Loc),
3178 Expression =>
3179 Make_Op_Multiply (Loc,
3180 Left_Opnd => Duplicate_Subexpr (Base),
3181 Right_Opnd => Duplicate_Subexpr (Base)))));
3182
3183 Xnode :=
3184 Make_Op_Multiply (Loc,
3185 Left_Opnd => New_Reference_To (Temp, Loc),
3186 Right_Opnd => New_Reference_To (Temp, Loc));
3187 end if;
3188
3189 Rewrite (N, Xnode);
3190 Analyze_And_Resolve (N, Typ);
3191 return;
3192 end if;
3193 end if;
3194
3195 -- Case of (2 ** expression) appearing as an argument of an integer
3196 -- multiplication, or as the right argument of a division of a non-
3197 -- negative integer. In such cases we lave the node untouched, setting
3198 -- the flag Is_Natural_Power_Of_2_for_Shift set, then the expansion
3199 -- of the higher level node converts it into a shift.
3200
3201 if Nkind (Base) = N_Integer_Literal
3202 and then Intval (Base) = 2
3203 and then Is_Integer_Type (Root_Type (Exptyp))
3204 and then Esize (Root_Type (Exptyp)) <= Esize (Standard_Integer)
3205 and then Is_Unsigned_Type (Exptyp)
3206 and then not Ovflo
3207 and then Nkind (Parent (N)) in N_Binary_Op
3208 then
3209 declare
3210 P : constant Node_Id := Parent (N);
3211 L : constant Node_Id := Left_Opnd (P);
3212 R : constant Node_Id := Right_Opnd (P);
3213
3214 begin
3215 if (Nkind (P) = N_Op_Multiply
3216 and then
3217 ((Is_Integer_Type (Etype (L)) and then R = N)
3218 or else
3219 (Is_Integer_Type (Etype (R)) and then L = N))
3220 and then not Do_Overflow_Check (P))
3221
3222 or else
3223 (Nkind (P) = N_Op_Divide
3224 and then Is_Integer_Type (Etype (L))
3225 and then Is_Unsigned_Type (Etype (L))
3226 and then R = N
3227 and then not Do_Overflow_Check (P))
3228 then
3229 Set_Is_Power_Of_2_For_Shift (N);
3230 return;
3231 end if;
3232 end;
3233 end if;
3234
07fc65c4
GB
3235 -- Fall through if exponentiation must be done using a runtime routine
3236
3237 if No_Run_Time then
3238 Disallow_In_No_Run_Time_Mode (N);
3239 return;
3240 end if;
70482933 3241
07fc65c4 3242 -- First deal with modular case
70482933
RK
3243
3244 if Is_Modular_Integer_Type (Rtyp) then
3245
3246 -- Non-binary case, we call the special exponentiation routine for
3247 -- the non-binary case, converting the argument to Long_Long_Integer
3248 -- and passing the modulus value. Then the result is converted back
3249 -- to the base type.
3250
3251 if Non_Binary_Modulus (Rtyp) then
3252
3253 Rewrite (N,
3254 Convert_To (Typ,
3255 Make_Function_Call (Loc,
3256 Name => New_Reference_To (RTE (RE_Exp_Modular), Loc),
3257 Parameter_Associations => New_List (
3258 Convert_To (Standard_Integer, Base),
3259 Make_Integer_Literal (Loc, Modulus (Rtyp)),
3260 Exp))));
3261
3262 -- Binary case, in this case, we call one of two routines, either
3263 -- the unsigned integer case, or the unsigned long long integer
3264 -- case, with a final "and" operation to do the required mod.
3265
3266 else
3267 if UI_To_Int (Esize (Rtyp)) <= Standard_Integer_Size then
3268 Ent := RTE (RE_Exp_Unsigned);
3269 else
3270 Ent := RTE (RE_Exp_Long_Long_Unsigned);
3271 end if;
3272
3273 Rewrite (N,
3274 Convert_To (Typ,
3275 Make_Op_And (Loc,
3276 Left_Opnd =>
3277 Make_Function_Call (Loc,
3278 Name => New_Reference_To (Ent, Loc),
3279 Parameter_Associations => New_List (
3280 Convert_To (Etype (First_Formal (Ent)), Base),
3281 Exp)),
3282 Right_Opnd =>
3283 Make_Integer_Literal (Loc, Modulus (Rtyp) - 1))));
3284
3285 end if;
3286
3287 -- Common exit point for modular type case
3288
3289 Analyze_And_Resolve (N, Typ);
3290 return;
3291
3292 -- Signed integer cases
3293
3294 elsif Rtyp = Base_Type (Standard_Integer) then
3295 if Ovflo then
3296 Rent := RE_Exp_Integer;
3297 else
3298 Rent := RE_Exn_Integer;
3299 end if;
3300
3301 elsif Rtyp = Base_Type (Standard_Short_Integer) then
3302 if Ovflo then
3303 Rent := RE_Exp_Short_Integer;
3304 else
3305 Rent := RE_Exn_Short_Integer;
3306 end if;
3307
3308 elsif Rtyp = Base_Type (Standard_Short_Short_Integer) then
3309 if Ovflo then
3310 Rent := RE_Exp_Short_Short_Integer;
3311 else
3312 Rent := RE_Exn_Short_Short_Integer;
3313 end if;
3314
3315 elsif Rtyp = Base_Type (Standard_Long_Integer) then
3316 if Ovflo then
3317 Rent := RE_Exp_Long_Integer;
3318 else
3319 Rent := RE_Exn_Long_Integer;
3320 end if;
3321
3322 elsif (Rtyp = Base_Type (Standard_Long_Long_Integer)
3323 or else Rtyp = Universal_Integer)
3324 then
3325 if Ovflo then
3326 Rent := RE_Exp_Long_Long_Integer;
3327 else
3328 Rent := RE_Exn_Long_Long_Integer;
3329 end if;
3330
3331 -- Floating-point cases
3332
3333 elsif Rtyp = Standard_Float then
3334 if Ovflo then
3335 Rent := RE_Exp_Float;
3336 else
3337 Rent := RE_Exn_Float;
3338 end if;
3339
3340 elsif Rtyp = Standard_Short_Float then
3341 if Ovflo then
3342 Rent := RE_Exp_Short_Float;
3343 else
3344 Rent := RE_Exn_Short_Float;
3345 end if;
3346
3347 elsif Rtyp = Standard_Long_Float then
3348 if Ovflo then
3349 Rent := RE_Exp_Long_Float;
3350 else
3351 Rent := RE_Exn_Long_Float;
3352 end if;
3353
3354 else
3355 pragma Assert
3356 (Rtyp = Standard_Long_Long_Float or else Rtyp = Universal_Real);
3357
3358 if Ovflo then
3359 Rent := RE_Exp_Long_Long_Float;
3360 else
3361 Rent := RE_Exn_Long_Long_Float;
3362 end if;
3363 end if;
3364
3365 -- Common processing for integer cases and floating-point cases.
3366 -- If we are in the base type, we can call runtime routine directly
3367
3368 if Typ = Rtyp
3369 and then Rtyp /= Universal_Integer
3370 and then Rtyp /= Universal_Real
3371 then
3372 Rewrite (N,
3373 Make_Function_Call (Loc,
3374 Name => New_Reference_To (RTE (Rent), Loc),
3375 Parameter_Associations => New_List (Base, Exp)));
3376
3377 -- Otherwise we have to introduce conversions (conversions are also
3378 -- required in the universal cases, since the runtime routine was
3379 -- typed using the largest integer or real case.
3380
3381 else
3382 Rewrite (N,
3383 Convert_To (Typ,
3384 Make_Function_Call (Loc,
3385 Name => New_Reference_To (RTE (Rent), Loc),
3386 Parameter_Associations => New_List (
3387 Convert_To (Rtyp, Base),
3388 Exp))));
3389 end if;
3390
3391 Analyze_And_Resolve (N, Typ);
3392 return;
3393
3394 end Expand_N_Op_Expon;
3395
3396 --------------------
3397 -- Expand_N_Op_Ge --
3398 --------------------
3399
3400 procedure Expand_N_Op_Ge (N : Node_Id) is
3401 Typ : constant Entity_Id := Etype (N);
3402 Op1 : constant Node_Id := Left_Opnd (N);
3403 Op2 : constant Node_Id := Right_Opnd (N);
3404 Typ1 : constant Entity_Id := Base_Type (Etype (Op1));
3405
3406 begin
3407 Binary_Op_Validity_Checks (N);
3408
3409 if Vax_Float (Typ1) then
3410 Expand_Vax_Comparison (N);
3411 return;
3412
3413 elsif Is_Array_Type (Typ1) then
3414 Expand_Array_Comparison (N);
3415 return;
3416 end if;
3417
3418 if Is_Boolean_Type (Typ1) then
3419 Adjust_Condition (Op1);
3420 Adjust_Condition (Op2);
3421 Set_Etype (N, Standard_Boolean);
3422 Adjust_Result_Type (N, Typ);
3423 end if;
3424
3425 Rewrite_Comparison (N);
3426 end Expand_N_Op_Ge;
3427
3428 --------------------
3429 -- Expand_N_Op_Gt --
3430 --------------------
3431
3432 procedure Expand_N_Op_Gt (N : Node_Id) is
3433 Typ : constant Entity_Id := Etype (N);
3434 Op1 : constant Node_Id := Left_Opnd (N);
3435 Op2 : constant Node_Id := Right_Opnd (N);
3436 Typ1 : constant Entity_Id := Base_Type (Etype (Op1));
3437
3438 begin
3439 Binary_Op_Validity_Checks (N);
3440
3441 if Vax_Float (Typ1) then
3442 Expand_Vax_Comparison (N);
3443 return;
3444
3445 elsif Is_Array_Type (Typ1) then
3446 Expand_Array_Comparison (N);
3447 return;
3448 end if;
3449
3450 if Is_Boolean_Type (Typ1) then
3451 Adjust_Condition (Op1);
3452 Adjust_Condition (Op2);
3453 Set_Etype (N, Standard_Boolean);
3454 Adjust_Result_Type (N, Typ);
3455 end if;
3456
3457 Rewrite_Comparison (N);
3458 end Expand_N_Op_Gt;
3459
3460 --------------------
3461 -- Expand_N_Op_Le --
3462 --------------------
3463
3464 procedure Expand_N_Op_Le (N : Node_Id) is
3465 Typ : constant Entity_Id := Etype (N);
3466 Op1 : constant Node_Id := Left_Opnd (N);
3467 Op2 : constant Node_Id := Right_Opnd (N);
3468 Typ1 : constant Entity_Id := Base_Type (Etype (Op1));
3469
3470 begin
3471 Binary_Op_Validity_Checks (N);
3472
3473 if Vax_Float (Typ1) then
3474 Expand_Vax_Comparison (N);
3475 return;
3476
3477 elsif Is_Array_Type (Typ1) then
3478 Expand_Array_Comparison (N);
3479 return;
3480 end if;
3481
3482 if Is_Boolean_Type (Typ1) then
3483 Adjust_Condition (Op1);
3484 Adjust_Condition (Op2);
3485 Set_Etype (N, Standard_Boolean);
3486 Adjust_Result_Type (N, Typ);
3487 end if;
3488
3489 Rewrite_Comparison (N);
3490 end Expand_N_Op_Le;
3491
3492 --------------------
3493 -- Expand_N_Op_Lt --
3494 --------------------
3495
3496 procedure Expand_N_Op_Lt (N : Node_Id) is
3497 Typ : constant Entity_Id := Etype (N);
3498 Op1 : constant Node_Id := Left_Opnd (N);
3499 Op2 : constant Node_Id := Right_Opnd (N);
3500 Typ1 : constant Entity_Id := Base_Type (Etype (Op1));
3501
3502 begin
3503 Binary_Op_Validity_Checks (N);
3504
3505 if Vax_Float (Typ1) then
3506 Expand_Vax_Comparison (N);
3507 return;
3508
3509 elsif Is_Array_Type (Typ1) then
3510 Expand_Array_Comparison (N);
3511 return;
3512 end if;
3513
3514 if Is_Boolean_Type (Typ1) then
3515 Adjust_Condition (Op1);
3516 Adjust_Condition (Op2);
3517 Set_Etype (N, Standard_Boolean);
3518 Adjust_Result_Type (N, Typ);
3519 end if;
3520
3521 Rewrite_Comparison (N);
3522 end Expand_N_Op_Lt;
3523
3524 -----------------------
3525 -- Expand_N_Op_Minus --
3526 -----------------------
3527
3528 procedure Expand_N_Op_Minus (N : Node_Id) is
3529 Loc : constant Source_Ptr := Sloc (N);
3530 Typ : constant Entity_Id := Etype (N);
3531
3532 begin
3533 Unary_Op_Validity_Checks (N);
3534
07fc65c4 3535 if not Backend_Overflow_Checks_On_Target
70482933
RK
3536 and then Is_Signed_Integer_Type (Etype (N))
3537 and then Do_Overflow_Check (N)
3538 then
3539 -- Software overflow checking expands -expr into (0 - expr)
3540
3541 Rewrite (N,
3542 Make_Op_Subtract (Loc,
3543 Left_Opnd => Make_Integer_Literal (Loc, 0),
3544 Right_Opnd => Right_Opnd (N)));
3545
3546 Analyze_And_Resolve (N, Typ);
3547
3548 -- Vax floating-point types case
3549
3550 elsif Vax_Float (Etype (N)) then
3551 Expand_Vax_Arith (N);
3552 end if;
3553 end Expand_N_Op_Minus;
3554
3555 ---------------------
3556 -- Expand_N_Op_Mod --
3557 ---------------------
3558
3559 procedure Expand_N_Op_Mod (N : Node_Id) is
3560 Loc : constant Source_Ptr := Sloc (N);
3561 T : constant Entity_Id := Etype (N);
3562 Left : constant Node_Id := Left_Opnd (N);
3563 Right : constant Node_Id := Right_Opnd (N);
3564 DOC : constant Boolean := Do_Overflow_Check (N);
3565 DDC : constant Boolean := Do_Division_Check (N);
3566
3567 LLB : Uint;
3568 Llo : Uint;
3569 Lhi : Uint;
3570 LOK : Boolean;
3571 Rlo : Uint;
3572 Rhi : Uint;
3573 ROK : Boolean;
3574
3575 begin
3576 Binary_Op_Validity_Checks (N);
3577
3578 Determine_Range (Right, ROK, Rlo, Rhi);
3579 Determine_Range (Left, LOK, Llo, Lhi);
3580
3581 -- Convert mod to rem if operands are known non-negative. We do this
3582 -- since it is quite likely that this will improve the quality of code,
3583 -- (the operation now corresponds to the hardware remainder), and it
3584 -- does not seem likely that it could be harmful.
3585
3586 if LOK and then Llo >= 0
3587 and then
3588 ROK and then Rlo >= 0
3589 then
3590 Rewrite (N,
3591 Make_Op_Rem (Sloc (N),
3592 Left_Opnd => Left_Opnd (N),
3593 Right_Opnd => Right_Opnd (N)));
3594
3595 -- Instead of reanalyzing the node we do the analysis manually.
3596 -- This avoids anomalies when the replacement is done in an
3597 -- instance and is epsilon more efficient.
3598
3599 Set_Entity (N, Standard_Entity (S_Op_Rem));
3600 Set_Etype (N, T);
3601 Set_Do_Overflow_Check (N, DOC);
3602 Set_Do_Division_Check (N, DDC);
3603 Expand_N_Op_Rem (N);
3604 Set_Analyzed (N);
3605
3606 -- Otherwise, normal mod processing
3607
3608 else
3609 if Is_Integer_Type (Etype (N)) then
3610 Apply_Divide_Check (N);
3611 end if;
3612
3613 -- Deal with annoying case of largest negative number remainder
3614 -- minus one. Gigi does not handle this case correctly, because
3615 -- it generates a divide instruction which may trap in this case.
3616
3617 -- In fact the check is quite easy, if the right operand is -1,
3618 -- then the mod value is always 0, and we can just ignore the
3619 -- left operand completely in this case.
3620
3621 LLB := Expr_Value (Type_Low_Bound (Base_Type (Etype (Left))));
3622
3623 if ((not ROK) or else (Rlo <= (-1) and then (-1) <= Rhi))
3624 and then
3625 ((not LOK) or else (Llo = LLB))
3626 then
3627 Rewrite (N,
3628 Make_Conditional_Expression (Loc,
3629 Expressions => New_List (
3630 Make_Op_Eq (Loc,
3631 Left_Opnd => Duplicate_Subexpr (Right),
3632 Right_Opnd =>
3633 Make_Integer_Literal (Loc, -1)),
3634 Make_Integer_Literal (Loc, Uint_0),
3635 Relocate_Node (N))));
3636
3637 Set_Analyzed (Next (Next (First (Expressions (N)))));
3638 Analyze_And_Resolve (N, T);
3639 end if;
3640 end if;
3641 end Expand_N_Op_Mod;
3642
3643 --------------------------
3644 -- Expand_N_Op_Multiply --
3645 --------------------------
3646
3647 procedure Expand_N_Op_Multiply (N : Node_Id) is
3648 Loc : constant Source_Ptr := Sloc (N);
3649 Lop : constant Node_Id := Left_Opnd (N);
3650 Rop : constant Node_Id := Right_Opnd (N);
3651 Ltyp : constant Entity_Id := Etype (Lop);
3652 Rtyp : constant Entity_Id := Etype (Rop);
3653 Typ : Entity_Id := Etype (N);
3654
3655 begin
3656 Binary_Op_Validity_Checks (N);
3657
3658 -- Special optimizations for integer types
3659
3660 if Is_Integer_Type (Typ) then
3661
3662 -- N * 0 = 0 * N = 0 for integer types
3663
3664 if (Compile_Time_Known_Value (Right_Opnd (N))
3665 and then Expr_Value (Right_Opnd (N)) = Uint_0)
3666 or else
3667 (Compile_Time_Known_Value (Left_Opnd (N))
3668 and then Expr_Value (Left_Opnd (N)) = Uint_0)
3669 then
3670 Rewrite (N, Make_Integer_Literal (Loc, Uint_0));
3671 Analyze_And_Resolve (N, Typ);
3672 return;
3673 end if;
3674
3675 -- N * 1 = 1 * N = N for integer types
3676
3677 if Compile_Time_Known_Value (Right_Opnd (N))
3678 and then Expr_Value (Right_Opnd (N)) = Uint_1
3679 then
3680 Rewrite (N, Left_Opnd (N));
3681 return;
3682
3683 elsif Compile_Time_Known_Value (Left_Opnd (N))
3684 and then Expr_Value (Left_Opnd (N)) = Uint_1
3685 then
3686 Rewrite (N, Right_Opnd (N));
3687 return;
3688 end if;
3689 end if;
3690
3691 -- Deal with VAX float case
3692
3693 if Vax_Float (Typ) then
3694 Expand_Vax_Arith (N);
3695 return;
3696 end if;
3697
3698 -- Convert x * 2 ** y to Shift_Left (x, y). Note that the fact that
3699 -- Is_Power_Of_2_For_Shift is set means that we know that our left
3700 -- operand is an integer, as required for this to work.
3701
3702 if Nkind (Rop) = N_Op_Expon
3703 and then Is_Power_Of_2_For_Shift (Rop)
3704 then
3705 if Nkind (Lop) = N_Op_Expon
3706 and then Is_Power_Of_2_For_Shift (Lop)
3707 then
3708
3709 -- convert 2 ** A * 2 ** B into 2 ** (A + B)
3710
3711 Rewrite (N,
3712 Make_Op_Expon (Loc,
3713 Left_Opnd => Make_Integer_Literal (Loc, 2),
3714 Right_Opnd =>
3715 Make_Op_Add (Loc,
3716 Left_Opnd => Right_Opnd (Lop),
3717 Right_Opnd => Right_Opnd (Rop))));
3718 Analyze_And_Resolve (N, Typ);
3719 return;
3720
3721 else
3722 Rewrite (N,
3723 Make_Op_Shift_Left (Loc,
3724 Left_Opnd => Lop,
3725 Right_Opnd =>
3726 Convert_To (Standard_Natural, Right_Opnd (Rop))));
3727 Analyze_And_Resolve (N, Typ);
3728 return;
3729 end if;
3730
3731 -- Same processing for the operands the other way round
3732
3733 elsif Nkind (Lop) = N_Op_Expon
3734 and then Is_Power_Of_2_For_Shift (Lop)
3735 then
3736 Rewrite (N,
3737 Make_Op_Shift_Left (Loc,
3738 Left_Opnd => Rop,
3739 Right_Opnd =>
3740 Convert_To (Standard_Natural, Right_Opnd (Lop))));
3741 Analyze_And_Resolve (N, Typ);
3742 return;
3743 end if;
3744
3745 -- Do required fixup of universal fixed operation
3746
3747 if Typ = Universal_Fixed then
3748 Fixup_Universal_Fixed_Operation (N);
3749 Typ := Etype (N);
3750 end if;
3751
3752 -- Multiplications with fixed-point results
3753
3754 if Is_Fixed_Point_Type (Typ) then
3755
3756 -- No special processing if Treat_Fixed_As_Integer is set,
3757 -- since from a semantic point of view such operations are
3758 -- simply integer operations and will be treated that way.
3759
3760 if not Treat_Fixed_As_Integer (N) then
3761
3762 -- Case of fixed * integer => fixed
3763
3764 if Is_Integer_Type (Rtyp) then
3765 Expand_Multiply_Fixed_By_Integer_Giving_Fixed (N);
3766
3767 -- Case of integer * fixed => fixed
3768
3769 elsif Is_Integer_Type (Ltyp) then
3770 Expand_Multiply_Integer_By_Fixed_Giving_Fixed (N);
3771
3772 -- Case of fixed * fixed => fixed
3773
3774 else
3775 Expand_Multiply_Fixed_By_Fixed_Giving_Fixed (N);
3776 end if;
3777 end if;
3778
3779 -- Other cases of multiplication of fixed-point operands. Again
3780 -- we exclude the cases where Treat_Fixed_As_Integer flag is set.
3781
3782 elsif (Is_Fixed_Point_Type (Ltyp) or else Is_Fixed_Point_Type (Rtyp))
3783 and then not Treat_Fixed_As_Integer (N)
3784 then
3785 if Is_Integer_Type (Typ) then
3786 Expand_Multiply_Fixed_By_Fixed_Giving_Integer (N);
3787 else
3788 pragma Assert (Is_Floating_Point_Type (Typ));
3789 Expand_Multiply_Fixed_By_Fixed_Giving_Float (N);
3790 end if;
3791
3792 -- Mixed-mode operations can appear in a non-static universal
3793 -- context, in which case the integer argument must be converted
3794 -- explicitly.
3795
3796 elsif Typ = Universal_Real
3797 and then Is_Integer_Type (Rtyp)
3798 then
3799 Rewrite (Rop, Convert_To (Universal_Real, Relocate_Node (Rop)));
3800
3801 Analyze_And_Resolve (Rop, Universal_Real);
3802
3803 elsif Typ = Universal_Real
3804 and then Is_Integer_Type (Ltyp)
3805 then
3806 Rewrite (Lop, Convert_To (Universal_Real, Relocate_Node (Lop)));
3807
3808 Analyze_And_Resolve (Lop, Universal_Real);
3809
3810 -- Non-fixed point cases, check software overflow checking required
3811
3812 elsif Is_Signed_Integer_Type (Etype (N)) then
3813 Apply_Arithmetic_Overflow_Check (N);
3814 end if;
3815 end Expand_N_Op_Multiply;
3816
3817 --------------------
3818 -- Expand_N_Op_Ne --
3819 --------------------
3820
3821 -- Rewrite node as the negation of an equality operation, and reanalyze.
3822 -- The equality to be used is defined in the same scope and has the same
3823 -- signature. It must be set explicitly because in an instance it may not
3824 -- have the same visibility as in the generic unit.
3825
3826 procedure Expand_N_Op_Ne (N : Node_Id) is
3827 Loc : constant Source_Ptr := Sloc (N);
3828 Neg : Node_Id;
3829 Ne : constant Entity_Id := Entity (N);
3830
3831 begin
3832 Binary_Op_Validity_Checks (N);
3833
3834 Neg :=
3835 Make_Op_Not (Loc,
3836 Right_Opnd =>
3837 Make_Op_Eq (Loc,
3838 Left_Opnd => Left_Opnd (N),
3839 Right_Opnd => Right_Opnd (N)));
3840 Set_Paren_Count (Right_Opnd (Neg), 1);
3841
3842 if Scope (Ne) /= Standard_Standard then
3843 Set_Entity (Right_Opnd (Neg), Corresponding_Equality (Ne));
3844 end if;
3845
3846 Rewrite (N, Neg);
3847 Analyze_And_Resolve (N, Standard_Boolean);
3848 end Expand_N_Op_Ne;
3849
3850 ---------------------
3851 -- Expand_N_Op_Not --
3852 ---------------------
3853
3854 -- If the argument is other than a Boolean array type, there is no
3855 -- special expansion required.
3856
3857 -- For the packed case, we call the special routine in Exp_Pakd, except
3858 -- that if the component size is greater than one, we use the standard
3859 -- routine generating a gruesome loop (it is so peculiar to have packed
3860 -- arrays with non-standard Boolean representations anyway, so it does
3861 -- not matter that we do not handle this case efficiently).
3862
3863 -- For the unpacked case (and for the special packed case where we have
3864 -- non standard Booleans, as discussed above), we generate and insert
3865 -- into the tree the following function definition:
3866
3867 -- function Nnnn (A : arr) is
3868 -- B : arr;
3869 -- begin
3870 -- for J in a'range loop
3871 -- B (J) := not A (J);
3872 -- end loop;
3873 -- return B;
3874 -- end Nnnn;
3875
3876 -- Here arr is the actual subtype of the parameter (and hence always
3877 -- constrained). Then we replace the not with a call to this function.
3878
3879 procedure Expand_N_Op_Not (N : Node_Id) is
3880 Loc : constant Source_Ptr := Sloc (N);
3881 Typ : constant Entity_Id := Etype (N);
3882 Opnd : Node_Id;
3883 Arr : Entity_Id;
3884 A : Entity_Id;
3885 B : Entity_Id;
3886 J : Entity_Id;
3887 A_J : Node_Id;
3888 B_J : Node_Id;
3889
3890 Func_Name : Entity_Id;
3891 Loop_Statement : Node_Id;
3892
3893 begin
3894 Unary_Op_Validity_Checks (N);
3895
3896 -- For boolean operand, deal with non-standard booleans
3897
3898 if Is_Boolean_Type (Typ) then
3899 Adjust_Condition (Right_Opnd (N));
3900 Set_Etype (N, Standard_Boolean);
3901 Adjust_Result_Type (N, Typ);
3902 return;
3903 end if;
3904
3905 -- Only array types need any other processing
3906
3907 if not Is_Array_Type (Typ) then
3908 return;
3909 end if;
3910
3911 -- Case of array operand. If bit packed, handle it in Exp_Pakd
3912
3913 if Is_Bit_Packed_Array (Typ) and then Component_Size (Typ) = 1 then
3914 Expand_Packed_Not (N);
3915 return;
3916 end if;
3917
3918 -- Case of array operand which is not bit-packed
3919
3920 Opnd := Relocate_Node (Right_Opnd (N));
3921 Convert_To_Actual_Subtype (Opnd);
3922 Arr := Etype (Opnd);
3923 Ensure_Defined (Arr, N);
3924
3925 A := Make_Defining_Identifier (Loc, Name_uA);
3926 B := Make_Defining_Identifier (Loc, Name_uB);
3927 J := Make_Defining_Identifier (Loc, Name_uJ);
3928
3929 A_J :=
3930 Make_Indexed_Component (Loc,
3931 Prefix => New_Reference_To (A, Loc),
3932 Expressions => New_List (New_Reference_To (J, Loc)));
3933
3934 B_J :=
3935 Make_Indexed_Component (Loc,
3936 Prefix => New_Reference_To (B, Loc),
3937 Expressions => New_List (New_Reference_To (J, Loc)));
3938
3939 Loop_Statement :=
3940 Make_Implicit_Loop_Statement (N,
3941 Identifier => Empty,
3942
3943 Iteration_Scheme =>
3944 Make_Iteration_Scheme (Loc,
3945 Loop_Parameter_Specification =>
3946 Make_Loop_Parameter_Specification (Loc,
3947 Defining_Identifier => J,
3948 Discrete_Subtype_Definition =>
3949 Make_Attribute_Reference (Loc,
3950 Prefix => Make_Identifier (Loc, Chars (A)),
3951 Attribute_Name => Name_Range))),
3952
3953 Statements => New_List (
3954 Make_Assignment_Statement (Loc,
3955 Name => B_J,
3956 Expression => Make_Op_Not (Loc, A_J))));
3957
3958 Func_Name := Make_Defining_Identifier (Loc, New_Internal_Name ('N'));
3959 Set_Is_Inlined (Func_Name);
3960
3961 Insert_Action (N,
3962 Make_Subprogram_Body (Loc,
3963 Specification =>
3964 Make_Function_Specification (Loc,
3965 Defining_Unit_Name => Func_Name,
3966 Parameter_Specifications => New_List (
3967 Make_Parameter_Specification (Loc,
3968 Defining_Identifier => A,
3969 Parameter_Type => New_Reference_To (Typ, Loc))),
3970 Subtype_Mark => New_Reference_To (Typ, Loc)),
3971
3972 Declarations => New_List (
3973 Make_Object_Declaration (Loc,
3974 Defining_Identifier => B,
3975 Object_Definition => New_Reference_To (Arr, Loc))),
3976
3977 Handled_Statement_Sequence =>
3978 Make_Handled_Sequence_Of_Statements (Loc,
3979 Statements => New_List (
3980 Loop_Statement,
3981 Make_Return_Statement (Loc,
3982 Expression =>
3983 Make_Identifier (Loc, Chars (B)))))));
3984
3985 Rewrite (N,
3986 Make_Function_Call (Loc,
3987 Name => New_Reference_To (Func_Name, Loc),
3988 Parameter_Associations => New_List (Opnd)));
3989
3990 Analyze_And_Resolve (N, Typ);
3991 end Expand_N_Op_Not;
3992
3993 --------------------
3994 -- Expand_N_Op_Or --
3995 --------------------
3996
3997 procedure Expand_N_Op_Or (N : Node_Id) is
3998 Typ : constant Entity_Id := Etype (N);
3999
4000 begin
4001 Binary_Op_Validity_Checks (N);
4002
4003 if Is_Array_Type (Etype (N)) then
4004 Expand_Boolean_Operator (N);
4005
4006 elsif Is_Boolean_Type (Etype (N)) then
4007 Adjust_Condition (Left_Opnd (N));
4008 Adjust_Condition (Right_Opnd (N));
4009 Set_Etype (N, Standard_Boolean);
4010 Adjust_Result_Type (N, Typ);
4011 end if;
4012 end Expand_N_Op_Or;
4013
4014 ----------------------
4015 -- Expand_N_Op_Plus --
4016 ----------------------
4017
4018 procedure Expand_N_Op_Plus (N : Node_Id) is
4019 begin
4020 Unary_Op_Validity_Checks (N);
4021 end Expand_N_Op_Plus;
4022
4023 ---------------------
4024 -- Expand_N_Op_Rem --
4025 ---------------------
4026
4027 procedure Expand_N_Op_Rem (N : Node_Id) is
4028 Loc : constant Source_Ptr := Sloc (N);
4029
4030 Left : constant Node_Id := Left_Opnd (N);
4031 Right : constant Node_Id := Right_Opnd (N);
4032
4033 LLB : Uint;
4034 Llo : Uint;
4035 Lhi : Uint;
4036 LOK : Boolean;
4037 Rlo : Uint;
4038 Rhi : Uint;
4039 ROK : Boolean;
4040 Typ : Entity_Id;
4041
4042 begin
4043 Binary_Op_Validity_Checks (N);
4044
4045 if Is_Integer_Type (Etype (N)) then
4046 Apply_Divide_Check (N);
4047 end if;
4048
4049 -- Deal with annoying case of largest negative number remainder
4050 -- minus one. Gigi does not handle this case correctly, because
4051 -- it generates a divide instruction which may trap in this case.
4052
4053 -- In fact the check is quite easy, if the right operand is -1,
4054 -- then the remainder is always 0, and we can just ignore the
4055 -- left operand completely in this case.
4056
4057 Determine_Range (Right, ROK, Rlo, Rhi);
4058 Determine_Range (Left, LOK, Llo, Lhi);
4059 LLB := Expr_Value (Type_Low_Bound (Base_Type (Etype (Left))));
4060 Typ := Etype (N);
4061
4062 if ((not ROK) or else (Rlo <= (-1) and then (-1) <= Rhi))
4063 and then
4064 ((not LOK) or else (Llo = LLB))
4065 then
4066 Rewrite (N,
4067 Make_Conditional_Expression (Loc,
4068 Expressions => New_List (
4069 Make_Op_Eq (Loc,
4070 Left_Opnd => Duplicate_Subexpr (Right),
4071 Right_Opnd =>
4072 Make_Integer_Literal (Loc, -1)),
4073
4074 Make_Integer_Literal (Loc, Uint_0),
4075
4076 Relocate_Node (N))));
4077
4078 Set_Analyzed (Next (Next (First (Expressions (N)))));
4079 Analyze_And_Resolve (N, Typ);
4080 end if;
4081 end Expand_N_Op_Rem;
4082
4083 -----------------------------
4084 -- Expand_N_Op_Rotate_Left --
4085 -----------------------------
4086
4087 procedure Expand_N_Op_Rotate_Left (N : Node_Id) is
4088 begin
4089 Binary_Op_Validity_Checks (N);
4090 end Expand_N_Op_Rotate_Left;
4091
4092 ------------------------------
4093 -- Expand_N_Op_Rotate_Right --
4094 ------------------------------
4095
4096 procedure Expand_N_Op_Rotate_Right (N : Node_Id) is
4097 begin
4098 Binary_Op_Validity_Checks (N);
4099 end Expand_N_Op_Rotate_Right;
4100
4101 ----------------------------
4102 -- Expand_N_Op_Shift_Left --
4103 ----------------------------
4104
4105 procedure Expand_N_Op_Shift_Left (N : Node_Id) is
4106 begin
4107 Binary_Op_Validity_Checks (N);
4108 end Expand_N_Op_Shift_Left;
4109
4110 -----------------------------
4111 -- Expand_N_Op_Shift_Right --
4112 -----------------------------
4113
4114 procedure Expand_N_Op_Shift_Right (N : Node_Id) is
4115 begin
4116 Binary_Op_Validity_Checks (N);
4117 end Expand_N_Op_Shift_Right;
4118
4119 ----------------------------------------
4120 -- Expand_N_Op_Shift_Right_Arithmetic --
4121 ----------------------------------------
4122
4123 procedure Expand_N_Op_Shift_Right_Arithmetic (N : Node_Id) is
4124 begin
4125 Binary_Op_Validity_Checks (N);
4126 end Expand_N_Op_Shift_Right_Arithmetic;
4127
4128 --------------------------
4129 -- Expand_N_Op_Subtract --
4130 --------------------------
4131
4132 procedure Expand_N_Op_Subtract (N : Node_Id) is
4133 Typ : constant Entity_Id := Etype (N);
4134
4135 begin
4136 Binary_Op_Validity_Checks (N);
4137
4138 -- N - 0 = N for integer types
4139
4140 if Is_Integer_Type (Typ)
4141 and then Compile_Time_Known_Value (Right_Opnd (N))
4142 and then Expr_Value (Right_Opnd (N)) = 0
4143 then
4144 Rewrite (N, Left_Opnd (N));
4145 return;
4146 end if;
4147
4148 -- Arithemtic overflow checks for signed integer/fixed point types
4149
4150 if Is_Signed_Integer_Type (Typ)
4151 or else Is_Fixed_Point_Type (Typ)
4152 then
4153 Apply_Arithmetic_Overflow_Check (N);
4154
4155 -- Vax floating-point types case
4156
4157 elsif Vax_Float (Typ) then
4158 Expand_Vax_Arith (N);
4159 end if;
4160 end Expand_N_Op_Subtract;
4161
4162 ---------------------
4163 -- Expand_N_Op_Xor --
4164 ---------------------
4165
4166 procedure Expand_N_Op_Xor (N : Node_Id) is
4167 Typ : constant Entity_Id := Etype (N);
4168
4169 begin
4170 Binary_Op_Validity_Checks (N);
4171
4172 if Is_Array_Type (Etype (N)) then
4173 Expand_Boolean_Operator (N);
4174
4175 elsif Is_Boolean_Type (Etype (N)) then
4176 Adjust_Condition (Left_Opnd (N));
4177 Adjust_Condition (Right_Opnd (N));
4178 Set_Etype (N, Standard_Boolean);
4179 Adjust_Result_Type (N, Typ);
4180 end if;
4181 end Expand_N_Op_Xor;
4182
4183 ----------------------
4184 -- Expand_N_Or_Else --
4185 ----------------------
4186
4187 -- Expand into conditional expression if Actions present, and also
4188 -- deal with optimizing case of arguments being True or False.
4189
4190 procedure Expand_N_Or_Else (N : Node_Id) is
4191 Loc : constant Source_Ptr := Sloc (N);
4192 Typ : constant Entity_Id := Etype (N);
4193 Left : constant Node_Id := Left_Opnd (N);
4194 Right : constant Node_Id := Right_Opnd (N);
4195 Actlist : List_Id;
4196
4197 begin
4198 -- Deal with non-standard booleans
4199
4200 if Is_Boolean_Type (Typ) then
4201 Adjust_Condition (Left);
4202 Adjust_Condition (Right);
4203 Set_Etype (N, Standard_Boolean);
4204
4205 -- Check for cases of left argument is True or False
4206
4207 elsif Nkind (Left) = N_Identifier then
4208
4209 -- If left argument is False, change (False or else Right) to Right.
4210 -- Any actions associated with Right will be executed unconditionally
4211 -- and can thus be inserted into the tree unconditionally.
4212
4213 if Entity (Left) = Standard_False then
4214 if Present (Actions (N)) then
4215 Insert_Actions (N, Actions (N));
4216 end if;
4217
4218 Rewrite (N, Right);
4219 Adjust_Result_Type (N, Typ);
4220 return;
4221
4222 -- If left argument is True, change (True and then Right) to
4223 -- True. In this case we can forget the actions associated with
4224 -- Right, since they will never be executed.
4225
4226 elsif Entity (Left) = Standard_True then
4227 Kill_Dead_Code (Right);
4228 Kill_Dead_Code (Actions (N));
4229 Rewrite (N, New_Occurrence_Of (Standard_True, Loc));
4230 Adjust_Result_Type (N, Typ);
4231 return;
4232 end if;
4233 end if;
4234
4235 -- If Actions are present, we expand
4236
4237 -- left or else right
4238
4239 -- into
4240
4241 -- if left then True else right end
4242
4243 -- with the actions becoming the Else_Actions of the conditional
4244 -- expression. This conditional expression is then further expanded
4245 -- (and will eventually disappear)
4246
4247 if Present (Actions (N)) then
4248 Actlist := Actions (N);
4249 Rewrite (N,
4250 Make_Conditional_Expression (Loc,
4251 Expressions => New_List (
4252 Left,
4253 New_Occurrence_Of (Standard_True, Loc),
4254 Right)));
4255
4256 Set_Else_Actions (N, Actlist);
4257 Analyze_And_Resolve (N, Standard_Boolean);
4258 Adjust_Result_Type (N, Typ);
4259 return;
4260 end if;
4261
4262 -- No actions present, check for cases of right argument True/False
4263
4264 if Nkind (Right) = N_Identifier then
4265
4266 -- Change (Left or else False) to Left. Note that we know there
4267 -- are no actions associated with the True operand, since we
4268 -- just checked for this case above.
4269
4270 if Entity (Right) = Standard_False then
4271 Rewrite (N, Left);
4272
4273 -- Change (Left or else True) to True, making sure to preserve
4274 -- any side effects associated with the Left operand.
4275
4276 elsif Entity (Right) = Standard_True then
4277 Remove_Side_Effects (Left);
4278 Rewrite
4279 (N, New_Occurrence_Of (Standard_True, Loc));
4280 end if;
4281 end if;
4282
4283 Adjust_Result_Type (N, Typ);
4284 end Expand_N_Or_Else;
4285
4286 -----------------------------------
4287 -- Expand_N_Qualified_Expression --
4288 -----------------------------------
4289
4290 procedure Expand_N_Qualified_Expression (N : Node_Id) is
4291 Operand : constant Node_Id := Expression (N);
4292 Target_Type : constant Entity_Id := Entity (Subtype_Mark (N));
4293
4294 begin
4295 Apply_Constraint_Check (Operand, Target_Type, No_Sliding => True);
4296 end Expand_N_Qualified_Expression;
4297
4298 ---------------------------------
4299 -- Expand_N_Selected_Component --
4300 ---------------------------------
4301
4302 -- If the selector is a discriminant of a concurrent object, rewrite the
4303 -- prefix to denote the corresponding record type.
4304
4305 procedure Expand_N_Selected_Component (N : Node_Id) is
4306 Loc : constant Source_Ptr := Sloc (N);
4307 Par : constant Node_Id := Parent (N);
4308 P : constant Node_Id := Prefix (N);
4309 Disc : Entity_Id;
4310 Ptyp : Entity_Id := Underlying_Type (Etype (P));
4311 New_N : Node_Id;
4312
4313 function In_Left_Hand_Side (Comp : Node_Id) return Boolean;
4314 -- Gigi needs a temporary for prefixes that depend on a discriminant,
4315 -- unless the context of an assignment can provide size information.
4316
4317 function In_Left_Hand_Side (Comp : Node_Id) return Boolean is
4318 begin
4319 return
4320 (Nkind (Parent (Comp)) = N_Assignment_Statement
4321 and then Comp = Name (Parent (Comp)))
4322 or else
4323 (Present (Parent (Comp))
4324 and then Nkind (Parent (Comp)) in N_Subexpr
4325 and then In_Left_Hand_Side (Parent (Comp)));
4326 end In_Left_Hand_Side;
4327
4328 begin
4329 if Do_Discriminant_Check (N) then
4330
4331 -- Present the discrminant checking function to the backend,
4332 -- so that it can inline the call to the function.
4333
4334 Add_Inlined_Body
4335 (Discriminant_Checking_Func
4336 (Original_Record_Component (Entity (Selector_Name (N)))));
4337 end if;
4338
4339 -- Insert explicit dereference call for the checked storage pool case
4340
4341 if Is_Access_Type (Ptyp) then
4342 Insert_Dereference_Action (P);
4343 return;
4344 end if;
4345
4346 -- Gigi cannot handle unchecked conversions that are the prefix of
4347 -- a selected component with discriminants. This must be checked
4348 -- during expansion, because during analysis the type of the selector
4349 -- is not known at the point the prefix is analyzed. If the conversion
4350 -- is the target of an assignment, we cannot force the evaluation, of
4351 -- course.
4352
4353 if Nkind (Prefix (N)) = N_Unchecked_Type_Conversion
4354 and then Has_Discriminants (Etype (N))
4355 and then not In_Left_Hand_Side (N)
4356 then
4357 Force_Evaluation (Prefix (N));
4358 end if;
4359
4360 -- Remaining processing applies only if selector is a discriminant
4361
4362 if Ekind (Entity (Selector_Name (N))) = E_Discriminant then
4363
4364 -- If the selector is a discriminant of a constrained record type,
4365 -- rewrite the expression with the actual value of the discriminant.
4366 -- Don't do this on the left hand of an assignment statement (this
4367 -- happens in generated code, and means we really want to set it!)
4368 -- We also only do this optimization for discrete types, and not
4369 -- for access types (access discriminants get us into trouble!)
4370 -- We also do not expand the prefix of an attribute or the
4371 -- operand of an object renaming declaration.
4372
4373 if Is_Record_Type (Ptyp)
4374 and then Has_Discriminants (Ptyp)
4375 and then Is_Constrained (Ptyp)
4376 and then Is_Discrete_Type (Etype (N))
4377 and then (Nkind (Par) /= N_Assignment_Statement
4378 or else Name (Par) /= N)
4379 and then (Nkind (Par) /= N_Attribute_Reference
4380 or else Prefix (Par) /= N)
4381 and then not Is_Renamed_Object (N)
4382 then
4383 declare
4384 D : Entity_Id;
4385 E : Elmt_Id;
4386
4387 begin
4388 D := First_Discriminant (Ptyp);
4389 E := First_Elmt (Discriminant_Constraint (Ptyp));
4390
4391 while Present (E) loop
4392 if D = Entity (Selector_Name (N)) then
4393
4394 -- In the context of a case statement, the expression
4395 -- may have the base type of the discriminant, and we
4396 -- need to preserve the constraint to avoid spurious
4397 -- errors on missing cases.
4398
4399 if Nkind (Parent (N)) = N_Case_Statement
4400 and then Etype (Node (E)) /= Etype (D)
4401 then
4402 Rewrite (N,
4403 Make_Qualified_Expression (Loc,
4404 Subtype_Mark => New_Occurrence_Of (Etype (D), Loc),
4405 Expression => New_Copy (Node (E))));
4406 Analyze (N);
4407 else
4408 Rewrite (N, New_Copy (Node (E)));
4409 end if;
4410
4411 Set_Is_Static_Expression (N, False);
4412 return;
4413 end if;
4414
4415 Next_Elmt (E);
4416 Next_Discriminant (D);
4417 end loop;
4418
4419 -- Note: the above loop should always terminate, but if
4420 -- it does not, we just missed an optimization due to
4421 -- some glitch (perhaps a previous error), so ignore!
4422 end;
4423 end if;
4424
4425 -- The only remaining processing is in the case of a discriminant of
4426 -- a concurrent object, where we rewrite the prefix to denote the
4427 -- corresponding record type. If the type is derived and has renamed
4428 -- discriminants, use corresponding discriminant, which is the one
4429 -- that appears in the corresponding record.
4430
4431 if not Is_Concurrent_Type (Ptyp) then
4432 return;
4433 end if;
4434
4435 Disc := Entity (Selector_Name (N));
4436
4437 if Is_Derived_Type (Ptyp)
4438 and then Present (Corresponding_Discriminant (Disc))
4439 then
4440 Disc := Corresponding_Discriminant (Disc);
4441 end if;
4442
4443 New_N :=
4444 Make_Selected_Component (Loc,
4445 Prefix =>
4446 Unchecked_Convert_To (Corresponding_Record_Type (Ptyp),
4447 New_Copy_Tree (P)),
4448 Selector_Name => Make_Identifier (Loc, Chars (Disc)));
4449
4450 Rewrite (N, New_N);
4451 Analyze (N);
4452 end if;
4453
4454 end Expand_N_Selected_Component;
4455
4456 --------------------
4457 -- Expand_N_Slice --
4458 --------------------
4459
4460 procedure Expand_N_Slice (N : Node_Id) is
4461 Loc : constant Source_Ptr := Sloc (N);
4462 Typ : constant Entity_Id := Etype (N);
4463 Pfx : constant Node_Id := Prefix (N);
4464 Ptp : Entity_Id := Etype (Pfx);
4465 Ent : Entity_Id;
4466 Decl : Node_Id;
4467
4468 begin
4469 -- Special handling for access types
4470
4471 if Is_Access_Type (Ptp) then
4472
4473 -- Check for explicit dereference required for checked pool
4474
4475 Insert_Dereference_Action (Pfx);
4476
4477 -- If we have an access to a packed array type, then put in an
4478 -- explicit dereference. We do this in case the slice must be
4479 -- expanded, and we want to make sure we get an access check.
4480
4481 Ptp := Designated_Type (Ptp);
4482
4483 if Is_Array_Type (Ptp) and then Is_Packed (Ptp) then
4484 Rewrite (Pfx,
4485 Make_Explicit_Dereference (Sloc (N),
4486 Prefix => Relocate_Node (Pfx)));
4487
4488 Analyze_And_Resolve (Pfx, Ptp);
4489
4490 -- The prefix will now carry the Access_Check flag for the back
4491 -- end, remove it from slice itself.
4492
4493 Set_Do_Access_Check (N, False);
4494 end if;
4495 end if;
4496
4497 -- Range checks are potentially also needed for cases involving
4498 -- a slice indexed by a subtype indication, but Do_Range_Check
4499 -- can currently only be set for expressions ???
4500
4501 if not Index_Checks_Suppressed (Ptp)
4502 and then (not Is_Entity_Name (Pfx)
4503 or else not Index_Checks_Suppressed (Entity (Pfx)))
4504 and then Nkind (Discrete_Range (N)) /= N_Subtype_Indication
4505 then
4506 Enable_Range_Check (Discrete_Range (N));
4507 end if;
4508
4509 -- The remaining case to be handled is packed slices. We can leave
4510 -- packed slices as they are in the following situations:
4511
4512 -- 1. Right or left side of an assignment (we can handle this
4513 -- situation correctly in the assignment statement expansion).
4514
4515 -- 2. Prefix of indexed component (the slide is optimized away
4516 -- in this case, see the start of Expand_N_Slice.
4517
4518 -- 3. Object renaming declaration, since we want the name of
4519 -- the slice, not the value.
4520
4521 -- 4. Argument to procedure call, since copy-in/copy-out handling
4522 -- may be required, and this is handled in the expansion of
4523 -- call itself.
4524
4525 -- 5. Prefix of an address attribute (this is an error which
4526 -- is caught elsewhere, and the expansion would intefere
4527 -- with generating the error message).
4528
4529 if Is_Packed (Typ)
4530 and then Nkind (Parent (N)) /= N_Assignment_Statement
4531 and then Nkind (Parent (N)) /= N_Indexed_Component
4532 and then not Is_Renamed_Object (N)
4533 and then Nkind (Parent (N)) /= N_Procedure_Call_Statement
4534 and then (Nkind (Parent (N)) /= N_Attribute_Reference
4535 or else
4536 Attribute_Name (Parent (N)) /= Name_Address)
4537 then
4538 Ent :=
4539 Make_Defining_Identifier (Loc, New_Internal_Name ('T'));
4540
4541 Decl :=
4542 Make_Object_Declaration (Loc,
4543 Defining_Identifier => Ent,
4544 Object_Definition => New_Occurrence_Of (Typ, Loc));
4545
4546 Set_No_Initialization (Decl);
4547
4548 Insert_Actions (N, New_List (
4549 Decl,
4550 Make_Assignment_Statement (Loc,
4551 Name => New_Occurrence_Of (Ent, Loc),
4552 Expression => Relocate_Node (N))));
4553
4554 Rewrite (N, New_Occurrence_Of (Ent, Loc));
4555 Analyze_And_Resolve (N, Typ);
4556 end if;
4557 end Expand_N_Slice;
4558
4559 ------------------------------
4560 -- Expand_N_Type_Conversion --
4561 ------------------------------
4562
4563 procedure Expand_N_Type_Conversion (N : Node_Id) is
4564 Loc : constant Source_Ptr := Sloc (N);
4565 Operand : constant Node_Id := Expression (N);
4566 Target_Type : constant Entity_Id := Etype (N);
4567 Operand_Type : Entity_Id := Etype (Operand);
4568
4569 procedure Handle_Changed_Representation;
4570 -- This is called in the case of record and array type conversions
4571 -- to see if there is a change of representation to be handled.
4572 -- Change of representation is actually handled at the assignment
4573 -- statement level, and what this procedure does is rewrite node N
4574 -- conversion as an assignment to temporary. If there is no change
4575 -- of representation, then the conversion node is unchanged.
4576
4577 procedure Real_Range_Check;
4578 -- Handles generation of range check for real target value
4579
4580 -----------------------------------
4581 -- Handle_Changed_Representation --
4582 -----------------------------------
4583
4584 procedure Handle_Changed_Representation is
4585 Temp : Entity_Id;
4586 Decl : Node_Id;
4587 Odef : Node_Id;
4588 Disc : Node_Id;
4589 N_Ix : Node_Id;
4590 Cons : List_Id;
4591
4592 begin
4593 -- Nothing to do if no change of representation
4594
4595 if Same_Representation (Operand_Type, Target_Type) then
4596 return;
4597
4598 -- The real change of representation work is done by the assignment
4599 -- statement processing. So if this type conversion is appearing as
4600 -- the expression of an assignment statement, nothing needs to be
4601 -- done to the conversion.
4602
4603 elsif Nkind (Parent (N)) = N_Assignment_Statement then
4604 return;
4605
4606 -- Otherwise we need to generate a temporary variable, and do the
4607 -- change of representation assignment into that temporary variable.
4608 -- The conversion is then replaced by a reference to this variable.
4609
4610 else
4611 Cons := No_List;
4612
4613 -- If type is unconstrained we have to add a constraint,
4614 -- copied from the actual value of the left hand side.
4615
4616 if not Is_Constrained (Target_Type) then
4617 if Has_Discriminants (Operand_Type) then
4618 Disc := First_Discriminant (Operand_Type);
4619 Cons := New_List;
4620 while Present (Disc) loop
4621 Append_To (Cons,
4622 Make_Selected_Component (Loc,
4623 Prefix => Duplicate_Subexpr (Operand),
4624 Selector_Name =>
4625 Make_Identifier (Loc, Chars (Disc))));
4626 Next_Discriminant (Disc);
4627 end loop;
4628
4629 elsif Is_Array_Type (Operand_Type) then
4630 N_Ix := First_Index (Target_Type);
4631 Cons := New_List;
4632
4633 for J in 1 .. Number_Dimensions (Operand_Type) loop
4634
4635 -- We convert the bounds explicitly. We use an unchecked
4636 -- conversion because bounds checks are done elsewhere.
4637
4638 Append_To (Cons,
4639 Make_Range (Loc,
4640 Low_Bound =>
4641 Unchecked_Convert_To (Etype (N_Ix),
4642 Make_Attribute_Reference (Loc,
4643 Prefix =>
4644 Duplicate_Subexpr
4645 (Operand, Name_Req => True),
4646 Attribute_Name => Name_First,
4647 Expressions => New_List (
4648 Make_Integer_Literal (Loc, J)))),
4649
4650 High_Bound =>
4651 Unchecked_Convert_To (Etype (N_Ix),
4652 Make_Attribute_Reference (Loc,
4653 Prefix =>
4654 Duplicate_Subexpr
4655 (Operand, Name_Req => True),
4656 Attribute_Name => Name_Last,
4657 Expressions => New_List (
4658 Make_Integer_Literal (Loc, J))))));
4659
4660 Next_Index (N_Ix);
4661 end loop;
4662 end if;
4663 end if;
4664
4665 Odef := New_Occurrence_Of (Target_Type, Loc);
4666
4667 if Present (Cons) then
4668 Odef :=
4669 Make_Subtype_Indication (Loc,
4670 Subtype_Mark => Odef,
4671 Constraint =>
4672 Make_Index_Or_Discriminant_Constraint (Loc,
4673 Constraints => Cons));
4674 end if;
4675
4676 Temp := Make_Defining_Identifier (Loc, New_Internal_Name ('C'));
4677 Decl :=
4678 Make_Object_Declaration (Loc,
4679 Defining_Identifier => Temp,
4680 Object_Definition => Odef);
4681
4682 Set_No_Initialization (Decl, True);
4683
4684 -- Insert required actions. It is essential to suppress checks
4685 -- since we have suppressed default initialization, which means
4686 -- that the variable we create may have no discriminants.
4687
4688 Insert_Actions (N,
4689 New_List (
4690 Decl,
4691 Make_Assignment_Statement (Loc,
4692 Name => New_Occurrence_Of (Temp, Loc),
4693 Expression => Relocate_Node (N))),
4694 Suppress => All_Checks);
4695
4696 Rewrite (N, New_Occurrence_Of (Temp, Loc));
4697 return;
4698 end if;
4699 end Handle_Changed_Representation;
4700
4701 ----------------------
4702 -- Real_Range_Check --
4703 ----------------------
4704
4705 -- Case of conversions to floating-point or fixed-point. If range
4706 -- checks are enabled and the target type has a range constraint,
4707 -- we convert:
4708
4709 -- typ (x)
4710
4711 -- to
4712
4713 -- Tnn : typ'Base := typ'Base (x);
4714 -- [constraint_error when Tnn < typ'First or else Tnn > typ'Last]
4715 -- Tnn
4716
4717 procedure Real_Range_Check is
4718 Btyp : constant Entity_Id := Base_Type (Target_Type);
4719 Lo : constant Node_Id := Type_Low_Bound (Target_Type);
4720 Hi : constant Node_Id := Type_High_Bound (Target_Type);
4721 Conv : Node_Id;
4722 Tnn : Entity_Id;
4723
4724 begin
4725 -- Nothing to do if conversion was rewritten
4726
4727 if Nkind (N) /= N_Type_Conversion then
4728 return;
4729 end if;
4730
4731 -- Nothing to do if range checks suppressed, or target has the
4732 -- same range as the base type (or is the base type).
4733
4734 if Range_Checks_Suppressed (Target_Type)
4735 or else (Lo = Type_Low_Bound (Btyp)
4736 and then
4737 Hi = Type_High_Bound (Btyp))
4738 then
4739 return;
4740 end if;
4741
4742 -- Nothing to do if expression is an entity on which checks
4743 -- have been suppressed.
4744
4745 if Is_Entity_Name (Expression (N))
4746 and then Range_Checks_Suppressed (Entity (Expression (N)))
4747 then
4748 return;
4749 end if;
4750
4751 -- Here we rewrite the conversion as described above
4752
4753 Conv := Relocate_Node (N);
4754 Rewrite
4755 (Subtype_Mark (Conv), New_Occurrence_Of (Btyp, Loc));
4756 Set_Etype (Conv, Btyp);
4757
4758 -- Skip overflow check for integer to float conversions,
4759 -- since it is not needed, and in any case gigi generates
4760 -- incorrect code for such overflow checks ???
4761
4762 if not Is_Integer_Type (Etype (Expression (N))) then
4763 Set_Do_Overflow_Check (Conv, True);
4764 end if;
4765
4766 Tnn :=
4767 Make_Defining_Identifier (Loc,
4768 Chars => New_Internal_Name ('T'));
4769
4770 Insert_Actions (N, New_List (
4771 Make_Object_Declaration (Loc,
4772 Defining_Identifier => Tnn,
4773 Object_Definition => New_Occurrence_Of (Btyp, Loc),
4774 Expression => Conv),
4775
4776 Make_Raise_Constraint_Error (Loc,
07fc65c4
GB
4777 Condition =>
4778 Make_Or_Else (Loc,
4779 Left_Opnd =>
4780 Make_Op_Lt (Loc,
4781 Left_Opnd => New_Occurrence_Of (Tnn, Loc),
4782 Right_Opnd =>
4783 Make_Attribute_Reference (Loc,
4784 Attribute_Name => Name_First,
4785 Prefix =>
4786 New_Occurrence_Of (Target_Type, Loc))),
70482933 4787
07fc65c4
GB
4788 Right_Opnd =>
4789 Make_Op_Gt (Loc,
4790 Left_Opnd => New_Occurrence_Of (Tnn, Loc),
4791 Right_Opnd =>
4792 Make_Attribute_Reference (Loc,
4793 Attribute_Name => Name_Last,
4794 Prefix =>
4795 New_Occurrence_Of (Target_Type, Loc)))),
4796 Reason => CE_Range_Check_Failed)));
70482933
RK
4797
4798 Rewrite (N, New_Occurrence_Of (Tnn, Loc));
4799 Analyze_And_Resolve (N, Btyp);
4800 end Real_Range_Check;
4801
4802 -- Start of processing for Expand_N_Type_Conversion
4803
4804 begin
4805 -- Nothing at all to do if conversion is to the identical type
4806 -- so remove the conversion completely, it is useless.
4807
4808 if Operand_Type = Target_Type then
4809 Rewrite (N, Relocate_Node (Expression (N)));
4810 return;
4811 end if;
4812
4813 -- Deal with Vax floating-point cases
4814
4815 if Vax_Float (Operand_Type) or else Vax_Float (Target_Type) then
4816 Expand_Vax_Conversion (N);
4817 return;
4818 end if;
4819
4820 -- Nothing to do if this is the second argument of read. This
4821 -- is a "backwards" conversion that will be handled by the
4822 -- specialized code in attribute processing.
4823
4824 if Nkind (Parent (N)) = N_Attribute_Reference
4825 and then Attribute_Name (Parent (N)) = Name_Read
4826 and then Next (First (Expressions (Parent (N)))) = N
4827 then
4828 return;
4829 end if;
4830
4831 -- Here if we may need to expand conversion
4832
4833 -- Special case of converting from non-standard boolean type
4834
4835 if Is_Boolean_Type (Operand_Type)
4836 and then (Nonzero_Is_True (Operand_Type))
4837 then
4838 Adjust_Condition (Operand);
4839 Set_Etype (Operand, Standard_Boolean);
4840 Operand_Type := Standard_Boolean;
4841 end if;
4842
4843 -- Case of converting to an access type
4844
4845 if Is_Access_Type (Target_Type) then
4846
4847 -- Apply an accessibility check if the operand is an
4848 -- access parameter. Note that other checks may still
4849 -- need to be applied below (such as tagged type checks).
4850
4851 if Is_Entity_Name (Operand)
4852 and then Ekind (Entity (Operand)) in Formal_Kind
4853 and then Ekind (Etype (Operand)) = E_Anonymous_Access_Type
4854 then
4855 Apply_Accessibility_Check (Operand, Target_Type);
4856
4857 -- If the level of the operand type is statically deeper
4858 -- then the level of the target type, then force Program_Error.
4859 -- Note that this can only occur for cases where the attribute
4860 -- is within the body of an instantiation (otherwise the
4861 -- conversion will already have been rejected as illegal).
4862 -- Note: warnings are issued by the analyzer for the instance
4863 -- cases.
4864
4865 elsif In_Instance_Body
07fc65c4
GB
4866 and then Type_Access_Level (Operand_Type) >
4867 Type_Access_Level (Target_Type)
70482933 4868 then
07fc65c4
GB
4869 Rewrite (N,
4870 Make_Raise_Program_Error (Sloc (N),
4871 Reason => PE_Accessibility_Check_Failed));
70482933
RK
4872 Set_Etype (N, Target_Type);
4873
4874 -- When the operand is a selected access discriminant
4875 -- the check needs to be made against the level of the
4876 -- object denoted by the prefix of the selected name.
4877 -- Force Program_Error for this case as well (this
4878 -- accessibility violation can only happen if within
4879 -- the body of an instantiation).
4880
4881 elsif In_Instance_Body
4882 and then Ekind (Operand_Type) = E_Anonymous_Access_Type
4883 and then Nkind (Operand) = N_Selected_Component
4884 and then Object_Access_Level (Operand) >
4885 Type_Access_Level (Target_Type)
4886 then
07fc65c4
GB
4887 Rewrite (N,
4888 Make_Raise_Program_Error (Sloc (N),
4889 Reason => PE_Accessibility_Check_Failed));
70482933
RK
4890 Set_Etype (N, Target_Type);
4891 end if;
4892 end if;
4893
4894 -- Case of conversions of tagged types and access to tagged types
4895
4896 -- When needed, that is to say when the expression is class-wide,
4897 -- Add runtime a tag check for (strict) downward conversion by using
4898 -- the membership test, generating:
4899
4900 -- [constraint_error when Operand not in Target_Type'Class]
4901
4902 -- or in the access type case
4903
4904 -- [constraint_error
4905 -- when Operand /= null
4906 -- and then Operand.all not in
4907 -- Designated_Type (Target_Type)'Class]
4908
4909 if (Is_Access_Type (Target_Type)
4910 and then Is_Tagged_Type (Designated_Type (Target_Type)))
4911 or else Is_Tagged_Type (Target_Type)
4912 then
4913 -- Do not do any expansion in the access type case if the
4914 -- parent is a renaming, since this is an error situation
4915 -- which will be caught by Sem_Ch8, and the expansion can
4916 -- intefere with this error check.
4917
4918 if Is_Access_Type (Target_Type)
4919 and then Is_Renamed_Object (N)
4920 then
4921 return;
4922 end if;
4923
4924 -- Oherwise, proceed with processing tagged conversion
4925
4926 declare
4927 Actual_Operand_Type : Entity_Id;
4928 Actual_Target_Type : Entity_Id;
4929
4930 Cond : Node_Id;
4931
4932 begin
4933 if Is_Access_Type (Target_Type) then
4934 Actual_Operand_Type := Designated_Type (Operand_Type);
4935 Actual_Target_Type := Designated_Type (Target_Type);
4936
4937 else
4938 Actual_Operand_Type := Operand_Type;
4939 Actual_Target_Type := Target_Type;
4940 end if;
4941
4942 if Is_Class_Wide_Type (Actual_Operand_Type)
4943 and then Root_Type (Actual_Operand_Type) /= Actual_Target_Type
4944 and then Is_Ancestor
4945 (Root_Type (Actual_Operand_Type),
4946 Actual_Target_Type)
4947 and then not Tag_Checks_Suppressed (Actual_Target_Type)
4948 then
4949 -- The conversion is valid for any descendant of the
4950 -- target type
4951
4952 Actual_Target_Type := Class_Wide_Type (Actual_Target_Type);
4953
4954 if Is_Access_Type (Target_Type) then
4955 Cond :=
4956 Make_And_Then (Loc,
4957 Left_Opnd =>
4958 Make_Op_Ne (Loc,
4959 Left_Opnd => Duplicate_Subexpr (Operand),
4960 Right_Opnd => Make_Null (Loc)),
4961
4962 Right_Opnd =>
4963 Make_Not_In (Loc,
4964 Left_Opnd =>
4965 Make_Explicit_Dereference (Loc,
4966 Prefix => Duplicate_Subexpr (Operand)),
4967 Right_Opnd =>
4968 New_Reference_To (Actual_Target_Type, Loc)));
4969
4970 else
4971 Cond :=
4972 Make_Not_In (Loc,
4973 Left_Opnd => Duplicate_Subexpr (Operand),
4974 Right_Opnd =>
4975 New_Reference_To (Actual_Target_Type, Loc));
4976 end if;
4977
4978 Insert_Action (N,
4979 Make_Raise_Constraint_Error (Loc,
07fc65c4
GB
4980 Condition => Cond,
4981 Reason => CE_Tag_Check_Failed));
70482933
RK
4982
4983 Change_Conversion_To_Unchecked (N);
4984 Analyze_And_Resolve (N, Target_Type);
4985 end if;
4986 end;
4987
4988 -- Case of other access type conversions
4989
4990 elsif Is_Access_Type (Target_Type) then
4991 Apply_Constraint_Check (Operand, Target_Type);
4992
4993 -- Case of conversions from a fixed-point type
4994
4995 -- These conversions require special expansion and processing, found
4996 -- in the Exp_Fixd package. We ignore cases where Conversion_OK is
4997 -- set, since from a semantic point of view, these are simple integer
4998 -- conversions, which do not need further processing.
4999
5000 elsif Is_Fixed_Point_Type (Operand_Type)
5001 and then not Conversion_OK (N)
5002 then
5003 -- We should never see universal fixed at this case, since the
5004 -- expansion of the constituent divide or multiply should have
5005 -- eliminated the explicit mention of universal fixed.
5006
5007 pragma Assert (Operand_Type /= Universal_Fixed);
5008
5009 -- Check for special case of the conversion to universal real
5010 -- that occurs as a result of the use of a round attribute.
5011 -- In this case, the real type for the conversion is taken
5012 -- from the target type of the Round attribute and the
5013 -- result must be marked as rounded.
5014
5015 if Target_Type = Universal_Real
5016 and then Nkind (Parent (N)) = N_Attribute_Reference
5017 and then Attribute_Name (Parent (N)) = Name_Round
5018 then
5019 Set_Rounded_Result (N);
5020 Set_Etype (N, Etype (Parent (N)));
5021 end if;
5022
5023 -- Otherwise do correct fixed-conversion, but skip these if the
5024 -- Conversion_OK flag is set, because from a semantic point of
5025 -- view these are simple integer conversions needing no further
5026 -- processing (the backend will simply treat them as integers)
5027
5028 if not Conversion_OK (N) then
5029 if Is_Fixed_Point_Type (Etype (N)) then
5030 Expand_Convert_Fixed_To_Fixed (N);
5031 Real_Range_Check;
5032
5033 elsif Is_Integer_Type (Etype (N)) then
5034 Expand_Convert_Fixed_To_Integer (N);
5035
5036 else
5037 pragma Assert (Is_Floating_Point_Type (Etype (N)));
5038 Expand_Convert_Fixed_To_Float (N);
5039 Real_Range_Check;
5040 end if;
5041 end if;
5042
5043 -- Case of conversions to a fixed-point type
5044
5045 -- These conversions require special expansion and processing, found
5046 -- in the Exp_Fixd package. Again, ignore cases where Conversion_OK
5047 -- is set, since from a semantic point of view, these are simple
5048 -- integer conversions, which do not need further processing.
5049
5050 elsif Is_Fixed_Point_Type (Target_Type)
5051 and then not Conversion_OK (N)
5052 then
5053 if Is_Integer_Type (Operand_Type) then
5054 Expand_Convert_Integer_To_Fixed (N);
5055 Real_Range_Check;
5056 else
5057 pragma Assert (Is_Floating_Point_Type (Operand_Type));
5058 Expand_Convert_Float_To_Fixed (N);
5059 Real_Range_Check;
5060 end if;
5061
5062 -- Case of float-to-integer conversions
5063
5064 -- We also handle float-to-fixed conversions with Conversion_OK set
5065 -- since semantically the fixed-point target is treated as though it
5066 -- were an integer in such cases.
5067
5068 elsif Is_Floating_Point_Type (Operand_Type)
5069 and then
5070 (Is_Integer_Type (Target_Type)
5071 or else
5072 (Is_Fixed_Point_Type (Target_Type) and then Conversion_OK (N)))
5073 then
5074 -- Special processing required if the conversion is the expression
5075 -- of a Truncation attribute reference. In this case we replace:
5076
5077 -- ityp (ftyp'Truncation (x))
5078
5079 -- by
5080
5081 -- ityp (x)
5082
5083 -- with the Float_Truncate flag set. This is clearly more efficient.
5084
5085 if Nkind (Operand) = N_Attribute_Reference
5086 and then Attribute_Name (Operand) = Name_Truncation
5087 then
5088 Rewrite (Operand,
5089 Relocate_Node (First (Expressions (Operand))));
5090 Set_Float_Truncate (N, True);
5091 end if;
5092
5093 -- One more check here, gcc is still not able to do conversions of
5094 -- this type with proper overflow checking, and so gigi is doing an
5095 -- approximation of what is required by doing floating-point compares
5096 -- with the end-point. But that can lose precision in some cases, and
5097 -- give a wrong result. Converting the operand to Long_Long_Float is
5098 -- helpful, but still does not catch all cases with 64-bit integers
5099 -- on targets with only 64-bit floats ???
5100
5101 if Do_Range_Check (Expression (N)) then
5102 Rewrite (Expression (N),
5103 Make_Type_Conversion (Loc,
5104 Subtype_Mark =>
5105 New_Occurrence_Of (Standard_Long_Long_Float, Loc),
5106 Expression =>
5107 Relocate_Node (Expression (N))));
5108
5109 Set_Etype (Expression (N), Standard_Long_Long_Float);
5110 Enable_Range_Check (Expression (N));
5111 Set_Do_Range_Check (Expression (Expression (N)), False);
5112 end if;
5113
5114 -- Case of array conversions
5115
5116 -- Expansion of array conversions, add required length/range checks
5117 -- but only do this if there is no change of representation. For
5118 -- handling of this case, see Handle_Changed_Representation.
5119
5120 elsif Is_Array_Type (Target_Type) then
5121
5122 if Is_Constrained (Target_Type) then
5123 Apply_Length_Check (Operand, Target_Type);
5124 else
5125 Apply_Range_Check (Operand, Target_Type);
5126 end if;
5127
5128 Handle_Changed_Representation;
5129
5130 -- Case of conversions of discriminated types
5131
5132 -- Add required discriminant checks if target is constrained. Again
5133 -- this change is skipped if we have a change of representation.
5134
5135 elsif Has_Discriminants (Target_Type)
5136 and then Is_Constrained (Target_Type)
5137 then
5138 Apply_Discriminant_Check (Operand, Target_Type);
5139 Handle_Changed_Representation;
5140
5141 -- Case of all other record conversions. The only processing required
5142 -- is to check for a change of representation requiring the special
5143 -- assignment processing.
5144
5145 elsif Is_Record_Type (Target_Type) then
5146 Handle_Changed_Representation;
5147
5148 -- Case of conversions of enumeration types
5149
5150 elsif Is_Enumeration_Type (Target_Type) then
5151
5152 -- Special processing is required if there is a change of
5153 -- representation (from enumeration representation clauses)
5154
5155 if not Same_Representation (Target_Type, Operand_Type) then
5156
5157 -- Convert: x(y) to x'val (ytyp'val (y))
5158
5159 Rewrite (N,
5160 Make_Attribute_Reference (Loc,
5161 Prefix => New_Occurrence_Of (Target_Type, Loc),
5162 Attribute_Name => Name_Val,
5163 Expressions => New_List (
5164 Make_Attribute_Reference (Loc,
5165 Prefix => New_Occurrence_Of (Operand_Type, Loc),
5166 Attribute_Name => Name_Pos,
5167 Expressions => New_List (Operand)))));
5168
5169 Analyze_And_Resolve (N, Target_Type);
5170 end if;
5171
5172 -- Case of conversions to floating-point
5173
5174 elsif Is_Floating_Point_Type (Target_Type) then
5175 Real_Range_Check;
5176
5177 -- The remaining cases require no front end processing
5178
5179 else
5180 null;
5181 end if;
5182
5183 -- At this stage, either the conversion node has been transformed
5184 -- into some other equivalent expression, or left as a conversion
5185 -- that can be handled by Gigi. The conversions that Gigi can handle
5186 -- are the following:
5187
5188 -- Conversions with no change of representation or type
5189
5190 -- Numeric conversions involving integer values, floating-point
5191 -- values, and fixed-point values. Fixed-point values are allowed
5192 -- only if Conversion_OK is set, i.e. if the fixed-point values
5193 -- are to be treated as integers.
5194
5195 -- No other conversions should be passed to Gigi.
5196
5197 end Expand_N_Type_Conversion;
5198
5199 -----------------------------------
5200 -- Expand_N_Unchecked_Expression --
5201 -----------------------------------
5202
5203 -- Remove the unchecked expression node from the tree. It's job was simply
5204 -- to make sure that its constituent expression was handled with checks
5205 -- off, and now that that is done, we can remove it from the tree, and
5206 -- indeed must, since gigi does not expect to see these nodes.
5207
5208 procedure Expand_N_Unchecked_Expression (N : Node_Id) is
5209 Exp : constant Node_Id := Expression (N);
5210
5211 begin
5212 Set_Assignment_OK (Exp, Assignment_OK (N) or Assignment_OK (Exp));
5213 Rewrite (N, Exp);
5214 end Expand_N_Unchecked_Expression;
5215
5216 ----------------------------------------
5217 -- Expand_N_Unchecked_Type_Conversion --
5218 ----------------------------------------
5219
5220 -- If this cannot be handled by Gigi and we haven't already made
5221 -- a temporary for it, do it now.
5222
5223 procedure Expand_N_Unchecked_Type_Conversion (N : Node_Id) is
5224 Target_Type : constant Entity_Id := Etype (N);
5225 Operand : constant Node_Id := Expression (N);
5226 Operand_Type : constant Entity_Id := Etype (Operand);
5227
5228 begin
5229 -- If we have a conversion of a compile time known value to a target
5230 -- type and the value is in range of the target type, then we can simply
5231 -- replace the construct by an integer literal of the correct type. We
5232 -- only apply this to integer types being converted. Possibly it may
5233 -- apply in other cases, but it is too much trouble to worry about.
5234
5235 -- Note that we do not do this transformation if the Kill_Range_Check
5236 -- flag is set, since then the value may be outside the expected range.
5237 -- This happens in the Normalize_Scalars case.
5238
5239 if Is_Integer_Type (Target_Type)
5240 and then Is_Integer_Type (Operand_Type)
5241 and then Compile_Time_Known_Value (Operand)
5242 and then not Kill_Range_Check (N)
5243 then
5244 declare
5245 Val : constant Uint := Expr_Value (Operand);
5246
5247 begin
5248 if Compile_Time_Known_Value (Type_Low_Bound (Target_Type))
5249 and then
5250 Compile_Time_Known_Value (Type_High_Bound (Target_Type))
5251 and then
5252 Val >= Expr_Value (Type_Low_Bound (Target_Type))
5253 and then
5254 Val <= Expr_Value (Type_High_Bound (Target_Type))
5255 then
5256 Rewrite (N, Make_Integer_Literal (Sloc (N), Val));
5257 Analyze_And_Resolve (N, Target_Type);
5258 return;
5259 end if;
5260 end;
5261 end if;
5262
5263 -- Nothing to do if conversion is safe
5264
5265 if Safe_Unchecked_Type_Conversion (N) then
5266 return;
5267 end if;
5268
5269 -- Otherwise force evaluation unless Assignment_OK flag is set (this
5270 -- flag indicates ??? -- more comments needed here)
5271
5272 if Assignment_OK (N) then
5273 null;
5274 else
5275 Force_Evaluation (N);
5276 end if;
5277 end Expand_N_Unchecked_Type_Conversion;
5278
5279 ----------------------------
5280 -- Expand_Record_Equality --
5281 ----------------------------
5282
5283 -- For non-variant records, Equality is expanded when needed into:
5284
5285 -- and then Lhs.Discr1 = Rhs.Discr1
5286 -- and then ...
5287 -- and then Lhs.Discrn = Rhs.Discrn
5288 -- and then Lhs.Cmp1 = Rhs.Cmp1
5289 -- and then ...
5290 -- and then Lhs.Cmpn = Rhs.Cmpn
5291
5292 -- The expression is folded by the back-end for adjacent fields. This
5293 -- function is called for tagged record in only one occasion: for imple-
5294 -- menting predefined primitive equality (see Predefined_Primitives_Bodies)
5295 -- otherwise the primitive "=" is used directly.
5296
5297 function Expand_Record_Equality
5298 (Nod : Node_Id;
5299 Typ : Entity_Id;
5300 Lhs : Node_Id;
5301 Rhs : Node_Id;
5302 Bodies : List_Id)
5303 return Node_Id
5304 is
5305 Loc : constant Source_Ptr := Sloc (Nod);
5306
5307 function Suitable_Element (C : Entity_Id) return Entity_Id;
5308 -- Return the first field to compare beginning with C, skipping the
5309 -- inherited components
5310
5311 function Suitable_Element (C : Entity_Id) return Entity_Id is
5312 begin
5313 if No (C) then
5314 return Empty;
5315
5316 elsif Ekind (C) /= E_Discriminant
5317 and then Ekind (C) /= E_Component
5318 then
5319 return Suitable_Element (Next_Entity (C));
5320
5321 elsif Is_Tagged_Type (Typ)
5322 and then C /= Original_Record_Component (C)
5323 then
5324 return Suitable_Element (Next_Entity (C));
5325
5326 elsif Chars (C) = Name_uController
5327 or else Chars (C) = Name_uTag
5328 then
5329 return Suitable_Element (Next_Entity (C));
5330
5331 else
5332 return C;
5333 end if;
5334 end Suitable_Element;
5335
5336 Result : Node_Id;
5337 C : Entity_Id;
5338
5339 First_Time : Boolean := True;
5340
5341 -- Start of processing for Expand_Record_Equality
5342
5343 begin
5344 -- Special processing for the unchecked union case, which will occur
5345 -- only in the context of tagged types and dynamic dispatching, since
5346 -- other cases are handled statically. We return True, but insert a
5347 -- raise Program_Error statement.
5348
5349 if Is_Unchecked_Union (Typ) then
5350
5351 -- If this is a component of an enclosing record, return the Raise
5352 -- statement directly.
5353
5354 if No (Parent (Lhs)) then
07fc65c4
GB
5355 Result :=
5356 Make_Raise_Program_Error (Loc,
5357 Reason => PE_Unchecked_Union_Restriction);
70482933
RK
5358 Set_Etype (Result, Standard_Boolean);
5359 return Result;
5360
5361 else
5362 Insert_Action (Lhs,
07fc65c4
GB
5363 Make_Raise_Program_Error (Loc,
5364 Reason => PE_Unchecked_Union_Restriction));
70482933
RK
5365 return New_Occurrence_Of (Standard_True, Loc);
5366 end if;
5367 end if;
5368
5369 -- Generates the following code: (assuming that Typ has one Discr and
5370 -- component C2 is also a record)
5371
5372 -- True
5373 -- and then Lhs.Discr1 = Rhs.Discr1
5374 -- and then Lhs.C1 = Rhs.C1
5375 -- and then Lhs.C2.C1=Rhs.C2.C1 and then ... Lhs.C2.Cn=Rhs.C2.Cn
5376 -- and then ...
5377 -- and then Lhs.Cmpn = Rhs.Cmpn
5378
5379 Result := New_Reference_To (Standard_True, Loc);
5380 C := Suitable_Element (First_Entity (Typ));
5381
5382 while Present (C) loop
5383
5384 declare
5385 New_Lhs : Node_Id;
5386 New_Rhs : Node_Id;
5387
5388 begin
5389 if First_Time then
5390 First_Time := False;
5391 New_Lhs := Lhs;
5392 New_Rhs := Rhs;
5393
5394 else
5395 New_Lhs := New_Copy_Tree (Lhs);
5396 New_Rhs := New_Copy_Tree (Rhs);
5397 end if;
5398
5399 Result :=
5400 Make_And_Then (Loc,
5401 Left_Opnd => Result,
5402 Right_Opnd =>
5403 Expand_Composite_Equality (Nod, Etype (C),
5404 Lhs =>
5405 Make_Selected_Component (Loc,
5406 Prefix => New_Lhs,
5407 Selector_Name => New_Reference_To (C, Loc)),
5408 Rhs =>
5409 Make_Selected_Component (Loc,
5410 Prefix => New_Rhs,
5411 Selector_Name => New_Reference_To (C, Loc)),
5412 Bodies => Bodies));
5413 end;
5414
5415 C := Suitable_Element (Next_Entity (C));
5416 end loop;
5417
5418 return Result;
5419 end Expand_Record_Equality;
5420
5421 -------------------------------------
5422 -- Fixup_Universal_Fixed_Operation --
5423 -------------------------------------
5424
5425 procedure Fixup_Universal_Fixed_Operation (N : Node_Id) is
5426 Conv : constant Node_Id := Parent (N);
5427
5428 begin
5429 -- We must have a type conversion immediately above us
5430
5431 pragma Assert (Nkind (Conv) = N_Type_Conversion);
5432
5433 -- Normally the type conversion gives our target type. The exception
5434 -- occurs in the case of the Round attribute, where the conversion
5435 -- will be to universal real, and our real type comes from the Round
5436 -- attribute (as well as an indication that we must round the result)
5437
5438 if Nkind (Parent (Conv)) = N_Attribute_Reference
5439 and then Attribute_Name (Parent (Conv)) = Name_Round
5440 then
5441 Set_Etype (N, Etype (Parent (Conv)));
5442 Set_Rounded_Result (N);
5443
5444 -- Normal case where type comes from conversion above us
5445
5446 else
5447 Set_Etype (N, Etype (Conv));
5448 end if;
5449 end Fixup_Universal_Fixed_Operation;
5450
5451 -------------------------------
5452 -- Insert_Dereference_Action --
5453 -------------------------------
5454
5455 procedure Insert_Dereference_Action (N : Node_Id) is
5456 Loc : constant Source_Ptr := Sloc (N);
5457 Typ : constant Entity_Id := Etype (N);
5458 Pool : constant Entity_Id := Associated_Storage_Pool (Typ);
5459
5460 function Is_Checked_Storage_Pool (P : Entity_Id) return Boolean;
5461 -- return true if type of P is derived from Checked_Pool;
5462
5463 function Is_Checked_Storage_Pool (P : Entity_Id) return Boolean is
5464 T : Entity_Id;
5465
5466 begin
5467 if No (P) then
5468 return False;
5469 end if;
5470
5471 T := Etype (P);
5472 while T /= Etype (T) loop
5473 if Is_RTE (T, RE_Checked_Pool) then
5474 return True;
5475 else
5476 T := Etype (T);
5477 end if;
5478 end loop;
5479
5480 return False;
5481 end Is_Checked_Storage_Pool;
5482
5483 -- Start of processing for Insert_Dereference_Action
5484
5485 begin
5486 if not Comes_From_Source (Parent (N)) then
5487 return;
5488
5489 elsif not Is_Checked_Storage_Pool (Pool) then
5490 return;
5491 end if;
5492
5493 Insert_Action (N,
5494 Make_Procedure_Call_Statement (Loc,
5495 Name => New_Reference_To (
5496 Find_Prim_Op (Etype (Pool), Name_Dereference), Loc),
5497
5498 Parameter_Associations => New_List (
5499
5500 -- Pool
5501
5502 New_Reference_To (Pool, Loc),
5503
5504 -- Storage_Address
5505
5506 Make_Attribute_Reference (Loc,
5507 Prefix =>
5508 Make_Explicit_Dereference (Loc, Duplicate_Subexpr (N)),
5509 Attribute_Name => Name_Address),
5510
5511 -- Size_In_Storage_Elements
5512
5513 Make_Op_Divide (Loc,
5514 Left_Opnd =>
5515 Make_Attribute_Reference (Loc,
5516 Prefix =>
5517 Make_Explicit_Dereference (Loc, Duplicate_Subexpr (N)),
5518 Attribute_Name => Name_Size),
5519 Right_Opnd =>
5520 Make_Integer_Literal (Loc, System_Storage_Unit)),
5521
5522 -- Alignment
5523
5524 Make_Attribute_Reference (Loc,
5525 Prefix =>
5526 Make_Explicit_Dereference (Loc, Duplicate_Subexpr (N)),
5527 Attribute_Name => Name_Alignment))));
5528
5529 end Insert_Dereference_Action;
5530
5531 ------------------------------
5532 -- Make_Array_Comparison_Op --
5533 ------------------------------
5534
5535 -- This is a hand-coded expansion of the following generic function:
5536
5537 -- generic
5538 -- type elem is (<>);
5539 -- type index is (<>);
5540 -- type a is array (index range <>) of elem;
5541 --
5542 -- function Gnnn (X : a; Y: a) return boolean is
5543 -- J : index := Y'first;
5544 --
5545 -- begin
5546 -- if X'length = 0 then
5547 -- return false;
5548 --
5549 -- elsif Y'length = 0 then
5550 -- return true;
5551 --
5552 -- else
5553 -- for I in X'range loop
5554 -- if X (I) = Y (J) then
5555 -- if J = Y'last then
5556 -- exit;
5557 -- else
5558 -- J := index'succ (J);
5559 -- end if;
5560 --
5561 -- else
5562 -- return X (I) > Y (J);
5563 -- end if;
5564 -- end loop;
5565 --
5566 -- return X'length > Y'length;
5567 -- end if;
5568 -- end Gnnn;
5569
5570 -- Note that since we are essentially doing this expansion by hand, we
5571 -- do not need to generate an actual or formal generic part, just the
5572 -- instantiated function itself.
5573
5574 function Make_Array_Comparison_Op
5575 (Typ : Entity_Id;
5576 Nod : Node_Id)
5577 return Node_Id
5578 is
5579 Loc : constant Source_Ptr := Sloc (Nod);
5580
5581 X : constant Entity_Id := Make_Defining_Identifier (Loc, Name_uX);
5582 Y : constant Entity_Id := Make_Defining_Identifier (Loc, Name_uY);
5583 I : constant Entity_Id := Make_Defining_Identifier (Loc, Name_uI);
5584 J : constant Entity_Id := Make_Defining_Identifier (Loc, Name_uJ);
5585
5586 Index : constant Entity_Id := Base_Type (Etype (First_Index (Typ)));
5587
5588 Loop_Statement : Node_Id;
5589 Loop_Body : Node_Id;
5590 If_Stat : Node_Id;
5591 Inner_If : Node_Id;
5592 Final_Expr : Node_Id;
5593 Func_Body : Node_Id;
5594 Func_Name : Entity_Id;
5595 Formals : List_Id;
5596 Length1 : Node_Id;
5597 Length2 : Node_Id;
5598
5599 begin
5600 -- if J = Y'last then
5601 -- exit;
5602 -- else
5603 -- J := index'succ (J);
5604 -- end if;
5605
5606 Inner_If :=
5607 Make_Implicit_If_Statement (Nod,
5608 Condition =>
5609 Make_Op_Eq (Loc,
5610 Left_Opnd => New_Reference_To (J, Loc),
5611 Right_Opnd =>
5612 Make_Attribute_Reference (Loc,
5613 Prefix => New_Reference_To (Y, Loc),
5614 Attribute_Name => Name_Last)),
5615
5616 Then_Statements => New_List (
5617 Make_Exit_Statement (Loc)),
5618
5619 Else_Statements =>
5620 New_List (
5621 Make_Assignment_Statement (Loc,
5622 Name => New_Reference_To (J, Loc),
5623 Expression =>
5624 Make_Attribute_Reference (Loc,
5625 Prefix => New_Reference_To (Index, Loc),
5626 Attribute_Name => Name_Succ,
5627 Expressions => New_List (New_Reference_To (J, Loc))))));
5628
5629 -- if X (I) = Y (J) then
5630 -- if ... end if;
5631 -- else
5632 -- return X (I) > Y (J);
5633 -- end if;
5634
5635 Loop_Body :=
5636 Make_Implicit_If_Statement (Nod,
5637 Condition =>
5638 Make_Op_Eq (Loc,
5639 Left_Opnd =>
5640 Make_Indexed_Component (Loc,
5641 Prefix => New_Reference_To (X, Loc),
5642 Expressions => New_List (New_Reference_To (I, Loc))),
5643
5644 Right_Opnd =>
5645 Make_Indexed_Component (Loc,
5646 Prefix => New_Reference_To (Y, Loc),
5647 Expressions => New_List (New_Reference_To (J, Loc)))),
5648
5649 Then_Statements => New_List (Inner_If),
5650
5651 Else_Statements => New_List (
5652 Make_Return_Statement (Loc,
5653 Expression =>
5654 Make_Op_Gt (Loc,
5655 Left_Opnd =>
5656 Make_Indexed_Component (Loc,
5657 Prefix => New_Reference_To (X, Loc),
5658 Expressions => New_List (New_Reference_To (I, Loc))),
5659
5660 Right_Opnd =>
5661 Make_Indexed_Component (Loc,
5662 Prefix => New_Reference_To (Y, Loc),
5663 Expressions => New_List (
5664 New_Reference_To (J, Loc)))))));
5665
5666 -- for I in X'range loop
5667 -- if ... end if;
5668 -- end loop;
5669
5670 Loop_Statement :=
5671 Make_Implicit_Loop_Statement (Nod,
5672 Identifier => Empty,
5673
5674 Iteration_Scheme =>
5675 Make_Iteration_Scheme (Loc,
5676 Loop_Parameter_Specification =>
5677 Make_Loop_Parameter_Specification (Loc,
5678 Defining_Identifier => I,
5679 Discrete_Subtype_Definition =>
5680 Make_Attribute_Reference (Loc,
5681 Prefix => New_Reference_To (X, Loc),
5682 Attribute_Name => Name_Range))),
5683
5684 Statements => New_List (Loop_Body));
5685
5686 -- if X'length = 0 then
5687 -- return false;
5688 -- elsif Y'length = 0 then
5689 -- return true;
5690 -- else
5691 -- for ... loop ... end loop;
5692 -- return X'length > Y'length;
5693 -- end if;
5694
5695 Length1 :=
5696 Make_Attribute_Reference (Loc,
5697 Prefix => New_Reference_To (X, Loc),
5698 Attribute_Name => Name_Length);
5699
5700 Length2 :=
5701 Make_Attribute_Reference (Loc,
5702 Prefix => New_Reference_To (Y, Loc),
5703 Attribute_Name => Name_Length);
5704
5705 Final_Expr :=
5706 Make_Op_Gt (Loc,
5707 Left_Opnd => Length1,
5708 Right_Opnd => Length2);
5709
5710 If_Stat :=
5711 Make_Implicit_If_Statement (Nod,
5712 Condition =>
5713 Make_Op_Eq (Loc,
5714 Left_Opnd =>
5715 Make_Attribute_Reference (Loc,
5716 Prefix => New_Reference_To (X, Loc),
5717 Attribute_Name => Name_Length),
5718 Right_Opnd =>
5719 Make_Integer_Literal (Loc, 0)),
5720
5721 Then_Statements =>
5722 New_List (
5723 Make_Return_Statement (Loc,
5724 Expression => New_Reference_To (Standard_False, Loc))),
5725
5726 Elsif_Parts => New_List (
5727 Make_Elsif_Part (Loc,
5728 Condition =>
5729 Make_Op_Eq (Loc,
5730 Left_Opnd =>
5731 Make_Attribute_Reference (Loc,
5732 Prefix => New_Reference_To (Y, Loc),
5733 Attribute_Name => Name_Length),
5734 Right_Opnd =>
5735 Make_Integer_Literal (Loc, 0)),
5736
5737 Then_Statements =>
5738 New_List (
5739 Make_Return_Statement (Loc,
5740 Expression => New_Reference_To (Standard_True, Loc))))),
5741
5742 Else_Statements => New_List (
5743 Loop_Statement,
5744 Make_Return_Statement (Loc,
5745 Expression => Final_Expr)));
5746
5747 -- (X : a; Y: a)
5748
5749 Formals := New_List (
5750 Make_Parameter_Specification (Loc,
5751 Defining_Identifier => X,
5752 Parameter_Type => New_Reference_To (Typ, Loc)),
5753
5754 Make_Parameter_Specification (Loc,
5755 Defining_Identifier => Y,
5756 Parameter_Type => New_Reference_To (Typ, Loc)));
5757
5758 -- function Gnnn (...) return boolean is
5759 -- J : index := Y'first;
5760 -- begin
5761 -- if ... end if;
5762 -- end Gnnn;
5763
5764 Func_Name := Make_Defining_Identifier (Loc, New_Internal_Name ('G'));
5765
5766 Func_Body :=
5767 Make_Subprogram_Body (Loc,
5768 Specification =>
5769 Make_Function_Specification (Loc,
5770 Defining_Unit_Name => Func_Name,
5771 Parameter_Specifications => Formals,
5772 Subtype_Mark => New_Reference_To (Standard_Boolean, Loc)),
5773
5774 Declarations => New_List (
5775 Make_Object_Declaration (Loc,
5776 Defining_Identifier => J,
5777 Object_Definition => New_Reference_To (Index, Loc),
5778 Expression =>
5779 Make_Attribute_Reference (Loc,
5780 Prefix => New_Reference_To (Y, Loc),
5781 Attribute_Name => Name_First))),
5782
5783 Handled_Statement_Sequence =>
5784 Make_Handled_Sequence_Of_Statements (Loc,
5785 Statements => New_List (If_Stat)));
5786
5787 return Func_Body;
5788
5789 end Make_Array_Comparison_Op;
5790
5791 ---------------------------
5792 -- Make_Boolean_Array_Op --
5793 ---------------------------
5794
5795 -- For logical operations on boolean arrays, expand in line the
5796 -- following, replacing 'and' with 'or' or 'xor' where needed:
5797
5798 -- function Annn (A : typ; B: typ) return typ is
5799 -- C : typ;
5800 -- begin
5801 -- for J in A'range loop
5802 -- C (J) := A (J) op B (J);
5803 -- end loop;
5804 -- return C;
5805 -- end Annn;
5806
5807 -- Here typ is the boolean array type
5808
5809 function Make_Boolean_Array_Op
5810 (Typ : Entity_Id;
5811 N : Node_Id)
5812 return Node_Id
5813 is
5814 Loc : constant Source_Ptr := Sloc (N);
5815
5816 A : constant Entity_Id := Make_Defining_Identifier (Loc, Name_uA);
5817 B : constant Entity_Id := Make_Defining_Identifier (Loc, Name_uB);
5818 C : constant Entity_Id := Make_Defining_Identifier (Loc, Name_uC);
5819 J : constant Entity_Id := Make_Defining_Identifier (Loc, Name_uJ);
5820
5821 A_J : Node_Id;
5822 B_J : Node_Id;
5823 C_J : Node_Id;
5824 Op : Node_Id;
5825
5826 Formals : List_Id;
5827 Func_Name : Entity_Id;
5828 Func_Body : Node_Id;
5829 Loop_Statement : Node_Id;
5830
5831 begin
5832 A_J :=
5833 Make_Indexed_Component (Loc,
5834 Prefix => New_Reference_To (A, Loc),
5835 Expressions => New_List (New_Reference_To (J, Loc)));
5836
5837 B_J :=
5838 Make_Indexed_Component (Loc,
5839 Prefix => New_Reference_To (B, Loc),
5840 Expressions => New_List (New_Reference_To (J, Loc)));
5841
5842 C_J :=
5843 Make_Indexed_Component (Loc,
5844 Prefix => New_Reference_To (C, Loc),
5845 Expressions => New_List (New_Reference_To (J, Loc)));
5846
5847 if Nkind (N) = N_Op_And then
5848 Op :=
5849 Make_Op_And (Loc,
5850 Left_Opnd => A_J,
5851 Right_Opnd => B_J);
5852
5853 elsif Nkind (N) = N_Op_Or then
5854 Op :=
5855 Make_Op_Or (Loc,
5856 Left_Opnd => A_J,
5857 Right_Opnd => B_J);
5858
5859 else
5860 Op :=
5861 Make_Op_Xor (Loc,
5862 Left_Opnd => A_J,
5863 Right_Opnd => B_J);
5864 end if;
5865
5866 Loop_Statement :=
5867 Make_Implicit_Loop_Statement (N,
5868 Identifier => Empty,
5869
5870 Iteration_Scheme =>
5871 Make_Iteration_Scheme (Loc,
5872 Loop_Parameter_Specification =>
5873 Make_Loop_Parameter_Specification (Loc,
5874 Defining_Identifier => J,
5875 Discrete_Subtype_Definition =>
5876 Make_Attribute_Reference (Loc,
5877 Prefix => New_Reference_To (A, Loc),
5878 Attribute_Name => Name_Range))),
5879
5880 Statements => New_List (
5881 Make_Assignment_Statement (Loc,
5882 Name => C_J,
5883 Expression => Op)));
5884
5885 Formals := New_List (
5886 Make_Parameter_Specification (Loc,
5887 Defining_Identifier => A,
5888 Parameter_Type => New_Reference_To (Typ, Loc)),
5889
5890 Make_Parameter_Specification (Loc,
5891 Defining_Identifier => B,
5892 Parameter_Type => New_Reference_To (Typ, Loc)));
5893
5894 Func_Name :=
5895 Make_Defining_Identifier (Loc, New_Internal_Name ('A'));
5896 Set_Is_Inlined (Func_Name);
5897
5898 Func_Body :=
5899 Make_Subprogram_Body (Loc,
5900 Specification =>
5901 Make_Function_Specification (Loc,
5902 Defining_Unit_Name => Func_Name,
5903 Parameter_Specifications => Formals,
5904 Subtype_Mark => New_Reference_To (Typ, Loc)),
5905
5906 Declarations => New_List (
5907 Make_Object_Declaration (Loc,
5908 Defining_Identifier => C,
5909 Object_Definition => New_Reference_To (Typ, Loc))),
5910
5911 Handled_Statement_Sequence =>
5912 Make_Handled_Sequence_Of_Statements (Loc,
5913 Statements => New_List (
5914 Loop_Statement,
5915 Make_Return_Statement (Loc,
5916 Expression => New_Reference_To (C, Loc)))));
5917
5918 return Func_Body;
5919 end Make_Boolean_Array_Op;
5920
5921 ------------------------
5922 -- Rewrite_Comparison --
5923 ------------------------
5924
5925 procedure Rewrite_Comparison (N : Node_Id) is
5926 Typ : constant Entity_Id := Etype (N);
5927 Op1 : constant Node_Id := Left_Opnd (N);
5928 Op2 : constant Node_Id := Right_Opnd (N);
5929
5930 Res : constant Compare_Result := Compile_Time_Compare (Op1, Op2);
5931 -- Res indicates if compare outcome can be determined at compile time
5932
5933 True_Result : Boolean;
5934 False_Result : Boolean;
5935
5936 begin
5937 case N_Op_Compare (Nkind (N)) is
5938 when N_Op_Eq =>
5939 True_Result := Res = EQ;
5940 False_Result := Res = LT or else Res = GT or else Res = NE;
5941
5942 when N_Op_Ge =>
5943 True_Result := Res in Compare_GE;
5944 False_Result := Res = LT;
5945
5946 when N_Op_Gt =>
5947 True_Result := Res = GT;
5948 False_Result := Res in Compare_LE;
5949
5950 when N_Op_Lt =>
5951 True_Result := Res = LT;
5952 False_Result := Res in Compare_GE;
5953
5954 when N_Op_Le =>
5955 True_Result := Res in Compare_LE;
5956 False_Result := Res = GT;
5957
5958 when N_Op_Ne =>
5959 True_Result := Res = NE;
5960 False_Result := Res = LT or else Res = GT or else Res = EQ;
5961 end case;
5962
5963 if True_Result then
5964 Rewrite (N,
5965 Convert_To (Typ, New_Occurrence_Of (Standard_True, Sloc (N))));
5966 Analyze_And_Resolve (N, Typ);
07fc65c4 5967 Warn_On_Known_Condition (N);
70482933
RK
5968
5969 elsif False_Result then
5970 Rewrite (N,
5971 Convert_To (Typ, New_Occurrence_Of (Standard_False, Sloc (N))));
5972 Analyze_And_Resolve (N, Typ);
07fc65c4 5973 Warn_On_Known_Condition (N);
70482933
RK
5974 end if;
5975 end Rewrite_Comparison;
5976
5977 -----------------------
5978 -- Tagged_Membership --
5979 -----------------------
5980
5981 -- There are two different cases to consider depending on whether
5982 -- the right operand is a class-wide type or not. If not we just
5983 -- compare the actual tag of the left expr to the target type tag:
5984 --
5985 -- Left_Expr.Tag = Right_Type'Tag;
5986 --
5987 -- If it is a class-wide type we use the RT function CW_Membership which
5988 -- is usually implemented by looking in the ancestor tables contained in
5989 -- the dispatch table pointed by Left_Expr.Tag for Typ'Tag
5990
5991 function Tagged_Membership (N : Node_Id) return Node_Id is
5992 Left : constant Node_Id := Left_Opnd (N);
5993 Right : constant Node_Id := Right_Opnd (N);
5994 Loc : constant Source_Ptr := Sloc (N);
5995
5996 Left_Type : Entity_Id;
5997 Right_Type : Entity_Id;
5998 Obj_Tag : Node_Id;
5999
6000 begin
6001 Left_Type := Etype (Left);
6002 Right_Type := Etype (Right);
6003
6004 if Is_Class_Wide_Type (Left_Type) then
6005 Left_Type := Root_Type (Left_Type);
6006 end if;
6007
6008 Obj_Tag :=
6009 Make_Selected_Component (Loc,
6010 Prefix => Relocate_Node (Left),
6011 Selector_Name => New_Reference_To (Tag_Component (Left_Type), Loc));
6012
6013 if Is_Class_Wide_Type (Right_Type) then
6014 return
6015 Make_DT_Access_Action (Left_Type,
6016 Action => CW_Membership,
6017 Args => New_List (
6018 Obj_Tag,
6019 New_Reference_To (
6020 Access_Disp_Table (Root_Type (Right_Type)), Loc)));
6021 else
6022 return
6023 Make_Op_Eq (Loc,
6024 Left_Opnd => Obj_Tag,
6025 Right_Opnd =>
6026 New_Reference_To (Access_Disp_Table (Right_Type), Loc));
6027 end if;
6028
6029 end Tagged_Membership;
6030
6031 ------------------------------
6032 -- Unary_Op_Validity_Checks --
6033 ------------------------------
6034
6035 procedure Unary_Op_Validity_Checks (N : Node_Id) is
6036 begin
6037 if Validity_Checks_On and Validity_Check_Operands then
6038 Ensure_Valid (Right_Opnd (N));
6039 end if;
6040 end Unary_Op_Validity_Checks;
6041
6042end Exp_Ch4;
This page took 0.912922 seconds and 5 git commands to generate.