* config/rs6000/aix61.h (TARGET_DEFAULT): Add MASK_PPC_GPOPT,
[official-gcc.git] / gcc / ada / exp_ch4.adb
blob9cc8865b64d1d0a5d051a233f1d44438bf151828
1 ------------------------------------------------------------------------------
2 -- --
3 -- GNAT COMPILER COMPONENTS --
4 -- --
5 -- E X P _ C H 4 --
6 -- --
7 -- B o d y --
8 -- --
9 -- Copyright (C) 1992-2012, Free Software Foundation, Inc. --
10 -- --
11 -- GNAT is free software; you can redistribute it and/or modify it under --
12 -- terms of the GNU General Public License as published by the Free Soft- --
13 -- ware Foundation; either version 3, or (at your option) any later ver- --
14 -- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
15 -- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
16 -- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License --
17 -- for more details. You should have received a copy of the GNU General --
18 -- Public License distributed with GNAT; see file COPYING3. If not, go to --
19 -- http://www.gnu.org/licenses for a complete copy of the license. --
20 -- --
21 -- GNAT was originally developed by the GNAT team at New York University. --
22 -- Extensive contributions were provided by Ada Core Technologies Inc. --
23 -- --
24 ------------------------------------------------------------------------------
26 with Atree; use Atree;
27 with Checks; use Checks;
28 with Debug; use Debug;
29 with Einfo; use Einfo;
30 with Elists; use Elists;
31 with Errout; use Errout;
32 with Exp_Aggr; use Exp_Aggr;
33 with Exp_Atag; use Exp_Atag;
34 with Exp_Ch2; use Exp_Ch2;
35 with Exp_Ch3; use Exp_Ch3;
36 with Exp_Ch6; use Exp_Ch6;
37 with Exp_Ch7; use Exp_Ch7;
38 with Exp_Ch9; use Exp_Ch9;
39 with Exp_Disp; use Exp_Disp;
40 with Exp_Fixd; use Exp_Fixd;
41 with Exp_Intr; use Exp_Intr;
42 with Exp_Pakd; use Exp_Pakd;
43 with Exp_Tss; use Exp_Tss;
44 with Exp_Util; use Exp_Util;
45 with Exp_VFpt; use Exp_VFpt;
46 with Freeze; use Freeze;
47 with Inline; use Inline;
48 with Lib; use Lib;
49 with Namet; use Namet;
50 with Nlists; use Nlists;
51 with Nmake; use Nmake;
52 with Opt; use Opt;
53 with Par_SCO; use Par_SCO;
54 with Restrict; use Restrict;
55 with Rident; use Rident;
56 with Rtsfind; use Rtsfind;
57 with Sem; use Sem;
58 with Sem_Aux; use Sem_Aux;
59 with Sem_Cat; use Sem_Cat;
60 with Sem_Ch3; use Sem_Ch3;
61 with Sem_Ch8; use Sem_Ch8;
62 with Sem_Ch13; use Sem_Ch13;
63 with Sem_Eval; use Sem_Eval;
64 with Sem_Res; use Sem_Res;
65 with Sem_Type; use Sem_Type;
66 with Sem_Util; use Sem_Util;
67 with Sem_Warn; use Sem_Warn;
68 with Sinfo; use Sinfo;
69 with Snames; use Snames;
70 with Stand; use Stand;
71 with SCIL_LL; use SCIL_LL;
72 with Targparm; use Targparm;
73 with Tbuild; use Tbuild;
74 with Ttypes; use Ttypes;
75 with Uintp; use Uintp;
76 with Urealp; use Urealp;
77 with Validsw; use Validsw;
79 package body Exp_Ch4 is
81 -----------------------
82 -- Local Subprograms --
83 -----------------------
85 procedure Binary_Op_Validity_Checks (N : Node_Id);
86 pragma Inline (Binary_Op_Validity_Checks);
87 -- Performs validity checks for a binary operator
89 procedure Build_Boolean_Array_Proc_Call
90 (N : Node_Id;
91 Op1 : Node_Id;
92 Op2 : Node_Id);
93 -- If a boolean array assignment can be done in place, build call to
94 -- corresponding library procedure.
96 function Current_Anonymous_Master return Entity_Id;
97 -- Return the entity of the heterogeneous finalization master belonging to
98 -- the current unit (either function, package or procedure). This master
99 -- services all anonymous access-to-controlled types. If the current unit
100 -- does not have such master, create one.
102 procedure Displace_Allocator_Pointer (N : Node_Id);
103 -- Ada 2005 (AI-251): Subsidiary procedure to Expand_N_Allocator and
104 -- Expand_Allocator_Expression. Allocating class-wide interface objects
105 -- this routine displaces the pointer to the allocated object to reference
106 -- the component referencing the corresponding secondary dispatch table.
108 procedure Expand_Allocator_Expression (N : Node_Id);
109 -- Subsidiary to Expand_N_Allocator, for the case when the expression
110 -- is a qualified expression or an aggregate.
112 procedure Expand_Array_Comparison (N : Node_Id);
113 -- This routine handles expansion of the comparison operators (N_Op_Lt,
114 -- N_Op_Le, N_Op_Gt, N_Op_Ge) when operating on an array type. The basic
115 -- code for these operators is similar, differing only in the details of
116 -- the actual comparison call that is made. Special processing (call a
117 -- run-time routine)
119 function Expand_Array_Equality
120 (Nod : Node_Id;
121 Lhs : Node_Id;
122 Rhs : Node_Id;
123 Bodies : List_Id;
124 Typ : Entity_Id) return Node_Id;
125 -- Expand an array equality into a call to a function implementing this
126 -- equality, and a call to it. Loc is the location for the generated nodes.
127 -- Lhs and Rhs are the array expressions to be compared. Bodies is a list
128 -- on which to attach bodies of local functions that are created in the
129 -- process. It is the responsibility of the caller to insert those bodies
130 -- at the right place. Nod provides the Sloc value for the generated code.
131 -- Normally the types used for the generated equality routine are taken
132 -- from Lhs and Rhs. However, in some situations of generated code, the
133 -- Etype fields of Lhs and Rhs are not set yet. In such cases, Typ supplies
134 -- the type to be used for the formal parameters.
136 procedure Expand_Boolean_Operator (N : Node_Id);
137 -- Common expansion processing for Boolean operators (And, Or, Xor) for the
138 -- case of array type arguments.
140 procedure Expand_Short_Circuit_Operator (N : Node_Id);
141 -- Common expansion processing for short-circuit boolean operators
143 function Expand_Composite_Equality
144 (Nod : Node_Id;
145 Typ : Entity_Id;
146 Lhs : Node_Id;
147 Rhs : Node_Id;
148 Bodies : List_Id) return Node_Id;
149 -- Local recursive function used to expand equality for nested composite
150 -- types. Used by Expand_Record/Array_Equality, Bodies is a list on which
151 -- to attach bodies of local functions that are created in the process.
152 -- It is the responsibility of the caller to insert those bodies at the
153 -- right place. Nod provides the Sloc value for generated code. Lhs and Rhs
154 -- are the left and right sides for the comparison, and Typ is the type of
155 -- the objects to compare.
157 procedure Expand_Concatenate (Cnode : Node_Id; Opnds : List_Id);
158 -- Routine to expand concatenation of a sequence of two or more operands
159 -- (in the list Operands) and replace node Cnode with the result of the
160 -- concatenation. The operands can be of any appropriate type, and can
161 -- include both arrays and singleton elements.
163 procedure Fixup_Universal_Fixed_Operation (N : Node_Id);
164 -- N is a N_Op_Divide or N_Op_Multiply node whose result is universal
165 -- fixed. We do not have such a type at runtime, so the purpose of this
166 -- routine is to find the real type by looking up the tree. We also
167 -- determine if the operation must be rounded.
169 function Has_Inferable_Discriminants (N : Node_Id) return Boolean;
170 -- Ada 2005 (AI-216): A view of an Unchecked_Union object has inferable
171 -- discriminants if it has a constrained nominal type, unless the object
172 -- is a component of an enclosing Unchecked_Union object that is subject
173 -- to a per-object constraint and the enclosing object lacks inferable
174 -- discriminants.
176 -- An expression of an Unchecked_Union type has inferable discriminants
177 -- if it is either a name of an object with inferable discriminants or a
178 -- qualified expression whose subtype mark denotes a constrained subtype.
180 procedure Insert_Dereference_Action (N : Node_Id);
181 -- N is an expression whose type is an access. When the type of the
182 -- associated storage pool is derived from Checked_Pool, generate a
183 -- call to the 'Dereference' primitive operation.
185 function Make_Array_Comparison_Op
186 (Typ : Entity_Id;
187 Nod : Node_Id) return Node_Id;
188 -- Comparisons between arrays are expanded in line. This function produces
189 -- the body of the implementation of (a > b), where a and b are one-
190 -- dimensional arrays of some discrete type. The original node is then
191 -- expanded into the appropriate call to this function. Nod provides the
192 -- Sloc value for the generated code.
194 function Make_Boolean_Array_Op
195 (Typ : Entity_Id;
196 N : Node_Id) return Node_Id;
197 -- Boolean operations on boolean arrays are expanded in line. This function
198 -- produce the body for the node N, which is (a and b), (a or b), or (a xor
199 -- b). It is used only the normal case and not the packed case. The type
200 -- involved, Typ, is the Boolean array type, and the logical operations in
201 -- the body are simple boolean operations. Note that Typ is always a
202 -- constrained type (the caller has ensured this by using
203 -- Convert_To_Actual_Subtype if necessary).
205 procedure Optimize_Length_Comparison (N : Node_Id);
206 -- Given an expression, if it is of the form X'Length op N (or the other
207 -- way round), where N is known at compile time to be 0 or 1, and X is a
208 -- simple entity, and op is a comparison operator, optimizes it into a
209 -- comparison of First and Last.
211 procedure Rewrite_Comparison (N : Node_Id);
212 -- If N is the node for a comparison whose outcome can be determined at
213 -- compile time, then the node N can be rewritten with True or False. If
214 -- the outcome cannot be determined at compile time, the call has no
215 -- effect. If N is a type conversion, then this processing is applied to
216 -- its expression. If N is neither comparison nor a type conversion, the
217 -- call has no effect.
219 procedure Tagged_Membership
220 (N : Node_Id;
221 SCIL_Node : out Node_Id;
222 Result : out Node_Id);
223 -- Construct the expression corresponding to the tagged membership test.
224 -- Deals with a second operand being (or not) a class-wide type.
226 function Safe_In_Place_Array_Op
227 (Lhs : Node_Id;
228 Op1 : Node_Id;
229 Op2 : Node_Id) return Boolean;
230 -- In the context of an assignment, where the right-hand side is a boolean
231 -- operation on arrays, check whether operation can be performed in place.
233 procedure Unary_Op_Validity_Checks (N : Node_Id);
234 pragma Inline (Unary_Op_Validity_Checks);
235 -- Performs validity checks for a unary operator
237 -------------------------------
238 -- Binary_Op_Validity_Checks --
239 -------------------------------
241 procedure Binary_Op_Validity_Checks (N : Node_Id) is
242 begin
243 if Validity_Checks_On and Validity_Check_Operands then
244 Ensure_Valid (Left_Opnd (N));
245 Ensure_Valid (Right_Opnd (N));
246 end if;
247 end Binary_Op_Validity_Checks;
249 ------------------------------------
250 -- Build_Boolean_Array_Proc_Call --
251 ------------------------------------
253 procedure Build_Boolean_Array_Proc_Call
254 (N : Node_Id;
255 Op1 : Node_Id;
256 Op2 : Node_Id)
258 Loc : constant Source_Ptr := Sloc (N);
259 Kind : constant Node_Kind := Nkind (Expression (N));
260 Target : constant Node_Id :=
261 Make_Attribute_Reference (Loc,
262 Prefix => Name (N),
263 Attribute_Name => Name_Address);
265 Arg1 : Node_Id := Op1;
266 Arg2 : Node_Id := Op2;
267 Call_Node : Node_Id;
268 Proc_Name : Entity_Id;
270 begin
271 if Kind = N_Op_Not then
272 if Nkind (Op1) in N_Binary_Op then
274 -- Use negated version of the binary operators
276 if Nkind (Op1) = N_Op_And then
277 Proc_Name := RTE (RE_Vector_Nand);
279 elsif Nkind (Op1) = N_Op_Or then
280 Proc_Name := RTE (RE_Vector_Nor);
282 else pragma Assert (Nkind (Op1) = N_Op_Xor);
283 Proc_Name := RTE (RE_Vector_Xor);
284 end if;
286 Call_Node :=
287 Make_Procedure_Call_Statement (Loc,
288 Name => New_Occurrence_Of (Proc_Name, Loc),
290 Parameter_Associations => New_List (
291 Target,
292 Make_Attribute_Reference (Loc,
293 Prefix => Left_Opnd (Op1),
294 Attribute_Name => Name_Address),
296 Make_Attribute_Reference (Loc,
297 Prefix => Right_Opnd (Op1),
298 Attribute_Name => Name_Address),
300 Make_Attribute_Reference (Loc,
301 Prefix => Left_Opnd (Op1),
302 Attribute_Name => Name_Length)));
304 else
305 Proc_Name := RTE (RE_Vector_Not);
307 Call_Node :=
308 Make_Procedure_Call_Statement (Loc,
309 Name => New_Occurrence_Of (Proc_Name, Loc),
310 Parameter_Associations => New_List (
311 Target,
313 Make_Attribute_Reference (Loc,
314 Prefix => Op1,
315 Attribute_Name => Name_Address),
317 Make_Attribute_Reference (Loc,
318 Prefix => Op1,
319 Attribute_Name => Name_Length)));
320 end if;
322 else
323 -- We use the following equivalences:
325 -- (not X) or (not Y) = not (X and Y) = Nand (X, Y)
326 -- (not X) and (not Y) = not (X or Y) = Nor (X, Y)
327 -- (not X) xor (not Y) = X xor Y
328 -- X xor (not Y) = not (X xor Y) = Nxor (X, Y)
330 if Nkind (Op1) = N_Op_Not then
331 Arg1 := Right_Opnd (Op1);
332 Arg2 := Right_Opnd (Op2);
333 if Kind = N_Op_And then
334 Proc_Name := RTE (RE_Vector_Nor);
335 elsif Kind = N_Op_Or then
336 Proc_Name := RTE (RE_Vector_Nand);
337 else
338 Proc_Name := RTE (RE_Vector_Xor);
339 end if;
341 else
342 if Kind = N_Op_And then
343 Proc_Name := RTE (RE_Vector_And);
344 elsif Kind = N_Op_Or then
345 Proc_Name := RTE (RE_Vector_Or);
346 elsif Nkind (Op2) = N_Op_Not then
347 Proc_Name := RTE (RE_Vector_Nxor);
348 Arg2 := Right_Opnd (Op2);
349 else
350 Proc_Name := RTE (RE_Vector_Xor);
351 end if;
352 end if;
354 Call_Node :=
355 Make_Procedure_Call_Statement (Loc,
356 Name => New_Occurrence_Of (Proc_Name, Loc),
357 Parameter_Associations => New_List (
358 Target,
359 Make_Attribute_Reference (Loc,
360 Prefix => Arg1,
361 Attribute_Name => Name_Address),
362 Make_Attribute_Reference (Loc,
363 Prefix => Arg2,
364 Attribute_Name => Name_Address),
365 Make_Attribute_Reference (Loc,
366 Prefix => Arg1,
367 Attribute_Name => Name_Length)));
368 end if;
370 Rewrite (N, Call_Node);
371 Analyze (N);
373 exception
374 when RE_Not_Available =>
375 return;
376 end Build_Boolean_Array_Proc_Call;
378 ------------------------------
379 -- Current_Anonymous_Master --
380 ------------------------------
382 function Current_Anonymous_Master return Entity_Id is
383 Decls : List_Id;
384 Loc : Source_Ptr;
385 Subp_Body : Node_Id;
386 Unit_Decl : Node_Id;
387 Unit_Id : Entity_Id;
389 begin
390 Unit_Id := Cunit_Entity (Current_Sem_Unit);
392 -- Find the entity of the current unit
394 if Ekind (Unit_Id) = E_Subprogram_Body then
396 -- When processing subprogram bodies, the proper scope is always that
397 -- of the spec.
399 Subp_Body := Unit_Id;
400 while Present (Subp_Body)
401 and then Nkind (Subp_Body) /= N_Subprogram_Body
402 loop
403 Subp_Body := Parent (Subp_Body);
404 end loop;
406 Unit_Id := Corresponding_Spec (Subp_Body);
407 end if;
409 Loc := Sloc (Unit_Id);
410 Unit_Decl := Unit (Cunit (Current_Sem_Unit));
412 -- Find the declarations list of the current unit
414 if Nkind (Unit_Decl) = N_Package_Declaration then
415 Unit_Decl := Specification (Unit_Decl);
416 Decls := Visible_Declarations (Unit_Decl);
418 if No (Decls) then
419 Decls := New_List (Make_Null_Statement (Loc));
420 Set_Visible_Declarations (Unit_Decl, Decls);
422 elsif Is_Empty_List (Decls) then
423 Append_To (Decls, Make_Null_Statement (Loc));
424 end if;
426 else
427 Decls := Declarations (Unit_Decl);
429 if No (Decls) then
430 Decls := New_List (Make_Null_Statement (Loc));
431 Set_Declarations (Unit_Decl, Decls);
433 elsif Is_Empty_List (Decls) then
434 Append_To (Decls, Make_Null_Statement (Loc));
435 end if;
436 end if;
438 -- The current unit has an existing anonymous master, traverse its
439 -- declarations and locate the entity.
441 if Has_Anonymous_Master (Unit_Id) then
442 declare
443 Decl : Node_Id;
444 Fin_Mas_Id : Entity_Id;
446 begin
447 Decl := First (Decls);
448 while Present (Decl) loop
450 -- Look for the first variable in the declarations whole type
451 -- is Finalization_Master.
453 if Nkind (Decl) = N_Object_Declaration then
454 Fin_Mas_Id := Defining_Identifier (Decl);
456 if Ekind (Fin_Mas_Id) = E_Variable
457 and then Etype (Fin_Mas_Id) = RTE (RE_Finalization_Master)
458 then
459 return Fin_Mas_Id;
460 end if;
461 end if;
463 Next (Decl);
464 end loop;
466 -- The master was not found even though the unit was labeled as
467 -- having one.
469 raise Program_Error;
470 end;
472 -- Create a new anonymous master
474 else
475 declare
476 First_Decl : constant Node_Id := First (Decls);
477 Action : Node_Id;
478 Fin_Mas_Id : Entity_Id;
480 begin
481 -- Since the master and its associated initialization is inserted
482 -- at top level, use the scope of the unit when analyzing.
484 Push_Scope (Unit_Id);
486 -- Create the finalization master
488 Fin_Mas_Id :=
489 Make_Defining_Identifier (Loc,
490 Chars => New_External_Name (Chars (Unit_Id), "AM"));
492 -- Generate:
493 -- <Fin_Mas_Id> : Finalization_Master;
495 Action :=
496 Make_Object_Declaration (Loc,
497 Defining_Identifier => Fin_Mas_Id,
498 Object_Definition =>
499 New_Reference_To (RTE (RE_Finalization_Master), Loc));
501 Insert_Before_And_Analyze (First_Decl, Action);
503 -- Mark the unit to prevent the generation of multiple masters
505 Set_Has_Anonymous_Master (Unit_Id);
507 -- Do not set the base pool and mode of operation on .NET/JVM
508 -- since those targets do not support pools and all VM masters
509 -- are heterogeneous by default.
511 if VM_Target = No_VM then
513 -- Generate:
514 -- Set_Base_Pool
515 -- (<Fin_Mas_Id>, Global_Pool_Object'Unrestricted_Access);
517 Action :=
518 Make_Procedure_Call_Statement (Loc,
519 Name =>
520 New_Reference_To (RTE (RE_Set_Base_Pool), Loc),
522 Parameter_Associations => New_List (
523 New_Reference_To (Fin_Mas_Id, Loc),
524 Make_Attribute_Reference (Loc,
525 Prefix =>
526 New_Reference_To (RTE (RE_Global_Pool_Object), Loc),
527 Attribute_Name => Name_Unrestricted_Access)));
529 Insert_Before_And_Analyze (First_Decl, Action);
531 -- Generate:
532 -- Set_Is_Heterogeneous (<Fin_Mas_Id>);
534 Action :=
535 Make_Procedure_Call_Statement (Loc,
536 Name =>
537 New_Reference_To (RTE (RE_Set_Is_Heterogeneous), Loc),
538 Parameter_Associations => New_List (
539 New_Reference_To (Fin_Mas_Id, Loc)));
541 Insert_Before_And_Analyze (First_Decl, Action);
542 end if;
544 -- Restore the original state of the scope stack
546 Pop_Scope;
548 return Fin_Mas_Id;
549 end;
550 end if;
551 end Current_Anonymous_Master;
553 --------------------------------
554 -- Displace_Allocator_Pointer --
555 --------------------------------
557 procedure Displace_Allocator_Pointer (N : Node_Id) is
558 Loc : constant Source_Ptr := Sloc (N);
559 Orig_Node : constant Node_Id := Original_Node (N);
560 Dtyp : Entity_Id;
561 Etyp : Entity_Id;
562 PtrT : Entity_Id;
564 begin
565 -- Do nothing in case of VM targets: the virtual machine will handle
566 -- interfaces directly.
568 if not Tagged_Type_Expansion then
569 return;
570 end if;
572 pragma Assert (Nkind (N) = N_Identifier
573 and then Nkind (Orig_Node) = N_Allocator);
575 PtrT := Etype (Orig_Node);
576 Dtyp := Available_View (Designated_Type (PtrT));
577 Etyp := Etype (Expression (Orig_Node));
579 if Is_Class_Wide_Type (Dtyp)
580 and then Is_Interface (Dtyp)
581 then
582 -- If the type of the allocator expression is not an interface type
583 -- we can generate code to reference the record component containing
584 -- the pointer to the secondary dispatch table.
586 if not Is_Interface (Etyp) then
587 declare
588 Saved_Typ : constant Entity_Id := Etype (Orig_Node);
590 begin
591 -- 1) Get access to the allocated object
593 Rewrite (N,
594 Make_Explicit_Dereference (Loc, Relocate_Node (N)));
595 Set_Etype (N, Etyp);
596 Set_Analyzed (N);
598 -- 2) Add the conversion to displace the pointer to reference
599 -- the secondary dispatch table.
601 Rewrite (N, Convert_To (Dtyp, Relocate_Node (N)));
602 Analyze_And_Resolve (N, Dtyp);
604 -- 3) The 'access to the secondary dispatch table will be used
605 -- as the value returned by the allocator.
607 Rewrite (N,
608 Make_Attribute_Reference (Loc,
609 Prefix => Relocate_Node (N),
610 Attribute_Name => Name_Access));
611 Set_Etype (N, Saved_Typ);
612 Set_Analyzed (N);
613 end;
615 -- If the type of the allocator expression is an interface type we
616 -- generate a run-time call to displace "this" to reference the
617 -- component containing the pointer to the secondary dispatch table
618 -- or else raise Constraint_Error if the actual object does not
619 -- implement the target interface. This case corresponds with the
620 -- following example:
622 -- function Op (Obj : Iface_1'Class) return access Iface_2'Class is
623 -- begin
624 -- return new Iface_2'Class'(Obj);
625 -- end Op;
627 else
628 Rewrite (N,
629 Unchecked_Convert_To (PtrT,
630 Make_Function_Call (Loc,
631 Name => New_Reference_To (RTE (RE_Displace), Loc),
632 Parameter_Associations => New_List (
633 Unchecked_Convert_To (RTE (RE_Address),
634 Relocate_Node (N)),
636 New_Occurrence_Of
637 (Elists.Node
638 (First_Elmt
639 (Access_Disp_Table (Etype (Base_Type (Dtyp))))),
640 Loc)))));
641 Analyze_And_Resolve (N, PtrT);
642 end if;
643 end if;
644 end Displace_Allocator_Pointer;
646 ---------------------------------
647 -- Expand_Allocator_Expression --
648 ---------------------------------
650 procedure Expand_Allocator_Expression (N : Node_Id) is
651 Loc : constant Source_Ptr := Sloc (N);
652 Exp : constant Node_Id := Expression (Expression (N));
653 PtrT : constant Entity_Id := Etype (N);
654 DesigT : constant Entity_Id := Designated_Type (PtrT);
656 procedure Apply_Accessibility_Check
657 (Ref : Node_Id;
658 Built_In_Place : Boolean := False);
659 -- Ada 2005 (AI-344): For an allocator with a class-wide designated
660 -- type, generate an accessibility check to verify that the level of the
661 -- type of the created object is not deeper than the level of the access
662 -- type. If the type of the qualified expression is class-wide, then
663 -- always generate the check (except in the case where it is known to be
664 -- unnecessary, see comment below). Otherwise, only generate the check
665 -- if the level of the qualified expression type is statically deeper
666 -- than the access type.
668 -- Although the static accessibility will generally have been performed
669 -- as a legality check, it won't have been done in cases where the
670 -- allocator appears in generic body, so a run-time check is needed in
671 -- general. One special case is when the access type is declared in the
672 -- same scope as the class-wide allocator, in which case the check can
673 -- never fail, so it need not be generated.
675 -- As an open issue, there seem to be cases where the static level
676 -- associated with the class-wide object's underlying type is not
677 -- sufficient to perform the proper accessibility check, such as for
678 -- allocators in nested subprograms or accept statements initialized by
679 -- class-wide formals when the actual originates outside at a deeper
680 -- static level. The nested subprogram case might require passing
681 -- accessibility levels along with class-wide parameters, and the task
682 -- case seems to be an actual gap in the language rules that needs to
683 -- be fixed by the ARG. ???
685 -------------------------------
686 -- Apply_Accessibility_Check --
687 -------------------------------
689 procedure Apply_Accessibility_Check
690 (Ref : Node_Id;
691 Built_In_Place : Boolean := False)
693 Pool_Id : constant Entity_Id := Associated_Storage_Pool (PtrT);
694 Cond : Node_Id;
695 Free_Stmt : Node_Id;
696 Obj_Ref : Node_Id;
697 Stmts : List_Id;
699 begin
700 if Ada_Version >= Ada_2005
701 and then Is_Class_Wide_Type (DesigT)
702 and then not Scope_Suppress.Suppress (Accessibility_Check)
703 and then
704 (Type_Access_Level (Etype (Exp)) > Type_Access_Level (PtrT)
705 or else
706 (Is_Class_Wide_Type (Etype (Exp))
707 and then Scope (PtrT) /= Current_Scope))
708 and then (Tagged_Type_Expansion or else VM_Target /= No_VM)
709 then
710 -- If the allocator was built in place, Ref is already a reference
711 -- to the access object initialized to the result of the allocator
712 -- (see Exp_Ch6.Make_Build_In_Place_Call_In_Allocator). We call
713 -- Remove_Side_Effects for cases where the build-in-place call may
714 -- still be the prefix of the reference (to avoid generating
715 -- duplicate calls). Otherwise, it is the entity associated with
716 -- the object containing the address of the allocated object.
718 if Built_In_Place then
719 Remove_Side_Effects (Ref);
720 Obj_Ref := New_Copy (Ref);
721 else
722 Obj_Ref := New_Reference_To (Ref, Loc);
723 end if;
725 -- Step 1: Create the object clean up code
727 Stmts := New_List;
729 -- Create an explicit free statement to clean up the allocated
730 -- object in case the accessibility check fails. Generate:
732 -- Free (Obj_Ref);
734 Free_Stmt := Make_Free_Statement (Loc, New_Copy (Obj_Ref));
735 Set_Storage_Pool (Free_Stmt, Pool_Id);
737 Append_To (Stmts, Free_Stmt);
739 -- Finalize the object (if applicable), but wrap the call inside
740 -- a block to ensure that the object would still be deallocated in
741 -- case the finalization fails. Generate:
743 -- begin
744 -- [Deep_]Finalize (Obj_Ref.all);
745 -- exception
746 -- when others =>
747 -- Free (Obj_Ref);
748 -- raise;
749 -- end;
751 if Needs_Finalization (DesigT) then
752 Prepend_To (Stmts,
753 Make_Block_Statement (Loc,
754 Handled_Statement_Sequence =>
755 Make_Handled_Sequence_Of_Statements (Loc,
756 Statements => New_List (
757 Make_Final_Call (
758 Obj_Ref =>
759 Make_Explicit_Dereference (Loc,
760 Prefix => New_Copy (Obj_Ref)),
761 Typ => DesigT)),
763 Exception_Handlers => New_List (
764 Make_Exception_Handler (Loc,
765 Exception_Choices => New_List (
766 Make_Others_Choice (Loc)),
767 Statements => New_List (
768 New_Copy_Tree (Free_Stmt),
769 Make_Raise_Statement (Loc)))))));
770 end if;
772 -- Signal the accessibility failure through a Program_Error
774 Append_To (Stmts,
775 Make_Raise_Program_Error (Loc,
776 Condition => New_Reference_To (Standard_True, Loc),
777 Reason => PE_Accessibility_Check_Failed));
779 -- Step 2: Create the accessibility comparison
781 -- Generate:
782 -- Ref'Tag
784 Obj_Ref :=
785 Make_Attribute_Reference (Loc,
786 Prefix => Obj_Ref,
787 Attribute_Name => Name_Tag);
789 -- For tagged types, determine the accessibility level by looking
790 -- at the type specific data of the dispatch table. Generate:
792 -- Type_Specific_Data (Address (Ref'Tag)).Access_Level
794 if Tagged_Type_Expansion then
795 Cond := Build_Get_Access_Level (Loc, Obj_Ref);
797 -- Use a runtime call to determine the accessibility level when
798 -- compiling on virtual machine targets. Generate:
800 -- Get_Access_Level (Ref'Tag)
802 else
803 Cond :=
804 Make_Function_Call (Loc,
805 Name =>
806 New_Reference_To (RTE (RE_Get_Access_Level), Loc),
807 Parameter_Associations => New_List (Obj_Ref));
808 end if;
810 Cond :=
811 Make_Op_Gt (Loc,
812 Left_Opnd => Cond,
813 Right_Opnd =>
814 Make_Integer_Literal (Loc, Type_Access_Level (PtrT)));
816 -- Due to the complexity and side effects of the check, utilize an
817 -- if statement instead of the regular Program_Error circuitry.
819 Insert_Action (N,
820 Make_If_Statement (Loc,
821 Condition => Cond,
822 Then_Statements => Stmts));
823 end if;
824 end Apply_Accessibility_Check;
826 -- Local variables
828 Aggr_In_Place : constant Boolean := Is_Delayed_Aggregate (Exp);
829 Indic : constant Node_Id := Subtype_Mark (Expression (N));
830 T : constant Entity_Id := Entity (Indic);
831 Node : Node_Id;
832 Tag_Assign : Node_Id;
833 Temp : Entity_Id;
834 Temp_Decl : Node_Id;
836 TagT : Entity_Id := Empty;
837 -- Type used as source for tag assignment
839 TagR : Node_Id := Empty;
840 -- Target reference for tag assignment
842 -- Start of processing for Expand_Allocator_Expression
844 begin
845 -- In the case of an Ada 2012 allocator whose initial value comes from a
846 -- function call, pass "the accessibility level determined by the point
847 -- of call" (AI05-0234) to the function. Conceptually, this belongs in
848 -- Expand_Call but it couldn't be done there (because the Etype of the
849 -- allocator wasn't set then) so we generate the parameter here. See
850 -- the Boolean variable Defer in (a block within) Expand_Call.
852 if Ada_Version >= Ada_2012 and then Nkind (Exp) = N_Function_Call then
853 declare
854 Subp : Entity_Id;
856 begin
857 if Nkind (Name (Exp)) = N_Explicit_Dereference then
858 Subp := Designated_Type (Etype (Prefix (Name (Exp))));
859 else
860 Subp := Entity (Name (Exp));
861 end if;
863 Subp := Ultimate_Alias (Subp);
865 if Present (Extra_Accessibility_Of_Result (Subp)) then
866 Add_Extra_Actual_To_Call
867 (Subprogram_Call => Exp,
868 Extra_Formal => Extra_Accessibility_Of_Result (Subp),
869 Extra_Actual => Dynamic_Accessibility_Level (PtrT));
870 end if;
871 end;
872 end if;
874 -- Would be nice to comment the branches of this very long if ???
876 if Is_Tagged_Type (T) or else Needs_Finalization (T) then
877 if Is_CPP_Constructor_Call (Exp) then
879 -- Generate:
880 -- Pnnn : constant ptr_T := new (T);
881 -- Init (Pnnn.all,...);
883 -- Allocate the object without an expression
885 Node := Relocate_Node (N);
886 Set_Expression (Node, New_Reference_To (Etype (Exp), Loc));
888 -- Avoid its expansion to avoid generating a call to the default
889 -- C++ constructor.
891 Set_Analyzed (Node);
893 Temp := Make_Temporary (Loc, 'P', N);
895 Temp_Decl :=
896 Make_Object_Declaration (Loc,
897 Defining_Identifier => Temp,
898 Constant_Present => True,
899 Object_Definition => New_Reference_To (PtrT, Loc),
900 Expression => Node);
901 Insert_Action (N, Temp_Decl);
903 Apply_Accessibility_Check (Temp);
905 -- Locate the enclosing list and insert the C++ constructor call
907 declare
908 P : Node_Id;
910 begin
911 P := Parent (Node);
912 while not Is_List_Member (P) loop
913 P := Parent (P);
914 end loop;
916 Insert_List_After_And_Analyze (P,
917 Build_Initialization_Call (Loc,
918 Id_Ref =>
919 Make_Explicit_Dereference (Loc,
920 Prefix => New_Reference_To (Temp, Loc)),
921 Typ => Etype (Exp),
922 Constructor_Ref => Exp));
923 end;
925 Rewrite (N, New_Reference_To (Temp, Loc));
926 Analyze_And_Resolve (N, PtrT);
927 return;
928 end if;
930 -- Ada 2005 (AI-318-02): If the initialization expression is a call
931 -- to a build-in-place function, then access to the allocated object
932 -- must be passed to the function. Currently we limit such functions
933 -- to those with constrained limited result subtypes, but eventually
934 -- we plan to expand the allowed forms of functions that are treated
935 -- as build-in-place.
937 if Ada_Version >= Ada_2005
938 and then Is_Build_In_Place_Function_Call (Exp)
939 then
940 Make_Build_In_Place_Call_In_Allocator (N, Exp);
941 Apply_Accessibility_Check (N, Built_In_Place => True);
942 return;
943 end if;
945 -- Actions inserted before:
946 -- Temp : constant ptr_T := new T'(Expression);
947 -- Temp._tag = T'tag; -- when not class-wide
948 -- [Deep_]Adjust (Temp.all);
950 -- We analyze by hand the new internal allocator to avoid any
951 -- recursion and inappropriate call to Initialize
953 -- We don't want to remove side effects when the expression must be
954 -- built in place. In the case of a build-in-place function call,
955 -- that could lead to a duplication of the call, which was already
956 -- substituted for the allocator.
958 if not Aggr_In_Place then
959 Remove_Side_Effects (Exp);
960 end if;
962 Temp := Make_Temporary (Loc, 'P', N);
964 -- For a class wide allocation generate the following code:
966 -- type Equiv_Record is record ... end record;
967 -- implicit subtype CW is <Class_Wide_Subytpe>;
968 -- temp : PtrT := new CW'(CW!(expr));
970 if Is_Class_Wide_Type (T) then
971 Expand_Subtype_From_Expr (Empty, T, Indic, Exp);
973 -- Ada 2005 (AI-251): If the expression is a class-wide interface
974 -- object we generate code to move up "this" to reference the
975 -- base of the object before allocating the new object.
977 -- Note that Exp'Address is recursively expanded into a call
978 -- to Base_Address (Exp.Tag)
980 if Is_Class_Wide_Type (Etype (Exp))
981 and then Is_Interface (Etype (Exp))
982 and then Tagged_Type_Expansion
983 then
984 Set_Expression
985 (Expression (N),
986 Unchecked_Convert_To (Entity (Indic),
987 Make_Explicit_Dereference (Loc,
988 Unchecked_Convert_To (RTE (RE_Tag_Ptr),
989 Make_Attribute_Reference (Loc,
990 Prefix => Exp,
991 Attribute_Name => Name_Address)))));
992 else
993 Set_Expression
994 (Expression (N),
995 Unchecked_Convert_To (Entity (Indic), Exp));
996 end if;
998 Analyze_And_Resolve (Expression (N), Entity (Indic));
999 end if;
1001 -- Processing for allocators returning non-interface types
1003 if not Is_Interface (Directly_Designated_Type (PtrT)) then
1004 if Aggr_In_Place then
1005 Temp_Decl :=
1006 Make_Object_Declaration (Loc,
1007 Defining_Identifier => Temp,
1008 Object_Definition => New_Reference_To (PtrT, Loc),
1009 Expression =>
1010 Make_Allocator (Loc,
1011 Expression =>
1012 New_Reference_To (Etype (Exp), Loc)));
1014 -- Copy the Comes_From_Source flag for the allocator we just
1015 -- built, since logically this allocator is a replacement of
1016 -- the original allocator node. This is for proper handling of
1017 -- restriction No_Implicit_Heap_Allocations.
1019 Set_Comes_From_Source
1020 (Expression (Temp_Decl), Comes_From_Source (N));
1022 Set_No_Initialization (Expression (Temp_Decl));
1023 Insert_Action (N, Temp_Decl);
1025 Build_Allocate_Deallocate_Proc (Temp_Decl, True);
1026 Convert_Aggr_In_Allocator (N, Temp_Decl, Exp);
1028 -- Attach the object to the associated finalization master.
1029 -- This is done manually on .NET/JVM since those compilers do
1030 -- no support pools and can't benefit from internally generated
1031 -- Allocate / Deallocate procedures.
1033 if VM_Target /= No_VM
1034 and then Is_Controlled (DesigT)
1035 and then Present (Finalization_Master (PtrT))
1036 then
1037 Insert_Action (N,
1038 Make_Attach_Call (
1039 Obj_Ref =>
1040 New_Reference_To (Temp, Loc),
1041 Ptr_Typ => PtrT));
1042 end if;
1044 else
1045 Node := Relocate_Node (N);
1046 Set_Analyzed (Node);
1048 Temp_Decl :=
1049 Make_Object_Declaration (Loc,
1050 Defining_Identifier => Temp,
1051 Constant_Present => True,
1052 Object_Definition => New_Reference_To (PtrT, Loc),
1053 Expression => Node);
1055 Insert_Action (N, Temp_Decl);
1056 Build_Allocate_Deallocate_Proc (Temp_Decl, True);
1058 -- Attach the object to the associated finalization master.
1059 -- This is done manually on .NET/JVM since those compilers do
1060 -- no support pools and can't benefit from internally generated
1061 -- Allocate / Deallocate procedures.
1063 if VM_Target /= No_VM
1064 and then Is_Controlled (DesigT)
1065 and then Present (Finalization_Master (PtrT))
1066 then
1067 Insert_Action (N,
1068 Make_Attach_Call (
1069 Obj_Ref =>
1070 New_Reference_To (Temp, Loc),
1071 Ptr_Typ => PtrT));
1072 end if;
1073 end if;
1075 -- Ada 2005 (AI-251): Handle allocators whose designated type is an
1076 -- interface type. In this case we use the type of the qualified
1077 -- expression to allocate the object.
1079 else
1080 declare
1081 Def_Id : constant Entity_Id := Make_Temporary (Loc, 'T');
1082 New_Decl : Node_Id;
1084 begin
1085 New_Decl :=
1086 Make_Full_Type_Declaration (Loc,
1087 Defining_Identifier => Def_Id,
1088 Type_Definition =>
1089 Make_Access_To_Object_Definition (Loc,
1090 All_Present => True,
1091 Null_Exclusion_Present => False,
1092 Constant_Present => False,
1093 Subtype_Indication =>
1094 New_Reference_To (Etype (Exp), Loc)));
1096 Insert_Action (N, New_Decl);
1098 -- Inherit the allocation-related attributes from the original
1099 -- access type.
1101 Set_Finalization_Master (Def_Id, Finalization_Master (PtrT));
1103 Set_Associated_Storage_Pool (Def_Id,
1104 Associated_Storage_Pool (PtrT));
1106 -- Declare the object using the previous type declaration
1108 if Aggr_In_Place then
1109 Temp_Decl :=
1110 Make_Object_Declaration (Loc,
1111 Defining_Identifier => Temp,
1112 Object_Definition => New_Reference_To (Def_Id, Loc),
1113 Expression =>
1114 Make_Allocator (Loc,
1115 New_Reference_To (Etype (Exp), Loc)));
1117 -- Copy the Comes_From_Source flag for the allocator we just
1118 -- built, since logically this allocator is a replacement of
1119 -- the original allocator node. This is for proper handling
1120 -- of restriction No_Implicit_Heap_Allocations.
1122 Set_Comes_From_Source
1123 (Expression (Temp_Decl), Comes_From_Source (N));
1125 Set_No_Initialization (Expression (Temp_Decl));
1126 Insert_Action (N, Temp_Decl);
1128 Build_Allocate_Deallocate_Proc (Temp_Decl, True);
1129 Convert_Aggr_In_Allocator (N, Temp_Decl, Exp);
1131 else
1132 Node := Relocate_Node (N);
1133 Set_Analyzed (Node);
1135 Temp_Decl :=
1136 Make_Object_Declaration (Loc,
1137 Defining_Identifier => Temp,
1138 Constant_Present => True,
1139 Object_Definition => New_Reference_To (Def_Id, Loc),
1140 Expression => Node);
1142 Insert_Action (N, Temp_Decl);
1143 Build_Allocate_Deallocate_Proc (Temp_Decl, True);
1144 end if;
1146 -- Generate an additional object containing the address of the
1147 -- returned object. The type of this second object declaration
1148 -- is the correct type required for the common processing that
1149 -- is still performed by this subprogram. The displacement of
1150 -- this pointer to reference the component associated with the
1151 -- interface type will be done at the end of common processing.
1153 New_Decl :=
1154 Make_Object_Declaration (Loc,
1155 Defining_Identifier => Make_Temporary (Loc, 'P'),
1156 Object_Definition => New_Reference_To (PtrT, Loc),
1157 Expression =>
1158 Unchecked_Convert_To (PtrT,
1159 New_Reference_To (Temp, Loc)));
1161 Insert_Action (N, New_Decl);
1163 Temp_Decl := New_Decl;
1164 Temp := Defining_Identifier (New_Decl);
1165 end;
1166 end if;
1168 Apply_Accessibility_Check (Temp);
1170 -- Generate the tag assignment
1172 -- Suppress the tag assignment when VM_Target because VM tags are
1173 -- represented implicitly in objects.
1175 if not Tagged_Type_Expansion then
1176 null;
1178 -- Ada 2005 (AI-251): Suppress the tag assignment with class-wide
1179 -- interface objects because in this case the tag does not change.
1181 elsif Is_Interface (Directly_Designated_Type (Etype (N))) then
1182 pragma Assert (Is_Class_Wide_Type
1183 (Directly_Designated_Type (Etype (N))));
1184 null;
1186 elsif Is_Tagged_Type (T) and then not Is_Class_Wide_Type (T) then
1187 TagT := T;
1188 TagR := New_Reference_To (Temp, Loc);
1190 elsif Is_Private_Type (T)
1191 and then Is_Tagged_Type (Underlying_Type (T))
1192 then
1193 TagT := Underlying_Type (T);
1194 TagR :=
1195 Unchecked_Convert_To (Underlying_Type (T),
1196 Make_Explicit_Dereference (Loc,
1197 Prefix => New_Reference_To (Temp, Loc)));
1198 end if;
1200 if Present (TagT) then
1201 declare
1202 Full_T : constant Entity_Id := Underlying_Type (TagT);
1203 begin
1204 Tag_Assign :=
1205 Make_Assignment_Statement (Loc,
1206 Name =>
1207 Make_Selected_Component (Loc,
1208 Prefix => TagR,
1209 Selector_Name =>
1210 New_Reference_To (First_Tag_Component (Full_T), Loc)),
1211 Expression =>
1212 Unchecked_Convert_To (RTE (RE_Tag),
1213 New_Reference_To
1214 (Elists.Node
1215 (First_Elmt (Access_Disp_Table (Full_T))), Loc)));
1216 end;
1218 -- The previous assignment has to be done in any case
1220 Set_Assignment_OK (Name (Tag_Assign));
1221 Insert_Action (N, Tag_Assign);
1222 end if;
1224 if Needs_Finalization (DesigT)
1225 and then Needs_Finalization (T)
1226 then
1227 -- Generate an Adjust call if the object will be moved. In Ada
1228 -- 2005, the object may be inherently limited, in which case
1229 -- there is no Adjust procedure, and the object is built in
1230 -- place. In Ada 95, the object can be limited but not
1231 -- inherently limited if this allocator came from a return
1232 -- statement (we're allocating the result on the secondary
1233 -- stack). In that case, the object will be moved, so we _do_
1234 -- want to Adjust.
1236 if not Aggr_In_Place
1237 and then not Is_Immutably_Limited_Type (T)
1238 then
1239 Insert_Action (N,
1240 Make_Adjust_Call (
1241 Obj_Ref =>
1243 -- An unchecked conversion is needed in the classwide
1244 -- case because the designated type can be an ancestor
1245 -- of the subtype mark of the allocator.
1247 Unchecked_Convert_To (T,
1248 Make_Explicit_Dereference (Loc,
1249 Prefix => New_Reference_To (Temp, Loc))),
1250 Typ => T));
1251 end if;
1253 -- Generate:
1254 -- Set_Finalize_Address (<PtrT>FM, <T>FD'Unrestricted_Access);
1256 -- Do not generate this call in the following cases:
1258 -- * .NET/JVM - these targets do not support address arithmetic
1259 -- and unchecked conversion, key elements of Finalize_Address.
1261 -- * Alfa mode - the call is useless and results in unwanted
1262 -- expansion.
1264 -- * CodePeer mode - TSS primitive Finalize_Address is not
1265 -- created in this mode.
1267 if VM_Target = No_VM
1268 and then not Alfa_Mode
1269 and then not CodePeer_Mode
1270 and then Present (Finalization_Master (PtrT))
1271 and then Present (Temp_Decl)
1272 and then Nkind (Expression (Temp_Decl)) = N_Allocator
1273 then
1274 Insert_Action (N,
1275 Make_Set_Finalize_Address_Call
1276 (Loc => Loc,
1277 Typ => T,
1278 Ptr_Typ => PtrT));
1279 end if;
1280 end if;
1282 Rewrite (N, New_Reference_To (Temp, Loc));
1283 Analyze_And_Resolve (N, PtrT);
1285 -- Ada 2005 (AI-251): Displace the pointer to reference the record
1286 -- component containing the secondary dispatch table of the interface
1287 -- type.
1289 if Is_Interface (Directly_Designated_Type (PtrT)) then
1290 Displace_Allocator_Pointer (N);
1291 end if;
1293 elsif Aggr_In_Place then
1294 Temp := Make_Temporary (Loc, 'P', N);
1295 Temp_Decl :=
1296 Make_Object_Declaration (Loc,
1297 Defining_Identifier => Temp,
1298 Object_Definition => New_Reference_To (PtrT, Loc),
1299 Expression =>
1300 Make_Allocator (Loc,
1301 Expression => New_Reference_To (Etype (Exp), Loc)));
1303 -- Copy the Comes_From_Source flag for the allocator we just built,
1304 -- since logically this allocator is a replacement of the original
1305 -- allocator node. This is for proper handling of restriction
1306 -- No_Implicit_Heap_Allocations.
1308 Set_Comes_From_Source
1309 (Expression (Temp_Decl), Comes_From_Source (N));
1311 Set_No_Initialization (Expression (Temp_Decl));
1312 Insert_Action (N, Temp_Decl);
1314 Build_Allocate_Deallocate_Proc (Temp_Decl, True);
1315 Convert_Aggr_In_Allocator (N, Temp_Decl, Exp);
1317 -- Attach the object to the associated finalization master. Thisis
1318 -- done manually on .NET/JVM since those compilers do no support
1319 -- pools and cannot benefit from internally generated Allocate and
1320 -- Deallocate procedures.
1322 if VM_Target /= No_VM
1323 and then Is_Controlled (DesigT)
1324 and then Present (Finalization_Master (PtrT))
1325 then
1326 Insert_Action (N,
1327 Make_Attach_Call
1328 (Obj_Ref => New_Reference_To (Temp, Loc),
1329 Ptr_Typ => PtrT));
1330 end if;
1332 Rewrite (N, New_Reference_To (Temp, Loc));
1333 Analyze_And_Resolve (N, PtrT);
1335 elsif Is_Access_Type (T)
1336 and then Can_Never_Be_Null (T)
1337 then
1338 Install_Null_Excluding_Check (Exp);
1340 elsif Is_Access_Type (DesigT)
1341 and then Nkind (Exp) = N_Allocator
1342 and then Nkind (Expression (Exp)) /= N_Qualified_Expression
1343 then
1344 -- Apply constraint to designated subtype indication
1346 Apply_Constraint_Check (Expression (Exp),
1347 Designated_Type (DesigT),
1348 No_Sliding => True);
1350 if Nkind (Expression (Exp)) = N_Raise_Constraint_Error then
1352 -- Propagate constraint_error to enclosing allocator
1354 Rewrite (Exp, New_Copy (Expression (Exp)));
1355 end if;
1357 else
1358 Build_Allocate_Deallocate_Proc (N, True);
1360 -- If we have:
1361 -- type A is access T1;
1362 -- X : A := new T2'(...);
1363 -- T1 and T2 can be different subtypes, and we might need to check
1364 -- both constraints. First check against the type of the qualified
1365 -- expression.
1367 Apply_Constraint_Check (Exp, T, No_Sliding => True);
1369 if Do_Range_Check (Exp) then
1370 Set_Do_Range_Check (Exp, False);
1371 Generate_Range_Check (Exp, DesigT, CE_Range_Check_Failed);
1372 end if;
1374 -- A check is also needed in cases where the designated subtype is
1375 -- constrained and differs from the subtype given in the qualified
1376 -- expression. Note that the check on the qualified expression does
1377 -- not allow sliding, but this check does (a relaxation from Ada 83).
1379 if Is_Constrained (DesigT)
1380 and then not Subtypes_Statically_Match (T, DesigT)
1381 then
1382 Apply_Constraint_Check
1383 (Exp, DesigT, No_Sliding => False);
1385 if Do_Range_Check (Exp) then
1386 Set_Do_Range_Check (Exp, False);
1387 Generate_Range_Check (Exp, DesigT, CE_Range_Check_Failed);
1388 end if;
1389 end if;
1391 -- For an access to unconstrained packed array, GIGI needs to see an
1392 -- expression with a constrained subtype in order to compute the
1393 -- proper size for the allocator.
1395 if Is_Array_Type (T)
1396 and then not Is_Constrained (T)
1397 and then Is_Packed (T)
1398 then
1399 declare
1400 ConstrT : constant Entity_Id := Make_Temporary (Loc, 'A');
1401 Internal_Exp : constant Node_Id := Relocate_Node (Exp);
1402 begin
1403 Insert_Action (Exp,
1404 Make_Subtype_Declaration (Loc,
1405 Defining_Identifier => ConstrT,
1406 Subtype_Indication =>
1407 Make_Subtype_From_Expr (Internal_Exp, T)));
1408 Freeze_Itype (ConstrT, Exp);
1409 Rewrite (Exp, OK_Convert_To (ConstrT, Internal_Exp));
1410 end;
1411 end if;
1413 -- Ada 2005 (AI-318-02): If the initialization expression is a call
1414 -- to a build-in-place function, then access to the allocated object
1415 -- must be passed to the function. Currently we limit such functions
1416 -- to those with constrained limited result subtypes, but eventually
1417 -- we plan to expand the allowed forms of functions that are treated
1418 -- as build-in-place.
1420 if Ada_Version >= Ada_2005
1421 and then Is_Build_In_Place_Function_Call (Exp)
1422 then
1423 Make_Build_In_Place_Call_In_Allocator (N, Exp);
1424 end if;
1425 end if;
1427 exception
1428 when RE_Not_Available =>
1429 return;
1430 end Expand_Allocator_Expression;
1432 -----------------------------
1433 -- Expand_Array_Comparison --
1434 -----------------------------
1436 -- Expansion is only required in the case of array types. For the unpacked
1437 -- case, an appropriate runtime routine is called. For packed cases, and
1438 -- also in some other cases where a runtime routine cannot be called, the
1439 -- form of the expansion is:
1441 -- [body for greater_nn; boolean_expression]
1443 -- The body is built by Make_Array_Comparison_Op, and the form of the
1444 -- Boolean expression depends on the operator involved.
1446 procedure Expand_Array_Comparison (N : Node_Id) is
1447 Loc : constant Source_Ptr := Sloc (N);
1448 Op1 : Node_Id := Left_Opnd (N);
1449 Op2 : Node_Id := Right_Opnd (N);
1450 Typ1 : constant Entity_Id := Base_Type (Etype (Op1));
1451 Ctyp : constant Entity_Id := Component_Type (Typ1);
1453 Expr : Node_Id;
1454 Func_Body : Node_Id;
1455 Func_Name : Entity_Id;
1457 Comp : RE_Id;
1459 Byte_Addressable : constant Boolean := System_Storage_Unit = Byte'Size;
1460 -- True for byte addressable target
1462 function Length_Less_Than_4 (Opnd : Node_Id) return Boolean;
1463 -- Returns True if the length of the given operand is known to be less
1464 -- than 4. Returns False if this length is known to be four or greater
1465 -- or is not known at compile time.
1467 ------------------------
1468 -- Length_Less_Than_4 --
1469 ------------------------
1471 function Length_Less_Than_4 (Opnd : Node_Id) return Boolean is
1472 Otyp : constant Entity_Id := Etype (Opnd);
1474 begin
1475 if Ekind (Otyp) = E_String_Literal_Subtype then
1476 return String_Literal_Length (Otyp) < 4;
1478 else
1479 declare
1480 Ityp : constant Entity_Id := Etype (First_Index (Otyp));
1481 Lo : constant Node_Id := Type_Low_Bound (Ityp);
1482 Hi : constant Node_Id := Type_High_Bound (Ityp);
1483 Lov : Uint;
1484 Hiv : Uint;
1486 begin
1487 if Compile_Time_Known_Value (Lo) then
1488 Lov := Expr_Value (Lo);
1489 else
1490 return False;
1491 end if;
1493 if Compile_Time_Known_Value (Hi) then
1494 Hiv := Expr_Value (Hi);
1495 else
1496 return False;
1497 end if;
1499 return Hiv < Lov + 3;
1500 end;
1501 end if;
1502 end Length_Less_Than_4;
1504 -- Start of processing for Expand_Array_Comparison
1506 begin
1507 -- Deal first with unpacked case, where we can call a runtime routine
1508 -- except that we avoid this for targets for which are not addressable
1509 -- by bytes, and for the JVM/CIL, since they do not support direct
1510 -- addressing of array components.
1512 if not Is_Bit_Packed_Array (Typ1)
1513 and then Byte_Addressable
1514 and then VM_Target = No_VM
1515 then
1516 -- The call we generate is:
1518 -- Compare_Array_xn[_Unaligned]
1519 -- (left'address, right'address, left'length, right'length) <op> 0
1521 -- x = U for unsigned, S for signed
1522 -- n = 8,16,32,64 for component size
1523 -- Add _Unaligned if length < 4 and component size is 8.
1524 -- <op> is the standard comparison operator
1526 if Component_Size (Typ1) = 8 then
1527 if Length_Less_Than_4 (Op1)
1528 or else
1529 Length_Less_Than_4 (Op2)
1530 then
1531 if Is_Unsigned_Type (Ctyp) then
1532 Comp := RE_Compare_Array_U8_Unaligned;
1533 else
1534 Comp := RE_Compare_Array_S8_Unaligned;
1535 end if;
1537 else
1538 if Is_Unsigned_Type (Ctyp) then
1539 Comp := RE_Compare_Array_U8;
1540 else
1541 Comp := RE_Compare_Array_S8;
1542 end if;
1543 end if;
1545 elsif Component_Size (Typ1) = 16 then
1546 if Is_Unsigned_Type (Ctyp) then
1547 Comp := RE_Compare_Array_U16;
1548 else
1549 Comp := RE_Compare_Array_S16;
1550 end if;
1552 elsif Component_Size (Typ1) = 32 then
1553 if Is_Unsigned_Type (Ctyp) then
1554 Comp := RE_Compare_Array_U32;
1555 else
1556 Comp := RE_Compare_Array_S32;
1557 end if;
1559 else pragma Assert (Component_Size (Typ1) = 64);
1560 if Is_Unsigned_Type (Ctyp) then
1561 Comp := RE_Compare_Array_U64;
1562 else
1563 Comp := RE_Compare_Array_S64;
1564 end if;
1565 end if;
1567 Remove_Side_Effects (Op1, Name_Req => True);
1568 Remove_Side_Effects (Op2, Name_Req => True);
1570 Rewrite (Op1,
1571 Make_Function_Call (Sloc (Op1),
1572 Name => New_Occurrence_Of (RTE (Comp), Loc),
1574 Parameter_Associations => New_List (
1575 Make_Attribute_Reference (Loc,
1576 Prefix => Relocate_Node (Op1),
1577 Attribute_Name => Name_Address),
1579 Make_Attribute_Reference (Loc,
1580 Prefix => Relocate_Node (Op2),
1581 Attribute_Name => Name_Address),
1583 Make_Attribute_Reference (Loc,
1584 Prefix => Relocate_Node (Op1),
1585 Attribute_Name => Name_Length),
1587 Make_Attribute_Reference (Loc,
1588 Prefix => Relocate_Node (Op2),
1589 Attribute_Name => Name_Length))));
1591 Rewrite (Op2,
1592 Make_Integer_Literal (Sloc (Op2),
1593 Intval => Uint_0));
1595 Analyze_And_Resolve (Op1, Standard_Integer);
1596 Analyze_And_Resolve (Op2, Standard_Integer);
1597 return;
1598 end if;
1600 -- Cases where we cannot make runtime call
1602 -- For (a <= b) we convert to not (a > b)
1604 if Chars (N) = Name_Op_Le then
1605 Rewrite (N,
1606 Make_Op_Not (Loc,
1607 Right_Opnd =>
1608 Make_Op_Gt (Loc,
1609 Left_Opnd => Op1,
1610 Right_Opnd => Op2)));
1611 Analyze_And_Resolve (N, Standard_Boolean);
1612 return;
1614 -- For < the Boolean expression is
1615 -- greater__nn (op2, op1)
1617 elsif Chars (N) = Name_Op_Lt then
1618 Func_Body := Make_Array_Comparison_Op (Typ1, N);
1620 -- Switch operands
1622 Op1 := Right_Opnd (N);
1623 Op2 := Left_Opnd (N);
1625 -- For (a >= b) we convert to not (a < b)
1627 elsif Chars (N) = Name_Op_Ge then
1628 Rewrite (N,
1629 Make_Op_Not (Loc,
1630 Right_Opnd =>
1631 Make_Op_Lt (Loc,
1632 Left_Opnd => Op1,
1633 Right_Opnd => Op2)));
1634 Analyze_And_Resolve (N, Standard_Boolean);
1635 return;
1637 -- For > the Boolean expression is
1638 -- greater__nn (op1, op2)
1640 else
1641 pragma Assert (Chars (N) = Name_Op_Gt);
1642 Func_Body := Make_Array_Comparison_Op (Typ1, N);
1643 end if;
1645 Func_Name := Defining_Unit_Name (Specification (Func_Body));
1646 Expr :=
1647 Make_Function_Call (Loc,
1648 Name => New_Reference_To (Func_Name, Loc),
1649 Parameter_Associations => New_List (Op1, Op2));
1651 Insert_Action (N, Func_Body);
1652 Rewrite (N, Expr);
1653 Analyze_And_Resolve (N, Standard_Boolean);
1655 exception
1656 when RE_Not_Available =>
1657 return;
1658 end Expand_Array_Comparison;
1660 ---------------------------
1661 -- Expand_Array_Equality --
1662 ---------------------------
1664 -- Expand an equality function for multi-dimensional arrays. Here is an
1665 -- example of such a function for Nb_Dimension = 2
1667 -- function Enn (A : atyp; B : btyp) return boolean is
1668 -- begin
1669 -- if (A'length (1) = 0 or else A'length (2) = 0)
1670 -- and then
1671 -- (B'length (1) = 0 or else B'length (2) = 0)
1672 -- then
1673 -- return True; -- RM 4.5.2(22)
1674 -- end if;
1676 -- if A'length (1) /= B'length (1)
1677 -- or else
1678 -- A'length (2) /= B'length (2)
1679 -- then
1680 -- return False; -- RM 4.5.2(23)
1681 -- end if;
1683 -- declare
1684 -- A1 : Index_T1 := A'first (1);
1685 -- B1 : Index_T1 := B'first (1);
1686 -- begin
1687 -- loop
1688 -- declare
1689 -- A2 : Index_T2 := A'first (2);
1690 -- B2 : Index_T2 := B'first (2);
1691 -- begin
1692 -- loop
1693 -- if A (A1, A2) /= B (B1, B2) then
1694 -- return False;
1695 -- end if;
1697 -- exit when A2 = A'last (2);
1698 -- A2 := Index_T2'succ (A2);
1699 -- B2 := Index_T2'succ (B2);
1700 -- end loop;
1701 -- end;
1703 -- exit when A1 = A'last (1);
1704 -- A1 := Index_T1'succ (A1);
1705 -- B1 := Index_T1'succ (B1);
1706 -- end loop;
1707 -- end;
1709 -- return true;
1710 -- end Enn;
1712 -- Note on the formal types used (atyp and btyp). If either of the arrays
1713 -- is of a private type, we use the underlying type, and do an unchecked
1714 -- conversion of the actual. If either of the arrays has a bound depending
1715 -- on a discriminant, then we use the base type since otherwise we have an
1716 -- escaped discriminant in the function.
1718 -- If both arrays are constrained and have the same bounds, we can generate
1719 -- a loop with an explicit iteration scheme using a 'Range attribute over
1720 -- the first array.
1722 function Expand_Array_Equality
1723 (Nod : Node_Id;
1724 Lhs : Node_Id;
1725 Rhs : Node_Id;
1726 Bodies : List_Id;
1727 Typ : Entity_Id) return Node_Id
1729 Loc : constant Source_Ptr := Sloc (Nod);
1730 Decls : constant List_Id := New_List;
1731 Index_List1 : constant List_Id := New_List;
1732 Index_List2 : constant List_Id := New_List;
1734 Actuals : List_Id;
1735 Formals : List_Id;
1736 Func_Name : Entity_Id;
1737 Func_Body : Node_Id;
1739 A : constant Entity_Id := Make_Defining_Identifier (Loc, Name_uA);
1740 B : constant Entity_Id := Make_Defining_Identifier (Loc, Name_uB);
1742 Ltyp : Entity_Id;
1743 Rtyp : Entity_Id;
1744 -- The parameter types to be used for the formals
1746 function Arr_Attr
1747 (Arr : Entity_Id;
1748 Nam : Name_Id;
1749 Num : Int) return Node_Id;
1750 -- This builds the attribute reference Arr'Nam (Expr)
1752 function Component_Equality (Typ : Entity_Id) return Node_Id;
1753 -- Create one statement to compare corresponding components, designated
1754 -- by a full set of indexes.
1756 function Get_Arg_Type (N : Node_Id) return Entity_Id;
1757 -- Given one of the arguments, computes the appropriate type to be used
1758 -- for that argument in the corresponding function formal
1760 function Handle_One_Dimension
1761 (N : Int;
1762 Index : Node_Id) return Node_Id;
1763 -- This procedure returns the following code
1765 -- declare
1766 -- Bn : Index_T := B'First (N);
1767 -- begin
1768 -- loop
1769 -- xxx
1770 -- exit when An = A'Last (N);
1771 -- An := Index_T'Succ (An)
1772 -- Bn := Index_T'Succ (Bn)
1773 -- end loop;
1774 -- end;
1776 -- If both indexes are constrained and identical, the procedure
1777 -- returns a simpler loop:
1779 -- for An in A'Range (N) loop
1780 -- xxx
1781 -- end loop
1783 -- N is the dimension for which we are generating a loop. Index is the
1784 -- N'th index node, whose Etype is Index_Type_n in the above code. The
1785 -- xxx statement is either the loop or declare for the next dimension
1786 -- or if this is the last dimension the comparison of corresponding
1787 -- components of the arrays.
1789 -- The actual way the code works is to return the comparison of
1790 -- corresponding components for the N+1 call. That's neater!
1792 function Test_Empty_Arrays return Node_Id;
1793 -- This function constructs the test for both arrays being empty
1794 -- (A'length (1) = 0 or else A'length (2) = 0 or else ...)
1795 -- and then
1796 -- (B'length (1) = 0 or else B'length (2) = 0 or else ...)
1798 function Test_Lengths_Correspond return Node_Id;
1799 -- This function constructs the test for arrays having different lengths
1800 -- in at least one index position, in which case the resulting code is:
1802 -- A'length (1) /= B'length (1)
1803 -- or else
1804 -- A'length (2) /= B'length (2)
1805 -- or else
1806 -- ...
1808 --------------
1809 -- Arr_Attr --
1810 --------------
1812 function Arr_Attr
1813 (Arr : Entity_Id;
1814 Nam : Name_Id;
1815 Num : Int) return Node_Id
1817 begin
1818 return
1819 Make_Attribute_Reference (Loc,
1820 Attribute_Name => Nam,
1821 Prefix => New_Reference_To (Arr, Loc),
1822 Expressions => New_List (Make_Integer_Literal (Loc, Num)));
1823 end Arr_Attr;
1825 ------------------------
1826 -- Component_Equality --
1827 ------------------------
1829 function Component_Equality (Typ : Entity_Id) return Node_Id is
1830 Test : Node_Id;
1831 L, R : Node_Id;
1833 begin
1834 -- if a(i1...) /= b(j1...) then return false; end if;
1836 L :=
1837 Make_Indexed_Component (Loc,
1838 Prefix => Make_Identifier (Loc, Chars (A)),
1839 Expressions => Index_List1);
1841 R :=
1842 Make_Indexed_Component (Loc,
1843 Prefix => Make_Identifier (Loc, Chars (B)),
1844 Expressions => Index_List2);
1846 Test := Expand_Composite_Equality
1847 (Nod, Component_Type (Typ), L, R, Decls);
1849 -- If some (sub)component is an unchecked_union, the whole operation
1850 -- will raise program error.
1852 if Nkind (Test) = N_Raise_Program_Error then
1854 -- This node is going to be inserted at a location where a
1855 -- statement is expected: clear its Etype so analysis will set
1856 -- it to the expected Standard_Void_Type.
1858 Set_Etype (Test, Empty);
1859 return Test;
1861 else
1862 return
1863 Make_Implicit_If_Statement (Nod,
1864 Condition => Make_Op_Not (Loc, Right_Opnd => Test),
1865 Then_Statements => New_List (
1866 Make_Simple_Return_Statement (Loc,
1867 Expression => New_Occurrence_Of (Standard_False, Loc))));
1868 end if;
1869 end Component_Equality;
1871 ------------------
1872 -- Get_Arg_Type --
1873 ------------------
1875 function Get_Arg_Type (N : Node_Id) return Entity_Id is
1876 T : Entity_Id;
1877 X : Node_Id;
1879 begin
1880 T := Etype (N);
1882 if No (T) then
1883 return Typ;
1885 else
1886 T := Underlying_Type (T);
1888 X := First_Index (T);
1889 while Present (X) loop
1890 if Denotes_Discriminant (Type_Low_Bound (Etype (X)))
1891 or else
1892 Denotes_Discriminant (Type_High_Bound (Etype (X)))
1893 then
1894 T := Base_Type (T);
1895 exit;
1896 end if;
1898 Next_Index (X);
1899 end loop;
1901 return T;
1902 end if;
1903 end Get_Arg_Type;
1905 --------------------------
1906 -- Handle_One_Dimension --
1907 ---------------------------
1909 function Handle_One_Dimension
1910 (N : Int;
1911 Index : Node_Id) return Node_Id
1913 Need_Separate_Indexes : constant Boolean :=
1914 Ltyp /= Rtyp
1915 or else not Is_Constrained (Ltyp);
1916 -- If the index types are identical, and we are working with
1917 -- constrained types, then we can use the same index for both
1918 -- of the arrays.
1920 An : constant Entity_Id := Make_Temporary (Loc, 'A');
1922 Bn : Entity_Id;
1923 Index_T : Entity_Id;
1924 Stm_List : List_Id;
1925 Loop_Stm : Node_Id;
1927 begin
1928 if N > Number_Dimensions (Ltyp) then
1929 return Component_Equality (Ltyp);
1930 end if;
1932 -- Case where we generate a loop
1934 Index_T := Base_Type (Etype (Index));
1936 if Need_Separate_Indexes then
1937 Bn := Make_Temporary (Loc, 'B');
1938 else
1939 Bn := An;
1940 end if;
1942 Append (New_Reference_To (An, Loc), Index_List1);
1943 Append (New_Reference_To (Bn, Loc), Index_List2);
1945 Stm_List := New_List (
1946 Handle_One_Dimension (N + 1, Next_Index (Index)));
1948 if Need_Separate_Indexes then
1950 -- Generate guard for loop, followed by increments of indexes
1952 Append_To (Stm_List,
1953 Make_Exit_Statement (Loc,
1954 Condition =>
1955 Make_Op_Eq (Loc,
1956 Left_Opnd => New_Reference_To (An, Loc),
1957 Right_Opnd => Arr_Attr (A, Name_Last, N))));
1959 Append_To (Stm_List,
1960 Make_Assignment_Statement (Loc,
1961 Name => New_Reference_To (An, Loc),
1962 Expression =>
1963 Make_Attribute_Reference (Loc,
1964 Prefix => New_Reference_To (Index_T, Loc),
1965 Attribute_Name => Name_Succ,
1966 Expressions => New_List (New_Reference_To (An, Loc)))));
1968 Append_To (Stm_List,
1969 Make_Assignment_Statement (Loc,
1970 Name => New_Reference_To (Bn, Loc),
1971 Expression =>
1972 Make_Attribute_Reference (Loc,
1973 Prefix => New_Reference_To (Index_T, Loc),
1974 Attribute_Name => Name_Succ,
1975 Expressions => New_List (New_Reference_To (Bn, Loc)))));
1976 end if;
1978 -- If separate indexes, we need a declare block for An and Bn, and a
1979 -- loop without an iteration scheme.
1981 if Need_Separate_Indexes then
1982 Loop_Stm :=
1983 Make_Implicit_Loop_Statement (Nod, Statements => Stm_List);
1985 return
1986 Make_Block_Statement (Loc,
1987 Declarations => New_List (
1988 Make_Object_Declaration (Loc,
1989 Defining_Identifier => An,
1990 Object_Definition => New_Reference_To (Index_T, Loc),
1991 Expression => Arr_Attr (A, Name_First, N)),
1993 Make_Object_Declaration (Loc,
1994 Defining_Identifier => Bn,
1995 Object_Definition => New_Reference_To (Index_T, Loc),
1996 Expression => Arr_Attr (B, Name_First, N))),
1998 Handled_Statement_Sequence =>
1999 Make_Handled_Sequence_Of_Statements (Loc,
2000 Statements => New_List (Loop_Stm)));
2002 -- If no separate indexes, return loop statement with explicit
2003 -- iteration scheme on its own
2005 else
2006 Loop_Stm :=
2007 Make_Implicit_Loop_Statement (Nod,
2008 Statements => Stm_List,
2009 Iteration_Scheme =>
2010 Make_Iteration_Scheme (Loc,
2011 Loop_Parameter_Specification =>
2012 Make_Loop_Parameter_Specification (Loc,
2013 Defining_Identifier => An,
2014 Discrete_Subtype_Definition =>
2015 Arr_Attr (A, Name_Range, N))));
2016 return Loop_Stm;
2017 end if;
2018 end Handle_One_Dimension;
2020 -----------------------
2021 -- Test_Empty_Arrays --
2022 -----------------------
2024 function Test_Empty_Arrays return Node_Id is
2025 Alist : Node_Id;
2026 Blist : Node_Id;
2028 Atest : Node_Id;
2029 Btest : Node_Id;
2031 begin
2032 Alist := Empty;
2033 Blist := Empty;
2034 for J in 1 .. Number_Dimensions (Ltyp) loop
2035 Atest :=
2036 Make_Op_Eq (Loc,
2037 Left_Opnd => Arr_Attr (A, Name_Length, J),
2038 Right_Opnd => Make_Integer_Literal (Loc, 0));
2040 Btest :=
2041 Make_Op_Eq (Loc,
2042 Left_Opnd => Arr_Attr (B, Name_Length, J),
2043 Right_Opnd => Make_Integer_Literal (Loc, 0));
2045 if No (Alist) then
2046 Alist := Atest;
2047 Blist := Btest;
2049 else
2050 Alist :=
2051 Make_Or_Else (Loc,
2052 Left_Opnd => Relocate_Node (Alist),
2053 Right_Opnd => Atest);
2055 Blist :=
2056 Make_Or_Else (Loc,
2057 Left_Opnd => Relocate_Node (Blist),
2058 Right_Opnd => Btest);
2059 end if;
2060 end loop;
2062 return
2063 Make_And_Then (Loc,
2064 Left_Opnd => Alist,
2065 Right_Opnd => Blist);
2066 end Test_Empty_Arrays;
2068 -----------------------------
2069 -- Test_Lengths_Correspond --
2070 -----------------------------
2072 function Test_Lengths_Correspond return Node_Id is
2073 Result : Node_Id;
2074 Rtest : Node_Id;
2076 begin
2077 Result := Empty;
2078 for J in 1 .. Number_Dimensions (Ltyp) loop
2079 Rtest :=
2080 Make_Op_Ne (Loc,
2081 Left_Opnd => Arr_Attr (A, Name_Length, J),
2082 Right_Opnd => Arr_Attr (B, Name_Length, J));
2084 if No (Result) then
2085 Result := Rtest;
2086 else
2087 Result :=
2088 Make_Or_Else (Loc,
2089 Left_Opnd => Relocate_Node (Result),
2090 Right_Opnd => Rtest);
2091 end if;
2092 end loop;
2094 return Result;
2095 end Test_Lengths_Correspond;
2097 -- Start of processing for Expand_Array_Equality
2099 begin
2100 Ltyp := Get_Arg_Type (Lhs);
2101 Rtyp := Get_Arg_Type (Rhs);
2103 -- For now, if the argument types are not the same, go to the base type,
2104 -- since the code assumes that the formals have the same type. This is
2105 -- fixable in future ???
2107 if Ltyp /= Rtyp then
2108 Ltyp := Base_Type (Ltyp);
2109 Rtyp := Base_Type (Rtyp);
2110 pragma Assert (Ltyp = Rtyp);
2111 end if;
2113 -- Build list of formals for function
2115 Formals := New_List (
2116 Make_Parameter_Specification (Loc,
2117 Defining_Identifier => A,
2118 Parameter_Type => New_Reference_To (Ltyp, Loc)),
2120 Make_Parameter_Specification (Loc,
2121 Defining_Identifier => B,
2122 Parameter_Type => New_Reference_To (Rtyp, Loc)));
2124 Func_Name := Make_Temporary (Loc, 'E');
2126 -- Build statement sequence for function
2128 Func_Body :=
2129 Make_Subprogram_Body (Loc,
2130 Specification =>
2131 Make_Function_Specification (Loc,
2132 Defining_Unit_Name => Func_Name,
2133 Parameter_Specifications => Formals,
2134 Result_Definition => New_Reference_To (Standard_Boolean, Loc)),
2136 Declarations => Decls,
2138 Handled_Statement_Sequence =>
2139 Make_Handled_Sequence_Of_Statements (Loc,
2140 Statements => New_List (
2142 Make_Implicit_If_Statement (Nod,
2143 Condition => Test_Empty_Arrays,
2144 Then_Statements => New_List (
2145 Make_Simple_Return_Statement (Loc,
2146 Expression =>
2147 New_Occurrence_Of (Standard_True, Loc)))),
2149 Make_Implicit_If_Statement (Nod,
2150 Condition => Test_Lengths_Correspond,
2151 Then_Statements => New_List (
2152 Make_Simple_Return_Statement (Loc,
2153 Expression =>
2154 New_Occurrence_Of (Standard_False, Loc)))),
2156 Handle_One_Dimension (1, First_Index (Ltyp)),
2158 Make_Simple_Return_Statement (Loc,
2159 Expression => New_Occurrence_Of (Standard_True, Loc)))));
2161 Set_Has_Completion (Func_Name, True);
2162 Set_Is_Inlined (Func_Name);
2164 -- If the array type is distinct from the type of the arguments, it
2165 -- is the full view of a private type. Apply an unchecked conversion
2166 -- to insure that analysis of the call succeeds.
2168 declare
2169 L, R : Node_Id;
2171 begin
2172 L := Lhs;
2173 R := Rhs;
2175 if No (Etype (Lhs))
2176 or else Base_Type (Etype (Lhs)) /= Base_Type (Ltyp)
2177 then
2178 L := OK_Convert_To (Ltyp, Lhs);
2179 end if;
2181 if No (Etype (Rhs))
2182 or else Base_Type (Etype (Rhs)) /= Base_Type (Rtyp)
2183 then
2184 R := OK_Convert_To (Rtyp, Rhs);
2185 end if;
2187 Actuals := New_List (L, R);
2188 end;
2190 Append_To (Bodies, Func_Body);
2192 return
2193 Make_Function_Call (Loc,
2194 Name => New_Reference_To (Func_Name, Loc),
2195 Parameter_Associations => Actuals);
2196 end Expand_Array_Equality;
2198 -----------------------------
2199 -- Expand_Boolean_Operator --
2200 -----------------------------
2202 -- Note that we first get the actual subtypes of the operands, since we
2203 -- always want to deal with types that have bounds.
2205 procedure Expand_Boolean_Operator (N : Node_Id) is
2206 Typ : constant Entity_Id := Etype (N);
2208 begin
2209 -- Special case of bit packed array where both operands are known to be
2210 -- properly aligned. In this case we use an efficient run time routine
2211 -- to carry out the operation (see System.Bit_Ops).
2213 if Is_Bit_Packed_Array (Typ)
2214 and then not Is_Possibly_Unaligned_Object (Left_Opnd (N))
2215 and then not Is_Possibly_Unaligned_Object (Right_Opnd (N))
2216 then
2217 Expand_Packed_Boolean_Operator (N);
2218 return;
2219 end if;
2221 -- For the normal non-packed case, the general expansion is to build
2222 -- function for carrying out the comparison (use Make_Boolean_Array_Op)
2223 -- and then inserting it into the tree. The original operator node is
2224 -- then rewritten as a call to this function. We also use this in the
2225 -- packed case if either operand is a possibly unaligned object.
2227 declare
2228 Loc : constant Source_Ptr := Sloc (N);
2229 L : constant Node_Id := Relocate_Node (Left_Opnd (N));
2230 R : constant Node_Id := Relocate_Node (Right_Opnd (N));
2231 Func_Body : Node_Id;
2232 Func_Name : Entity_Id;
2234 begin
2235 Convert_To_Actual_Subtype (L);
2236 Convert_To_Actual_Subtype (R);
2237 Ensure_Defined (Etype (L), N);
2238 Ensure_Defined (Etype (R), N);
2239 Apply_Length_Check (R, Etype (L));
2241 if Nkind (N) = N_Op_Xor then
2242 Silly_Boolean_Array_Xor_Test (N, Etype (L));
2243 end if;
2245 if Nkind (Parent (N)) = N_Assignment_Statement
2246 and then Safe_In_Place_Array_Op (Name (Parent (N)), L, R)
2247 then
2248 Build_Boolean_Array_Proc_Call (Parent (N), L, R);
2250 elsif Nkind (Parent (N)) = N_Op_Not
2251 and then Nkind (N) = N_Op_And
2252 and then
2253 Safe_In_Place_Array_Op (Name (Parent (Parent (N))), L, R)
2254 then
2255 return;
2256 else
2258 Func_Body := Make_Boolean_Array_Op (Etype (L), N);
2259 Func_Name := Defining_Unit_Name (Specification (Func_Body));
2260 Insert_Action (N, Func_Body);
2262 -- Now rewrite the expression with a call
2264 Rewrite (N,
2265 Make_Function_Call (Loc,
2266 Name => New_Reference_To (Func_Name, Loc),
2267 Parameter_Associations =>
2268 New_List (
2270 Make_Type_Conversion
2271 (Loc, New_Reference_To (Etype (L), Loc), R))));
2273 Analyze_And_Resolve (N, Typ);
2274 end if;
2275 end;
2276 end Expand_Boolean_Operator;
2278 -------------------------------
2279 -- Expand_Composite_Equality --
2280 -------------------------------
2282 -- This function is only called for comparing internal fields of composite
2283 -- types when these fields are themselves composites. This is a special
2284 -- case because it is not possible to respect normal Ada visibility rules.
2286 function Expand_Composite_Equality
2287 (Nod : Node_Id;
2288 Typ : Entity_Id;
2289 Lhs : Node_Id;
2290 Rhs : Node_Id;
2291 Bodies : List_Id) return Node_Id
2293 Loc : constant Source_Ptr := Sloc (Nod);
2294 Full_Type : Entity_Id;
2295 Prim : Elmt_Id;
2296 Eq_Op : Entity_Id;
2298 function Find_Primitive_Eq return Node_Id;
2299 -- AI05-0123: Locate primitive equality for type if it exists, and
2300 -- build the corresponding call. If operation is abstract, replace
2301 -- call with an explicit raise. Return Empty if there is no primitive.
2303 -----------------------
2304 -- Find_Primitive_Eq --
2305 -----------------------
2307 function Find_Primitive_Eq return Node_Id is
2308 Prim_E : Elmt_Id;
2309 Prim : Node_Id;
2311 begin
2312 Prim_E := First_Elmt (Collect_Primitive_Operations (Typ));
2313 while Present (Prim_E) loop
2314 Prim := Node (Prim_E);
2316 -- Locate primitive equality with the right signature
2318 if Chars (Prim) = Name_Op_Eq
2319 and then Etype (First_Formal (Prim)) =
2320 Etype (Next_Formal (First_Formal (Prim)))
2321 and then Etype (Prim) = Standard_Boolean
2322 then
2323 if Is_Abstract_Subprogram (Prim) then
2324 return
2325 Make_Raise_Program_Error (Loc,
2326 Reason => PE_Explicit_Raise);
2328 else
2329 return
2330 Make_Function_Call (Loc,
2331 Name => New_Reference_To (Prim, Loc),
2332 Parameter_Associations => New_List (Lhs, Rhs));
2333 end if;
2334 end if;
2336 Next_Elmt (Prim_E);
2337 end loop;
2339 -- If not found, predefined operation will be used
2341 return Empty;
2342 end Find_Primitive_Eq;
2344 -- Start of processing for Expand_Composite_Equality
2346 begin
2347 if Is_Private_Type (Typ) then
2348 Full_Type := Underlying_Type (Typ);
2349 else
2350 Full_Type := Typ;
2351 end if;
2353 -- Defense against malformed private types with no completion the error
2354 -- will be diagnosed later by check_completion
2356 if No (Full_Type) then
2357 return New_Reference_To (Standard_False, Loc);
2358 end if;
2360 Full_Type := Base_Type (Full_Type);
2362 if Is_Array_Type (Full_Type) then
2364 -- If the operand is an elementary type other than a floating-point
2365 -- type, then we can simply use the built-in block bitwise equality,
2366 -- since the predefined equality operators always apply and bitwise
2367 -- equality is fine for all these cases.
2369 if Is_Elementary_Type (Component_Type (Full_Type))
2370 and then not Is_Floating_Point_Type (Component_Type (Full_Type))
2371 then
2372 return Make_Op_Eq (Loc, Left_Opnd => Lhs, Right_Opnd => Rhs);
2374 -- For composite component types, and floating-point types, use the
2375 -- expansion. This deals with tagged component types (where we use
2376 -- the applicable equality routine) and floating-point, (where we
2377 -- need to worry about negative zeroes), and also the case of any
2378 -- composite type recursively containing such fields.
2380 else
2381 return Expand_Array_Equality (Nod, Lhs, Rhs, Bodies, Full_Type);
2382 end if;
2384 elsif Is_Tagged_Type (Full_Type) then
2386 -- Call the primitive operation "=" of this type
2388 if Is_Class_Wide_Type (Full_Type) then
2389 Full_Type := Root_Type (Full_Type);
2390 end if;
2392 -- If this is derived from an untagged private type completed with a
2393 -- tagged type, it does not have a full view, so we use the primitive
2394 -- operations of the private type. This check should no longer be
2395 -- necessary when these types receive their full views ???
2397 if Is_Private_Type (Typ)
2398 and then not Is_Tagged_Type (Typ)
2399 and then not Is_Controlled (Typ)
2400 and then Is_Derived_Type (Typ)
2401 and then No (Full_View (Typ))
2402 then
2403 Prim := First_Elmt (Collect_Primitive_Operations (Typ));
2404 else
2405 Prim := First_Elmt (Primitive_Operations (Full_Type));
2406 end if;
2408 loop
2409 Eq_Op := Node (Prim);
2410 exit when Chars (Eq_Op) = Name_Op_Eq
2411 and then Etype (First_Formal (Eq_Op)) =
2412 Etype (Next_Formal (First_Formal (Eq_Op)))
2413 and then Base_Type (Etype (Eq_Op)) = Standard_Boolean;
2414 Next_Elmt (Prim);
2415 pragma Assert (Present (Prim));
2416 end loop;
2418 Eq_Op := Node (Prim);
2420 return
2421 Make_Function_Call (Loc,
2422 Name => New_Reference_To (Eq_Op, Loc),
2423 Parameter_Associations =>
2424 New_List
2425 (Unchecked_Convert_To (Etype (First_Formal (Eq_Op)), Lhs),
2426 Unchecked_Convert_To (Etype (First_Formal (Eq_Op)), Rhs)));
2428 elsif Is_Record_Type (Full_Type) then
2429 Eq_Op := TSS (Full_Type, TSS_Composite_Equality);
2431 if Present (Eq_Op) then
2432 if Etype (First_Formal (Eq_Op)) /= Full_Type then
2434 -- Inherited equality from parent type. Convert the actuals to
2435 -- match signature of operation.
2437 declare
2438 T : constant Entity_Id := Etype (First_Formal (Eq_Op));
2440 begin
2441 return
2442 Make_Function_Call (Loc,
2443 Name => New_Reference_To (Eq_Op, Loc),
2444 Parameter_Associations => New_List (
2445 OK_Convert_To (T, Lhs),
2446 OK_Convert_To (T, Rhs)));
2447 end;
2449 else
2450 -- Comparison between Unchecked_Union components
2452 if Is_Unchecked_Union (Full_Type) then
2453 declare
2454 Lhs_Type : Node_Id := Full_Type;
2455 Rhs_Type : Node_Id := Full_Type;
2456 Lhs_Discr_Val : Node_Id;
2457 Rhs_Discr_Val : Node_Id;
2459 begin
2460 -- Lhs subtype
2462 if Nkind (Lhs) = N_Selected_Component then
2463 Lhs_Type := Etype (Entity (Selector_Name (Lhs)));
2464 end if;
2466 -- Rhs subtype
2468 if Nkind (Rhs) = N_Selected_Component then
2469 Rhs_Type := Etype (Entity (Selector_Name (Rhs)));
2470 end if;
2472 -- Lhs of the composite equality
2474 if Is_Constrained (Lhs_Type) then
2476 -- Since the enclosing record type can never be an
2477 -- Unchecked_Union (this code is executed for records
2478 -- that do not have variants), we may reference its
2479 -- discriminant(s).
2481 if Nkind (Lhs) = N_Selected_Component
2482 and then Has_Per_Object_Constraint (
2483 Entity (Selector_Name (Lhs)))
2484 then
2485 Lhs_Discr_Val :=
2486 Make_Selected_Component (Loc,
2487 Prefix => Prefix (Lhs),
2488 Selector_Name =>
2489 New_Copy
2490 (Get_Discriminant_Value
2491 (First_Discriminant (Lhs_Type),
2492 Lhs_Type,
2493 Stored_Constraint (Lhs_Type))));
2495 else
2496 Lhs_Discr_Val :=
2497 New_Copy
2498 (Get_Discriminant_Value
2499 (First_Discriminant (Lhs_Type),
2500 Lhs_Type,
2501 Stored_Constraint (Lhs_Type)));
2503 end if;
2504 else
2505 -- It is not possible to infer the discriminant since
2506 -- the subtype is not constrained.
2508 return
2509 Make_Raise_Program_Error (Loc,
2510 Reason => PE_Unchecked_Union_Restriction);
2511 end if;
2513 -- Rhs of the composite equality
2515 if Is_Constrained (Rhs_Type) then
2516 if Nkind (Rhs) = N_Selected_Component
2517 and then Has_Per_Object_Constraint
2518 (Entity (Selector_Name (Rhs)))
2519 then
2520 Rhs_Discr_Val :=
2521 Make_Selected_Component (Loc,
2522 Prefix => Prefix (Rhs),
2523 Selector_Name =>
2524 New_Copy
2525 (Get_Discriminant_Value
2526 (First_Discriminant (Rhs_Type),
2527 Rhs_Type,
2528 Stored_Constraint (Rhs_Type))));
2530 else
2531 Rhs_Discr_Val :=
2532 New_Copy
2533 (Get_Discriminant_Value
2534 (First_Discriminant (Rhs_Type),
2535 Rhs_Type,
2536 Stored_Constraint (Rhs_Type)));
2538 end if;
2539 else
2540 return
2541 Make_Raise_Program_Error (Loc,
2542 Reason => PE_Unchecked_Union_Restriction);
2543 end if;
2545 -- Call the TSS equality function with the inferred
2546 -- discriminant values.
2548 return
2549 Make_Function_Call (Loc,
2550 Name => New_Reference_To (Eq_Op, Loc),
2551 Parameter_Associations => New_List (
2552 Lhs,
2553 Rhs,
2554 Lhs_Discr_Val,
2555 Rhs_Discr_Val));
2556 end;
2558 else
2559 return
2560 Make_Function_Call (Loc,
2561 Name => New_Reference_To (Eq_Op, Loc),
2562 Parameter_Associations => New_List (Lhs, Rhs));
2563 end if;
2564 end if;
2566 -- Equality composes in Ada 2012 for untagged record types. It also
2567 -- composes for bounded strings, because they are part of the
2568 -- predefined environment. We could make it compose for bounded
2569 -- strings by making them tagged, or by making sure all subcomponents
2570 -- are set to the same value, even when not used. Instead, we have
2571 -- this special case in the compiler, because it's more efficient.
2573 elsif Ada_Version >= Ada_2012 or else Is_Bounded_String (Typ) then
2575 -- if no TSS has been created for the type, check whether there is
2576 -- a primitive equality declared for it.
2578 declare
2579 Op : constant Node_Id := Find_Primitive_Eq;
2581 begin
2582 -- Use user-defined primitive if it exists, otherwise use
2583 -- predefined equality.
2585 if Present (Op) then
2586 return Op;
2587 else
2588 return Make_Op_Eq (Loc, Lhs, Rhs);
2589 end if;
2590 end;
2592 else
2593 return Expand_Record_Equality (Nod, Full_Type, Lhs, Rhs, Bodies);
2594 end if;
2596 else
2597 -- If not array or record type, it is predefined equality.
2599 return Make_Op_Eq (Loc, Left_Opnd => Lhs, Right_Opnd => Rhs);
2600 end if;
2601 end Expand_Composite_Equality;
2603 ------------------------
2604 -- Expand_Concatenate --
2605 ------------------------
2607 procedure Expand_Concatenate (Cnode : Node_Id; Opnds : List_Id) is
2608 Loc : constant Source_Ptr := Sloc (Cnode);
2610 Atyp : constant Entity_Id := Base_Type (Etype (Cnode));
2611 -- Result type of concatenation
2613 Ctyp : constant Entity_Id := Base_Type (Component_Type (Etype (Cnode)));
2614 -- Component type. Elements of this component type can appear as one
2615 -- of the operands of concatenation as well as arrays.
2617 Istyp : constant Entity_Id := Etype (First_Index (Atyp));
2618 -- Index subtype
2620 Ityp : constant Entity_Id := Base_Type (Istyp);
2621 -- Index type. This is the base type of the index subtype, and is used
2622 -- for all computed bounds (which may be out of range of Istyp in the
2623 -- case of null ranges).
2625 Artyp : Entity_Id;
2626 -- This is the type we use to do arithmetic to compute the bounds and
2627 -- lengths of operands. The choice of this type is a little subtle and
2628 -- is discussed in a separate section at the start of the body code.
2630 Concatenation_Error : exception;
2631 -- Raised if concatenation is sure to raise a CE
2633 Result_May_Be_Null : Boolean := True;
2634 -- Reset to False if at least one operand is encountered which is known
2635 -- at compile time to be non-null. Used for handling the special case
2636 -- of setting the high bound to the last operand high bound for a null
2637 -- result, thus ensuring a proper high bound in the super-flat case.
2639 N : constant Nat := List_Length (Opnds);
2640 -- Number of concatenation operands including possibly null operands
2642 NN : Nat := 0;
2643 -- Number of operands excluding any known to be null, except that the
2644 -- last operand is always retained, in case it provides the bounds for
2645 -- a null result.
2647 Opnd : Node_Id;
2648 -- Current operand being processed in the loop through operands. After
2649 -- this loop is complete, always contains the last operand (which is not
2650 -- the same as Operands (NN), since null operands are skipped).
2652 -- Arrays describing the operands, only the first NN entries of each
2653 -- array are set (NN < N when we exclude known null operands).
2655 Is_Fixed_Length : array (1 .. N) of Boolean;
2656 -- True if length of corresponding operand known at compile time
2658 Operands : array (1 .. N) of Node_Id;
2659 -- Set to the corresponding entry in the Opnds list (but note that null
2660 -- operands are excluded, so not all entries in the list are stored).
2662 Fixed_Length : array (1 .. N) of Uint;
2663 -- Set to length of operand. Entries in this array are set only if the
2664 -- corresponding entry in Is_Fixed_Length is True.
2666 Opnd_Low_Bound : array (1 .. N) of Node_Id;
2667 -- Set to lower bound of operand. Either an integer literal in the case
2668 -- where the bound is known at compile time, else actual lower bound.
2669 -- The operand low bound is of type Ityp.
2671 Var_Length : array (1 .. N) of Entity_Id;
2672 -- Set to an entity of type Natural that contains the length of an
2673 -- operand whose length is not known at compile time. Entries in this
2674 -- array are set only if the corresponding entry in Is_Fixed_Length
2675 -- is False. The entity is of type Artyp.
2677 Aggr_Length : array (0 .. N) of Node_Id;
2678 -- The J'th entry in an expression node that represents the total length
2679 -- of operands 1 through J. It is either an integer literal node, or a
2680 -- reference to a constant entity with the right value, so it is fine
2681 -- to just do a Copy_Node to get an appropriate copy. The extra zero'th
2682 -- entry always is set to zero. The length is of type Artyp.
2684 Low_Bound : Node_Id;
2685 -- A tree node representing the low bound of the result (of type Ityp).
2686 -- This is either an integer literal node, or an identifier reference to
2687 -- a constant entity initialized to the appropriate value.
2689 Last_Opnd_Low_Bound : Node_Id;
2690 -- A tree node representing the low bound of the last operand. This
2691 -- need only be set if the result could be null. It is used for the
2692 -- special case of setting the right low bound for a null result.
2693 -- This is of type Ityp.
2695 Last_Opnd_High_Bound : Node_Id;
2696 -- A tree node representing the high bound of the last operand. This
2697 -- need only be set if the result could be null. It is used for the
2698 -- special case of setting the right high bound for a null result.
2699 -- This is of type Ityp.
2701 High_Bound : Node_Id;
2702 -- A tree node representing the high bound of the result (of type Ityp)
2704 Result : Node_Id;
2705 -- Result of the concatenation (of type Ityp)
2707 Actions : constant List_Id := New_List;
2708 -- Collect actions to be inserted
2710 Known_Non_Null_Operand_Seen : Boolean;
2711 -- Set True during generation of the assignments of operands into
2712 -- result once an operand known to be non-null has been seen.
2714 function Make_Artyp_Literal (Val : Nat) return Node_Id;
2715 -- This function makes an N_Integer_Literal node that is returned in
2716 -- analyzed form with the type set to Artyp. Importantly this literal
2717 -- is not flagged as static, so that if we do computations with it that
2718 -- result in statically detected out of range conditions, we will not
2719 -- generate error messages but instead warning messages.
2721 function To_Artyp (X : Node_Id) return Node_Id;
2722 -- Given a node of type Ityp, returns the corresponding value of type
2723 -- Artyp. For non-enumeration types, this is a plain integer conversion.
2724 -- For enum types, the Pos of the value is returned.
2726 function To_Ityp (X : Node_Id) return Node_Id;
2727 -- The inverse function (uses Val in the case of enumeration types)
2729 ------------------------
2730 -- Make_Artyp_Literal --
2731 ------------------------
2733 function Make_Artyp_Literal (Val : Nat) return Node_Id is
2734 Result : constant Node_Id := Make_Integer_Literal (Loc, Val);
2735 begin
2736 Set_Etype (Result, Artyp);
2737 Set_Analyzed (Result, True);
2738 Set_Is_Static_Expression (Result, False);
2739 return Result;
2740 end Make_Artyp_Literal;
2742 --------------
2743 -- To_Artyp --
2744 --------------
2746 function To_Artyp (X : Node_Id) return Node_Id is
2747 begin
2748 if Ityp = Base_Type (Artyp) then
2749 return X;
2751 elsif Is_Enumeration_Type (Ityp) then
2752 return
2753 Make_Attribute_Reference (Loc,
2754 Prefix => New_Occurrence_Of (Ityp, Loc),
2755 Attribute_Name => Name_Pos,
2756 Expressions => New_List (X));
2758 else
2759 return Convert_To (Artyp, X);
2760 end if;
2761 end To_Artyp;
2763 -------------
2764 -- To_Ityp --
2765 -------------
2767 function To_Ityp (X : Node_Id) return Node_Id is
2768 begin
2769 if Is_Enumeration_Type (Ityp) then
2770 return
2771 Make_Attribute_Reference (Loc,
2772 Prefix => New_Occurrence_Of (Ityp, Loc),
2773 Attribute_Name => Name_Val,
2774 Expressions => New_List (X));
2776 -- Case where we will do a type conversion
2778 else
2779 if Ityp = Base_Type (Artyp) then
2780 return X;
2781 else
2782 return Convert_To (Ityp, X);
2783 end if;
2784 end if;
2785 end To_Ityp;
2787 -- Local Declarations
2789 Opnd_Typ : Entity_Id;
2790 Ent : Entity_Id;
2791 Len : Uint;
2792 J : Nat;
2793 Clen : Node_Id;
2794 Set : Boolean;
2796 -- Start of processing for Expand_Concatenate
2798 begin
2799 -- Choose an appropriate computational type
2801 -- We will be doing calculations of lengths and bounds in this routine
2802 -- and computing one from the other in some cases, e.g. getting the high
2803 -- bound by adding the length-1 to the low bound.
2805 -- We can't just use the index type, or even its base type for this
2806 -- purpose for two reasons. First it might be an enumeration type which
2807 -- is not suitable for computations of any kind, and second it may
2808 -- simply not have enough range. For example if the index type is
2809 -- -128..+127 then lengths can be up to 256, which is out of range of
2810 -- the type.
2812 -- For enumeration types, we can simply use Standard_Integer, this is
2813 -- sufficient since the actual number of enumeration literals cannot
2814 -- possibly exceed the range of integer (remember we will be doing the
2815 -- arithmetic with POS values, not representation values).
2817 if Is_Enumeration_Type (Ityp) then
2818 Artyp := Standard_Integer;
2820 -- If index type is Positive, we use the standard unsigned type, to give
2821 -- more room on the top of the range, obviating the need for an overflow
2822 -- check when creating the upper bound. This is needed to avoid junk
2823 -- overflow checks in the common case of String types.
2825 -- ??? Disabled for now
2827 -- elsif Istyp = Standard_Positive then
2828 -- Artyp := Standard_Unsigned;
2830 -- For modular types, we use a 32-bit modular type for types whose size
2831 -- is in the range 1-31 bits. For 32-bit unsigned types, we use the
2832 -- identity type, and for larger unsigned types we use 64-bits.
2834 elsif Is_Modular_Integer_Type (Ityp) then
2835 if RM_Size (Ityp) < RM_Size (Standard_Unsigned) then
2836 Artyp := Standard_Unsigned;
2837 elsif RM_Size (Ityp) = RM_Size (Standard_Unsigned) then
2838 Artyp := Ityp;
2839 else
2840 Artyp := RTE (RE_Long_Long_Unsigned);
2841 end if;
2843 -- Similar treatment for signed types
2845 else
2846 if RM_Size (Ityp) < RM_Size (Standard_Integer) then
2847 Artyp := Standard_Integer;
2848 elsif RM_Size (Ityp) = RM_Size (Standard_Integer) then
2849 Artyp := Ityp;
2850 else
2851 Artyp := Standard_Long_Long_Integer;
2852 end if;
2853 end if;
2855 -- Supply dummy entry at start of length array
2857 Aggr_Length (0) := Make_Artyp_Literal (0);
2859 -- Go through operands setting up the above arrays
2861 J := 1;
2862 while J <= N loop
2863 Opnd := Remove_Head (Opnds);
2864 Opnd_Typ := Etype (Opnd);
2866 -- The parent got messed up when we put the operands in a list,
2867 -- so now put back the proper parent for the saved operand, that
2868 -- is to say the concatenation node, to make sure that each operand
2869 -- is seen as a subexpression, e.g. if actions must be inserted.
2871 Set_Parent (Opnd, Cnode);
2873 -- Set will be True when we have setup one entry in the array
2875 Set := False;
2877 -- Singleton element (or character literal) case
2879 if Base_Type (Opnd_Typ) = Ctyp then
2880 NN := NN + 1;
2881 Operands (NN) := Opnd;
2882 Is_Fixed_Length (NN) := True;
2883 Fixed_Length (NN) := Uint_1;
2884 Result_May_Be_Null := False;
2886 -- Set low bound of operand (no need to set Last_Opnd_High_Bound
2887 -- since we know that the result cannot be null).
2889 Opnd_Low_Bound (NN) :=
2890 Make_Attribute_Reference (Loc,
2891 Prefix => New_Reference_To (Istyp, Loc),
2892 Attribute_Name => Name_First);
2894 Set := True;
2896 -- String literal case (can only occur for strings of course)
2898 elsif Nkind (Opnd) = N_String_Literal then
2899 Len := String_Literal_Length (Opnd_Typ);
2901 if Len /= 0 then
2902 Result_May_Be_Null := False;
2903 end if;
2905 -- Capture last operand low and high bound if result could be null
2907 if J = N and then Result_May_Be_Null then
2908 Last_Opnd_Low_Bound :=
2909 New_Copy_Tree (String_Literal_Low_Bound (Opnd_Typ));
2911 Last_Opnd_High_Bound :=
2912 Make_Op_Subtract (Loc,
2913 Left_Opnd =>
2914 New_Copy_Tree (String_Literal_Low_Bound (Opnd_Typ)),
2915 Right_Opnd => Make_Integer_Literal (Loc, 1));
2916 end if;
2918 -- Skip null string literal
2920 if J < N and then Len = 0 then
2921 goto Continue;
2922 end if;
2924 NN := NN + 1;
2925 Operands (NN) := Opnd;
2926 Is_Fixed_Length (NN) := True;
2928 -- Set length and bounds
2930 Fixed_Length (NN) := Len;
2932 Opnd_Low_Bound (NN) :=
2933 New_Copy_Tree (String_Literal_Low_Bound (Opnd_Typ));
2935 Set := True;
2937 -- All other cases
2939 else
2940 -- Check constrained case with known bounds
2942 if Is_Constrained (Opnd_Typ) then
2943 declare
2944 Index : constant Node_Id := First_Index (Opnd_Typ);
2945 Indx_Typ : constant Entity_Id := Etype (Index);
2946 Lo : constant Node_Id := Type_Low_Bound (Indx_Typ);
2947 Hi : constant Node_Id := Type_High_Bound (Indx_Typ);
2949 begin
2950 -- Fixed length constrained array type with known at compile
2951 -- time bounds is last case of fixed length operand.
2953 if Compile_Time_Known_Value (Lo)
2954 and then
2955 Compile_Time_Known_Value (Hi)
2956 then
2957 declare
2958 Loval : constant Uint := Expr_Value (Lo);
2959 Hival : constant Uint := Expr_Value (Hi);
2960 Len : constant Uint :=
2961 UI_Max (Hival - Loval + 1, Uint_0);
2963 begin
2964 if Len > 0 then
2965 Result_May_Be_Null := False;
2966 end if;
2968 -- Capture last operand bounds if result could be null
2970 if J = N and then Result_May_Be_Null then
2971 Last_Opnd_Low_Bound :=
2972 Convert_To (Ityp,
2973 Make_Integer_Literal (Loc, Expr_Value (Lo)));
2975 Last_Opnd_High_Bound :=
2976 Convert_To (Ityp,
2977 Make_Integer_Literal (Loc, Expr_Value (Hi)));
2978 end if;
2980 -- Exclude null length case unless last operand
2982 if J < N and then Len = 0 then
2983 goto Continue;
2984 end if;
2986 NN := NN + 1;
2987 Operands (NN) := Opnd;
2988 Is_Fixed_Length (NN) := True;
2989 Fixed_Length (NN) := Len;
2991 Opnd_Low_Bound (NN) :=
2992 To_Ityp
2993 (Make_Integer_Literal (Loc, Expr_Value (Lo)));
2994 Set := True;
2995 end;
2996 end if;
2997 end;
2998 end if;
3000 -- All cases where the length is not known at compile time, or the
3001 -- special case of an operand which is known to be null but has a
3002 -- lower bound other than 1 or is other than a string type.
3004 if not Set then
3005 NN := NN + 1;
3007 -- Capture operand bounds
3009 Opnd_Low_Bound (NN) :=
3010 Make_Attribute_Reference (Loc,
3011 Prefix =>
3012 Duplicate_Subexpr (Opnd, Name_Req => True),
3013 Attribute_Name => Name_First);
3015 -- Capture last operand bounds if result could be null
3017 if J = N and Result_May_Be_Null then
3018 Last_Opnd_Low_Bound :=
3019 Convert_To (Ityp,
3020 Make_Attribute_Reference (Loc,
3021 Prefix =>
3022 Duplicate_Subexpr (Opnd, Name_Req => True),
3023 Attribute_Name => Name_First));
3025 Last_Opnd_High_Bound :=
3026 Convert_To (Ityp,
3027 Make_Attribute_Reference (Loc,
3028 Prefix =>
3029 Duplicate_Subexpr (Opnd, Name_Req => True),
3030 Attribute_Name => Name_Last));
3031 end if;
3033 -- Capture length of operand in entity
3035 Operands (NN) := Opnd;
3036 Is_Fixed_Length (NN) := False;
3038 Var_Length (NN) := Make_Temporary (Loc, 'L');
3040 Append_To (Actions,
3041 Make_Object_Declaration (Loc,
3042 Defining_Identifier => Var_Length (NN),
3043 Constant_Present => True,
3044 Object_Definition => New_Occurrence_Of (Artyp, Loc),
3045 Expression =>
3046 Make_Attribute_Reference (Loc,
3047 Prefix =>
3048 Duplicate_Subexpr (Opnd, Name_Req => True),
3049 Attribute_Name => Name_Length)));
3050 end if;
3051 end if;
3053 -- Set next entry in aggregate length array
3055 -- For first entry, make either integer literal for fixed length
3056 -- or a reference to the saved length for variable length.
3058 if NN = 1 then
3059 if Is_Fixed_Length (1) then
3060 Aggr_Length (1) := Make_Integer_Literal (Loc, Fixed_Length (1));
3061 else
3062 Aggr_Length (1) := New_Reference_To (Var_Length (1), Loc);
3063 end if;
3065 -- If entry is fixed length and only fixed lengths so far, make
3066 -- appropriate new integer literal adding new length.
3068 elsif Is_Fixed_Length (NN)
3069 and then Nkind (Aggr_Length (NN - 1)) = N_Integer_Literal
3070 then
3071 Aggr_Length (NN) :=
3072 Make_Integer_Literal (Loc,
3073 Intval => Fixed_Length (NN) + Intval (Aggr_Length (NN - 1)));
3075 -- All other cases, construct an addition node for the length and
3076 -- create an entity initialized to this length.
3078 else
3079 Ent := Make_Temporary (Loc, 'L');
3081 if Is_Fixed_Length (NN) then
3082 Clen := Make_Integer_Literal (Loc, Fixed_Length (NN));
3083 else
3084 Clen := New_Reference_To (Var_Length (NN), Loc);
3085 end if;
3087 Append_To (Actions,
3088 Make_Object_Declaration (Loc,
3089 Defining_Identifier => Ent,
3090 Constant_Present => True,
3091 Object_Definition => New_Occurrence_Of (Artyp, Loc),
3092 Expression =>
3093 Make_Op_Add (Loc,
3094 Left_Opnd => New_Copy (Aggr_Length (NN - 1)),
3095 Right_Opnd => Clen)));
3097 Aggr_Length (NN) := Make_Identifier (Loc, Chars => Chars (Ent));
3098 end if;
3100 <<Continue>>
3101 J := J + 1;
3102 end loop;
3104 -- If we have only skipped null operands, return the last operand
3106 if NN = 0 then
3107 Result := Opnd;
3108 goto Done;
3109 end if;
3111 -- If we have only one non-null operand, return it and we are done.
3112 -- There is one case in which this cannot be done, and that is when
3113 -- the sole operand is of the element type, in which case it must be
3114 -- converted to an array, and the easiest way of doing that is to go
3115 -- through the normal general circuit.
3117 if NN = 1
3118 and then Base_Type (Etype (Operands (1))) /= Ctyp
3119 then
3120 Result := Operands (1);
3121 goto Done;
3122 end if;
3124 -- Cases where we have a real concatenation
3126 -- Next step is to find the low bound for the result array that we
3127 -- will allocate. The rules for this are in (RM 4.5.6(5-7)).
3129 -- If the ultimate ancestor of the index subtype is a constrained array
3130 -- definition, then the lower bound is that of the index subtype as
3131 -- specified by (RM 4.5.3(6)).
3133 -- The right test here is to go to the root type, and then the ultimate
3134 -- ancestor is the first subtype of this root type.
3136 if Is_Constrained (First_Subtype (Root_Type (Atyp))) then
3137 Low_Bound :=
3138 Make_Attribute_Reference (Loc,
3139 Prefix =>
3140 New_Occurrence_Of (First_Subtype (Root_Type (Atyp)), Loc),
3141 Attribute_Name => Name_First);
3143 -- If the first operand in the list has known length we know that
3144 -- the lower bound of the result is the lower bound of this operand.
3146 elsif Is_Fixed_Length (1) then
3147 Low_Bound := Opnd_Low_Bound (1);
3149 -- OK, we don't know the lower bound, we have to build a horrible
3150 -- conditional expression node of the form
3152 -- if Cond1'Length /= 0 then
3153 -- Opnd1 low bound
3154 -- else
3155 -- if Opnd2'Length /= 0 then
3156 -- Opnd2 low bound
3157 -- else
3158 -- ...
3160 -- The nesting ends either when we hit an operand whose length is known
3161 -- at compile time, or on reaching the last operand, whose low bound we
3162 -- take unconditionally whether or not it is null. It's easiest to do
3163 -- this with a recursive procedure:
3165 else
3166 declare
3167 function Get_Known_Bound (J : Nat) return Node_Id;
3168 -- Returns the lower bound determined by operands J .. NN
3170 ---------------------
3171 -- Get_Known_Bound --
3172 ---------------------
3174 function Get_Known_Bound (J : Nat) return Node_Id is
3175 begin
3176 if Is_Fixed_Length (J) or else J = NN then
3177 return New_Copy (Opnd_Low_Bound (J));
3179 else
3180 return
3181 Make_Conditional_Expression (Loc,
3182 Expressions => New_List (
3184 Make_Op_Ne (Loc,
3185 Left_Opnd => New_Reference_To (Var_Length (J), Loc),
3186 Right_Opnd => Make_Integer_Literal (Loc, 0)),
3188 New_Copy (Opnd_Low_Bound (J)),
3189 Get_Known_Bound (J + 1)));
3190 end if;
3191 end Get_Known_Bound;
3193 begin
3194 Ent := Make_Temporary (Loc, 'L');
3196 Append_To (Actions,
3197 Make_Object_Declaration (Loc,
3198 Defining_Identifier => Ent,
3199 Constant_Present => True,
3200 Object_Definition => New_Occurrence_Of (Ityp, Loc),
3201 Expression => Get_Known_Bound (1)));
3203 Low_Bound := New_Reference_To (Ent, Loc);
3204 end;
3205 end if;
3207 -- Now we can safely compute the upper bound, normally
3208 -- Low_Bound + Length - 1.
3210 High_Bound :=
3211 To_Ityp (
3212 Make_Op_Add (Loc,
3213 Left_Opnd => To_Artyp (New_Copy (Low_Bound)),
3214 Right_Opnd =>
3215 Make_Op_Subtract (Loc,
3216 Left_Opnd => New_Copy (Aggr_Length (NN)),
3217 Right_Opnd => Make_Artyp_Literal (1))));
3219 -- Note that calculation of the high bound may cause overflow in some
3220 -- very weird cases, so in the general case we need an overflow check on
3221 -- the high bound. We can avoid this for the common case of string types
3222 -- and other types whose index is Positive, since we chose a wider range
3223 -- for the arithmetic type.
3225 if Istyp /= Standard_Positive then
3226 Activate_Overflow_Check (High_Bound);
3227 end if;
3229 -- Handle the exceptional case where the result is null, in which case
3230 -- case the bounds come from the last operand (so that we get the proper
3231 -- bounds if the last operand is super-flat).
3233 if Result_May_Be_Null then
3234 Low_Bound :=
3235 Make_Conditional_Expression (Loc,
3236 Expressions => New_List (
3237 Make_Op_Eq (Loc,
3238 Left_Opnd => New_Copy (Aggr_Length (NN)),
3239 Right_Opnd => Make_Artyp_Literal (0)),
3240 Last_Opnd_Low_Bound,
3241 Low_Bound));
3243 High_Bound :=
3244 Make_Conditional_Expression (Loc,
3245 Expressions => New_List (
3246 Make_Op_Eq (Loc,
3247 Left_Opnd => New_Copy (Aggr_Length (NN)),
3248 Right_Opnd => Make_Artyp_Literal (0)),
3249 Last_Opnd_High_Bound,
3250 High_Bound));
3251 end if;
3253 -- Here is where we insert the saved up actions
3255 Insert_Actions (Cnode, Actions, Suppress => All_Checks);
3257 -- Now we construct an array object with appropriate bounds. We mark
3258 -- the target as internal to prevent useless initialization when
3259 -- Initialize_Scalars is enabled. Also since this is the actual result
3260 -- entity, we make sure we have debug information for the result.
3262 Ent := Make_Temporary (Loc, 'S');
3263 Set_Is_Internal (Ent);
3264 Set_Needs_Debug_Info (Ent);
3266 -- If the bound is statically known to be out of range, we do not want
3267 -- to abort, we want a warning and a runtime constraint error. Note that
3268 -- we have arranged that the result will not be treated as a static
3269 -- constant, so we won't get an illegality during this insertion.
3271 Insert_Action (Cnode,
3272 Make_Object_Declaration (Loc,
3273 Defining_Identifier => Ent,
3274 Object_Definition =>
3275 Make_Subtype_Indication (Loc,
3276 Subtype_Mark => New_Occurrence_Of (Atyp, Loc),
3277 Constraint =>
3278 Make_Index_Or_Discriminant_Constraint (Loc,
3279 Constraints => New_List (
3280 Make_Range (Loc,
3281 Low_Bound => Low_Bound,
3282 High_Bound => High_Bound))))),
3283 Suppress => All_Checks);
3285 -- If the result of the concatenation appears as the initializing
3286 -- expression of an object declaration, we can just rename the
3287 -- result, rather than copying it.
3289 Set_OK_To_Rename (Ent);
3291 -- Catch the static out of range case now
3293 if Raises_Constraint_Error (High_Bound) then
3294 raise Concatenation_Error;
3295 end if;
3297 -- Now we will generate the assignments to do the actual concatenation
3299 -- There is one case in which we will not do this, namely when all the
3300 -- following conditions are met:
3302 -- The result type is Standard.String
3304 -- There are nine or fewer retained (non-null) operands
3306 -- The optimization level is -O0
3308 -- The corresponding System.Concat_n.Str_Concat_n routine is
3309 -- available in the run time.
3311 -- The debug flag gnatd.c is not set
3313 -- If all these conditions are met then we generate a call to the
3314 -- relevant concatenation routine. The purpose of this is to avoid
3315 -- undesirable code bloat at -O0.
3317 if Atyp = Standard_String
3318 and then NN in 2 .. 9
3319 and then (Opt.Optimization_Level = 0 or else Debug_Flag_Dot_CC)
3320 and then not Debug_Flag_Dot_C
3321 then
3322 declare
3323 RR : constant array (Nat range 2 .. 9) of RE_Id :=
3324 (RE_Str_Concat_2,
3325 RE_Str_Concat_3,
3326 RE_Str_Concat_4,
3327 RE_Str_Concat_5,
3328 RE_Str_Concat_6,
3329 RE_Str_Concat_7,
3330 RE_Str_Concat_8,
3331 RE_Str_Concat_9);
3333 begin
3334 if RTE_Available (RR (NN)) then
3335 declare
3336 Opnds : constant List_Id :=
3337 New_List (New_Occurrence_Of (Ent, Loc));
3339 begin
3340 for J in 1 .. NN loop
3341 if Is_List_Member (Operands (J)) then
3342 Remove (Operands (J));
3343 end if;
3345 if Base_Type (Etype (Operands (J))) = Ctyp then
3346 Append_To (Opnds,
3347 Make_Aggregate (Loc,
3348 Component_Associations => New_List (
3349 Make_Component_Association (Loc,
3350 Choices => New_List (
3351 Make_Integer_Literal (Loc, 1)),
3352 Expression => Operands (J)))));
3354 else
3355 Append_To (Opnds, Operands (J));
3356 end if;
3357 end loop;
3359 Insert_Action (Cnode,
3360 Make_Procedure_Call_Statement (Loc,
3361 Name => New_Reference_To (RTE (RR (NN)), Loc),
3362 Parameter_Associations => Opnds));
3364 Result := New_Reference_To (Ent, Loc);
3365 goto Done;
3366 end;
3367 end if;
3368 end;
3369 end if;
3371 -- Not special case so generate the assignments
3373 Known_Non_Null_Operand_Seen := False;
3375 for J in 1 .. NN loop
3376 declare
3377 Lo : constant Node_Id :=
3378 Make_Op_Add (Loc,
3379 Left_Opnd => To_Artyp (New_Copy (Low_Bound)),
3380 Right_Opnd => Aggr_Length (J - 1));
3382 Hi : constant Node_Id :=
3383 Make_Op_Add (Loc,
3384 Left_Opnd => To_Artyp (New_Copy (Low_Bound)),
3385 Right_Opnd =>
3386 Make_Op_Subtract (Loc,
3387 Left_Opnd => Aggr_Length (J),
3388 Right_Opnd => Make_Artyp_Literal (1)));
3390 begin
3391 -- Singleton case, simple assignment
3393 if Base_Type (Etype (Operands (J))) = Ctyp then
3394 Known_Non_Null_Operand_Seen := True;
3395 Insert_Action (Cnode,
3396 Make_Assignment_Statement (Loc,
3397 Name =>
3398 Make_Indexed_Component (Loc,
3399 Prefix => New_Occurrence_Of (Ent, Loc),
3400 Expressions => New_List (To_Ityp (Lo))),
3401 Expression => Operands (J)),
3402 Suppress => All_Checks);
3404 -- Array case, slice assignment, skipped when argument is fixed
3405 -- length and known to be null.
3407 elsif (not Is_Fixed_Length (J)) or else (Fixed_Length (J) > 0) then
3408 declare
3409 Assign : Node_Id :=
3410 Make_Assignment_Statement (Loc,
3411 Name =>
3412 Make_Slice (Loc,
3413 Prefix =>
3414 New_Occurrence_Of (Ent, Loc),
3415 Discrete_Range =>
3416 Make_Range (Loc,
3417 Low_Bound => To_Ityp (Lo),
3418 High_Bound => To_Ityp (Hi))),
3419 Expression => Operands (J));
3420 begin
3421 if Is_Fixed_Length (J) then
3422 Known_Non_Null_Operand_Seen := True;
3424 elsif not Known_Non_Null_Operand_Seen then
3426 -- Here if operand length is not statically known and no
3427 -- operand known to be non-null has been processed yet.
3428 -- If operand length is 0, we do not need to perform the
3429 -- assignment, and we must avoid the evaluation of the
3430 -- high bound of the slice, since it may underflow if the
3431 -- low bound is Ityp'First.
3433 Assign :=
3434 Make_Implicit_If_Statement (Cnode,
3435 Condition =>
3436 Make_Op_Ne (Loc,
3437 Left_Opnd =>
3438 New_Occurrence_Of (Var_Length (J), Loc),
3439 Right_Opnd => Make_Integer_Literal (Loc, 0)),
3440 Then_Statements => New_List (Assign));
3441 end if;
3443 Insert_Action (Cnode, Assign, Suppress => All_Checks);
3444 end;
3445 end if;
3446 end;
3447 end loop;
3449 -- Finally we build the result, which is a reference to the array object
3451 Result := New_Reference_To (Ent, Loc);
3453 <<Done>>
3454 Rewrite (Cnode, Result);
3455 Analyze_And_Resolve (Cnode, Atyp);
3457 exception
3458 when Concatenation_Error =>
3460 -- Kill warning generated for the declaration of the static out of
3461 -- range high bound, and instead generate a Constraint_Error with
3462 -- an appropriate specific message.
3464 Kill_Dead_Code (Declaration_Node (Entity (High_Bound)));
3465 Apply_Compile_Time_Constraint_Error
3466 (N => Cnode,
3467 Msg => "concatenation result upper bound out of range?",
3468 Reason => CE_Range_Check_Failed);
3469 -- Set_Etype (Cnode, Atyp);
3470 end Expand_Concatenate;
3472 ------------------------
3473 -- Expand_N_Allocator --
3474 ------------------------
3476 procedure Expand_N_Allocator (N : Node_Id) is
3477 PtrT : constant Entity_Id := Etype (N);
3478 Dtyp : constant Entity_Id := Available_View (Designated_Type (PtrT));
3479 Etyp : constant Entity_Id := Etype (Expression (N));
3480 Loc : constant Source_Ptr := Sloc (N);
3481 Desig : Entity_Id;
3482 Nod : Node_Id;
3483 Pool : Entity_Id;
3484 Temp : Entity_Id;
3486 procedure Rewrite_Coextension (N : Node_Id);
3487 -- Static coextensions have the same lifetime as the entity they
3488 -- constrain. Such occurrences can be rewritten as aliased objects
3489 -- and their unrestricted access used instead of the coextension.
3491 function Size_In_Storage_Elements (E : Entity_Id) return Node_Id;
3492 -- Given a constrained array type E, returns a node representing the
3493 -- code to compute the size in storage elements for the given type.
3494 -- This is done without using the attribute (which malfunctions for
3495 -- large sizes ???)
3497 -------------------------
3498 -- Rewrite_Coextension --
3499 -------------------------
3501 procedure Rewrite_Coextension (N : Node_Id) is
3502 Temp_Id : constant Node_Id := Make_Temporary (Loc, 'C');
3503 Temp_Decl : Node_Id;
3505 begin
3506 -- Generate:
3507 -- Cnn : aliased Etyp;
3509 Temp_Decl :=
3510 Make_Object_Declaration (Loc,
3511 Defining_Identifier => Temp_Id,
3512 Aliased_Present => True,
3513 Object_Definition => New_Occurrence_Of (Etyp, Loc));
3515 if Nkind (Expression (N)) = N_Qualified_Expression then
3516 Set_Expression (Temp_Decl, Expression (Expression (N)));
3517 end if;
3519 Insert_Action (N, Temp_Decl);
3520 Rewrite (N,
3521 Make_Attribute_Reference (Loc,
3522 Prefix => New_Occurrence_Of (Temp_Id, Loc),
3523 Attribute_Name => Name_Unrestricted_Access));
3525 Analyze_And_Resolve (N, PtrT);
3526 end Rewrite_Coextension;
3528 ------------------------------
3529 -- Size_In_Storage_Elements --
3530 ------------------------------
3532 function Size_In_Storage_Elements (E : Entity_Id) return Node_Id is
3533 begin
3534 -- Logically this just returns E'Max_Size_In_Storage_Elements.
3535 -- However, the reason for the existence of this function is
3536 -- to construct a test for sizes too large, which means near the
3537 -- 32-bit limit on a 32-bit machine, and precisely the trouble
3538 -- is that we get overflows when sizes are greater than 2**31.
3540 -- So what we end up doing for array types is to use the expression:
3542 -- number-of-elements * component_type'Max_Size_In_Storage_Elements
3544 -- which avoids this problem. All this is a bit bogus, but it does
3545 -- mean we catch common cases of trying to allocate arrays that
3546 -- are too large, and which in the absence of a check results in
3547 -- undetected chaos ???
3549 declare
3550 Len : Node_Id;
3551 Res : Node_Id;
3553 begin
3554 for J in 1 .. Number_Dimensions (E) loop
3555 Len :=
3556 Make_Attribute_Reference (Loc,
3557 Prefix => New_Occurrence_Of (E, Loc),
3558 Attribute_Name => Name_Length,
3559 Expressions => New_List (Make_Integer_Literal (Loc, J)));
3561 if J = 1 then
3562 Res := Len;
3564 else
3565 Res :=
3566 Make_Op_Multiply (Loc,
3567 Left_Opnd => Res,
3568 Right_Opnd => Len);
3569 end if;
3570 end loop;
3572 return
3573 Make_Op_Multiply (Loc,
3574 Left_Opnd => Len,
3575 Right_Opnd =>
3576 Make_Attribute_Reference (Loc,
3577 Prefix => New_Occurrence_Of (Component_Type (E), Loc),
3578 Attribute_Name => Name_Max_Size_In_Storage_Elements));
3579 end;
3580 end Size_In_Storage_Elements;
3582 -- Start of processing for Expand_N_Allocator
3584 begin
3585 -- RM E.2.3(22). We enforce that the expected type of an allocator
3586 -- shall not be a remote access-to-class-wide-limited-private type
3588 -- Why is this being done at expansion time, seems clearly wrong ???
3590 Validate_Remote_Access_To_Class_Wide_Type (N);
3592 -- Processing for anonymous access-to-controlled types. These access
3593 -- types receive a special finalization master which appears in the
3594 -- declarations of the enclosing semantic unit. This expansion is done
3595 -- now to ensure that any additional types generated by this routine or
3596 -- Expand_Allocator_Expression inherit the proper type attributes.
3598 if (Ekind (PtrT) = E_Anonymous_Access_Type
3599 or else
3600 (Is_Itype (PtrT) and then No (Finalization_Master (PtrT))))
3601 and then Needs_Finalization (Dtyp)
3602 then
3603 -- Anonymous access-to-controlled types allocate on the global pool.
3604 -- Do not set this attribute on .NET/JVM since those targets do not
3605 -- support pools.
3607 if No (Associated_Storage_Pool (PtrT)) and then VM_Target = No_VM then
3608 Set_Associated_Storage_Pool
3609 (PtrT, Get_Global_Pool_For_Access_Type (PtrT));
3610 end if;
3612 -- The finalization master must be inserted and analyzed as part of
3613 -- the current semantic unit. This form of expansion is not carried
3614 -- out in Alfa mode because it is useless. Note that the master is
3615 -- updated when analysis changes current units.
3617 if not Alfa_Mode then
3618 Set_Finalization_Master (PtrT, Current_Anonymous_Master);
3619 end if;
3620 end if;
3622 -- Set the storage pool and find the appropriate version of Allocate to
3623 -- call. Do not overwrite the storage pool if it is already set, which
3624 -- can happen for build-in-place function returns (see
3625 -- Exp_Ch4.Expand_N_Extended_Return_Statement).
3627 if No (Storage_Pool (N)) then
3628 Pool := Associated_Storage_Pool (Root_Type (PtrT));
3630 if Present (Pool) then
3631 Set_Storage_Pool (N, Pool);
3633 if Is_RTE (Pool, RE_SS_Pool) then
3634 if VM_Target = No_VM then
3635 Set_Procedure_To_Call (N, RTE (RE_SS_Allocate));
3636 end if;
3638 -- In the case of an allocator for a simple storage pool, locate
3639 -- and save a reference to the pool type's Allocate routine.
3641 elsif Present (Get_Rep_Pragma
3642 (Etype (Pool), Name_Simple_Storage_Pool_Type))
3643 then
3644 declare
3645 Pool_Type : constant Entity_Id := Base_Type (Etype (Pool));
3646 Alloc_Op : Entity_Id;
3647 begin
3648 Alloc_Op := Get_Name_Entity_Id (Name_Allocate);
3649 while Present (Alloc_Op) loop
3650 if Scope (Alloc_Op) = Scope (Pool_Type)
3651 and then Present (First_Formal (Alloc_Op))
3652 and then Etype (First_Formal (Alloc_Op)) = Pool_Type
3653 then
3654 Set_Procedure_To_Call (N, Alloc_Op);
3655 exit;
3656 else
3657 Alloc_Op := Homonym (Alloc_Op);
3658 end if;
3659 end loop;
3660 end;
3662 elsif Is_Class_Wide_Type (Etype (Pool)) then
3663 Set_Procedure_To_Call (N, RTE (RE_Allocate_Any));
3665 else
3666 Set_Procedure_To_Call (N,
3667 Find_Prim_Op (Etype (Pool), Name_Allocate));
3668 end if;
3669 end if;
3670 end if;
3672 -- Under certain circumstances we can replace an allocator by an access
3673 -- to statically allocated storage. The conditions, as noted in AARM
3674 -- 3.10 (10c) are as follows:
3676 -- Size and initial value is known at compile time
3677 -- Access type is access-to-constant
3679 -- The allocator is not part of a constraint on a record component,
3680 -- because in that case the inserted actions are delayed until the
3681 -- record declaration is fully analyzed, which is too late for the
3682 -- analysis of the rewritten allocator.
3684 if Is_Access_Constant (PtrT)
3685 and then Nkind (Expression (N)) = N_Qualified_Expression
3686 and then Compile_Time_Known_Value (Expression (Expression (N)))
3687 and then Size_Known_At_Compile_Time
3688 (Etype (Expression (Expression (N))))
3689 and then not Is_Record_Type (Current_Scope)
3690 then
3691 -- Here we can do the optimization. For the allocator
3693 -- new x'(y)
3695 -- We insert an object declaration
3697 -- Tnn : aliased x := y;
3699 -- and replace the allocator by Tnn'Unrestricted_Access. Tnn is
3700 -- marked as requiring static allocation.
3702 Temp := Make_Temporary (Loc, 'T', Expression (Expression (N)));
3703 Desig := Subtype_Mark (Expression (N));
3705 -- If context is constrained, use constrained subtype directly,
3706 -- so that the constant is not labelled as having a nominally
3707 -- unconstrained subtype.
3709 if Entity (Desig) = Base_Type (Dtyp) then
3710 Desig := New_Occurrence_Of (Dtyp, Loc);
3711 end if;
3713 Insert_Action (N,
3714 Make_Object_Declaration (Loc,
3715 Defining_Identifier => Temp,
3716 Aliased_Present => True,
3717 Constant_Present => Is_Access_Constant (PtrT),
3718 Object_Definition => Desig,
3719 Expression => Expression (Expression (N))));
3721 Rewrite (N,
3722 Make_Attribute_Reference (Loc,
3723 Prefix => New_Occurrence_Of (Temp, Loc),
3724 Attribute_Name => Name_Unrestricted_Access));
3726 Analyze_And_Resolve (N, PtrT);
3728 -- We set the variable as statically allocated, since we don't want
3729 -- it going on the stack of the current procedure!
3731 Set_Is_Statically_Allocated (Temp);
3732 return;
3733 end if;
3735 -- Same if the allocator is an access discriminant for a local object:
3736 -- instead of an allocator we create a local value and constrain the
3737 -- enclosing object with the corresponding access attribute.
3739 if Is_Static_Coextension (N) then
3740 Rewrite_Coextension (N);
3741 return;
3742 end if;
3744 -- Check for size too large, we do this because the back end misses
3745 -- proper checks here and can generate rubbish allocation calls when
3746 -- we are near the limit. We only do this for the 32-bit address case
3747 -- since that is from a practical point of view where we see a problem.
3749 if System_Address_Size = 32
3750 and then not Storage_Checks_Suppressed (PtrT)
3751 and then not Storage_Checks_Suppressed (Dtyp)
3752 and then not Storage_Checks_Suppressed (Etyp)
3753 then
3754 -- The check we want to generate should look like
3756 -- if Etyp'Max_Size_In_Storage_Elements > 3.5 gigabytes then
3757 -- raise Storage_Error;
3758 -- end if;
3760 -- where 3.5 gigabytes is a constant large enough to accommodate any
3761 -- reasonable request for. But we can't do it this way because at
3762 -- least at the moment we don't compute this attribute right, and
3763 -- can silently give wrong results when the result gets large. Since
3764 -- this is all about large results, that's bad, so instead we only
3765 -- apply the check for constrained arrays, and manually compute the
3766 -- value of the attribute ???
3768 if Is_Array_Type (Etyp) and then Is_Constrained (Etyp) then
3769 Insert_Action (N,
3770 Make_Raise_Storage_Error (Loc,
3771 Condition =>
3772 Make_Op_Gt (Loc,
3773 Left_Opnd => Size_In_Storage_Elements (Etyp),
3774 Right_Opnd =>
3775 Make_Integer_Literal (Loc, Uint_7 * (Uint_2 ** 29))),
3776 Reason => SE_Object_Too_Large));
3777 end if;
3778 end if;
3780 -- Handle case of qualified expression (other than optimization above)
3781 -- First apply constraint checks, because the bounds or discriminants
3782 -- in the aggregate might not match the subtype mark in the allocator.
3784 if Nkind (Expression (N)) = N_Qualified_Expression then
3785 Apply_Constraint_Check
3786 (Expression (Expression (N)), Etype (Expression (N)));
3788 Expand_Allocator_Expression (N);
3789 return;
3790 end if;
3792 -- If the allocator is for a type which requires initialization, and
3793 -- there is no initial value (i.e. operand is a subtype indication
3794 -- rather than a qualified expression), then we must generate a call to
3795 -- the initialization routine using an expressions action node:
3797 -- [Pnnn : constant ptr_T := new (T); Init (Pnnn.all,...); Pnnn]
3799 -- Here ptr_T is the pointer type for the allocator, and T is the
3800 -- subtype of the allocator. A special case arises if the designated
3801 -- type of the access type is a task or contains tasks. In this case
3802 -- the call to Init (Temp.all ...) is replaced by code that ensures
3803 -- that tasks get activated (see Exp_Ch9.Build_Task_Allocate_Block
3804 -- for details). In addition, if the type T is a task T, then the
3805 -- first argument to Init must be converted to the task record type.
3807 declare
3808 T : constant Entity_Id := Entity (Expression (N));
3809 Args : List_Id;
3810 Decls : List_Id;
3811 Decl : Node_Id;
3812 Discr : Elmt_Id;
3813 Init : Entity_Id;
3814 Init_Arg1 : Node_Id;
3815 Temp_Decl : Node_Id;
3816 Temp_Type : Entity_Id;
3818 begin
3819 if No_Initialization (N) then
3821 -- Even though this might be a simple allocation, create a custom
3822 -- Allocate if the context requires it. Since .NET/JVM compilers
3823 -- do not support pools, this step is skipped.
3825 if VM_Target = No_VM
3826 and then Present (Finalization_Master (PtrT))
3827 then
3828 Build_Allocate_Deallocate_Proc
3829 (N => N,
3830 Is_Allocate => True);
3831 end if;
3833 -- Case of no initialization procedure present
3835 elsif not Has_Non_Null_Base_Init_Proc (T) then
3837 -- Case of simple initialization required
3839 if Needs_Simple_Initialization (T) then
3840 Check_Restriction (No_Default_Initialization, N);
3841 Rewrite (Expression (N),
3842 Make_Qualified_Expression (Loc,
3843 Subtype_Mark => New_Occurrence_Of (T, Loc),
3844 Expression => Get_Simple_Init_Val (T, N)));
3846 Analyze_And_Resolve (Expression (Expression (N)), T);
3847 Analyze_And_Resolve (Expression (N), T);
3848 Set_Paren_Count (Expression (Expression (N)), 1);
3849 Expand_N_Allocator (N);
3851 -- No initialization required
3853 else
3854 null;
3855 end if;
3857 -- Case of initialization procedure present, must be called
3859 else
3860 Check_Restriction (No_Default_Initialization, N);
3862 if not Restriction_Active (No_Default_Initialization) then
3863 Init := Base_Init_Proc (T);
3864 Nod := N;
3865 Temp := Make_Temporary (Loc, 'P');
3867 -- Construct argument list for the initialization routine call
3869 Init_Arg1 :=
3870 Make_Explicit_Dereference (Loc,
3871 Prefix =>
3872 New_Reference_To (Temp, Loc));
3874 Set_Assignment_OK (Init_Arg1);
3875 Temp_Type := PtrT;
3877 -- The initialization procedure expects a specific type. if the
3878 -- context is access to class wide, indicate that the object
3879 -- being allocated has the right specific type.
3881 if Is_Class_Wide_Type (Dtyp) then
3882 Init_Arg1 := Unchecked_Convert_To (T, Init_Arg1);
3883 end if;
3885 -- If designated type is a concurrent type or if it is private
3886 -- type whose definition is a concurrent type, the first
3887 -- argument in the Init routine has to be unchecked conversion
3888 -- to the corresponding record type. If the designated type is
3889 -- a derived type, also convert the argument to its root type.
3891 if Is_Concurrent_Type (T) then
3892 Init_Arg1 :=
3893 Unchecked_Convert_To (
3894 Corresponding_Record_Type (T), Init_Arg1);
3896 elsif Is_Private_Type (T)
3897 and then Present (Full_View (T))
3898 and then Is_Concurrent_Type (Full_View (T))
3899 then
3900 Init_Arg1 :=
3901 Unchecked_Convert_To
3902 (Corresponding_Record_Type (Full_View (T)), Init_Arg1);
3904 elsif Etype (First_Formal (Init)) /= Base_Type (T) then
3905 declare
3906 Ftyp : constant Entity_Id := Etype (First_Formal (Init));
3908 begin
3909 Init_Arg1 := OK_Convert_To (Etype (Ftyp), Init_Arg1);
3910 Set_Etype (Init_Arg1, Ftyp);
3911 end;
3912 end if;
3914 Args := New_List (Init_Arg1);
3916 -- For the task case, pass the Master_Id of the access type as
3917 -- the value of the _Master parameter, and _Chain as the value
3918 -- of the _Chain parameter (_Chain will be defined as part of
3919 -- the generated code for the allocator).
3921 -- In Ada 2005, the context may be a function that returns an
3922 -- anonymous access type. In that case the Master_Id has been
3923 -- created when expanding the function declaration.
3925 if Has_Task (T) then
3926 if No (Master_Id (Base_Type (PtrT))) then
3928 -- The designated type was an incomplete type, and the
3929 -- access type did not get expanded. Salvage it now.
3931 if not Restriction_Active (No_Task_Hierarchy) then
3932 pragma Assert (Present (Parent (Base_Type (PtrT))));
3933 Expand_N_Full_Type_Declaration
3934 (Parent (Base_Type (PtrT)));
3935 end if;
3936 end if;
3938 -- If the context of the allocator is a declaration or an
3939 -- assignment, we can generate a meaningful image for it,
3940 -- even though subsequent assignments might remove the
3941 -- connection between task and entity. We build this image
3942 -- when the left-hand side is a simple variable, a simple
3943 -- indexed assignment or a simple selected component.
3945 if Nkind (Parent (N)) = N_Assignment_Statement then
3946 declare
3947 Nam : constant Node_Id := Name (Parent (N));
3949 begin
3950 if Is_Entity_Name (Nam) then
3951 Decls :=
3952 Build_Task_Image_Decls
3953 (Loc,
3954 New_Occurrence_Of
3955 (Entity (Nam), Sloc (Nam)), T);
3957 elsif Nkind_In (Nam, N_Indexed_Component,
3958 N_Selected_Component)
3959 and then Is_Entity_Name (Prefix (Nam))
3960 then
3961 Decls :=
3962 Build_Task_Image_Decls
3963 (Loc, Nam, Etype (Prefix (Nam)));
3964 else
3965 Decls := Build_Task_Image_Decls (Loc, T, T);
3966 end if;
3967 end;
3969 elsif Nkind (Parent (N)) = N_Object_Declaration then
3970 Decls :=
3971 Build_Task_Image_Decls
3972 (Loc, Defining_Identifier (Parent (N)), T);
3974 else
3975 Decls := Build_Task_Image_Decls (Loc, T, T);
3976 end if;
3978 if Restriction_Active (No_Task_Hierarchy) then
3979 Append_To (Args,
3980 New_Occurrence_Of (RTE (RE_Library_Task_Level), Loc));
3981 else
3982 Append_To (Args,
3983 New_Reference_To
3984 (Master_Id (Base_Type (Root_Type (PtrT))), Loc));
3985 end if;
3987 Append_To (Args, Make_Identifier (Loc, Name_uChain));
3989 Decl := Last (Decls);
3990 Append_To (Args,
3991 New_Occurrence_Of (Defining_Identifier (Decl), Loc));
3993 -- Has_Task is false, Decls not used
3995 else
3996 Decls := No_List;
3997 end if;
3999 -- Add discriminants if discriminated type
4001 declare
4002 Dis : Boolean := False;
4003 Typ : Entity_Id;
4005 begin
4006 if Has_Discriminants (T) then
4007 Dis := True;
4008 Typ := T;
4010 elsif Is_Private_Type (T)
4011 and then Present (Full_View (T))
4012 and then Has_Discriminants (Full_View (T))
4013 then
4014 Dis := True;
4015 Typ := Full_View (T);
4016 end if;
4018 if Dis then
4020 -- If the allocated object will be constrained by the
4021 -- default values for discriminants, then build a subtype
4022 -- with those defaults, and change the allocated subtype
4023 -- to that. Note that this happens in fewer cases in Ada
4024 -- 2005 (AI-363).
4026 if not Is_Constrained (Typ)
4027 and then Present (Discriminant_Default_Value
4028 (First_Discriminant (Typ)))
4029 and then (Ada_Version < Ada_2005
4030 or else not
4031 Effectively_Has_Constrained_Partial_View
4032 (Typ => Typ,
4033 Scop => Current_Scope))
4034 then
4035 Typ := Build_Default_Subtype (Typ, N);
4036 Set_Expression (N, New_Reference_To (Typ, Loc));
4037 end if;
4039 Discr := First_Elmt (Discriminant_Constraint (Typ));
4040 while Present (Discr) loop
4041 Nod := Node (Discr);
4042 Append (New_Copy_Tree (Node (Discr)), Args);
4044 -- AI-416: when the discriminant constraint is an
4045 -- anonymous access type make sure an accessibility
4046 -- check is inserted if necessary (3.10.2(22.q/2))
4048 if Ada_Version >= Ada_2005
4049 and then
4050 Ekind (Etype (Nod)) = E_Anonymous_Access_Type
4051 then
4052 Apply_Accessibility_Check
4053 (Nod, Typ, Insert_Node => Nod);
4054 end if;
4056 Next_Elmt (Discr);
4057 end loop;
4058 end if;
4059 end;
4061 -- We set the allocator as analyzed so that when we analyze
4062 -- the conditional expression node, we do not get an unwanted
4063 -- recursive expansion of the allocator expression.
4065 Set_Analyzed (N, True);
4066 Nod := Relocate_Node (N);
4068 -- Here is the transformation:
4069 -- input: new Ctrl_Typ
4070 -- output: Temp : constant Ctrl_Typ_Ptr := new Ctrl_Typ;
4071 -- Ctrl_TypIP (Temp.all, ...);
4072 -- [Deep_]Initialize (Temp.all);
4074 -- Here Ctrl_Typ_Ptr is the pointer type for the allocator, and
4075 -- is the subtype of the allocator.
4077 Temp_Decl :=
4078 Make_Object_Declaration (Loc,
4079 Defining_Identifier => Temp,
4080 Constant_Present => True,
4081 Object_Definition => New_Reference_To (Temp_Type, Loc),
4082 Expression => Nod);
4084 Set_Assignment_OK (Temp_Decl);
4085 Insert_Action (N, Temp_Decl, Suppress => All_Checks);
4087 Build_Allocate_Deallocate_Proc (Temp_Decl, True);
4089 -- If the designated type is a task type or contains tasks,
4090 -- create block to activate created tasks, and insert
4091 -- declaration for Task_Image variable ahead of call.
4093 if Has_Task (T) then
4094 declare
4095 L : constant List_Id := New_List;
4096 Blk : Node_Id;
4097 begin
4098 Build_Task_Allocate_Block (L, Nod, Args);
4099 Blk := Last (L);
4100 Insert_List_Before (First (Declarations (Blk)), Decls);
4101 Insert_Actions (N, L);
4102 end;
4104 else
4105 Insert_Action (N,
4106 Make_Procedure_Call_Statement (Loc,
4107 Name => New_Reference_To (Init, Loc),
4108 Parameter_Associations => Args));
4109 end if;
4111 if Needs_Finalization (T) then
4113 -- Generate:
4114 -- [Deep_]Initialize (Init_Arg1);
4116 Insert_Action (N,
4117 Make_Init_Call
4118 (Obj_Ref => New_Copy_Tree (Init_Arg1),
4119 Typ => T));
4121 if Present (Finalization_Master (PtrT)) then
4123 -- Special processing for .NET/JVM, the allocated object
4124 -- is attached to the finalization master. Generate:
4126 -- Attach (<PtrT>FM, Root_Controlled_Ptr (Init_Arg1));
4128 -- Types derived from [Limited_]Controlled are the only
4129 -- ones considered since they have fields Prev and Next.
4131 if VM_Target /= No_VM then
4132 if Is_Controlled (T) then
4133 Insert_Action (N,
4134 Make_Attach_Call
4135 (Obj_Ref => New_Copy_Tree (Init_Arg1),
4136 Ptr_Typ => PtrT));
4137 end if;
4139 -- Default case, generate:
4141 -- Set_Finalize_Address
4142 -- (<PtrT>FM, <T>FD'Unrestricted_Access);
4144 -- Do not generate this call in the following cases:
4146 -- * Alfa mode - the call is useless and results in
4147 -- unwanted expansion.
4149 -- * CodePeer mode - TSS primitive Finalize_Address is
4150 -- not created in this mode.
4152 elsif not Alfa_Mode
4153 and then not CodePeer_Mode
4154 then
4155 Insert_Action (N,
4156 Make_Set_Finalize_Address_Call
4157 (Loc => Loc,
4158 Typ => T,
4159 Ptr_Typ => PtrT));
4160 end if;
4161 end if;
4162 end if;
4164 Rewrite (N, New_Reference_To (Temp, Loc));
4165 Analyze_And_Resolve (N, PtrT);
4166 end if;
4167 end if;
4168 end;
4170 -- Ada 2005 (AI-251): If the allocator is for a class-wide interface
4171 -- object that has been rewritten as a reference, we displace "this"
4172 -- to reference properly its secondary dispatch table.
4174 if Nkind (N) = N_Identifier
4175 and then Is_Interface (Dtyp)
4176 then
4177 Displace_Allocator_Pointer (N);
4178 end if;
4180 exception
4181 when RE_Not_Available =>
4182 return;
4183 end Expand_N_Allocator;
4185 -----------------------
4186 -- Expand_N_And_Then --
4187 -----------------------
4189 procedure Expand_N_And_Then (N : Node_Id)
4190 renames Expand_Short_Circuit_Operator;
4192 ------------------------------
4193 -- Expand_N_Case_Expression --
4194 ------------------------------
4196 procedure Expand_N_Case_Expression (N : Node_Id) is
4197 Loc : constant Source_Ptr := Sloc (N);
4198 Typ : constant Entity_Id := Etype (N);
4199 Cstmt : Node_Id;
4200 Tnn : Entity_Id;
4201 Pnn : Entity_Id;
4202 Actions : List_Id;
4203 Ttyp : Entity_Id;
4204 Alt : Node_Id;
4205 Fexp : Node_Id;
4207 begin
4208 -- We expand
4210 -- case X is when A => AX, when B => BX ...
4212 -- to
4214 -- do
4215 -- Tnn : typ;
4216 -- case X is
4217 -- when A =>
4218 -- Tnn := AX;
4219 -- when B =>
4220 -- Tnn := BX;
4221 -- ...
4222 -- end case;
4223 -- in Tnn end;
4225 -- However, this expansion is wrong for limited types, and also
4226 -- wrong for unconstrained types (since the bounds may not be the
4227 -- same in all branches). Furthermore it involves an extra copy
4228 -- for large objects. So we take care of this by using the following
4229 -- modified expansion for non-scalar types:
4231 -- do
4232 -- type Pnn is access all typ;
4233 -- Tnn : Pnn;
4234 -- case X is
4235 -- when A =>
4236 -- T := AX'Unrestricted_Access;
4237 -- when B =>
4238 -- T := BX'Unrestricted_Access;
4239 -- ...
4240 -- end case;
4241 -- in Tnn.all end;
4243 Cstmt :=
4244 Make_Case_Statement (Loc,
4245 Expression => Expression (N),
4246 Alternatives => New_List);
4248 Actions := New_List;
4250 -- Scalar case
4252 if Is_Scalar_Type (Typ) then
4253 Ttyp := Typ;
4255 else
4256 Pnn := Make_Temporary (Loc, 'P');
4257 Append_To (Actions,
4258 Make_Full_Type_Declaration (Loc,
4259 Defining_Identifier => Pnn,
4260 Type_Definition =>
4261 Make_Access_To_Object_Definition (Loc,
4262 All_Present => True,
4263 Subtype_Indication =>
4264 New_Reference_To (Typ, Loc))));
4265 Ttyp := Pnn;
4266 end if;
4268 Tnn := Make_Temporary (Loc, 'T');
4269 Append_To (Actions,
4270 Make_Object_Declaration (Loc,
4271 Defining_Identifier => Tnn,
4272 Object_Definition => New_Occurrence_Of (Ttyp, Loc)));
4274 -- Now process the alternatives
4276 Alt := First (Alternatives (N));
4277 while Present (Alt) loop
4278 declare
4279 Aexp : Node_Id := Expression (Alt);
4280 Aloc : constant Source_Ptr := Sloc (Aexp);
4281 Stats : List_Id;
4283 begin
4284 -- As described above, take Unrestricted_Access for case of non-
4285 -- scalar types, to avoid big copies, and special cases.
4287 if not Is_Scalar_Type (Typ) then
4288 Aexp :=
4289 Make_Attribute_Reference (Aloc,
4290 Prefix => Relocate_Node (Aexp),
4291 Attribute_Name => Name_Unrestricted_Access);
4292 end if;
4294 Stats := New_List (
4295 Make_Assignment_Statement (Aloc,
4296 Name => New_Occurrence_Of (Tnn, Loc),
4297 Expression => Aexp));
4299 -- Propagate declarations inserted in the node by Insert_Actions
4300 -- (for example, temporaries generated to remove side effects).
4301 -- These actions must remain attached to the alternative, given
4302 -- that they are generated by the corresponding expression.
4304 if Present (Sinfo.Actions (Alt)) then
4305 Prepend_List (Sinfo.Actions (Alt), Stats);
4306 end if;
4308 Append_To
4309 (Alternatives (Cstmt),
4310 Make_Case_Statement_Alternative (Sloc (Alt),
4311 Discrete_Choices => Discrete_Choices (Alt),
4312 Statements => Stats));
4313 end;
4315 Next (Alt);
4316 end loop;
4318 Append_To (Actions, Cstmt);
4320 -- Construct and return final expression with actions
4322 if Is_Scalar_Type (Typ) then
4323 Fexp := New_Occurrence_Of (Tnn, Loc);
4324 else
4325 Fexp :=
4326 Make_Explicit_Dereference (Loc,
4327 Prefix => New_Occurrence_Of (Tnn, Loc));
4328 end if;
4330 Rewrite (N,
4331 Make_Expression_With_Actions (Loc,
4332 Expression => Fexp,
4333 Actions => Actions));
4335 Analyze_And_Resolve (N, Typ);
4336 end Expand_N_Case_Expression;
4338 -------------------------------------
4339 -- Expand_N_Conditional_Expression --
4340 -------------------------------------
4342 -- Deal with limited types and condition actions
4344 procedure Expand_N_Conditional_Expression (N : Node_Id) is
4345 function Create_Alternative
4346 (Loc : Source_Ptr;
4347 Temp_Id : Entity_Id;
4348 Flag_Id : Entity_Id;
4349 Expr : Node_Id) return List_Id;
4350 -- Build the statements of a "then" or "else" conditional expression
4351 -- alternative. Temp_Id is the conditional expression result, Flag_Id
4352 -- is a finalization flag created to service expression Expr.
4354 function Is_Controlled_Function_Call (Expr : Node_Id) return Boolean;
4355 -- Determine if expression Expr is a rewritten controlled function call
4357 ------------------------
4358 -- Create_Alternative --
4359 ------------------------
4361 function Create_Alternative
4362 (Loc : Source_Ptr;
4363 Temp_Id : Entity_Id;
4364 Flag_Id : Entity_Id;
4365 Expr : Node_Id) return List_Id
4367 Result : constant List_Id := New_List;
4369 begin
4370 -- Generate:
4371 -- Fnn := True;
4373 if Present (Flag_Id)
4374 and then not Is_Controlled_Function_Call (Expr)
4375 then
4376 Append_To (Result,
4377 Make_Assignment_Statement (Loc,
4378 Name => New_Reference_To (Flag_Id, Loc),
4379 Expression => New_Reference_To (Standard_True, Loc)));
4380 end if;
4382 -- Generate:
4383 -- Cnn := <expr>'Unrestricted_Access;
4385 Append_To (Result,
4386 Make_Assignment_Statement (Loc,
4387 Name => New_Reference_To (Temp_Id, Loc),
4388 Expression =>
4389 Make_Attribute_Reference (Loc,
4390 Prefix => Relocate_Node (Expr),
4391 Attribute_Name => Name_Unrestricted_Access)));
4393 return Result;
4394 end Create_Alternative;
4396 ---------------------------------
4397 -- Is_Controlled_Function_Call --
4398 ---------------------------------
4400 function Is_Controlled_Function_Call (Expr : Node_Id) return Boolean is
4401 begin
4402 return
4403 Nkind (Original_Node (Expr)) = N_Function_Call
4404 and then Needs_Finalization (Etype (Expr));
4405 end Is_Controlled_Function_Call;
4407 -- Local variables
4409 Loc : constant Source_Ptr := Sloc (N);
4410 Cond : constant Node_Id := First (Expressions (N));
4411 Thenx : constant Node_Id := Next (Cond);
4412 Elsex : constant Node_Id := Next (Thenx);
4413 Typ : constant Entity_Id := Etype (N);
4415 Actions : List_Id;
4416 Cnn : Entity_Id;
4417 Decl : Node_Id;
4418 Expr : Node_Id;
4419 New_If : Node_Id;
4420 New_N : Node_Id;
4422 begin
4423 -- Fold at compile time if condition known. We have already folded
4424 -- static conditional expressions, but it is possible to fold any
4425 -- case in which the condition is known at compile time, even though
4426 -- the result is non-static.
4428 -- Note that we don't do the fold of such cases in Sem_Elab because
4429 -- it can cause infinite loops with the expander adding a conditional
4430 -- expression, and Sem_Elab circuitry removing it repeatedly.
4432 if Compile_Time_Known_Value (Cond) then
4433 if Is_True (Expr_Value (Cond)) then
4434 Expr := Thenx;
4435 Actions := Then_Actions (N);
4436 else
4437 Expr := Elsex;
4438 Actions := Else_Actions (N);
4439 end if;
4441 Remove (Expr);
4443 if Present (Actions) then
4445 -- If we are not allowed to use Expression_With_Actions, just skip
4446 -- the optimization, it is not critical for correctness.
4448 if not Use_Expression_With_Actions then
4449 goto Skip_Optimization;
4450 end if;
4452 Rewrite (N,
4453 Make_Expression_With_Actions (Loc,
4454 Expression => Relocate_Node (Expr),
4455 Actions => Actions));
4456 Analyze_And_Resolve (N, Typ);
4458 else
4459 Rewrite (N, Relocate_Node (Expr));
4460 end if;
4462 -- Note that the result is never static (legitimate cases of static
4463 -- conditional expressions were folded in Sem_Eval).
4465 Set_Is_Static_Expression (N, False);
4466 return;
4467 end if;
4469 <<Skip_Optimization>>
4471 -- If the type is limited or unconstrained, we expand as follows to
4472 -- avoid any possibility of improper copies.
4474 -- Note: it may be possible to avoid this special processing if the
4475 -- back end uses its own mechanisms for handling by-reference types ???
4477 -- type Ptr is access all Typ;
4478 -- Cnn : Ptr;
4479 -- if cond then
4480 -- <<then actions>>
4481 -- Cnn := then-expr'Unrestricted_Access;
4482 -- else
4483 -- <<else actions>>
4484 -- Cnn := else-expr'Unrestricted_Access;
4485 -- end if;
4487 -- and replace the conditional expression by a reference to Cnn.all.
4489 -- This special case can be skipped if the back end handles limited
4490 -- types properly and ensures that no incorrect copies are made.
4492 if Is_By_Reference_Type (Typ)
4493 and then not Back_End_Handles_Limited_Types
4494 then
4495 declare
4496 Flag_Id : Entity_Id;
4497 Ptr_Typ : Entity_Id;
4499 begin
4500 Flag_Id := Empty;
4502 -- At least one of the conditional expression alternatives uses a
4503 -- controlled function to provide the result. Create a status flag
4504 -- to signal the finalization machinery that Cnn needs special
4505 -- handling.
4507 if Is_Controlled_Function_Call (Thenx)
4508 or else
4509 Is_Controlled_Function_Call (Elsex)
4510 then
4511 Flag_Id := Make_Temporary (Loc, 'F');
4513 Insert_Action (N,
4514 Make_Object_Declaration (Loc,
4515 Defining_Identifier => Flag_Id,
4516 Object_Definition =>
4517 New_Reference_To (Standard_Boolean, Loc),
4518 Expression =>
4519 New_Reference_To (Standard_False, Loc)));
4520 end if;
4522 -- Generate:
4523 -- type Ann is access all Typ;
4525 Ptr_Typ := Make_Temporary (Loc, 'A');
4527 Insert_Action (N,
4528 Make_Full_Type_Declaration (Loc,
4529 Defining_Identifier => Ptr_Typ,
4530 Type_Definition =>
4531 Make_Access_To_Object_Definition (Loc,
4532 All_Present => True,
4533 Subtype_Indication => New_Reference_To (Typ, Loc))));
4535 -- Generate:
4536 -- Cnn : Ann;
4538 Cnn := Make_Temporary (Loc, 'C', N);
4539 Set_Ekind (Cnn, E_Variable);
4540 Set_Status_Flag_Or_Transient_Decl (Cnn, Flag_Id);
4542 Decl :=
4543 Make_Object_Declaration (Loc,
4544 Defining_Identifier => Cnn,
4545 Object_Definition => New_Occurrence_Of (Ptr_Typ, Loc));
4547 New_If :=
4548 Make_Implicit_If_Statement (N,
4549 Condition => Relocate_Node (Cond),
4550 Then_Statements =>
4551 Create_Alternative (Sloc (Thenx), Cnn, Flag_Id, Thenx),
4552 Else_Statements =>
4553 Create_Alternative (Sloc (Elsex), Cnn, Flag_Id, Elsex));
4555 New_N :=
4556 Make_Explicit_Dereference (Loc,
4557 Prefix => New_Occurrence_Of (Cnn, Loc));
4558 end;
4560 -- For other types, we only need to expand if there are other actions
4561 -- associated with either branch.
4563 elsif Present (Then_Actions (N)) or else Present (Else_Actions (N)) then
4565 -- We have two approaches to handling this. If we are allowed to use
4566 -- N_Expression_With_Actions, then we can just wrap the actions into
4567 -- the appropriate expression.
4569 if Use_Expression_With_Actions then
4570 if Present (Then_Actions (N)) then
4571 Rewrite (Thenx,
4572 Make_Expression_With_Actions (Sloc (Thenx),
4573 Actions => Then_Actions (N),
4574 Expression => Relocate_Node (Thenx)));
4575 Set_Then_Actions (N, No_List);
4576 Analyze_And_Resolve (Thenx, Typ);
4577 end if;
4579 if Present (Else_Actions (N)) then
4580 Rewrite (Elsex,
4581 Make_Expression_With_Actions (Sloc (Elsex),
4582 Actions => Else_Actions (N),
4583 Expression => Relocate_Node (Elsex)));
4584 Set_Else_Actions (N, No_List);
4585 Analyze_And_Resolve (Elsex, Typ);
4586 end if;
4588 return;
4590 -- if we can't use N_Expression_With_Actions nodes, then we insert
4591 -- the following sequence of actions (using Insert_Actions):
4593 -- Cnn : typ;
4594 -- if cond then
4595 -- <<then actions>>
4596 -- Cnn := then-expr;
4597 -- else
4598 -- <<else actions>>
4599 -- Cnn := else-expr
4600 -- end if;
4602 -- and replace the conditional expression by a reference to Cnn
4604 else
4605 Cnn := Make_Temporary (Loc, 'C', N);
4607 Decl :=
4608 Make_Object_Declaration (Loc,
4609 Defining_Identifier => Cnn,
4610 Object_Definition => New_Occurrence_Of (Typ, Loc));
4612 New_If :=
4613 Make_Implicit_If_Statement (N,
4614 Condition => Relocate_Node (Cond),
4616 Then_Statements => New_List (
4617 Make_Assignment_Statement (Sloc (Thenx),
4618 Name => New_Occurrence_Of (Cnn, Sloc (Thenx)),
4619 Expression => Relocate_Node (Thenx))),
4621 Else_Statements => New_List (
4622 Make_Assignment_Statement (Sloc (Elsex),
4623 Name => New_Occurrence_Of (Cnn, Sloc (Elsex)),
4624 Expression => Relocate_Node (Elsex))));
4626 Set_Assignment_OK (Name (First (Then_Statements (New_If))));
4627 Set_Assignment_OK (Name (First (Else_Statements (New_If))));
4629 New_N := New_Occurrence_Of (Cnn, Loc);
4630 end if;
4632 -- If no actions then no expansion needed, gigi will handle it using
4633 -- the same approach as a C conditional expression.
4635 else
4636 return;
4637 end if;
4639 -- Fall through here for either the limited expansion, or the case of
4640 -- inserting actions for non-limited types. In both these cases, we must
4641 -- move the SLOC of the parent If statement to the newly created one and
4642 -- change it to the SLOC of the expression which, after expansion, will
4643 -- correspond to what is being evaluated.
4645 if Present (Parent (N))
4646 and then Nkind (Parent (N)) = N_If_Statement
4647 then
4648 Set_Sloc (New_If, Sloc (Parent (N)));
4649 Set_Sloc (Parent (N), Loc);
4650 end if;
4652 -- Make sure Then_Actions and Else_Actions are appropriately moved
4653 -- to the new if statement.
4655 if Present (Then_Actions (N)) then
4656 Insert_List_Before
4657 (First (Then_Statements (New_If)), Then_Actions (N));
4658 end if;
4660 if Present (Else_Actions (N)) then
4661 Insert_List_Before
4662 (First (Else_Statements (New_If)), Else_Actions (N));
4663 end if;
4665 Insert_Action (N, Decl);
4666 Insert_Action (N, New_If);
4667 Rewrite (N, New_N);
4668 Analyze_And_Resolve (N, Typ);
4669 end Expand_N_Conditional_Expression;
4671 -----------------------------------
4672 -- Expand_N_Explicit_Dereference --
4673 -----------------------------------
4675 procedure Expand_N_Explicit_Dereference (N : Node_Id) is
4676 begin
4677 -- Insert explicit dereference call for the checked storage pool case
4679 Insert_Dereference_Action (Prefix (N));
4681 -- If the type is an Atomic type for which Atomic_Sync is enabled, then
4682 -- we set the atomic sync flag.
4684 if Is_Atomic (Etype (N))
4685 and then not Atomic_Synchronization_Disabled (Etype (N))
4686 then
4687 Activate_Atomic_Synchronization (N);
4688 end if;
4689 end Expand_N_Explicit_Dereference;
4691 --------------------------------------
4692 -- Expand_N_Expression_With_Actions --
4693 --------------------------------------
4695 procedure Expand_N_Expression_With_Actions (N : Node_Id) is
4697 procedure Process_Transient_Object (Decl : Node_Id);
4698 -- Given the declaration of a controlled transient declared inside the
4699 -- Actions list of an Expression_With_Actions, generate all necessary
4700 -- types and hooks in order to properly finalize the transient. This
4701 -- mechanism works in conjunction with Build_Finalizer.
4703 ------------------------------
4704 -- Process_Transient_Object --
4705 ------------------------------
4707 procedure Process_Transient_Object (Decl : Node_Id) is
4709 function Find_Insertion_Node return Node_Id;
4710 -- Complex conditions in if statements may be converted into nested
4711 -- EWAs. In this case, any generated code must be inserted before the
4712 -- if statement to ensure proper visibility of the hook objects. This
4713 -- routine returns the top most short circuit operator or the parent
4714 -- of the EWA if no nesting was detected.
4716 -------------------------
4717 -- Find_Insertion_Node --
4718 -------------------------
4720 function Find_Insertion_Node return Node_Id is
4721 Par : Node_Id;
4723 begin
4724 -- Climb up the branches of a complex condition
4726 Par := N;
4727 while Nkind_In (Parent (Par), N_And_Then, N_Op_Not, N_Or_Else) loop
4728 Par := Parent (Par);
4729 end loop;
4731 return Par;
4732 end Find_Insertion_Node;
4734 -- Local variables
4736 Ins_Node : constant Node_Id := Find_Insertion_Node;
4737 Loc : constant Source_Ptr := Sloc (Decl);
4738 Obj_Id : constant Entity_Id := Defining_Identifier (Decl);
4739 Obj_Typ : constant Entity_Id := Etype (Obj_Id);
4740 Desig_Typ : Entity_Id;
4741 Expr : Node_Id;
4742 Ptr_Decl : Node_Id;
4743 Ptr_Id : Entity_Id;
4744 Temp_Decl : Node_Id;
4745 Temp_Id : Node_Id;
4747 -- Start of processing for Process_Transient_Object
4749 begin
4750 -- Step 1: Create the access type which provides a reference to the
4751 -- transient object.
4753 if Is_Access_Type (Obj_Typ) then
4754 Desig_Typ := Directly_Designated_Type (Obj_Typ);
4755 else
4756 Desig_Typ := Obj_Typ;
4757 end if;
4759 -- Generate:
4760 -- Ann : access [all] <Desig_Typ>;
4762 Ptr_Id := Make_Temporary (Loc, 'A');
4764 Ptr_Decl :=
4765 Make_Full_Type_Declaration (Loc,
4766 Defining_Identifier => Ptr_Id,
4767 Type_Definition =>
4768 Make_Access_To_Object_Definition (Loc,
4769 All_Present =>
4770 Ekind (Obj_Typ) = E_General_Access_Type,
4771 Subtype_Indication => New_Reference_To (Desig_Typ, Loc)));
4773 Insert_Action (Ins_Node, Ptr_Decl);
4774 Analyze (Ptr_Decl);
4776 -- Step 2: Create a temporary which acts as a hook to the transient
4777 -- object. Generate:
4779 -- Temp : Ptr_Id := null;
4781 Temp_Id := Make_Temporary (Loc, 'T');
4783 Temp_Decl :=
4784 Make_Object_Declaration (Loc,
4785 Defining_Identifier => Temp_Id,
4786 Object_Definition => New_Reference_To (Ptr_Id, Loc));
4788 Insert_Action (Ins_Node, Temp_Decl);
4789 Analyze (Temp_Decl);
4791 -- Mark this temporary as created for the purposes of exporting the
4792 -- transient declaration out of the Actions list. This signals the
4793 -- machinery in Build_Finalizer to recognize this special case.
4795 Set_Status_Flag_Or_Transient_Decl (Temp_Id, Decl);
4797 -- Step 3: Hook the transient object to the temporary
4799 if Is_Access_Type (Obj_Typ) then
4800 Expr := Convert_To (Ptr_Id, New_Reference_To (Obj_Id, Loc));
4801 else
4802 Expr :=
4803 Make_Attribute_Reference (Loc,
4804 Prefix => New_Reference_To (Obj_Id, Loc),
4805 Attribute_Name => Name_Unrestricted_Access);
4806 end if;
4808 -- Generate:
4809 -- Temp := Ptr_Id (Obj_Id);
4810 -- <or>
4811 -- Temp := Obj_Id'Unrestricted_Access;
4813 Insert_After_And_Analyze (Decl,
4814 Make_Assignment_Statement (Loc,
4815 Name => New_Reference_To (Temp_Id, Loc),
4816 Expression => Expr));
4817 end Process_Transient_Object;
4819 -- Local variables
4821 Decl : Node_Id;
4823 -- Start of processing for Expand_N_Expression_With_Actions
4825 begin
4826 Decl := First (Actions (N));
4827 while Present (Decl) loop
4828 if Nkind (Decl) = N_Object_Declaration
4829 and then Is_Finalizable_Transient (Decl, N)
4830 then
4831 Process_Transient_Object (Decl);
4832 end if;
4834 Next (Decl);
4835 end loop;
4836 end Expand_N_Expression_With_Actions;
4838 -----------------
4839 -- Expand_N_In --
4840 -----------------
4842 procedure Expand_N_In (N : Node_Id) is
4843 Loc : constant Source_Ptr := Sloc (N);
4844 Restyp : constant Entity_Id := Etype (N);
4845 Lop : constant Node_Id := Left_Opnd (N);
4846 Rop : constant Node_Id := Right_Opnd (N);
4847 Static : constant Boolean := Is_OK_Static_Expression (N);
4849 Ltyp : Entity_Id;
4850 Rtyp : Entity_Id;
4852 procedure Substitute_Valid_Check;
4853 -- Replaces node N by Lop'Valid. This is done when we have an explicit
4854 -- test for the left operand being in range of its subtype.
4856 ----------------------------
4857 -- Substitute_Valid_Check --
4858 ----------------------------
4860 procedure Substitute_Valid_Check is
4861 begin
4862 Rewrite (N,
4863 Make_Attribute_Reference (Loc,
4864 Prefix => Relocate_Node (Lop),
4865 Attribute_Name => Name_Valid));
4867 Analyze_And_Resolve (N, Restyp);
4869 Error_Msg_N ("?explicit membership test may be optimized away", N);
4870 Error_Msg_N -- CODEFIX
4871 ("\?use ''Valid attribute instead", N);
4872 return;
4873 end Substitute_Valid_Check;
4875 -- Start of processing for Expand_N_In
4877 begin
4878 -- If set membership case, expand with separate procedure
4880 if Present (Alternatives (N)) then
4881 Expand_Set_Membership (N);
4882 return;
4883 end if;
4885 -- Not set membership, proceed with expansion
4887 Ltyp := Etype (Left_Opnd (N));
4888 Rtyp := Etype (Right_Opnd (N));
4890 -- Check case of explicit test for an expression in range of its
4891 -- subtype. This is suspicious usage and we replace it with a 'Valid
4892 -- test and give a warning. For floating point types however, this is a
4893 -- standard way to check for finite numbers, and using 'Valid would
4894 -- typically be a pessimization. Also skip this test for predicated
4895 -- types, since it is perfectly reasonable to check if a value meets
4896 -- its predicate.
4898 if Is_Scalar_Type (Ltyp)
4899 and then not Is_Floating_Point_Type (Ltyp)
4900 and then Nkind (Rop) in N_Has_Entity
4901 and then Ltyp = Entity (Rop)
4902 and then Comes_From_Source (N)
4903 and then VM_Target = No_VM
4904 and then not (Is_Discrete_Type (Ltyp)
4905 and then Present (Predicate_Function (Ltyp)))
4906 then
4907 Substitute_Valid_Check;
4908 return;
4909 end if;
4911 -- Do validity check on operands
4913 if Validity_Checks_On and Validity_Check_Operands then
4914 Ensure_Valid (Left_Opnd (N));
4915 Validity_Check_Range (Right_Opnd (N));
4916 end if;
4918 -- Case of explicit range
4920 if Nkind (Rop) = N_Range then
4921 declare
4922 Lo : constant Node_Id := Low_Bound (Rop);
4923 Hi : constant Node_Id := High_Bound (Rop);
4925 Lo_Orig : constant Node_Id := Original_Node (Lo);
4926 Hi_Orig : constant Node_Id := Original_Node (Hi);
4928 Lcheck : Compare_Result;
4929 Ucheck : Compare_Result;
4931 Warn1 : constant Boolean :=
4932 Constant_Condition_Warnings
4933 and then Comes_From_Source (N)
4934 and then not In_Instance;
4935 -- This must be true for any of the optimization warnings, we
4936 -- clearly want to give them only for source with the flag on. We
4937 -- also skip these warnings in an instance since it may be the
4938 -- case that different instantiations have different ranges.
4940 Warn2 : constant Boolean :=
4941 Warn1
4942 and then Nkind (Original_Node (Rop)) = N_Range
4943 and then Is_Integer_Type (Etype (Lo));
4944 -- For the case where only one bound warning is elided, we also
4945 -- insist on an explicit range and an integer type. The reason is
4946 -- that the use of enumeration ranges including an end point is
4947 -- common, as is the use of a subtype name, one of whose bounds is
4948 -- the same as the type of the expression.
4950 begin
4951 -- If test is explicit x'First .. x'Last, replace by valid check
4953 -- Could use some individual comments for this complex test ???
4955 if Is_Scalar_Type (Ltyp)
4956 and then Nkind (Lo_Orig) = N_Attribute_Reference
4957 and then Attribute_Name (Lo_Orig) = Name_First
4958 and then Nkind (Prefix (Lo_Orig)) in N_Has_Entity
4959 and then Entity (Prefix (Lo_Orig)) = Ltyp
4960 and then Nkind (Hi_Orig) = N_Attribute_Reference
4961 and then Attribute_Name (Hi_Orig) = Name_Last
4962 and then Nkind (Prefix (Hi_Orig)) in N_Has_Entity
4963 and then Entity (Prefix (Hi_Orig)) = Ltyp
4964 and then Comes_From_Source (N)
4965 and then VM_Target = No_VM
4966 then
4967 Substitute_Valid_Check;
4968 goto Leave;
4969 end if;
4971 -- If bounds of type are known at compile time, and the end points
4972 -- are known at compile time and identical, this is another case
4973 -- for substituting a valid test. We only do this for discrete
4974 -- types, since it won't arise in practice for float types.
4976 if Comes_From_Source (N)
4977 and then Is_Discrete_Type (Ltyp)
4978 and then Compile_Time_Known_Value (Type_High_Bound (Ltyp))
4979 and then Compile_Time_Known_Value (Type_Low_Bound (Ltyp))
4980 and then Compile_Time_Known_Value (Lo)
4981 and then Compile_Time_Known_Value (Hi)
4982 and then Expr_Value (Type_High_Bound (Ltyp)) = Expr_Value (Hi)
4983 and then Expr_Value (Type_Low_Bound (Ltyp)) = Expr_Value (Lo)
4985 -- Kill warnings in instances, since they may be cases where we
4986 -- have a test in the generic that makes sense with some types
4987 -- and not with other types.
4989 and then not In_Instance
4990 then
4991 Substitute_Valid_Check;
4992 goto Leave;
4993 end if;
4995 -- If we have an explicit range, do a bit of optimization based on
4996 -- range analysis (we may be able to kill one or both checks).
4998 Lcheck := Compile_Time_Compare (Lop, Lo, Assume_Valid => False);
4999 Ucheck := Compile_Time_Compare (Lop, Hi, Assume_Valid => False);
5001 -- If either check is known to fail, replace result by False since
5002 -- the other check does not matter. Preserve the static flag for
5003 -- legality checks, because we are constant-folding beyond RM 4.9.
5005 if Lcheck = LT or else Ucheck = GT then
5006 if Warn1 then
5007 Error_Msg_N ("?range test optimized away", N);
5008 Error_Msg_N ("\?value is known to be out of range", N);
5009 end if;
5011 Rewrite (N, New_Reference_To (Standard_False, Loc));
5012 Analyze_And_Resolve (N, Restyp);
5013 Set_Is_Static_Expression (N, Static);
5014 goto Leave;
5016 -- If both checks are known to succeed, replace result by True,
5017 -- since we know we are in range.
5019 elsif Lcheck in Compare_GE and then Ucheck in Compare_LE then
5020 if Warn1 then
5021 Error_Msg_N ("?range test optimized away", N);
5022 Error_Msg_N ("\?value is known to be in range", N);
5023 end if;
5025 Rewrite (N, New_Reference_To (Standard_True, Loc));
5026 Analyze_And_Resolve (N, Restyp);
5027 Set_Is_Static_Expression (N, Static);
5028 goto Leave;
5030 -- If lower bound check succeeds and upper bound check is not
5031 -- known to succeed or fail, then replace the range check with
5032 -- a comparison against the upper bound.
5034 elsif Lcheck in Compare_GE then
5035 if Warn2 and then not In_Instance then
5036 Error_Msg_N ("?lower bound test optimized away", Lo);
5037 Error_Msg_N ("\?value is known to be in range", Lo);
5038 end if;
5040 Rewrite (N,
5041 Make_Op_Le (Loc,
5042 Left_Opnd => Lop,
5043 Right_Opnd => High_Bound (Rop)));
5044 Analyze_And_Resolve (N, Restyp);
5045 goto Leave;
5047 -- If upper bound check succeeds and lower bound check is not
5048 -- known to succeed or fail, then replace the range check with
5049 -- a comparison against the lower bound.
5051 elsif Ucheck in Compare_LE then
5052 if Warn2 and then not In_Instance then
5053 Error_Msg_N ("?upper bound test optimized away", Hi);
5054 Error_Msg_N ("\?value is known to be in range", Hi);
5055 end if;
5057 Rewrite (N,
5058 Make_Op_Ge (Loc,
5059 Left_Opnd => Lop,
5060 Right_Opnd => Low_Bound (Rop)));
5061 Analyze_And_Resolve (N, Restyp);
5062 goto Leave;
5063 end if;
5065 -- We couldn't optimize away the range check, but there is one
5066 -- more issue. If we are checking constant conditionals, then we
5067 -- see if we can determine the outcome assuming everything is
5068 -- valid, and if so give an appropriate warning.
5070 if Warn1 and then not Assume_No_Invalid_Values then
5071 Lcheck := Compile_Time_Compare (Lop, Lo, Assume_Valid => True);
5072 Ucheck := Compile_Time_Compare (Lop, Hi, Assume_Valid => True);
5074 -- Result is out of range for valid value
5076 if Lcheck = LT or else Ucheck = GT then
5077 Error_Msg_N
5078 ("?value can only be in range if it is invalid", N);
5080 -- Result is in range for valid value
5082 elsif Lcheck in Compare_GE and then Ucheck in Compare_LE then
5083 Error_Msg_N
5084 ("?value can only be out of range if it is invalid", N);
5086 -- Lower bound check succeeds if value is valid
5088 elsif Warn2 and then Lcheck in Compare_GE then
5089 Error_Msg_N
5090 ("?lower bound check only fails if it is invalid", Lo);
5092 -- Upper bound check succeeds if value is valid
5094 elsif Warn2 and then Ucheck in Compare_LE then
5095 Error_Msg_N
5096 ("?upper bound check only fails for invalid values", Hi);
5097 end if;
5098 end if;
5099 end;
5101 -- For all other cases of an explicit range, nothing to be done
5103 goto Leave;
5105 -- Here right operand is a subtype mark
5107 else
5108 declare
5109 Typ : Entity_Id := Etype (Rop);
5110 Is_Acc : constant Boolean := Is_Access_Type (Typ);
5111 Cond : Node_Id := Empty;
5112 New_N : Node_Id;
5113 Obj : Node_Id := Lop;
5114 SCIL_Node : Node_Id;
5116 begin
5117 Remove_Side_Effects (Obj);
5119 -- For tagged type, do tagged membership operation
5121 if Is_Tagged_Type (Typ) then
5123 -- No expansion will be performed when VM_Target, as the VM
5124 -- back-ends will handle the membership tests directly (tags
5125 -- are not explicitly represented in Java objects, so the
5126 -- normal tagged membership expansion is not what we want).
5128 if Tagged_Type_Expansion then
5129 Tagged_Membership (N, SCIL_Node, New_N);
5130 Rewrite (N, New_N);
5131 Analyze_And_Resolve (N, Restyp);
5133 -- Update decoration of relocated node referenced by the
5134 -- SCIL node.
5136 if Generate_SCIL and then Present (SCIL_Node) then
5137 Set_SCIL_Node (N, SCIL_Node);
5138 end if;
5139 end if;
5141 goto Leave;
5143 -- If type is scalar type, rewrite as x in t'First .. t'Last.
5144 -- This reason we do this is that the bounds may have the wrong
5145 -- type if they come from the original type definition. Also this
5146 -- way we get all the processing above for an explicit range.
5148 -- Don't do this for predicated types, since in this case we
5149 -- want to check the predicate!
5151 elsif Is_Scalar_Type (Typ) then
5152 if No (Predicate_Function (Typ)) then
5153 Rewrite (Rop,
5154 Make_Range (Loc,
5155 Low_Bound =>
5156 Make_Attribute_Reference (Loc,
5157 Attribute_Name => Name_First,
5158 Prefix => New_Reference_To (Typ, Loc)),
5160 High_Bound =>
5161 Make_Attribute_Reference (Loc,
5162 Attribute_Name => Name_Last,
5163 Prefix => New_Reference_To (Typ, Loc))));
5164 Analyze_And_Resolve (N, Restyp);
5165 end if;
5167 goto Leave;
5169 -- Ada 2005 (AI-216): Program_Error is raised when evaluating
5170 -- a membership test if the subtype mark denotes a constrained
5171 -- Unchecked_Union subtype and the expression lacks inferable
5172 -- discriminants.
5174 elsif Is_Unchecked_Union (Base_Type (Typ))
5175 and then Is_Constrained (Typ)
5176 and then not Has_Inferable_Discriminants (Lop)
5177 then
5178 Insert_Action (N,
5179 Make_Raise_Program_Error (Loc,
5180 Reason => PE_Unchecked_Union_Restriction));
5182 -- Prevent Gigi from generating incorrect code by rewriting the
5183 -- test as False.
5185 Rewrite (N, New_Occurrence_Of (Standard_False, Loc));
5186 goto Leave;
5187 end if;
5189 -- Here we have a non-scalar type
5191 if Is_Acc then
5192 Typ := Designated_Type (Typ);
5193 end if;
5195 if not Is_Constrained (Typ) then
5196 Rewrite (N, New_Reference_To (Standard_True, Loc));
5197 Analyze_And_Resolve (N, Restyp);
5199 -- For the constrained array case, we have to check the subscripts
5200 -- for an exact match if the lengths are non-zero (the lengths
5201 -- must match in any case).
5203 elsif Is_Array_Type (Typ) then
5204 Check_Subscripts : declare
5205 function Build_Attribute_Reference
5206 (E : Node_Id;
5207 Nam : Name_Id;
5208 Dim : Nat) return Node_Id;
5209 -- Build attribute reference E'Nam (Dim)
5211 -------------------------------
5212 -- Build_Attribute_Reference --
5213 -------------------------------
5215 function Build_Attribute_Reference
5216 (E : Node_Id;
5217 Nam : Name_Id;
5218 Dim : Nat) return Node_Id
5220 begin
5221 return
5222 Make_Attribute_Reference (Loc,
5223 Prefix => E,
5224 Attribute_Name => Nam,
5225 Expressions => New_List (
5226 Make_Integer_Literal (Loc, Dim)));
5227 end Build_Attribute_Reference;
5229 -- Start of processing for Check_Subscripts
5231 begin
5232 for J in 1 .. Number_Dimensions (Typ) loop
5233 Evolve_And_Then (Cond,
5234 Make_Op_Eq (Loc,
5235 Left_Opnd =>
5236 Build_Attribute_Reference
5237 (Duplicate_Subexpr_No_Checks (Obj),
5238 Name_First, J),
5239 Right_Opnd =>
5240 Build_Attribute_Reference
5241 (New_Occurrence_Of (Typ, Loc), Name_First, J)));
5243 Evolve_And_Then (Cond,
5244 Make_Op_Eq (Loc,
5245 Left_Opnd =>
5246 Build_Attribute_Reference
5247 (Duplicate_Subexpr_No_Checks (Obj),
5248 Name_Last, J),
5249 Right_Opnd =>
5250 Build_Attribute_Reference
5251 (New_Occurrence_Of (Typ, Loc), Name_Last, J)));
5252 end loop;
5254 if Is_Acc then
5255 Cond :=
5256 Make_Or_Else (Loc,
5257 Left_Opnd =>
5258 Make_Op_Eq (Loc,
5259 Left_Opnd => Obj,
5260 Right_Opnd => Make_Null (Loc)),
5261 Right_Opnd => Cond);
5262 end if;
5264 Rewrite (N, Cond);
5265 Analyze_And_Resolve (N, Restyp);
5266 end Check_Subscripts;
5268 -- These are the cases where constraint checks may be required,
5269 -- e.g. records with possible discriminants
5271 else
5272 -- Expand the test into a series of discriminant comparisons.
5273 -- The expression that is built is the negation of the one that
5274 -- is used for checking discriminant constraints.
5276 Obj := Relocate_Node (Left_Opnd (N));
5278 if Has_Discriminants (Typ) then
5279 Cond := Make_Op_Not (Loc,
5280 Right_Opnd => Build_Discriminant_Checks (Obj, Typ));
5282 if Is_Acc then
5283 Cond := Make_Or_Else (Loc,
5284 Left_Opnd =>
5285 Make_Op_Eq (Loc,
5286 Left_Opnd => Obj,
5287 Right_Opnd => Make_Null (Loc)),
5288 Right_Opnd => Cond);
5289 end if;
5291 else
5292 Cond := New_Occurrence_Of (Standard_True, Loc);
5293 end if;
5295 Rewrite (N, Cond);
5296 Analyze_And_Resolve (N, Restyp);
5297 end if;
5299 -- Ada 2012 (AI05-0149): Handle membership tests applied to an
5300 -- expression of an anonymous access type. This can involve an
5301 -- accessibility test and a tagged type membership test in the
5302 -- case of tagged designated types.
5304 if Ada_Version >= Ada_2012
5305 and then Is_Acc
5306 and then Ekind (Ltyp) = E_Anonymous_Access_Type
5307 then
5308 declare
5309 Expr_Entity : Entity_Id := Empty;
5310 New_N : Node_Id;
5311 Param_Level : Node_Id;
5312 Type_Level : Node_Id;
5314 begin
5315 if Is_Entity_Name (Lop) then
5316 Expr_Entity := Param_Entity (Lop);
5318 if not Present (Expr_Entity) then
5319 Expr_Entity := Entity (Lop);
5320 end if;
5321 end if;
5323 -- If a conversion of the anonymous access value to the
5324 -- tested type would be illegal, then the result is False.
5326 if not Valid_Conversion
5327 (Lop, Rtyp, Lop, Report_Errs => False)
5328 then
5329 Rewrite (N, New_Occurrence_Of (Standard_False, Loc));
5330 Analyze_And_Resolve (N, Restyp);
5332 -- Apply an accessibility check if the access object has an
5333 -- associated access level and when the level of the type is
5334 -- less deep than the level of the access parameter. This
5335 -- only occur for access parameters and stand-alone objects
5336 -- of an anonymous access type.
5338 else
5339 if Present (Expr_Entity)
5340 and then
5341 Present
5342 (Effective_Extra_Accessibility (Expr_Entity))
5343 and then UI_Gt (Object_Access_Level (Lop),
5344 Type_Access_Level (Rtyp))
5345 then
5346 Param_Level :=
5347 New_Occurrence_Of
5348 (Effective_Extra_Accessibility (Expr_Entity), Loc);
5350 Type_Level :=
5351 Make_Integer_Literal (Loc, Type_Access_Level (Rtyp));
5353 -- Return True only if the accessibility level of the
5354 -- expression entity is not deeper than the level of
5355 -- the tested access type.
5357 Rewrite (N,
5358 Make_And_Then (Loc,
5359 Left_Opnd => Relocate_Node (N),
5360 Right_Opnd => Make_Op_Le (Loc,
5361 Left_Opnd => Param_Level,
5362 Right_Opnd => Type_Level)));
5364 Analyze_And_Resolve (N);
5365 end if;
5367 -- If the designated type is tagged, do tagged membership
5368 -- operation.
5370 -- *** NOTE: we have to check not null before doing the
5371 -- tagged membership test (but maybe that can be done
5372 -- inside Tagged_Membership?).
5374 if Is_Tagged_Type (Typ) then
5375 Rewrite (N,
5376 Make_And_Then (Loc,
5377 Left_Opnd => Relocate_Node (N),
5378 Right_Opnd =>
5379 Make_Op_Ne (Loc,
5380 Left_Opnd => Obj,
5381 Right_Opnd => Make_Null (Loc))));
5383 -- No expansion will be performed when VM_Target, as
5384 -- the VM back-ends will handle the membership tests
5385 -- directly (tags are not explicitly represented in
5386 -- Java objects, so the normal tagged membership
5387 -- expansion is not what we want).
5389 if Tagged_Type_Expansion then
5391 -- Note that we have to pass Original_Node, because
5392 -- the membership test might already have been
5393 -- rewritten by earlier parts of membership test.
5395 Tagged_Membership
5396 (Original_Node (N), SCIL_Node, New_N);
5398 -- Update decoration of relocated node referenced
5399 -- by the SCIL node.
5401 if Generate_SCIL and then Present (SCIL_Node) then
5402 Set_SCIL_Node (New_N, SCIL_Node);
5403 end if;
5405 Rewrite (N,
5406 Make_And_Then (Loc,
5407 Left_Opnd => Relocate_Node (N),
5408 Right_Opnd => New_N));
5410 Analyze_And_Resolve (N, Restyp);
5411 end if;
5412 end if;
5413 end if;
5414 end;
5415 end if;
5416 end;
5417 end if;
5419 -- At this point, we have done the processing required for the basic
5420 -- membership test, but not yet dealt with the predicate.
5422 <<Leave>>
5424 -- If a predicate is present, then we do the predicate test, but we
5425 -- most certainly want to omit this if we are within the predicate
5426 -- function itself, since otherwise we have an infinite recursion!
5428 declare
5429 PFunc : constant Entity_Id := Predicate_Function (Rtyp);
5431 begin
5432 if Present (PFunc)
5433 and then Current_Scope /= PFunc
5434 then
5435 Rewrite (N,
5436 Make_And_Then (Loc,
5437 Left_Opnd => Relocate_Node (N),
5438 Right_Opnd => Make_Predicate_Call (Rtyp, Lop)));
5440 -- Analyze new expression, mark left operand as analyzed to
5441 -- avoid infinite recursion adding predicate calls. Similarly,
5442 -- suppress further range checks on the call.
5444 Set_Analyzed (Left_Opnd (N));
5445 Analyze_And_Resolve (N, Standard_Boolean, Suppress => All_Checks);
5447 -- All done, skip attempt at compile time determination of result
5449 return;
5450 end if;
5451 end;
5452 end Expand_N_In;
5454 --------------------------------
5455 -- Expand_N_Indexed_Component --
5456 --------------------------------
5458 procedure Expand_N_Indexed_Component (N : Node_Id) is
5459 Loc : constant Source_Ptr := Sloc (N);
5460 Typ : constant Entity_Id := Etype (N);
5461 P : constant Node_Id := Prefix (N);
5462 T : constant Entity_Id := Etype (P);
5463 Atp : Entity_Id;
5465 begin
5466 -- A special optimization, if we have an indexed component that is
5467 -- selecting from a slice, then we can eliminate the slice, since, for
5468 -- example, x (i .. j)(k) is identical to x(k). The only difference is
5469 -- the range check required by the slice. The range check for the slice
5470 -- itself has already been generated. The range check for the
5471 -- subscripting operation is ensured by converting the subject to
5472 -- the subtype of the slice.
5474 -- This optimization not only generates better code, avoiding slice
5475 -- messing especially in the packed case, but more importantly bypasses
5476 -- some problems in handling this peculiar case, for example, the issue
5477 -- of dealing specially with object renamings.
5479 if Nkind (P) = N_Slice then
5480 Rewrite (N,
5481 Make_Indexed_Component (Loc,
5482 Prefix => Prefix (P),
5483 Expressions => New_List (
5484 Convert_To
5485 (Etype (First_Index (Etype (P))),
5486 First (Expressions (N))))));
5487 Analyze_And_Resolve (N, Typ);
5488 return;
5489 end if;
5491 -- Ada 2005 (AI-318-02): If the prefix is a call to a build-in-place
5492 -- function, then additional actuals must be passed.
5494 if Ada_Version >= Ada_2005
5495 and then Is_Build_In_Place_Function_Call (P)
5496 then
5497 Make_Build_In_Place_Call_In_Anonymous_Context (P);
5498 end if;
5500 -- If the prefix is an access type, then we unconditionally rewrite if
5501 -- as an explicit dereference. This simplifies processing for several
5502 -- cases, including packed array cases and certain cases in which checks
5503 -- must be generated. We used to try to do this only when it was
5504 -- necessary, but it cleans up the code to do it all the time.
5506 if Is_Access_Type (T) then
5507 Insert_Explicit_Dereference (P);
5508 Analyze_And_Resolve (P, Designated_Type (T));
5509 Atp := Designated_Type (T);
5510 else
5511 Atp := T;
5512 end if;
5514 -- Generate index and validity checks
5516 Generate_Index_Checks (N);
5518 if Validity_Checks_On and then Validity_Check_Subscripts then
5519 Apply_Subscript_Validity_Checks (N);
5520 end if;
5522 -- If selecting from an array with atomic components, and atomic sync
5523 -- is not suppressed for this array type, set atomic sync flag.
5525 if (Has_Atomic_Components (Atp)
5526 and then not Atomic_Synchronization_Disabled (Atp))
5527 or else (Is_Atomic (Typ)
5528 and then not Atomic_Synchronization_Disabled (Typ))
5529 then
5530 Activate_Atomic_Synchronization (N);
5531 end if;
5533 -- All done for the non-packed case
5535 if not Is_Packed (Etype (Prefix (N))) then
5536 return;
5537 end if;
5539 -- For packed arrays that are not bit-packed (i.e. the case of an array
5540 -- with one or more index types with a non-contiguous enumeration type),
5541 -- we can always use the normal packed element get circuit.
5543 if not Is_Bit_Packed_Array (Etype (Prefix (N))) then
5544 Expand_Packed_Element_Reference (N);
5545 return;
5546 end if;
5548 -- For a reference to a component of a bit packed array, we have to
5549 -- convert it to a reference to the corresponding Packed_Array_Type.
5550 -- We only want to do this for simple references, and not for:
5552 -- Left side of assignment, or prefix of left side of assignment, or
5553 -- prefix of the prefix, to handle packed arrays of packed arrays,
5554 -- This case is handled in Exp_Ch5.Expand_N_Assignment_Statement
5556 -- Renaming objects in renaming associations
5557 -- This case is handled when a use of the renamed variable occurs
5559 -- Actual parameters for a procedure call
5560 -- This case is handled in Exp_Ch6.Expand_Actuals
5562 -- The second expression in a 'Read attribute reference
5564 -- The prefix of an address or bit or size attribute reference
5566 -- The following circuit detects these exceptions
5568 declare
5569 Child : Node_Id := N;
5570 Parnt : Node_Id := Parent (N);
5572 begin
5573 loop
5574 if Nkind (Parnt) = N_Unchecked_Expression then
5575 null;
5577 elsif Nkind_In (Parnt, N_Object_Renaming_Declaration,
5578 N_Procedure_Call_Statement)
5579 or else (Nkind (Parnt) = N_Parameter_Association
5580 and then
5581 Nkind (Parent (Parnt)) = N_Procedure_Call_Statement)
5582 then
5583 return;
5585 elsif Nkind (Parnt) = N_Attribute_Reference
5586 and then (Attribute_Name (Parnt) = Name_Address
5587 or else
5588 Attribute_Name (Parnt) = Name_Bit
5589 or else
5590 Attribute_Name (Parnt) = Name_Size)
5591 and then Prefix (Parnt) = Child
5592 then
5593 return;
5595 elsif Nkind (Parnt) = N_Assignment_Statement
5596 and then Name (Parnt) = Child
5597 then
5598 return;
5600 -- If the expression is an index of an indexed component, it must
5601 -- be expanded regardless of context.
5603 elsif Nkind (Parnt) = N_Indexed_Component
5604 and then Child /= Prefix (Parnt)
5605 then
5606 Expand_Packed_Element_Reference (N);
5607 return;
5609 elsif Nkind (Parent (Parnt)) = N_Assignment_Statement
5610 and then Name (Parent (Parnt)) = Parnt
5611 then
5612 return;
5614 elsif Nkind (Parnt) = N_Attribute_Reference
5615 and then Attribute_Name (Parnt) = Name_Read
5616 and then Next (First (Expressions (Parnt))) = Child
5617 then
5618 return;
5620 elsif Nkind_In (Parnt, N_Indexed_Component, N_Selected_Component)
5621 and then Prefix (Parnt) = Child
5622 then
5623 null;
5625 else
5626 Expand_Packed_Element_Reference (N);
5627 return;
5628 end if;
5630 -- Keep looking up tree for unchecked expression, or if we are the
5631 -- prefix of a possible assignment left side.
5633 Child := Parnt;
5634 Parnt := Parent (Child);
5635 end loop;
5636 end;
5637 end Expand_N_Indexed_Component;
5639 ---------------------
5640 -- Expand_N_Not_In --
5641 ---------------------
5643 -- Replace a not in b by not (a in b) so that the expansions for (a in b)
5644 -- can be done. This avoids needing to duplicate this expansion code.
5646 procedure Expand_N_Not_In (N : Node_Id) is
5647 Loc : constant Source_Ptr := Sloc (N);
5648 Typ : constant Entity_Id := Etype (N);
5649 Cfs : constant Boolean := Comes_From_Source (N);
5651 begin
5652 Rewrite (N,
5653 Make_Op_Not (Loc,
5654 Right_Opnd =>
5655 Make_In (Loc,
5656 Left_Opnd => Left_Opnd (N),
5657 Right_Opnd => Right_Opnd (N))));
5659 -- If this is a set membership, preserve list of alternatives
5661 Set_Alternatives (Right_Opnd (N), Alternatives (Original_Node (N)));
5663 -- We want this to appear as coming from source if original does (see
5664 -- transformations in Expand_N_In).
5666 Set_Comes_From_Source (N, Cfs);
5667 Set_Comes_From_Source (Right_Opnd (N), Cfs);
5669 -- Now analyze transformed node
5671 Analyze_And_Resolve (N, Typ);
5672 end Expand_N_Not_In;
5674 -------------------
5675 -- Expand_N_Null --
5676 -------------------
5678 -- The only replacement required is for the case of a null of a type that
5679 -- is an access to protected subprogram, or a subtype thereof. We represent
5680 -- such access values as a record, and so we must replace the occurrence of
5681 -- null by the equivalent record (with a null address and a null pointer in
5682 -- it), so that the backend creates the proper value.
5684 procedure Expand_N_Null (N : Node_Id) is
5685 Loc : constant Source_Ptr := Sloc (N);
5686 Typ : constant Entity_Id := Base_Type (Etype (N));
5687 Agg : Node_Id;
5689 begin
5690 if Is_Access_Protected_Subprogram_Type (Typ) then
5691 Agg :=
5692 Make_Aggregate (Loc,
5693 Expressions => New_List (
5694 New_Occurrence_Of (RTE (RE_Null_Address), Loc),
5695 Make_Null (Loc)));
5697 Rewrite (N, Agg);
5698 Analyze_And_Resolve (N, Equivalent_Type (Typ));
5700 -- For subsequent semantic analysis, the node must retain its type.
5701 -- Gigi in any case replaces this type by the corresponding record
5702 -- type before processing the node.
5704 Set_Etype (N, Typ);
5705 end if;
5707 exception
5708 when RE_Not_Available =>
5709 return;
5710 end Expand_N_Null;
5712 ---------------------
5713 -- Expand_N_Op_Abs --
5714 ---------------------
5716 procedure Expand_N_Op_Abs (N : Node_Id) is
5717 Loc : constant Source_Ptr := Sloc (N);
5718 Expr : constant Node_Id := Right_Opnd (N);
5720 begin
5721 Unary_Op_Validity_Checks (N);
5723 -- Deal with software overflow checking
5725 if not Backend_Overflow_Checks_On_Target
5726 and then Is_Signed_Integer_Type (Etype (N))
5727 and then Do_Overflow_Check (N)
5728 then
5729 -- The only case to worry about is when the argument is equal to the
5730 -- largest negative number, so what we do is to insert the check:
5732 -- [constraint_error when Expr = typ'Base'First]
5734 -- with the usual Duplicate_Subexpr use coding for expr
5736 Insert_Action (N,
5737 Make_Raise_Constraint_Error (Loc,
5738 Condition =>
5739 Make_Op_Eq (Loc,
5740 Left_Opnd => Duplicate_Subexpr (Expr),
5741 Right_Opnd =>
5742 Make_Attribute_Reference (Loc,
5743 Prefix =>
5744 New_Occurrence_Of (Base_Type (Etype (Expr)), Loc),
5745 Attribute_Name => Name_First)),
5746 Reason => CE_Overflow_Check_Failed));
5747 end if;
5749 -- Vax floating-point types case
5751 if Vax_Float (Etype (N)) then
5752 Expand_Vax_Arith (N);
5753 end if;
5754 end Expand_N_Op_Abs;
5756 ---------------------
5757 -- Expand_N_Op_Add --
5758 ---------------------
5760 procedure Expand_N_Op_Add (N : Node_Id) is
5761 Typ : constant Entity_Id := Etype (N);
5763 begin
5764 Binary_Op_Validity_Checks (N);
5766 -- N + 0 = 0 + N = N for integer types
5768 if Is_Integer_Type (Typ) then
5769 if Compile_Time_Known_Value (Right_Opnd (N))
5770 and then Expr_Value (Right_Opnd (N)) = Uint_0
5771 then
5772 Rewrite (N, Left_Opnd (N));
5773 return;
5775 elsif Compile_Time_Known_Value (Left_Opnd (N))
5776 and then Expr_Value (Left_Opnd (N)) = Uint_0
5777 then
5778 Rewrite (N, Right_Opnd (N));
5779 return;
5780 end if;
5781 end if;
5783 -- Arithmetic overflow checks for signed integer/fixed point types
5785 if Is_Signed_Integer_Type (Typ)
5786 or else Is_Fixed_Point_Type (Typ)
5787 then
5788 Apply_Arithmetic_Overflow_Check (N);
5789 return;
5791 -- Vax floating-point types case
5793 elsif Vax_Float (Typ) then
5794 Expand_Vax_Arith (N);
5795 end if;
5796 end Expand_N_Op_Add;
5798 ---------------------
5799 -- Expand_N_Op_And --
5800 ---------------------
5802 procedure Expand_N_Op_And (N : Node_Id) is
5803 Typ : constant Entity_Id := Etype (N);
5805 begin
5806 Binary_Op_Validity_Checks (N);
5808 if Is_Array_Type (Etype (N)) then
5809 Expand_Boolean_Operator (N);
5811 elsif Is_Boolean_Type (Etype (N)) then
5812 Adjust_Condition (Left_Opnd (N));
5813 Adjust_Condition (Right_Opnd (N));
5814 Set_Etype (N, Standard_Boolean);
5815 Adjust_Result_Type (N, Typ);
5817 elsif Is_Intrinsic_Subprogram (Entity (N)) then
5818 Expand_Intrinsic_Call (N, Entity (N));
5820 end if;
5821 end Expand_N_Op_And;
5823 ------------------------
5824 -- Expand_N_Op_Concat --
5825 ------------------------
5827 procedure Expand_N_Op_Concat (N : Node_Id) is
5828 Opnds : List_Id;
5829 -- List of operands to be concatenated
5831 Cnode : Node_Id;
5832 -- Node which is to be replaced by the result of concatenating the nodes
5833 -- in the list Opnds.
5835 begin
5836 -- Ensure validity of both operands
5838 Binary_Op_Validity_Checks (N);
5840 -- If we are the left operand of a concatenation higher up the tree,
5841 -- then do nothing for now, since we want to deal with a series of
5842 -- concatenations as a unit.
5844 if Nkind (Parent (N)) = N_Op_Concat
5845 and then N = Left_Opnd (Parent (N))
5846 then
5847 return;
5848 end if;
5850 -- We get here with a concatenation whose left operand may be a
5851 -- concatenation itself with a consistent type. We need to process
5852 -- these concatenation operands from left to right, which means
5853 -- from the deepest node in the tree to the highest node.
5855 Cnode := N;
5856 while Nkind (Left_Opnd (Cnode)) = N_Op_Concat loop
5857 Cnode := Left_Opnd (Cnode);
5858 end loop;
5860 -- Now Cnode is the deepest concatenation, and its parents are the
5861 -- concatenation nodes above, so now we process bottom up, doing the
5862 -- operations. We gather a string that is as long as possible up to five
5863 -- operands.
5865 -- The outer loop runs more than once if more than one concatenation
5866 -- type is involved.
5868 Outer : loop
5869 Opnds := New_List (Left_Opnd (Cnode), Right_Opnd (Cnode));
5870 Set_Parent (Opnds, N);
5872 -- The inner loop gathers concatenation operands
5874 Inner : while Cnode /= N
5875 and then Base_Type (Etype (Cnode)) =
5876 Base_Type (Etype (Parent (Cnode)))
5877 loop
5878 Cnode := Parent (Cnode);
5879 Append (Right_Opnd (Cnode), Opnds);
5880 end loop Inner;
5882 Expand_Concatenate (Cnode, Opnds);
5884 exit Outer when Cnode = N;
5885 Cnode := Parent (Cnode);
5886 end loop Outer;
5887 end Expand_N_Op_Concat;
5889 ------------------------
5890 -- Expand_N_Op_Divide --
5891 ------------------------
5893 procedure Expand_N_Op_Divide (N : Node_Id) is
5894 Loc : constant Source_Ptr := Sloc (N);
5895 Lopnd : constant Node_Id := Left_Opnd (N);
5896 Ropnd : constant Node_Id := Right_Opnd (N);
5897 Ltyp : constant Entity_Id := Etype (Lopnd);
5898 Rtyp : constant Entity_Id := Etype (Ropnd);
5899 Typ : Entity_Id := Etype (N);
5900 Rknow : constant Boolean := Is_Integer_Type (Typ)
5901 and then
5902 Compile_Time_Known_Value (Ropnd);
5903 Rval : Uint;
5905 begin
5906 Binary_Op_Validity_Checks (N);
5908 if Rknow then
5909 Rval := Expr_Value (Ropnd);
5910 end if;
5912 -- N / 1 = N for integer types
5914 if Rknow and then Rval = Uint_1 then
5915 Rewrite (N, Lopnd);
5916 return;
5917 end if;
5919 -- Convert x / 2 ** y to Shift_Right (x, y). Note that the fact that
5920 -- Is_Power_Of_2_For_Shift is set means that we know that our left
5921 -- operand is an unsigned integer, as required for this to work.
5923 if Nkind (Ropnd) = N_Op_Expon
5924 and then Is_Power_Of_2_For_Shift (Ropnd)
5926 -- We cannot do this transformation in configurable run time mode if we
5927 -- have 64-bit integers and long shifts are not available.
5929 and then
5930 (Esize (Ltyp) <= 32
5931 or else Support_Long_Shifts_On_Target)
5932 then
5933 Rewrite (N,
5934 Make_Op_Shift_Right (Loc,
5935 Left_Opnd => Lopnd,
5936 Right_Opnd =>
5937 Convert_To (Standard_Natural, Right_Opnd (Ropnd))));
5938 Analyze_And_Resolve (N, Typ);
5939 return;
5940 end if;
5942 -- Do required fixup of universal fixed operation
5944 if Typ = Universal_Fixed then
5945 Fixup_Universal_Fixed_Operation (N);
5946 Typ := Etype (N);
5947 end if;
5949 -- Divisions with fixed-point results
5951 if Is_Fixed_Point_Type (Typ) then
5953 -- No special processing if Treat_Fixed_As_Integer is set, since
5954 -- from a semantic point of view such operations are simply integer
5955 -- operations and will be treated that way.
5957 if not Treat_Fixed_As_Integer (N) then
5958 if Is_Integer_Type (Rtyp) then
5959 Expand_Divide_Fixed_By_Integer_Giving_Fixed (N);
5960 else
5961 Expand_Divide_Fixed_By_Fixed_Giving_Fixed (N);
5962 end if;
5963 end if;
5965 -- Other cases of division of fixed-point operands. Again we exclude the
5966 -- case where Treat_Fixed_As_Integer is set.
5968 elsif (Is_Fixed_Point_Type (Ltyp) or else
5969 Is_Fixed_Point_Type (Rtyp))
5970 and then not Treat_Fixed_As_Integer (N)
5971 then
5972 if Is_Integer_Type (Typ) then
5973 Expand_Divide_Fixed_By_Fixed_Giving_Integer (N);
5974 else
5975 pragma Assert (Is_Floating_Point_Type (Typ));
5976 Expand_Divide_Fixed_By_Fixed_Giving_Float (N);
5977 end if;
5979 -- Mixed-mode operations can appear in a non-static universal context,
5980 -- in which case the integer argument must be converted explicitly.
5982 elsif Typ = Universal_Real
5983 and then Is_Integer_Type (Rtyp)
5984 then
5985 Rewrite (Ropnd,
5986 Convert_To (Universal_Real, Relocate_Node (Ropnd)));
5988 Analyze_And_Resolve (Ropnd, Universal_Real);
5990 elsif Typ = Universal_Real
5991 and then Is_Integer_Type (Ltyp)
5992 then
5993 Rewrite (Lopnd,
5994 Convert_To (Universal_Real, Relocate_Node (Lopnd)));
5996 Analyze_And_Resolve (Lopnd, Universal_Real);
5998 -- Non-fixed point cases, do integer zero divide and overflow checks
6000 elsif Is_Integer_Type (Typ) then
6001 Apply_Divide_Check (N);
6003 -- Deal with Vax_Float
6005 elsif Vax_Float (Typ) then
6006 Expand_Vax_Arith (N);
6007 return;
6008 end if;
6009 end Expand_N_Op_Divide;
6011 --------------------
6012 -- Expand_N_Op_Eq --
6013 --------------------
6015 procedure Expand_N_Op_Eq (N : Node_Id) is
6016 Loc : constant Source_Ptr := Sloc (N);
6017 Typ : constant Entity_Id := Etype (N);
6018 Lhs : constant Node_Id := Left_Opnd (N);
6019 Rhs : constant Node_Id := Right_Opnd (N);
6020 Bodies : constant List_Id := New_List;
6021 A_Typ : constant Entity_Id := Etype (Lhs);
6023 Typl : Entity_Id := A_Typ;
6024 Op_Name : Entity_Id;
6025 Prim : Elmt_Id;
6027 procedure Build_Equality_Call (Eq : Entity_Id);
6028 -- If a constructed equality exists for the type or for its parent,
6029 -- build and analyze call, adding conversions if the operation is
6030 -- inherited.
6032 function Has_Unconstrained_UU_Component (Typ : Node_Id) return Boolean;
6033 -- Determines whether a type has a subcomponent of an unconstrained
6034 -- Unchecked_Union subtype. Typ is a record type.
6036 -------------------------
6037 -- Build_Equality_Call --
6038 -------------------------
6040 procedure Build_Equality_Call (Eq : Entity_Id) is
6041 Op_Type : constant Entity_Id := Etype (First_Formal (Eq));
6042 L_Exp : Node_Id := Relocate_Node (Lhs);
6043 R_Exp : Node_Id := Relocate_Node (Rhs);
6045 begin
6046 if Base_Type (Op_Type) /= Base_Type (A_Typ)
6047 and then not Is_Class_Wide_Type (A_Typ)
6048 then
6049 L_Exp := OK_Convert_To (Op_Type, L_Exp);
6050 R_Exp := OK_Convert_To (Op_Type, R_Exp);
6051 end if;
6053 -- If we have an Unchecked_Union, we need to add the inferred
6054 -- discriminant values as actuals in the function call. At this
6055 -- point, the expansion has determined that both operands have
6056 -- inferable discriminants.
6058 if Is_Unchecked_Union (Op_Type) then
6059 declare
6060 Lhs_Type : constant Node_Id := Etype (L_Exp);
6061 Rhs_Type : constant Node_Id := Etype (R_Exp);
6062 Lhs_Discr_Val : Node_Id;
6063 Rhs_Discr_Val : Node_Id;
6065 begin
6066 -- Per-object constrained selected components require special
6067 -- attention. If the enclosing scope of the component is an
6068 -- Unchecked_Union, we cannot reference its discriminants
6069 -- directly. This is why we use the two extra parameters of
6070 -- the equality function of the enclosing Unchecked_Union.
6072 -- type UU_Type (Discr : Integer := 0) is
6073 -- . . .
6074 -- end record;
6075 -- pragma Unchecked_Union (UU_Type);
6077 -- 1. Unchecked_Union enclosing record:
6079 -- type Enclosing_UU_Type (Discr : Integer := 0) is record
6080 -- . . .
6081 -- Comp : UU_Type (Discr);
6082 -- . . .
6083 -- end Enclosing_UU_Type;
6084 -- pragma Unchecked_Union (Enclosing_UU_Type);
6086 -- Obj1 : Enclosing_UU_Type;
6087 -- Obj2 : Enclosing_UU_Type (1);
6089 -- [. . .] Obj1 = Obj2 [. . .]
6091 -- Generated code:
6093 -- if not (uu_typeEQ (obj1.comp, obj2.comp, a, b)) then
6095 -- A and B are the formal parameters of the equality function
6096 -- of Enclosing_UU_Type. The function always has two extra
6097 -- formals to capture the inferred discriminant values.
6099 -- 2. Non-Unchecked_Union enclosing record:
6101 -- type
6102 -- Enclosing_Non_UU_Type (Discr : Integer := 0)
6103 -- is record
6104 -- . . .
6105 -- Comp : UU_Type (Discr);
6106 -- . . .
6107 -- end Enclosing_Non_UU_Type;
6109 -- Obj1 : Enclosing_Non_UU_Type;
6110 -- Obj2 : Enclosing_Non_UU_Type (1);
6112 -- ... Obj1 = Obj2 ...
6114 -- Generated code:
6116 -- if not (uu_typeEQ (obj1.comp, obj2.comp,
6117 -- obj1.discr, obj2.discr)) then
6119 -- In this case we can directly reference the discriminants of
6120 -- the enclosing record.
6122 -- Lhs of equality
6124 if Nkind (Lhs) = N_Selected_Component
6125 and then Has_Per_Object_Constraint
6126 (Entity (Selector_Name (Lhs)))
6127 then
6128 -- Enclosing record is an Unchecked_Union, use formal A
6130 if Is_Unchecked_Union
6131 (Scope (Entity (Selector_Name (Lhs))))
6132 then
6133 Lhs_Discr_Val := Make_Identifier (Loc, Name_A);
6135 -- Enclosing record is of a non-Unchecked_Union type, it is
6136 -- possible to reference the discriminant.
6138 else
6139 Lhs_Discr_Val :=
6140 Make_Selected_Component (Loc,
6141 Prefix => Prefix (Lhs),
6142 Selector_Name =>
6143 New_Copy
6144 (Get_Discriminant_Value
6145 (First_Discriminant (Lhs_Type),
6146 Lhs_Type,
6147 Stored_Constraint (Lhs_Type))));
6148 end if;
6150 -- Comment needed here ???
6152 else
6153 -- Infer the discriminant value
6155 Lhs_Discr_Val :=
6156 New_Copy
6157 (Get_Discriminant_Value
6158 (First_Discriminant (Lhs_Type),
6159 Lhs_Type,
6160 Stored_Constraint (Lhs_Type)));
6161 end if;
6163 -- Rhs of equality
6165 if Nkind (Rhs) = N_Selected_Component
6166 and then Has_Per_Object_Constraint
6167 (Entity (Selector_Name (Rhs)))
6168 then
6169 if Is_Unchecked_Union
6170 (Scope (Entity (Selector_Name (Rhs))))
6171 then
6172 Rhs_Discr_Val := Make_Identifier (Loc, Name_B);
6174 else
6175 Rhs_Discr_Val :=
6176 Make_Selected_Component (Loc,
6177 Prefix => Prefix (Rhs),
6178 Selector_Name =>
6179 New_Copy (Get_Discriminant_Value (
6180 First_Discriminant (Rhs_Type),
6181 Rhs_Type,
6182 Stored_Constraint (Rhs_Type))));
6184 end if;
6185 else
6186 Rhs_Discr_Val :=
6187 New_Copy (Get_Discriminant_Value (
6188 First_Discriminant (Rhs_Type),
6189 Rhs_Type,
6190 Stored_Constraint (Rhs_Type)));
6192 end if;
6194 Rewrite (N,
6195 Make_Function_Call (Loc,
6196 Name => New_Reference_To (Eq, Loc),
6197 Parameter_Associations => New_List (
6198 L_Exp,
6199 R_Exp,
6200 Lhs_Discr_Val,
6201 Rhs_Discr_Val)));
6202 end;
6204 -- Normal case, not an unchecked union
6206 else
6207 Rewrite (N,
6208 Make_Function_Call (Loc,
6209 Name => New_Reference_To (Eq, Loc),
6210 Parameter_Associations => New_List (L_Exp, R_Exp)));
6211 end if;
6213 Analyze_And_Resolve (N, Standard_Boolean, Suppress => All_Checks);
6214 end Build_Equality_Call;
6216 ------------------------------------
6217 -- Has_Unconstrained_UU_Component --
6218 ------------------------------------
6220 function Has_Unconstrained_UU_Component
6221 (Typ : Node_Id) return Boolean
6223 Tdef : constant Node_Id :=
6224 Type_Definition (Declaration_Node (Base_Type (Typ)));
6225 Clist : Node_Id;
6226 Vpart : Node_Id;
6228 function Component_Is_Unconstrained_UU
6229 (Comp : Node_Id) return Boolean;
6230 -- Determines whether the subtype of the component is an
6231 -- unconstrained Unchecked_Union.
6233 function Variant_Is_Unconstrained_UU
6234 (Variant : Node_Id) return Boolean;
6235 -- Determines whether a component of the variant has an unconstrained
6236 -- Unchecked_Union subtype.
6238 -----------------------------------
6239 -- Component_Is_Unconstrained_UU --
6240 -----------------------------------
6242 function Component_Is_Unconstrained_UU
6243 (Comp : Node_Id) return Boolean
6245 begin
6246 if Nkind (Comp) /= N_Component_Declaration then
6247 return False;
6248 end if;
6250 declare
6251 Sindic : constant Node_Id :=
6252 Subtype_Indication (Component_Definition (Comp));
6254 begin
6255 -- Unconstrained nominal type. In the case of a constraint
6256 -- present, the node kind would have been N_Subtype_Indication.
6258 if Nkind (Sindic) = N_Identifier then
6259 return Is_Unchecked_Union (Base_Type (Etype (Sindic)));
6260 end if;
6262 return False;
6263 end;
6264 end Component_Is_Unconstrained_UU;
6266 ---------------------------------
6267 -- Variant_Is_Unconstrained_UU --
6268 ---------------------------------
6270 function Variant_Is_Unconstrained_UU
6271 (Variant : Node_Id) return Boolean
6273 Clist : constant Node_Id := Component_List (Variant);
6275 begin
6276 if Is_Empty_List (Component_Items (Clist)) then
6277 return False;
6278 end if;
6280 -- We only need to test one component
6282 declare
6283 Comp : Node_Id := First (Component_Items (Clist));
6285 begin
6286 while Present (Comp) loop
6287 if Component_Is_Unconstrained_UU (Comp) then
6288 return True;
6289 end if;
6291 Next (Comp);
6292 end loop;
6293 end;
6295 -- None of the components withing the variant were of
6296 -- unconstrained Unchecked_Union type.
6298 return False;
6299 end Variant_Is_Unconstrained_UU;
6301 -- Start of processing for Has_Unconstrained_UU_Component
6303 begin
6304 if Null_Present (Tdef) then
6305 return False;
6306 end if;
6308 Clist := Component_List (Tdef);
6309 Vpart := Variant_Part (Clist);
6311 -- Inspect available components
6313 if Present (Component_Items (Clist)) then
6314 declare
6315 Comp : Node_Id := First (Component_Items (Clist));
6317 begin
6318 while Present (Comp) loop
6320 -- One component is sufficient
6322 if Component_Is_Unconstrained_UU (Comp) then
6323 return True;
6324 end if;
6326 Next (Comp);
6327 end loop;
6328 end;
6329 end if;
6331 -- Inspect available components withing variants
6333 if Present (Vpart) then
6334 declare
6335 Variant : Node_Id := First (Variants (Vpart));
6337 begin
6338 while Present (Variant) loop
6340 -- One component within a variant is sufficient
6342 if Variant_Is_Unconstrained_UU (Variant) then
6343 return True;
6344 end if;
6346 Next (Variant);
6347 end loop;
6348 end;
6349 end if;
6351 -- Neither the available components, nor the components inside the
6352 -- variant parts were of an unconstrained Unchecked_Union subtype.
6354 return False;
6355 end Has_Unconstrained_UU_Component;
6357 -- Start of processing for Expand_N_Op_Eq
6359 begin
6360 Binary_Op_Validity_Checks (N);
6362 if Ekind (Typl) = E_Private_Type then
6363 Typl := Underlying_Type (Typl);
6364 elsif Ekind (Typl) = E_Private_Subtype then
6365 Typl := Underlying_Type (Base_Type (Typl));
6366 else
6367 null;
6368 end if;
6370 -- It may happen in error situations that the underlying type is not
6371 -- set. The error will be detected later, here we just defend the
6372 -- expander code.
6374 if No (Typl) then
6375 return;
6376 end if;
6378 Typl := Base_Type (Typl);
6380 -- Boolean types (requiring handling of non-standard case)
6382 if Is_Boolean_Type (Typl) then
6383 Adjust_Condition (Left_Opnd (N));
6384 Adjust_Condition (Right_Opnd (N));
6385 Set_Etype (N, Standard_Boolean);
6386 Adjust_Result_Type (N, Typ);
6388 -- Array types
6390 elsif Is_Array_Type (Typl) then
6392 -- If we are doing full validity checking, and it is possible for the
6393 -- array elements to be invalid then expand out array comparisons to
6394 -- make sure that we check the array elements.
6396 if Validity_Check_Operands
6397 and then not Is_Known_Valid (Component_Type (Typl))
6398 then
6399 declare
6400 Save_Force_Validity_Checks : constant Boolean :=
6401 Force_Validity_Checks;
6402 begin
6403 Force_Validity_Checks := True;
6404 Rewrite (N,
6405 Expand_Array_Equality
6407 Relocate_Node (Lhs),
6408 Relocate_Node (Rhs),
6409 Bodies,
6410 Typl));
6411 Insert_Actions (N, Bodies);
6412 Analyze_And_Resolve (N, Standard_Boolean);
6413 Force_Validity_Checks := Save_Force_Validity_Checks;
6414 end;
6416 -- Packed case where both operands are known aligned
6418 elsif Is_Bit_Packed_Array (Typl)
6419 and then not Is_Possibly_Unaligned_Object (Lhs)
6420 and then not Is_Possibly_Unaligned_Object (Rhs)
6421 then
6422 Expand_Packed_Eq (N);
6424 -- Where the component type is elementary we can use a block bit
6425 -- comparison (if supported on the target) exception in the case
6426 -- of floating-point (negative zero issues require element by
6427 -- element comparison), and atomic types (where we must be sure
6428 -- to load elements independently) and possibly unaligned arrays.
6430 elsif Is_Elementary_Type (Component_Type (Typl))
6431 and then not Is_Floating_Point_Type (Component_Type (Typl))
6432 and then not Is_Atomic (Component_Type (Typl))
6433 and then not Is_Possibly_Unaligned_Object (Lhs)
6434 and then not Is_Possibly_Unaligned_Object (Rhs)
6435 and then Support_Composite_Compare_On_Target
6436 then
6437 null;
6439 -- For composite and floating-point cases, expand equality loop to
6440 -- make sure of using proper comparisons for tagged types, and
6441 -- correctly handling the floating-point case.
6443 else
6444 Rewrite (N,
6445 Expand_Array_Equality
6447 Relocate_Node (Lhs),
6448 Relocate_Node (Rhs),
6449 Bodies,
6450 Typl));
6451 Insert_Actions (N, Bodies, Suppress => All_Checks);
6452 Analyze_And_Resolve (N, Standard_Boolean, Suppress => All_Checks);
6453 end if;
6455 -- Record Types
6457 elsif Is_Record_Type (Typl) then
6459 -- For tagged types, use the primitive "="
6461 if Is_Tagged_Type (Typl) then
6463 -- No need to do anything else compiling under restriction
6464 -- No_Dispatching_Calls. During the semantic analysis we
6465 -- already notified such violation.
6467 if Restriction_Active (No_Dispatching_Calls) then
6468 return;
6469 end if;
6471 -- If this is derived from an untagged private type completed with
6472 -- a tagged type, it does not have a full view, so we use the
6473 -- primitive operations of the private type. This check should no
6474 -- longer be necessary when these types get their full views???
6476 if Is_Private_Type (A_Typ)
6477 and then not Is_Tagged_Type (A_Typ)
6478 and then Is_Derived_Type (A_Typ)
6479 and then No (Full_View (A_Typ))
6480 then
6481 -- Search for equality operation, checking that the operands
6482 -- have the same type. Note that we must find a matching entry,
6483 -- or something is very wrong!
6485 Prim := First_Elmt (Collect_Primitive_Operations (A_Typ));
6487 while Present (Prim) loop
6488 exit when Chars (Node (Prim)) = Name_Op_Eq
6489 and then Etype (First_Formal (Node (Prim))) =
6490 Etype (Next_Formal (First_Formal (Node (Prim))))
6491 and then
6492 Base_Type (Etype (Node (Prim))) = Standard_Boolean;
6494 Next_Elmt (Prim);
6495 end loop;
6497 pragma Assert (Present (Prim));
6498 Op_Name := Node (Prim);
6500 -- Find the type's predefined equality or an overriding
6501 -- user- defined equality. The reason for not simply calling
6502 -- Find_Prim_Op here is that there may be a user-defined
6503 -- overloaded equality op that precedes the equality that we want,
6504 -- so we have to explicitly search (e.g., there could be an
6505 -- equality with two different parameter types).
6507 else
6508 if Is_Class_Wide_Type (Typl) then
6509 Typl := Root_Type (Typl);
6510 end if;
6512 Prim := First_Elmt (Primitive_Operations (Typl));
6513 while Present (Prim) loop
6514 exit when Chars (Node (Prim)) = Name_Op_Eq
6515 and then Etype (First_Formal (Node (Prim))) =
6516 Etype (Next_Formal (First_Formal (Node (Prim))))
6517 and then
6518 Base_Type (Etype (Node (Prim))) = Standard_Boolean;
6520 Next_Elmt (Prim);
6521 end loop;
6523 pragma Assert (Present (Prim));
6524 Op_Name := Node (Prim);
6525 end if;
6527 Build_Equality_Call (Op_Name);
6529 -- Ada 2005 (AI-216): Program_Error is raised when evaluating the
6530 -- predefined equality operator for a type which has a subcomponent
6531 -- of an Unchecked_Union type whose nominal subtype is unconstrained.
6533 elsif Has_Unconstrained_UU_Component (Typl) then
6534 Insert_Action (N,
6535 Make_Raise_Program_Error (Loc,
6536 Reason => PE_Unchecked_Union_Restriction));
6538 -- Prevent Gigi from generating incorrect code by rewriting the
6539 -- equality as a standard False.
6541 Rewrite (N,
6542 New_Occurrence_Of (Standard_False, Loc));
6544 elsif Is_Unchecked_Union (Typl) then
6546 -- If we can infer the discriminants of the operands, we make a
6547 -- call to the TSS equality function.
6549 if Has_Inferable_Discriminants (Lhs)
6550 and then
6551 Has_Inferable_Discriminants (Rhs)
6552 then
6553 Build_Equality_Call
6554 (TSS (Root_Type (Typl), TSS_Composite_Equality));
6556 else
6557 -- Ada 2005 (AI-216): Program_Error is raised when evaluating
6558 -- the predefined equality operator for an Unchecked_Union type
6559 -- if either of the operands lack inferable discriminants.
6561 Insert_Action (N,
6562 Make_Raise_Program_Error (Loc,
6563 Reason => PE_Unchecked_Union_Restriction));
6565 -- Prevent Gigi from generating incorrect code by rewriting
6566 -- the equality as a standard False.
6568 Rewrite (N,
6569 New_Occurrence_Of (Standard_False, Loc));
6571 end if;
6573 -- If a type support function is present (for complex cases), use it
6575 elsif Present (TSS (Root_Type (Typl), TSS_Composite_Equality)) then
6576 Build_Equality_Call
6577 (TSS (Root_Type (Typl), TSS_Composite_Equality));
6579 -- Otherwise expand the component by component equality. Note that
6580 -- we never use block-bit comparisons for records, because of the
6581 -- problems with gaps. The backend will often be able to recombine
6582 -- the separate comparisons that we generate here.
6584 else
6585 Remove_Side_Effects (Lhs);
6586 Remove_Side_Effects (Rhs);
6587 Rewrite (N,
6588 Expand_Record_Equality (N, Typl, Lhs, Rhs, Bodies));
6590 Insert_Actions (N, Bodies, Suppress => All_Checks);
6591 Analyze_And_Resolve (N, Standard_Boolean, Suppress => All_Checks);
6592 end if;
6593 end if;
6595 -- Test if result is known at compile time
6597 Rewrite_Comparison (N);
6599 -- If we still have comparison for Vax_Float, process it
6601 if Vax_Float (Typl) and then Nkind (N) in N_Op_Compare then
6602 Expand_Vax_Comparison (N);
6603 return;
6604 end if;
6606 Optimize_Length_Comparison (N);
6607 end Expand_N_Op_Eq;
6609 -----------------------
6610 -- Expand_N_Op_Expon --
6611 -----------------------
6613 procedure Expand_N_Op_Expon (N : Node_Id) is
6614 Loc : constant Source_Ptr := Sloc (N);
6615 Typ : constant Entity_Id := Etype (N);
6616 Rtyp : constant Entity_Id := Root_Type (Typ);
6617 Base : constant Node_Id := Relocate_Node (Left_Opnd (N));
6618 Bastyp : constant Node_Id := Etype (Base);
6619 Exp : constant Node_Id := Relocate_Node (Right_Opnd (N));
6620 Exptyp : constant Entity_Id := Etype (Exp);
6621 Ovflo : constant Boolean := Do_Overflow_Check (N);
6622 Expv : Uint;
6623 Xnode : Node_Id;
6624 Temp : Node_Id;
6625 Rent : RE_Id;
6626 Ent : Entity_Id;
6627 Etyp : Entity_Id;
6629 begin
6630 Binary_Op_Validity_Checks (N);
6632 -- CodePeer and GNATprove want to see the unexpanded N_Op_Expon node
6634 if CodePeer_Mode or Alfa_Mode then
6635 return;
6636 end if;
6638 -- If either operand is of a private type, then we have the use of an
6639 -- intrinsic operator, and we get rid of the privateness, by using root
6640 -- types of underlying types for the actual operation. Otherwise the
6641 -- private types will cause trouble if we expand multiplications or
6642 -- shifts etc. We also do this transformation if the result type is
6643 -- different from the base type.
6645 if Is_Private_Type (Etype (Base))
6646 or else Is_Private_Type (Typ)
6647 or else Is_Private_Type (Exptyp)
6648 or else Rtyp /= Root_Type (Bastyp)
6649 then
6650 declare
6651 Bt : constant Entity_Id := Root_Type (Underlying_Type (Bastyp));
6652 Et : constant Entity_Id := Root_Type (Underlying_Type (Exptyp));
6654 begin
6655 Rewrite (N,
6656 Unchecked_Convert_To (Typ,
6657 Make_Op_Expon (Loc,
6658 Left_Opnd => Unchecked_Convert_To (Bt, Base),
6659 Right_Opnd => Unchecked_Convert_To (Et, Exp))));
6660 Analyze_And_Resolve (N, Typ);
6661 return;
6662 end;
6663 end if;
6665 -- Test for case of known right argument
6667 if Compile_Time_Known_Value (Exp) then
6668 Expv := Expr_Value (Exp);
6670 -- We only fold small non-negative exponents. You might think we
6671 -- could fold small negative exponents for the real case, but we
6672 -- can't because we are required to raise Constraint_Error for
6673 -- the case of 0.0 ** (negative) even if Machine_Overflows = False.
6674 -- See ACVC test C4A012B.
6676 if Expv >= 0 and then Expv <= 4 then
6678 -- X ** 0 = 1 (or 1.0)
6680 if Expv = 0 then
6682 -- Call Remove_Side_Effects to ensure that any side effects
6683 -- in the ignored left operand (in particular function calls
6684 -- to user defined functions) are properly executed.
6686 Remove_Side_Effects (Base);
6688 if Ekind (Typ) in Integer_Kind then
6689 Xnode := Make_Integer_Literal (Loc, Intval => 1);
6690 else
6691 Xnode := Make_Real_Literal (Loc, Ureal_1);
6692 end if;
6694 -- X ** 1 = X
6696 elsif Expv = 1 then
6697 Xnode := Base;
6699 -- X ** 2 = X * X
6701 elsif Expv = 2 then
6702 Xnode :=
6703 Make_Op_Multiply (Loc,
6704 Left_Opnd => Duplicate_Subexpr (Base),
6705 Right_Opnd => Duplicate_Subexpr_No_Checks (Base));
6707 -- X ** 3 = X * X * X
6709 elsif Expv = 3 then
6710 Xnode :=
6711 Make_Op_Multiply (Loc,
6712 Left_Opnd =>
6713 Make_Op_Multiply (Loc,
6714 Left_Opnd => Duplicate_Subexpr (Base),
6715 Right_Opnd => Duplicate_Subexpr_No_Checks (Base)),
6716 Right_Opnd => Duplicate_Subexpr_No_Checks (Base));
6718 -- X ** 4 ->
6719 -- En : constant base'type := base * base;
6720 -- ...
6721 -- En * En
6723 else -- Expv = 4
6724 Temp := Make_Temporary (Loc, 'E', Base);
6726 Insert_Actions (N, New_List (
6727 Make_Object_Declaration (Loc,
6728 Defining_Identifier => Temp,
6729 Constant_Present => True,
6730 Object_Definition => New_Reference_To (Typ, Loc),
6731 Expression =>
6732 Make_Op_Multiply (Loc,
6733 Left_Opnd => Duplicate_Subexpr (Base),
6734 Right_Opnd => Duplicate_Subexpr_No_Checks (Base)))));
6736 Xnode :=
6737 Make_Op_Multiply (Loc,
6738 Left_Opnd => New_Reference_To (Temp, Loc),
6739 Right_Opnd => New_Reference_To (Temp, Loc));
6740 end if;
6742 Rewrite (N, Xnode);
6743 Analyze_And_Resolve (N, Typ);
6744 return;
6745 end if;
6746 end if;
6748 -- Case of (2 ** expression) appearing as an argument of an integer
6749 -- multiplication, or as the right argument of a division of a non-
6750 -- negative integer. In such cases we leave the node untouched, setting
6751 -- the flag Is_Natural_Power_Of_2_for_Shift set, then the expansion
6752 -- of the higher level node converts it into a shift.
6754 -- Another case is 2 ** N in any other context. We simply convert
6755 -- this to 1 * 2 ** N, and then the above transformation applies.
6757 -- Note: this transformation is not applicable for a modular type with
6758 -- a non-binary modulus in the multiplication case, since we get a wrong
6759 -- result if the shift causes an overflow before the modular reduction.
6761 if Nkind (Base) = N_Integer_Literal
6762 and then Intval (Base) = 2
6763 and then Is_Integer_Type (Root_Type (Exptyp))
6764 and then Esize (Root_Type (Exptyp)) <= Esize (Standard_Integer)
6765 and then Is_Unsigned_Type (Exptyp)
6766 and then not Ovflo
6767 then
6768 -- First the multiply and divide cases
6770 if Nkind_In (Parent (N), N_Op_Divide, N_Op_Multiply) then
6771 declare
6772 P : constant Node_Id := Parent (N);
6773 L : constant Node_Id := Left_Opnd (P);
6774 R : constant Node_Id := Right_Opnd (P);
6776 begin
6777 if (Nkind (P) = N_Op_Multiply
6778 and then not Non_Binary_Modulus (Typ)
6779 and then
6780 ((Is_Integer_Type (Etype (L)) and then R = N)
6781 or else
6782 (Is_Integer_Type (Etype (R)) and then L = N))
6783 and then not Do_Overflow_Check (P))
6784 or else
6785 (Nkind (P) = N_Op_Divide
6786 and then Is_Integer_Type (Etype (L))
6787 and then Is_Unsigned_Type (Etype (L))
6788 and then R = N
6789 and then not Do_Overflow_Check (P))
6790 then
6791 Set_Is_Power_Of_2_For_Shift (N);
6792 return;
6793 end if;
6794 end;
6796 -- Now the other cases
6798 elsif not Non_Binary_Modulus (Typ) then
6799 Rewrite (N,
6800 Make_Op_Multiply (Loc,
6801 Left_Opnd => Make_Integer_Literal (Loc, 1),
6802 Right_Opnd => Relocate_Node (N)));
6803 Analyze_And_Resolve (N, Typ);
6804 return;
6805 end if;
6806 end if;
6808 -- Fall through if exponentiation must be done using a runtime routine
6810 -- First deal with modular case
6812 if Is_Modular_Integer_Type (Rtyp) then
6814 -- Non-binary case, we call the special exponentiation routine for
6815 -- the non-binary case, converting the argument to Long_Long_Integer
6816 -- and passing the modulus value. Then the result is converted back
6817 -- to the base type.
6819 if Non_Binary_Modulus (Rtyp) then
6820 Rewrite (N,
6821 Convert_To (Typ,
6822 Make_Function_Call (Loc,
6823 Name => New_Reference_To (RTE (RE_Exp_Modular), Loc),
6824 Parameter_Associations => New_List (
6825 Convert_To (Standard_Integer, Base),
6826 Make_Integer_Literal (Loc, Modulus (Rtyp)),
6827 Exp))));
6829 -- Binary case, in this case, we call one of two routines, either the
6830 -- unsigned integer case, or the unsigned long long integer case,
6831 -- with a final "and" operation to do the required mod.
6833 else
6834 if UI_To_Int (Esize (Rtyp)) <= Standard_Integer_Size then
6835 Ent := RTE (RE_Exp_Unsigned);
6836 else
6837 Ent := RTE (RE_Exp_Long_Long_Unsigned);
6838 end if;
6840 Rewrite (N,
6841 Convert_To (Typ,
6842 Make_Op_And (Loc,
6843 Left_Opnd =>
6844 Make_Function_Call (Loc,
6845 Name => New_Reference_To (Ent, Loc),
6846 Parameter_Associations => New_List (
6847 Convert_To (Etype (First_Formal (Ent)), Base),
6848 Exp)),
6849 Right_Opnd =>
6850 Make_Integer_Literal (Loc, Modulus (Rtyp) - 1))));
6852 end if;
6854 -- Common exit point for modular type case
6856 Analyze_And_Resolve (N, Typ);
6857 return;
6859 -- Signed integer cases, done using either Integer or Long_Long_Integer.
6860 -- It is not worth having routines for Short_[Short_]Integer, since for
6861 -- most machines it would not help, and it would generate more code that
6862 -- might need certification when a certified run time is required.
6864 -- In the integer cases, we have two routines, one for when overflow
6865 -- checks are required, and one when they are not required, since there
6866 -- is a real gain in omitting checks on many machines.
6868 elsif Rtyp = Base_Type (Standard_Long_Long_Integer)
6869 or else (Rtyp = Base_Type (Standard_Long_Integer)
6870 and then
6871 Esize (Standard_Long_Integer) > Esize (Standard_Integer))
6872 or else (Rtyp = Universal_Integer)
6873 then
6874 Etyp := Standard_Long_Long_Integer;
6876 if Ovflo then
6877 Rent := RE_Exp_Long_Long_Integer;
6878 else
6879 Rent := RE_Exn_Long_Long_Integer;
6880 end if;
6882 elsif Is_Signed_Integer_Type (Rtyp) then
6883 Etyp := Standard_Integer;
6885 if Ovflo then
6886 Rent := RE_Exp_Integer;
6887 else
6888 Rent := RE_Exn_Integer;
6889 end if;
6891 -- Floating-point cases, always done using Long_Long_Float. We do not
6892 -- need separate routines for the overflow case here, since in the case
6893 -- of floating-point, we generate infinities anyway as a rule (either
6894 -- that or we automatically trap overflow), and if there is an infinity
6895 -- generated and a range check is required, the check will fail anyway.
6897 else
6898 pragma Assert (Is_Floating_Point_Type (Rtyp));
6899 Etyp := Standard_Long_Long_Float;
6900 Rent := RE_Exn_Long_Long_Float;
6901 end if;
6903 -- Common processing for integer cases and floating-point cases.
6904 -- If we are in the right type, we can call runtime routine directly
6906 if Typ = Etyp
6907 and then Rtyp /= Universal_Integer
6908 and then Rtyp /= Universal_Real
6909 then
6910 Rewrite (N,
6911 Make_Function_Call (Loc,
6912 Name => New_Reference_To (RTE (Rent), Loc),
6913 Parameter_Associations => New_List (Base, Exp)));
6915 -- Otherwise we have to introduce conversions (conversions are also
6916 -- required in the universal cases, since the runtime routine is
6917 -- typed using one of the standard types).
6919 else
6920 Rewrite (N,
6921 Convert_To (Typ,
6922 Make_Function_Call (Loc,
6923 Name => New_Reference_To (RTE (Rent), Loc),
6924 Parameter_Associations => New_List (
6925 Convert_To (Etyp, Base),
6926 Exp))));
6927 end if;
6929 Analyze_And_Resolve (N, Typ);
6930 return;
6932 exception
6933 when RE_Not_Available =>
6934 return;
6935 end Expand_N_Op_Expon;
6937 --------------------
6938 -- Expand_N_Op_Ge --
6939 --------------------
6941 procedure Expand_N_Op_Ge (N : Node_Id) is
6942 Typ : constant Entity_Id := Etype (N);
6943 Op1 : constant Node_Id := Left_Opnd (N);
6944 Op2 : constant Node_Id := Right_Opnd (N);
6945 Typ1 : constant Entity_Id := Base_Type (Etype (Op1));
6947 begin
6948 Binary_Op_Validity_Checks (N);
6950 if Is_Array_Type (Typ1) then
6951 Expand_Array_Comparison (N);
6952 return;
6953 end if;
6955 if Is_Boolean_Type (Typ1) then
6956 Adjust_Condition (Op1);
6957 Adjust_Condition (Op2);
6958 Set_Etype (N, Standard_Boolean);
6959 Adjust_Result_Type (N, Typ);
6960 end if;
6962 Rewrite_Comparison (N);
6964 -- If we still have comparison, and Vax_Float type, process it
6966 if Vax_Float (Typ1) and then Nkind (N) in N_Op_Compare then
6967 Expand_Vax_Comparison (N);
6968 return;
6969 end if;
6971 Optimize_Length_Comparison (N);
6972 end Expand_N_Op_Ge;
6974 --------------------
6975 -- Expand_N_Op_Gt --
6976 --------------------
6978 procedure Expand_N_Op_Gt (N : Node_Id) is
6979 Typ : constant Entity_Id := Etype (N);
6980 Op1 : constant Node_Id := Left_Opnd (N);
6981 Op2 : constant Node_Id := Right_Opnd (N);
6982 Typ1 : constant Entity_Id := Base_Type (Etype (Op1));
6984 begin
6985 Binary_Op_Validity_Checks (N);
6987 if Is_Array_Type (Typ1) then
6988 Expand_Array_Comparison (N);
6989 return;
6990 end if;
6992 if Is_Boolean_Type (Typ1) then
6993 Adjust_Condition (Op1);
6994 Adjust_Condition (Op2);
6995 Set_Etype (N, Standard_Boolean);
6996 Adjust_Result_Type (N, Typ);
6997 end if;
6999 Rewrite_Comparison (N);
7001 -- If we still have comparison, and Vax_Float type, process it
7003 if Vax_Float (Typ1) and then Nkind (N) in N_Op_Compare then
7004 Expand_Vax_Comparison (N);
7005 return;
7006 end if;
7008 Optimize_Length_Comparison (N);
7009 end Expand_N_Op_Gt;
7011 --------------------
7012 -- Expand_N_Op_Le --
7013 --------------------
7015 procedure Expand_N_Op_Le (N : Node_Id) is
7016 Typ : constant Entity_Id := Etype (N);
7017 Op1 : constant Node_Id := Left_Opnd (N);
7018 Op2 : constant Node_Id := Right_Opnd (N);
7019 Typ1 : constant Entity_Id := Base_Type (Etype (Op1));
7021 begin
7022 Binary_Op_Validity_Checks (N);
7024 if Is_Array_Type (Typ1) then
7025 Expand_Array_Comparison (N);
7026 return;
7027 end if;
7029 if Is_Boolean_Type (Typ1) then
7030 Adjust_Condition (Op1);
7031 Adjust_Condition (Op2);
7032 Set_Etype (N, Standard_Boolean);
7033 Adjust_Result_Type (N, Typ);
7034 end if;
7036 Rewrite_Comparison (N);
7038 -- If we still have comparison, and Vax_Float type, process it
7040 if Vax_Float (Typ1) and then Nkind (N) in N_Op_Compare then
7041 Expand_Vax_Comparison (N);
7042 return;
7043 end if;
7045 Optimize_Length_Comparison (N);
7046 end Expand_N_Op_Le;
7048 --------------------
7049 -- Expand_N_Op_Lt --
7050 --------------------
7052 procedure Expand_N_Op_Lt (N : Node_Id) is
7053 Typ : constant Entity_Id := Etype (N);
7054 Op1 : constant Node_Id := Left_Opnd (N);
7055 Op2 : constant Node_Id := Right_Opnd (N);
7056 Typ1 : constant Entity_Id := Base_Type (Etype (Op1));
7058 begin
7059 Binary_Op_Validity_Checks (N);
7061 if Is_Array_Type (Typ1) then
7062 Expand_Array_Comparison (N);
7063 return;
7064 end if;
7066 if Is_Boolean_Type (Typ1) then
7067 Adjust_Condition (Op1);
7068 Adjust_Condition (Op2);
7069 Set_Etype (N, Standard_Boolean);
7070 Adjust_Result_Type (N, Typ);
7071 end if;
7073 Rewrite_Comparison (N);
7075 -- If we still have comparison, and Vax_Float type, process it
7077 if Vax_Float (Typ1) and then Nkind (N) in N_Op_Compare then
7078 Expand_Vax_Comparison (N);
7079 return;
7080 end if;
7082 Optimize_Length_Comparison (N);
7083 end Expand_N_Op_Lt;
7085 -----------------------
7086 -- Expand_N_Op_Minus --
7087 -----------------------
7089 procedure Expand_N_Op_Minus (N : Node_Id) is
7090 Loc : constant Source_Ptr := Sloc (N);
7091 Typ : constant Entity_Id := Etype (N);
7093 begin
7094 Unary_Op_Validity_Checks (N);
7096 if not Backend_Overflow_Checks_On_Target
7097 and then Is_Signed_Integer_Type (Etype (N))
7098 and then Do_Overflow_Check (N)
7099 then
7100 -- Software overflow checking expands -expr into (0 - expr)
7102 Rewrite (N,
7103 Make_Op_Subtract (Loc,
7104 Left_Opnd => Make_Integer_Literal (Loc, 0),
7105 Right_Opnd => Right_Opnd (N)));
7107 Analyze_And_Resolve (N, Typ);
7109 -- Vax floating-point types case
7111 elsif Vax_Float (Etype (N)) then
7112 Expand_Vax_Arith (N);
7113 end if;
7114 end Expand_N_Op_Minus;
7116 ---------------------
7117 -- Expand_N_Op_Mod --
7118 ---------------------
7120 procedure Expand_N_Op_Mod (N : Node_Id) is
7121 Loc : constant Source_Ptr := Sloc (N);
7122 Typ : constant Entity_Id := Etype (N);
7123 Left : constant Node_Id := Left_Opnd (N);
7124 Right : constant Node_Id := Right_Opnd (N);
7125 DOC : constant Boolean := Do_Overflow_Check (N);
7126 DDC : constant Boolean := Do_Division_Check (N);
7128 LLB : Uint;
7129 Llo : Uint;
7130 Lhi : Uint;
7131 LOK : Boolean;
7132 Rlo : Uint;
7133 Rhi : Uint;
7134 ROK : Boolean;
7136 pragma Warnings (Off, Lhi);
7138 begin
7139 Binary_Op_Validity_Checks (N);
7141 Determine_Range (Right, ROK, Rlo, Rhi, Assume_Valid => True);
7142 Determine_Range (Left, LOK, Llo, Lhi, Assume_Valid => True);
7144 -- Convert mod to rem if operands are known non-negative. We do this
7145 -- since it is quite likely that this will improve the quality of code,
7146 -- (the operation now corresponds to the hardware remainder), and it
7147 -- does not seem likely that it could be harmful.
7149 if LOK and then Llo >= 0
7150 and then
7151 ROK and then Rlo >= 0
7152 then
7153 Rewrite (N,
7154 Make_Op_Rem (Sloc (N),
7155 Left_Opnd => Left_Opnd (N),
7156 Right_Opnd => Right_Opnd (N)));
7158 -- Instead of reanalyzing the node we do the analysis manually. This
7159 -- avoids anomalies when the replacement is done in an instance and
7160 -- is epsilon more efficient.
7162 Set_Entity (N, Standard_Entity (S_Op_Rem));
7163 Set_Etype (N, Typ);
7164 Set_Do_Overflow_Check (N, DOC);
7165 Set_Do_Division_Check (N, DDC);
7166 Expand_N_Op_Rem (N);
7167 Set_Analyzed (N);
7169 -- Otherwise, normal mod processing
7171 else
7172 if Is_Integer_Type (Etype (N)) then
7173 Apply_Divide_Check (N);
7174 end if;
7176 -- Apply optimization x mod 1 = 0. We don't really need that with
7177 -- gcc, but it is useful with other back ends (e.g. AAMP), and is
7178 -- certainly harmless.
7180 if Is_Integer_Type (Etype (N))
7181 and then Compile_Time_Known_Value (Right)
7182 and then Expr_Value (Right) = Uint_1
7183 then
7184 -- Call Remove_Side_Effects to ensure that any side effects in
7185 -- the ignored left operand (in particular function calls to
7186 -- user defined functions) are properly executed.
7188 Remove_Side_Effects (Left);
7190 Rewrite (N, Make_Integer_Literal (Loc, 0));
7191 Analyze_And_Resolve (N, Typ);
7192 return;
7193 end if;
7195 -- Deal with annoying case of largest negative number remainder
7196 -- minus one. Gigi does not handle this case correctly, because
7197 -- it generates a divide instruction which may trap in this case.
7199 -- In fact the check is quite easy, if the right operand is -1, then
7200 -- the mod value is always 0, and we can just ignore the left operand
7201 -- completely in this case.
7203 -- The operand type may be private (e.g. in the expansion of an
7204 -- intrinsic operation) so we must use the underlying type to get the
7205 -- bounds, and convert the literals explicitly.
7207 LLB :=
7208 Expr_Value
7209 (Type_Low_Bound (Base_Type (Underlying_Type (Etype (Left)))));
7211 if ((not ROK) or else (Rlo <= (-1) and then (-1) <= Rhi))
7212 and then
7213 ((not LOK) or else (Llo = LLB))
7214 then
7215 Rewrite (N,
7216 Make_Conditional_Expression (Loc,
7217 Expressions => New_List (
7218 Make_Op_Eq (Loc,
7219 Left_Opnd => Duplicate_Subexpr (Right),
7220 Right_Opnd =>
7221 Unchecked_Convert_To (Typ,
7222 Make_Integer_Literal (Loc, -1))),
7223 Unchecked_Convert_To (Typ,
7224 Make_Integer_Literal (Loc, Uint_0)),
7225 Relocate_Node (N))));
7227 Set_Analyzed (Next (Next (First (Expressions (N)))));
7228 Analyze_And_Resolve (N, Typ);
7229 end if;
7230 end if;
7231 end Expand_N_Op_Mod;
7233 --------------------------
7234 -- Expand_N_Op_Multiply --
7235 --------------------------
7237 procedure Expand_N_Op_Multiply (N : Node_Id) is
7238 Loc : constant Source_Ptr := Sloc (N);
7239 Lop : constant Node_Id := Left_Opnd (N);
7240 Rop : constant Node_Id := Right_Opnd (N);
7242 Lp2 : constant Boolean :=
7243 Nkind (Lop) = N_Op_Expon
7244 and then Is_Power_Of_2_For_Shift (Lop);
7246 Rp2 : constant Boolean :=
7247 Nkind (Rop) = N_Op_Expon
7248 and then Is_Power_Of_2_For_Shift (Rop);
7250 Ltyp : constant Entity_Id := Etype (Lop);
7251 Rtyp : constant Entity_Id := Etype (Rop);
7252 Typ : Entity_Id := Etype (N);
7254 begin
7255 Binary_Op_Validity_Checks (N);
7257 -- Special optimizations for integer types
7259 if Is_Integer_Type (Typ) then
7261 -- N * 0 = 0 for integer types
7263 if Compile_Time_Known_Value (Rop)
7264 and then Expr_Value (Rop) = Uint_0
7265 then
7266 -- Call Remove_Side_Effects to ensure that any side effects in
7267 -- the ignored left operand (in particular function calls to
7268 -- user defined functions) are properly executed.
7270 Remove_Side_Effects (Lop);
7272 Rewrite (N, Make_Integer_Literal (Loc, Uint_0));
7273 Analyze_And_Resolve (N, Typ);
7274 return;
7275 end if;
7277 -- Similar handling for 0 * N = 0
7279 if Compile_Time_Known_Value (Lop)
7280 and then Expr_Value (Lop) = Uint_0
7281 then
7282 Remove_Side_Effects (Rop);
7283 Rewrite (N, Make_Integer_Literal (Loc, Uint_0));
7284 Analyze_And_Resolve (N, Typ);
7285 return;
7286 end if;
7288 -- N * 1 = 1 * N = N for integer types
7290 -- This optimisation is not done if we are going to
7291 -- rewrite the product 1 * 2 ** N to a shift.
7293 if Compile_Time_Known_Value (Rop)
7294 and then Expr_Value (Rop) = Uint_1
7295 and then not Lp2
7296 then
7297 Rewrite (N, Lop);
7298 return;
7300 elsif Compile_Time_Known_Value (Lop)
7301 and then Expr_Value (Lop) = Uint_1
7302 and then not Rp2
7303 then
7304 Rewrite (N, Rop);
7305 return;
7306 end if;
7307 end if;
7309 -- Convert x * 2 ** y to Shift_Left (x, y). Note that the fact that
7310 -- Is_Power_Of_2_For_Shift is set means that we know that our left
7311 -- operand is an integer, as required for this to work.
7313 if Rp2 then
7314 if Lp2 then
7316 -- Convert 2 ** A * 2 ** B into 2 ** (A + B)
7318 Rewrite (N,
7319 Make_Op_Expon (Loc,
7320 Left_Opnd => Make_Integer_Literal (Loc, 2),
7321 Right_Opnd =>
7322 Make_Op_Add (Loc,
7323 Left_Opnd => Right_Opnd (Lop),
7324 Right_Opnd => Right_Opnd (Rop))));
7325 Analyze_And_Resolve (N, Typ);
7326 return;
7328 else
7329 Rewrite (N,
7330 Make_Op_Shift_Left (Loc,
7331 Left_Opnd => Lop,
7332 Right_Opnd =>
7333 Convert_To (Standard_Natural, Right_Opnd (Rop))));
7334 Analyze_And_Resolve (N, Typ);
7335 return;
7336 end if;
7338 -- Same processing for the operands the other way round
7340 elsif Lp2 then
7341 Rewrite (N,
7342 Make_Op_Shift_Left (Loc,
7343 Left_Opnd => Rop,
7344 Right_Opnd =>
7345 Convert_To (Standard_Natural, Right_Opnd (Lop))));
7346 Analyze_And_Resolve (N, Typ);
7347 return;
7348 end if;
7350 -- Do required fixup of universal fixed operation
7352 if Typ = Universal_Fixed then
7353 Fixup_Universal_Fixed_Operation (N);
7354 Typ := Etype (N);
7355 end if;
7357 -- Multiplications with fixed-point results
7359 if Is_Fixed_Point_Type (Typ) then
7361 -- No special processing if Treat_Fixed_As_Integer is set, since from
7362 -- a semantic point of view such operations are simply integer
7363 -- operations and will be treated that way.
7365 if not Treat_Fixed_As_Integer (N) then
7367 -- Case of fixed * integer => fixed
7369 if Is_Integer_Type (Rtyp) then
7370 Expand_Multiply_Fixed_By_Integer_Giving_Fixed (N);
7372 -- Case of integer * fixed => fixed
7374 elsif Is_Integer_Type (Ltyp) then
7375 Expand_Multiply_Integer_By_Fixed_Giving_Fixed (N);
7377 -- Case of fixed * fixed => fixed
7379 else
7380 Expand_Multiply_Fixed_By_Fixed_Giving_Fixed (N);
7381 end if;
7382 end if;
7384 -- Other cases of multiplication of fixed-point operands. Again we
7385 -- exclude the cases where Treat_Fixed_As_Integer flag is set.
7387 elsif (Is_Fixed_Point_Type (Ltyp) or else Is_Fixed_Point_Type (Rtyp))
7388 and then not Treat_Fixed_As_Integer (N)
7389 then
7390 if Is_Integer_Type (Typ) then
7391 Expand_Multiply_Fixed_By_Fixed_Giving_Integer (N);
7392 else
7393 pragma Assert (Is_Floating_Point_Type (Typ));
7394 Expand_Multiply_Fixed_By_Fixed_Giving_Float (N);
7395 end if;
7397 -- Mixed-mode operations can appear in a non-static universal context,
7398 -- in which case the integer argument must be converted explicitly.
7400 elsif Typ = Universal_Real
7401 and then Is_Integer_Type (Rtyp)
7402 then
7403 Rewrite (Rop, Convert_To (Universal_Real, Relocate_Node (Rop)));
7405 Analyze_And_Resolve (Rop, Universal_Real);
7407 elsif Typ = Universal_Real
7408 and then Is_Integer_Type (Ltyp)
7409 then
7410 Rewrite (Lop, Convert_To (Universal_Real, Relocate_Node (Lop)));
7412 Analyze_And_Resolve (Lop, Universal_Real);
7414 -- Non-fixed point cases, check software overflow checking required
7416 elsif Is_Signed_Integer_Type (Etype (N)) then
7417 Apply_Arithmetic_Overflow_Check (N);
7419 -- Deal with VAX float case
7421 elsif Vax_Float (Typ) then
7422 Expand_Vax_Arith (N);
7423 return;
7424 end if;
7425 end Expand_N_Op_Multiply;
7427 --------------------
7428 -- Expand_N_Op_Ne --
7429 --------------------
7431 procedure Expand_N_Op_Ne (N : Node_Id) is
7432 Typ : constant Entity_Id := Etype (Left_Opnd (N));
7434 begin
7435 -- Case of elementary type with standard operator
7437 if Is_Elementary_Type (Typ)
7438 and then Sloc (Entity (N)) = Standard_Location
7439 then
7440 Binary_Op_Validity_Checks (N);
7442 -- Boolean types (requiring handling of non-standard case)
7444 if Is_Boolean_Type (Typ) then
7445 Adjust_Condition (Left_Opnd (N));
7446 Adjust_Condition (Right_Opnd (N));
7447 Set_Etype (N, Standard_Boolean);
7448 Adjust_Result_Type (N, Typ);
7449 end if;
7451 Rewrite_Comparison (N);
7453 -- If we still have comparison for Vax_Float, process it
7455 if Vax_Float (Typ) and then Nkind (N) in N_Op_Compare then
7456 Expand_Vax_Comparison (N);
7457 return;
7458 end if;
7460 -- For all cases other than elementary types, we rewrite node as the
7461 -- negation of an equality operation, and reanalyze. The equality to be
7462 -- used is defined in the same scope and has the same signature. This
7463 -- signature must be set explicitly since in an instance it may not have
7464 -- the same visibility as in the generic unit. This avoids duplicating
7465 -- or factoring the complex code for record/array equality tests etc.
7467 else
7468 declare
7469 Loc : constant Source_Ptr := Sloc (N);
7470 Neg : Node_Id;
7471 Ne : constant Entity_Id := Entity (N);
7473 begin
7474 Binary_Op_Validity_Checks (N);
7476 Neg :=
7477 Make_Op_Not (Loc,
7478 Right_Opnd =>
7479 Make_Op_Eq (Loc,
7480 Left_Opnd => Left_Opnd (N),
7481 Right_Opnd => Right_Opnd (N)));
7482 Set_Paren_Count (Right_Opnd (Neg), 1);
7484 if Scope (Ne) /= Standard_Standard then
7485 Set_Entity (Right_Opnd (Neg), Corresponding_Equality (Ne));
7486 end if;
7488 -- For navigation purposes, we want to treat the inequality as an
7489 -- implicit reference to the corresponding equality. Preserve the
7490 -- Comes_From_ source flag to generate proper Xref entries.
7492 Preserve_Comes_From_Source (Neg, N);
7493 Preserve_Comes_From_Source (Right_Opnd (Neg), N);
7494 Rewrite (N, Neg);
7495 Analyze_And_Resolve (N, Standard_Boolean);
7496 end;
7497 end if;
7499 Optimize_Length_Comparison (N);
7500 end Expand_N_Op_Ne;
7502 ---------------------
7503 -- Expand_N_Op_Not --
7504 ---------------------
7506 -- If the argument is other than a Boolean array type, there is no special
7507 -- expansion required, except for VMS operations on signed integers.
7509 -- For the packed case, we call the special routine in Exp_Pakd, except
7510 -- that if the component size is greater than one, we use the standard
7511 -- routine generating a gruesome loop (it is so peculiar to have packed
7512 -- arrays with non-standard Boolean representations anyway, so it does not
7513 -- matter that we do not handle this case efficiently).
7515 -- For the unpacked case (and for the special packed case where we have non
7516 -- standard Booleans, as discussed above), we generate and insert into the
7517 -- tree the following function definition:
7519 -- function Nnnn (A : arr) is
7520 -- B : arr;
7521 -- begin
7522 -- for J in a'range loop
7523 -- B (J) := not A (J);
7524 -- end loop;
7525 -- return B;
7526 -- end Nnnn;
7528 -- Here arr is the actual subtype of the parameter (and hence always
7529 -- constrained). Then we replace the not with a call to this function.
7531 procedure Expand_N_Op_Not (N : Node_Id) is
7532 Loc : constant Source_Ptr := Sloc (N);
7533 Typ : constant Entity_Id := Etype (N);
7534 Opnd : Node_Id;
7535 Arr : Entity_Id;
7536 A : Entity_Id;
7537 B : Entity_Id;
7538 J : Entity_Id;
7539 A_J : Node_Id;
7540 B_J : Node_Id;
7542 Func_Name : Entity_Id;
7543 Loop_Statement : Node_Id;
7545 begin
7546 Unary_Op_Validity_Checks (N);
7548 -- For boolean operand, deal with non-standard booleans
7550 if Is_Boolean_Type (Typ) then
7551 Adjust_Condition (Right_Opnd (N));
7552 Set_Etype (N, Standard_Boolean);
7553 Adjust_Result_Type (N, Typ);
7554 return;
7555 end if;
7557 -- For the VMS "not" on signed integer types, use conversion to and from
7558 -- a predefined modular type.
7560 if Is_VMS_Operator (Entity (N)) then
7561 declare
7562 Rtyp : Entity_Id;
7563 Utyp : Entity_Id;
7565 begin
7566 -- If this is a derived type, retrieve original VMS type so that
7567 -- the proper sized type is used for intermediate values.
7569 if Is_Derived_Type (Typ) then
7570 Rtyp := First_Subtype (Etype (Typ));
7571 else
7572 Rtyp := Typ;
7573 end if;
7575 -- The proper unsigned type must have a size compatible with the
7576 -- operand, to prevent misalignment.
7578 if RM_Size (Rtyp) <= 8 then
7579 Utyp := RTE (RE_Unsigned_8);
7581 elsif RM_Size (Rtyp) <= 16 then
7582 Utyp := RTE (RE_Unsigned_16);
7584 elsif RM_Size (Rtyp) = RM_Size (Standard_Unsigned) then
7585 Utyp := RTE (RE_Unsigned_32);
7587 else
7588 Utyp := RTE (RE_Long_Long_Unsigned);
7589 end if;
7591 Rewrite (N,
7592 Unchecked_Convert_To (Typ,
7593 Make_Op_Not (Loc,
7594 Unchecked_Convert_To (Utyp, Right_Opnd (N)))));
7595 Analyze_And_Resolve (N, Typ);
7596 return;
7597 end;
7598 end if;
7600 -- Only array types need any other processing
7602 if not Is_Array_Type (Typ) then
7603 return;
7604 end if;
7606 -- Case of array operand. If bit packed with a component size of 1,
7607 -- handle it in Exp_Pakd if the operand is known to be aligned.
7609 if Is_Bit_Packed_Array (Typ)
7610 and then Component_Size (Typ) = 1
7611 and then not Is_Possibly_Unaligned_Object (Right_Opnd (N))
7612 then
7613 Expand_Packed_Not (N);
7614 return;
7615 end if;
7617 -- Case of array operand which is not bit-packed. If the context is
7618 -- a safe assignment, call in-place operation, If context is a larger
7619 -- boolean expression in the context of a safe assignment, expansion is
7620 -- done by enclosing operation.
7622 Opnd := Relocate_Node (Right_Opnd (N));
7623 Convert_To_Actual_Subtype (Opnd);
7624 Arr := Etype (Opnd);
7625 Ensure_Defined (Arr, N);
7626 Silly_Boolean_Array_Not_Test (N, Arr);
7628 if Nkind (Parent (N)) = N_Assignment_Statement then
7629 if Safe_In_Place_Array_Op (Name (Parent (N)), N, Empty) then
7630 Build_Boolean_Array_Proc_Call (Parent (N), Opnd, Empty);
7631 return;
7633 -- Special case the negation of a binary operation
7635 elsif Nkind_In (Opnd, N_Op_And, N_Op_Or, N_Op_Xor)
7636 and then Safe_In_Place_Array_Op
7637 (Name (Parent (N)), Left_Opnd (Opnd), Right_Opnd (Opnd))
7638 then
7639 Build_Boolean_Array_Proc_Call (Parent (N), Opnd, Empty);
7640 return;
7641 end if;
7643 elsif Nkind (Parent (N)) in N_Binary_Op
7644 and then Nkind (Parent (Parent (N))) = N_Assignment_Statement
7645 then
7646 declare
7647 Op1 : constant Node_Id := Left_Opnd (Parent (N));
7648 Op2 : constant Node_Id := Right_Opnd (Parent (N));
7649 Lhs : constant Node_Id := Name (Parent (Parent (N)));
7651 begin
7652 if Safe_In_Place_Array_Op (Lhs, Op1, Op2) then
7654 -- (not A) op (not B) can be reduced to a single call
7656 if N = Op1 and then Nkind (Op2) = N_Op_Not then
7657 return;
7659 elsif N = Op2 and then Nkind (Op1) = N_Op_Not then
7660 return;
7662 -- A xor (not B) can also be special-cased
7664 elsif N = Op2 and then Nkind (Parent (N)) = N_Op_Xor then
7665 return;
7666 end if;
7667 end if;
7668 end;
7669 end if;
7671 A := Make_Defining_Identifier (Loc, Name_uA);
7672 B := Make_Defining_Identifier (Loc, Name_uB);
7673 J := Make_Defining_Identifier (Loc, Name_uJ);
7675 A_J :=
7676 Make_Indexed_Component (Loc,
7677 Prefix => New_Reference_To (A, Loc),
7678 Expressions => New_List (New_Reference_To (J, Loc)));
7680 B_J :=
7681 Make_Indexed_Component (Loc,
7682 Prefix => New_Reference_To (B, Loc),
7683 Expressions => New_List (New_Reference_To (J, Loc)));
7685 Loop_Statement :=
7686 Make_Implicit_Loop_Statement (N,
7687 Identifier => Empty,
7689 Iteration_Scheme =>
7690 Make_Iteration_Scheme (Loc,
7691 Loop_Parameter_Specification =>
7692 Make_Loop_Parameter_Specification (Loc,
7693 Defining_Identifier => J,
7694 Discrete_Subtype_Definition =>
7695 Make_Attribute_Reference (Loc,
7696 Prefix => Make_Identifier (Loc, Chars (A)),
7697 Attribute_Name => Name_Range))),
7699 Statements => New_List (
7700 Make_Assignment_Statement (Loc,
7701 Name => B_J,
7702 Expression => Make_Op_Not (Loc, A_J))));
7704 Func_Name := Make_Temporary (Loc, 'N');
7705 Set_Is_Inlined (Func_Name);
7707 Insert_Action (N,
7708 Make_Subprogram_Body (Loc,
7709 Specification =>
7710 Make_Function_Specification (Loc,
7711 Defining_Unit_Name => Func_Name,
7712 Parameter_Specifications => New_List (
7713 Make_Parameter_Specification (Loc,
7714 Defining_Identifier => A,
7715 Parameter_Type => New_Reference_To (Typ, Loc))),
7716 Result_Definition => New_Reference_To (Typ, Loc)),
7718 Declarations => New_List (
7719 Make_Object_Declaration (Loc,
7720 Defining_Identifier => B,
7721 Object_Definition => New_Reference_To (Arr, Loc))),
7723 Handled_Statement_Sequence =>
7724 Make_Handled_Sequence_Of_Statements (Loc,
7725 Statements => New_List (
7726 Loop_Statement,
7727 Make_Simple_Return_Statement (Loc,
7728 Expression => Make_Identifier (Loc, Chars (B)))))));
7730 Rewrite (N,
7731 Make_Function_Call (Loc,
7732 Name => New_Reference_To (Func_Name, Loc),
7733 Parameter_Associations => New_List (Opnd)));
7735 Analyze_And_Resolve (N, Typ);
7736 end Expand_N_Op_Not;
7738 --------------------
7739 -- Expand_N_Op_Or --
7740 --------------------
7742 procedure Expand_N_Op_Or (N : Node_Id) is
7743 Typ : constant Entity_Id := Etype (N);
7745 begin
7746 Binary_Op_Validity_Checks (N);
7748 if Is_Array_Type (Etype (N)) then
7749 Expand_Boolean_Operator (N);
7751 elsif Is_Boolean_Type (Etype (N)) then
7752 Adjust_Condition (Left_Opnd (N));
7753 Adjust_Condition (Right_Opnd (N));
7754 Set_Etype (N, Standard_Boolean);
7755 Adjust_Result_Type (N, Typ);
7757 elsif Is_Intrinsic_Subprogram (Entity (N)) then
7758 Expand_Intrinsic_Call (N, Entity (N));
7760 end if;
7761 end Expand_N_Op_Or;
7763 ----------------------
7764 -- Expand_N_Op_Plus --
7765 ----------------------
7767 procedure Expand_N_Op_Plus (N : Node_Id) is
7768 begin
7769 Unary_Op_Validity_Checks (N);
7770 end Expand_N_Op_Plus;
7772 ---------------------
7773 -- Expand_N_Op_Rem --
7774 ---------------------
7776 procedure Expand_N_Op_Rem (N : Node_Id) is
7777 Loc : constant Source_Ptr := Sloc (N);
7778 Typ : constant Entity_Id := Etype (N);
7780 Left : constant Node_Id := Left_Opnd (N);
7781 Right : constant Node_Id := Right_Opnd (N);
7783 Lo : Uint;
7784 Hi : Uint;
7785 OK : Boolean;
7787 Lneg : Boolean;
7788 Rneg : Boolean;
7789 -- Set if corresponding operand can be negative
7791 pragma Unreferenced (Hi);
7793 begin
7794 Binary_Op_Validity_Checks (N);
7796 if Is_Integer_Type (Etype (N)) then
7797 Apply_Divide_Check (N);
7798 end if;
7800 -- Apply optimization x rem 1 = 0. We don't really need that with gcc,
7801 -- but it is useful with other back ends (e.g. AAMP), and is certainly
7802 -- harmless.
7804 if Is_Integer_Type (Etype (N))
7805 and then Compile_Time_Known_Value (Right)
7806 and then Expr_Value (Right) = Uint_1
7807 then
7808 -- Call Remove_Side_Effects to ensure that any side effects in the
7809 -- ignored left operand (in particular function calls to user defined
7810 -- functions) are properly executed.
7812 Remove_Side_Effects (Left);
7814 Rewrite (N, Make_Integer_Literal (Loc, 0));
7815 Analyze_And_Resolve (N, Typ);
7816 return;
7817 end if;
7819 -- Deal with annoying case of largest negative number remainder minus
7820 -- one. Gigi does not handle this case correctly, because it generates
7821 -- a divide instruction which may trap in this case.
7823 -- In fact the check is quite easy, if the right operand is -1, then
7824 -- the remainder is always 0, and we can just ignore the left operand
7825 -- completely in this case.
7827 Determine_Range (Right, OK, Lo, Hi, Assume_Valid => True);
7828 Lneg := (not OK) or else Lo < 0;
7830 Determine_Range (Left, OK, Lo, Hi, Assume_Valid => True);
7831 Rneg := (not OK) or else Lo < 0;
7833 -- We won't mess with trying to find out if the left operand can really
7834 -- be the largest negative number (that's a pain in the case of private
7835 -- types and this is really marginal). We will just assume that we need
7836 -- the test if the left operand can be negative at all.
7838 if Lneg and Rneg then
7839 Rewrite (N,
7840 Make_Conditional_Expression (Loc,
7841 Expressions => New_List (
7842 Make_Op_Eq (Loc,
7843 Left_Opnd => Duplicate_Subexpr (Right),
7844 Right_Opnd =>
7845 Unchecked_Convert_To (Typ, Make_Integer_Literal (Loc, -1))),
7847 Unchecked_Convert_To (Typ,
7848 Make_Integer_Literal (Loc, Uint_0)),
7850 Relocate_Node (N))));
7852 Set_Analyzed (Next (Next (First (Expressions (N)))));
7853 Analyze_And_Resolve (N, Typ);
7854 end if;
7855 end Expand_N_Op_Rem;
7857 -----------------------------
7858 -- Expand_N_Op_Rotate_Left --
7859 -----------------------------
7861 procedure Expand_N_Op_Rotate_Left (N : Node_Id) is
7862 begin
7863 Binary_Op_Validity_Checks (N);
7864 end Expand_N_Op_Rotate_Left;
7866 ------------------------------
7867 -- Expand_N_Op_Rotate_Right --
7868 ------------------------------
7870 procedure Expand_N_Op_Rotate_Right (N : Node_Id) is
7871 begin
7872 Binary_Op_Validity_Checks (N);
7873 end Expand_N_Op_Rotate_Right;
7875 ----------------------------
7876 -- Expand_N_Op_Shift_Left --
7877 ----------------------------
7879 procedure Expand_N_Op_Shift_Left (N : Node_Id) is
7880 begin
7881 Binary_Op_Validity_Checks (N);
7882 end Expand_N_Op_Shift_Left;
7884 -----------------------------
7885 -- Expand_N_Op_Shift_Right --
7886 -----------------------------
7888 procedure Expand_N_Op_Shift_Right (N : Node_Id) is
7889 begin
7890 Binary_Op_Validity_Checks (N);
7891 end Expand_N_Op_Shift_Right;
7893 ----------------------------------------
7894 -- Expand_N_Op_Shift_Right_Arithmetic --
7895 ----------------------------------------
7897 procedure Expand_N_Op_Shift_Right_Arithmetic (N : Node_Id) is
7898 begin
7899 Binary_Op_Validity_Checks (N);
7900 end Expand_N_Op_Shift_Right_Arithmetic;
7902 --------------------------
7903 -- Expand_N_Op_Subtract --
7904 --------------------------
7906 procedure Expand_N_Op_Subtract (N : Node_Id) is
7907 Typ : constant Entity_Id := Etype (N);
7909 begin
7910 Binary_Op_Validity_Checks (N);
7912 -- N - 0 = N for integer types
7914 if Is_Integer_Type (Typ)
7915 and then Compile_Time_Known_Value (Right_Opnd (N))
7916 and then Expr_Value (Right_Opnd (N)) = 0
7917 then
7918 Rewrite (N, Left_Opnd (N));
7919 return;
7920 end if;
7922 -- Arithmetic overflow checks for signed integer/fixed point types
7924 if Is_Signed_Integer_Type (Typ)
7925 or else
7926 Is_Fixed_Point_Type (Typ)
7927 then
7928 Apply_Arithmetic_Overflow_Check (N);
7930 -- VAX floating-point types case
7932 elsif Vax_Float (Typ) then
7933 Expand_Vax_Arith (N);
7934 end if;
7935 end Expand_N_Op_Subtract;
7937 ---------------------
7938 -- Expand_N_Op_Xor --
7939 ---------------------
7941 procedure Expand_N_Op_Xor (N : Node_Id) is
7942 Typ : constant Entity_Id := Etype (N);
7944 begin
7945 Binary_Op_Validity_Checks (N);
7947 if Is_Array_Type (Etype (N)) then
7948 Expand_Boolean_Operator (N);
7950 elsif Is_Boolean_Type (Etype (N)) then
7951 Adjust_Condition (Left_Opnd (N));
7952 Adjust_Condition (Right_Opnd (N));
7953 Set_Etype (N, Standard_Boolean);
7954 Adjust_Result_Type (N, Typ);
7956 elsif Is_Intrinsic_Subprogram (Entity (N)) then
7957 Expand_Intrinsic_Call (N, Entity (N));
7959 end if;
7960 end Expand_N_Op_Xor;
7962 ----------------------
7963 -- Expand_N_Or_Else --
7964 ----------------------
7966 procedure Expand_N_Or_Else (N : Node_Id)
7967 renames Expand_Short_Circuit_Operator;
7969 -----------------------------------
7970 -- Expand_N_Qualified_Expression --
7971 -----------------------------------
7973 procedure Expand_N_Qualified_Expression (N : Node_Id) is
7974 Operand : constant Node_Id := Expression (N);
7975 Target_Type : constant Entity_Id := Entity (Subtype_Mark (N));
7977 begin
7978 -- Do validity check if validity checking operands
7980 if Validity_Checks_On and then Validity_Check_Operands then
7981 Ensure_Valid (Operand);
7982 end if;
7984 -- Apply possible constraint check
7986 Apply_Constraint_Check (Operand, Target_Type, No_Sliding => True);
7988 if Do_Range_Check (Operand) then
7989 Set_Do_Range_Check (Operand, False);
7990 Generate_Range_Check (Operand, Target_Type, CE_Range_Check_Failed);
7991 end if;
7992 end Expand_N_Qualified_Expression;
7994 ------------------------------------
7995 -- Expand_N_Quantified_Expression --
7996 ------------------------------------
7998 -- We expand:
8000 -- for all X in range => Cond
8002 -- into:
8004 -- T := True;
8005 -- for X in range loop
8006 -- if not Cond then
8007 -- T := False;
8008 -- exit;
8009 -- end if;
8010 -- end loop;
8012 -- Similarly, an existentially quantified expression:
8014 -- for some X in range => Cond
8016 -- becomes:
8018 -- T := False;
8019 -- for X in range loop
8020 -- if Cond then
8021 -- T := True;
8022 -- exit;
8023 -- end if;
8024 -- end loop;
8026 -- In both cases, the iteration may be over a container in which case it is
8027 -- given by an iterator specification, not a loop parameter specification.
8029 procedure Expand_N_Quantified_Expression (N : Node_Id) is
8030 Actions : constant List_Id := New_List;
8031 For_All : constant Boolean := All_Present (N);
8032 Iter_Spec : constant Node_Id := Iterator_Specification (N);
8033 Loc : constant Source_Ptr := Sloc (N);
8034 Loop_Spec : constant Node_Id := Loop_Parameter_Specification (N);
8035 Cond : Node_Id;
8036 Flag : Entity_Id;
8037 Scheme : Node_Id;
8038 Stmts : List_Id;
8040 begin
8041 -- Create the declaration of the flag which tracks the status of the
8042 -- quantified expression. Generate:
8044 -- Flag : Boolean := (True | False);
8046 Flag := Make_Temporary (Loc, 'T', N);
8048 Append_To (Actions,
8049 Make_Object_Declaration (Loc,
8050 Defining_Identifier => Flag,
8051 Object_Definition => New_Occurrence_Of (Standard_Boolean, Loc),
8052 Expression =>
8053 New_Occurrence_Of (Boolean_Literals (For_All), Loc)));
8055 -- Construct the circuitry which tracks the status of the quantified
8056 -- expression. Generate:
8058 -- if [not] Cond then
8059 -- Flag := (False | True);
8060 -- exit;
8061 -- end if;
8063 Cond := Relocate_Node (Condition (N));
8065 if For_All then
8066 Cond := Make_Op_Not (Loc, Cond);
8067 end if;
8069 Stmts := New_List (
8070 Make_Implicit_If_Statement (N,
8071 Condition => Cond,
8072 Then_Statements => New_List (
8073 Make_Assignment_Statement (Loc,
8074 Name => New_Occurrence_Of (Flag, Loc),
8075 Expression =>
8076 New_Occurrence_Of (Boolean_Literals (not For_All), Loc)),
8077 Make_Exit_Statement (Loc))));
8079 -- Build the loop equivalent of the quantified expression
8081 if Present (Iter_Spec) then
8082 Scheme :=
8083 Make_Iteration_Scheme (Loc,
8084 Iterator_Specification => Iter_Spec);
8085 else
8086 Scheme :=
8087 Make_Iteration_Scheme (Loc,
8088 Loop_Parameter_Specification => Loop_Spec);
8089 end if;
8091 Append_To (Actions,
8092 Make_Loop_Statement (Loc,
8093 Iteration_Scheme => Scheme,
8094 Statements => Stmts,
8095 End_Label => Empty));
8097 -- Transform the quantified expression
8099 Rewrite (N,
8100 Make_Expression_With_Actions (Loc,
8101 Expression => New_Occurrence_Of (Flag, Loc),
8102 Actions => Actions));
8103 Analyze_And_Resolve (N, Standard_Boolean);
8104 end Expand_N_Quantified_Expression;
8106 ---------------------------------
8107 -- Expand_N_Selected_Component --
8108 ---------------------------------
8110 procedure Expand_N_Selected_Component (N : Node_Id) is
8111 Loc : constant Source_Ptr := Sloc (N);
8112 Par : constant Node_Id := Parent (N);
8113 P : constant Node_Id := Prefix (N);
8114 Ptyp : Entity_Id := Underlying_Type (Etype (P));
8115 Disc : Entity_Id;
8116 New_N : Node_Id;
8117 Dcon : Elmt_Id;
8118 Dval : Node_Id;
8120 function In_Left_Hand_Side (Comp : Node_Id) return Boolean;
8121 -- Gigi needs a temporary for prefixes that depend on a discriminant,
8122 -- unless the context of an assignment can provide size information.
8123 -- Don't we have a general routine that does this???
8125 function Is_Subtype_Declaration return Boolean;
8126 -- The replacement of a discriminant reference by its value is required
8127 -- if this is part of the initialization of an temporary generated by a
8128 -- change of representation. This shows up as the construction of a
8129 -- discriminant constraint for a subtype declared at the same point as
8130 -- the entity in the prefix of the selected component. We recognize this
8131 -- case when the context of the reference is:
8132 -- subtype ST is T(Obj.D);
8133 -- where the entity for Obj comes from source, and ST has the same sloc.
8135 -----------------------
8136 -- In_Left_Hand_Side --
8137 -----------------------
8139 function In_Left_Hand_Side (Comp : Node_Id) return Boolean is
8140 begin
8141 return (Nkind (Parent (Comp)) = N_Assignment_Statement
8142 and then Comp = Name (Parent (Comp)))
8143 or else (Present (Parent (Comp))
8144 and then Nkind (Parent (Comp)) in N_Subexpr
8145 and then In_Left_Hand_Side (Parent (Comp)));
8146 end In_Left_Hand_Side;
8148 -----------------------------
8149 -- Is_Subtype_Declaration --
8150 -----------------------------
8152 function Is_Subtype_Declaration return Boolean is
8153 Par : constant Node_Id := Parent (N);
8154 begin
8155 return
8156 Nkind (Par) = N_Index_Or_Discriminant_Constraint
8157 and then Nkind (Parent (Parent (Par))) = N_Subtype_Declaration
8158 and then Comes_From_Source (Entity (Prefix (N)))
8159 and then Sloc (Par) = Sloc (Entity (Prefix (N)));
8160 end Is_Subtype_Declaration;
8162 -- Start of processing for Expand_N_Selected_Component
8164 begin
8165 -- Insert explicit dereference if required
8167 if Is_Access_Type (Ptyp) then
8169 -- First set prefix type to proper access type, in case it currently
8170 -- has a private (non-access) view of this type.
8172 Set_Etype (P, Ptyp);
8174 Insert_Explicit_Dereference (P);
8175 Analyze_And_Resolve (P, Designated_Type (Ptyp));
8177 if Ekind (Etype (P)) = E_Private_Subtype
8178 and then Is_For_Access_Subtype (Etype (P))
8179 then
8180 Set_Etype (P, Base_Type (Etype (P)));
8181 end if;
8183 Ptyp := Etype (P);
8184 end if;
8186 -- Deal with discriminant check required
8188 if Do_Discriminant_Check (N) then
8190 -- Present the discriminant checking function to the backend, so that
8191 -- it can inline the call to the function.
8193 Add_Inlined_Body
8194 (Discriminant_Checking_Func
8195 (Original_Record_Component (Entity (Selector_Name (N)))));
8197 -- Now reset the flag and generate the call
8199 Set_Do_Discriminant_Check (N, False);
8200 Generate_Discriminant_Check (N);
8201 end if;
8203 -- Ada 2005 (AI-318-02): If the prefix is a call to a build-in-place
8204 -- function, then additional actuals must be passed.
8206 if Ada_Version >= Ada_2005
8207 and then Is_Build_In_Place_Function_Call (P)
8208 then
8209 Make_Build_In_Place_Call_In_Anonymous_Context (P);
8210 end if;
8212 -- Gigi cannot handle unchecked conversions that are the prefix of a
8213 -- selected component with discriminants. This must be checked during
8214 -- expansion, because during analysis the type of the selector is not
8215 -- known at the point the prefix is analyzed. If the conversion is the
8216 -- target of an assignment, then we cannot force the evaluation.
8218 if Nkind (Prefix (N)) = N_Unchecked_Type_Conversion
8219 and then Has_Discriminants (Etype (N))
8220 and then not In_Left_Hand_Side (N)
8221 then
8222 Force_Evaluation (Prefix (N));
8223 end if;
8225 -- Remaining processing applies only if selector is a discriminant
8227 if Ekind (Entity (Selector_Name (N))) = E_Discriminant then
8229 -- If the selector is a discriminant of a constrained record type,
8230 -- we may be able to rewrite the expression with the actual value
8231 -- of the discriminant, a useful optimization in some cases.
8233 if Is_Record_Type (Ptyp)
8234 and then Has_Discriminants (Ptyp)
8235 and then Is_Constrained (Ptyp)
8236 then
8237 -- Do this optimization for discrete types only, and not for
8238 -- access types (access discriminants get us into trouble!)
8240 if not Is_Discrete_Type (Etype (N)) then
8241 null;
8243 -- Don't do this on the left hand of an assignment statement.
8244 -- Normally one would think that references like this would not
8245 -- occur, but they do in generated code, and mean that we really
8246 -- do want to assign the discriminant!
8248 elsif Nkind (Par) = N_Assignment_Statement
8249 and then Name (Par) = N
8250 then
8251 null;
8253 -- Don't do this optimization for the prefix of an attribute or
8254 -- the name of an object renaming declaration since these are
8255 -- contexts where we do not want the value anyway.
8257 elsif (Nkind (Par) = N_Attribute_Reference
8258 and then Prefix (Par) = N)
8259 or else Is_Renamed_Object (N)
8260 then
8261 null;
8263 -- Don't do this optimization if we are within the code for a
8264 -- discriminant check, since the whole point of such a check may
8265 -- be to verify the condition on which the code below depends!
8267 elsif Is_In_Discriminant_Check (N) then
8268 null;
8270 -- Green light to see if we can do the optimization. There is
8271 -- still one condition that inhibits the optimization below but
8272 -- now is the time to check the particular discriminant.
8274 else
8275 -- Loop through discriminants to find the matching discriminant
8276 -- constraint to see if we can copy it.
8278 Disc := First_Discriminant (Ptyp);
8279 Dcon := First_Elmt (Discriminant_Constraint (Ptyp));
8280 Discr_Loop : while Present (Dcon) loop
8281 Dval := Node (Dcon);
8283 -- Check if this is the matching discriminant and if the
8284 -- discriminant value is simple enough to make sense to
8285 -- copy. We don't want to copy complex expressions, and
8286 -- indeed to do so can cause trouble (before we put in
8287 -- this guard, a discriminant expression containing an
8288 -- AND THEN was copied, causing problems for coverage
8289 -- analysis tools).
8291 -- However, if the reference is part of the initialization
8292 -- code generated for an object declaration, we must use
8293 -- the discriminant value from the subtype constraint,
8294 -- because the selected component may be a reference to the
8295 -- object being initialized, whose discriminant is not yet
8296 -- set. This only happens in complex cases involving changes
8297 -- or representation.
8299 if Disc = Entity (Selector_Name (N))
8300 and then (Is_Entity_Name (Dval)
8301 or else Compile_Time_Known_Value (Dval)
8302 or else Is_Subtype_Declaration)
8303 then
8304 -- Here we have the matching discriminant. Check for
8305 -- the case of a discriminant of a component that is
8306 -- constrained by an outer discriminant, which cannot
8307 -- be optimized away.
8309 if Denotes_Discriminant
8310 (Dval, Check_Concurrent => True)
8311 then
8312 exit Discr_Loop;
8314 elsif Nkind (Original_Node (Dval)) = N_Selected_Component
8315 and then
8316 Denotes_Discriminant
8317 (Selector_Name (Original_Node (Dval)), True)
8318 then
8319 exit Discr_Loop;
8321 -- Do not retrieve value if constraint is not static. It
8322 -- is generally not useful, and the constraint may be a
8323 -- rewritten outer discriminant in which case it is in
8324 -- fact incorrect.
8326 elsif Is_Entity_Name (Dval)
8327 and then Nkind (Parent (Entity (Dval))) =
8328 N_Object_Declaration
8329 and then Present (Expression (Parent (Entity (Dval))))
8330 and then
8331 not Is_Static_Expression
8332 (Expression (Parent (Entity (Dval))))
8333 then
8334 exit Discr_Loop;
8336 -- In the context of a case statement, the expression may
8337 -- have the base type of the discriminant, and we need to
8338 -- preserve the constraint to avoid spurious errors on
8339 -- missing cases.
8341 elsif Nkind (Parent (N)) = N_Case_Statement
8342 and then Etype (Dval) /= Etype (Disc)
8343 then
8344 Rewrite (N,
8345 Make_Qualified_Expression (Loc,
8346 Subtype_Mark =>
8347 New_Occurrence_Of (Etype (Disc), Loc),
8348 Expression =>
8349 New_Copy_Tree (Dval)));
8350 Analyze_And_Resolve (N, Etype (Disc));
8352 -- In case that comes out as a static expression,
8353 -- reset it (a selected component is never static).
8355 Set_Is_Static_Expression (N, False);
8356 return;
8358 -- Otherwise we can just copy the constraint, but the
8359 -- result is certainly not static! In some cases the
8360 -- discriminant constraint has been analyzed in the
8361 -- context of the original subtype indication, but for
8362 -- itypes the constraint might not have been analyzed
8363 -- yet, and this must be done now.
8365 else
8366 Rewrite (N, New_Copy_Tree (Dval));
8367 Analyze_And_Resolve (N);
8368 Set_Is_Static_Expression (N, False);
8369 return;
8370 end if;
8371 end if;
8373 Next_Elmt (Dcon);
8374 Next_Discriminant (Disc);
8375 end loop Discr_Loop;
8377 -- Note: the above loop should always find a matching
8378 -- discriminant, but if it does not, we just missed an
8379 -- optimization due to some glitch (perhaps a previous
8380 -- error), so ignore.
8382 end if;
8383 end if;
8385 -- The only remaining processing is in the case of a discriminant of
8386 -- a concurrent object, where we rewrite the prefix to denote the
8387 -- corresponding record type. If the type is derived and has renamed
8388 -- discriminants, use corresponding discriminant, which is the one
8389 -- that appears in the corresponding record.
8391 if not Is_Concurrent_Type (Ptyp) then
8392 return;
8393 end if;
8395 Disc := Entity (Selector_Name (N));
8397 if Is_Derived_Type (Ptyp)
8398 and then Present (Corresponding_Discriminant (Disc))
8399 then
8400 Disc := Corresponding_Discriminant (Disc);
8401 end if;
8403 New_N :=
8404 Make_Selected_Component (Loc,
8405 Prefix =>
8406 Unchecked_Convert_To (Corresponding_Record_Type (Ptyp),
8407 New_Copy_Tree (P)),
8408 Selector_Name => Make_Identifier (Loc, Chars (Disc)));
8410 Rewrite (N, New_N);
8411 Analyze (N);
8412 end if;
8414 -- Set Atomic_Sync_Required if necessary for atomic component
8416 if Nkind (N) = N_Selected_Component then
8417 declare
8418 E : constant Entity_Id := Entity (Selector_Name (N));
8419 Set : Boolean;
8421 begin
8422 -- If component is atomic, but type is not, setting depends on
8423 -- disable/enable state for the component.
8425 if Is_Atomic (E) and then not Is_Atomic (Etype (E)) then
8426 Set := not Atomic_Synchronization_Disabled (E);
8428 -- If component is not atomic, but its type is atomic, setting
8429 -- depends on disable/enable state for the type.
8431 elsif not Is_Atomic (E) and then Is_Atomic (Etype (E)) then
8432 Set := not Atomic_Synchronization_Disabled (Etype (E));
8434 -- If both component and type are atomic, we disable if either
8435 -- component or its type have sync disabled.
8437 elsif Is_Atomic (E) and then Is_Atomic (Etype (E)) then
8438 Set := (not Atomic_Synchronization_Disabled (E))
8439 and then
8440 (not Atomic_Synchronization_Disabled (Etype (E)));
8442 else
8443 Set := False;
8444 end if;
8446 -- Set flag if required
8448 if Set then
8449 Activate_Atomic_Synchronization (N);
8450 end if;
8451 end;
8452 end if;
8453 end Expand_N_Selected_Component;
8455 --------------------
8456 -- Expand_N_Slice --
8457 --------------------
8459 procedure Expand_N_Slice (N : Node_Id) is
8460 Loc : constant Source_Ptr := Sloc (N);
8461 Typ : constant Entity_Id := Etype (N);
8462 Pfx : constant Node_Id := Prefix (N);
8463 Ptp : Entity_Id := Etype (Pfx);
8465 function Is_Procedure_Actual (N : Node_Id) return Boolean;
8466 -- Check whether the argument is an actual for a procedure call, in
8467 -- which case the expansion of a bit-packed slice is deferred until the
8468 -- call itself is expanded. The reason this is required is that we might
8469 -- have an IN OUT or OUT parameter, and the copy out is essential, and
8470 -- that copy out would be missed if we created a temporary here in
8471 -- Expand_N_Slice. Note that we don't bother to test specifically for an
8472 -- IN OUT or OUT mode parameter, since it is a bit tricky to do, and it
8473 -- is harmless to defer expansion in the IN case, since the call
8474 -- processing will still generate the appropriate copy in operation,
8475 -- which will take care of the slice.
8477 procedure Make_Temporary_For_Slice;
8478 -- Create a named variable for the value of the slice, in cases where
8479 -- the back-end cannot handle it properly, e.g. when packed types or
8480 -- unaligned slices are involved.
8482 -------------------------
8483 -- Is_Procedure_Actual --
8484 -------------------------
8486 function Is_Procedure_Actual (N : Node_Id) return Boolean is
8487 Par : Node_Id := Parent (N);
8489 begin
8490 loop
8491 -- If our parent is a procedure call we can return
8493 if Nkind (Par) = N_Procedure_Call_Statement then
8494 return True;
8496 -- If our parent is a type conversion, keep climbing the tree,
8497 -- since a type conversion can be a procedure actual. Also keep
8498 -- climbing if parameter association or a qualified expression,
8499 -- since these are additional cases that do can appear on
8500 -- procedure actuals.
8502 elsif Nkind_In (Par, N_Type_Conversion,
8503 N_Parameter_Association,
8504 N_Qualified_Expression)
8505 then
8506 Par := Parent (Par);
8508 -- Any other case is not what we are looking for
8510 else
8511 return False;
8512 end if;
8513 end loop;
8514 end Is_Procedure_Actual;
8516 ------------------------------
8517 -- Make_Temporary_For_Slice --
8518 ------------------------------
8520 procedure Make_Temporary_For_Slice is
8521 Decl : Node_Id;
8522 Ent : constant Entity_Id := Make_Temporary (Loc, 'T', N);
8524 begin
8525 Decl :=
8526 Make_Object_Declaration (Loc,
8527 Defining_Identifier => Ent,
8528 Object_Definition => New_Occurrence_Of (Typ, Loc));
8530 Set_No_Initialization (Decl);
8532 Insert_Actions (N, New_List (
8533 Decl,
8534 Make_Assignment_Statement (Loc,
8535 Name => New_Occurrence_Of (Ent, Loc),
8536 Expression => Relocate_Node (N))));
8538 Rewrite (N, New_Occurrence_Of (Ent, Loc));
8539 Analyze_And_Resolve (N, Typ);
8540 end Make_Temporary_For_Slice;
8542 -- Start of processing for Expand_N_Slice
8544 begin
8545 -- Special handling for access types
8547 if Is_Access_Type (Ptp) then
8549 Ptp := Designated_Type (Ptp);
8551 Rewrite (Pfx,
8552 Make_Explicit_Dereference (Sloc (N),
8553 Prefix => Relocate_Node (Pfx)));
8555 Analyze_And_Resolve (Pfx, Ptp);
8556 end if;
8558 -- Ada 2005 (AI-318-02): If the prefix is a call to a build-in-place
8559 -- function, then additional actuals must be passed.
8561 if Ada_Version >= Ada_2005
8562 and then Is_Build_In_Place_Function_Call (Pfx)
8563 then
8564 Make_Build_In_Place_Call_In_Anonymous_Context (Pfx);
8565 end if;
8567 -- The remaining case to be handled is packed slices. We can leave
8568 -- packed slices as they are in the following situations:
8570 -- 1. Right or left side of an assignment (we can handle this
8571 -- situation correctly in the assignment statement expansion).
8573 -- 2. Prefix of indexed component (the slide is optimized away in this
8574 -- case, see the start of Expand_N_Slice.)
8576 -- 3. Object renaming declaration, since we want the name of the
8577 -- slice, not the value.
8579 -- 4. Argument to procedure call, since copy-in/copy-out handling may
8580 -- be required, and this is handled in the expansion of call
8581 -- itself.
8583 -- 5. Prefix of an address attribute (this is an error which is caught
8584 -- elsewhere, and the expansion would interfere with generating the
8585 -- error message).
8587 if not Is_Packed (Typ) then
8589 -- Apply transformation for actuals of a function call, where
8590 -- Expand_Actuals is not used.
8592 if Nkind (Parent (N)) = N_Function_Call
8593 and then Is_Possibly_Unaligned_Slice (N)
8594 then
8595 Make_Temporary_For_Slice;
8596 end if;
8598 elsif Nkind (Parent (N)) = N_Assignment_Statement
8599 or else (Nkind (Parent (Parent (N))) = N_Assignment_Statement
8600 and then Parent (N) = Name (Parent (Parent (N))))
8601 then
8602 return;
8604 elsif Nkind (Parent (N)) = N_Indexed_Component
8605 or else Is_Renamed_Object (N)
8606 or else Is_Procedure_Actual (N)
8607 then
8608 return;
8610 elsif Nkind (Parent (N)) = N_Attribute_Reference
8611 and then Attribute_Name (Parent (N)) = Name_Address
8612 then
8613 return;
8615 else
8616 Make_Temporary_For_Slice;
8617 end if;
8618 end Expand_N_Slice;
8620 ------------------------------
8621 -- Expand_N_Type_Conversion --
8622 ------------------------------
8624 procedure Expand_N_Type_Conversion (N : Node_Id) is
8625 Loc : constant Source_Ptr := Sloc (N);
8626 Operand : constant Node_Id := Expression (N);
8627 Target_Type : constant Entity_Id := Etype (N);
8628 Operand_Type : Entity_Id := Etype (Operand);
8630 procedure Handle_Changed_Representation;
8631 -- This is called in the case of record and array type conversions to
8632 -- see if there is a change of representation to be handled. Change of
8633 -- representation is actually handled at the assignment statement level,
8634 -- and what this procedure does is rewrite node N conversion as an
8635 -- assignment to temporary. If there is no change of representation,
8636 -- then the conversion node is unchanged.
8638 procedure Raise_Accessibility_Error;
8639 -- Called when we know that an accessibility check will fail. Rewrites
8640 -- node N to an appropriate raise statement and outputs warning msgs.
8641 -- The Etype of the raise node is set to Target_Type.
8643 procedure Real_Range_Check;
8644 -- Handles generation of range check for real target value
8646 function Has_Extra_Accessibility (Id : Entity_Id) return Boolean;
8647 -- True iff Present (Effective_Extra_Accessibility (Id)) successfully
8648 -- evaluates to True.
8650 -----------------------------------
8651 -- Handle_Changed_Representation --
8652 -----------------------------------
8654 procedure Handle_Changed_Representation is
8655 Temp : Entity_Id;
8656 Decl : Node_Id;
8657 Odef : Node_Id;
8658 Disc : Node_Id;
8659 N_Ix : Node_Id;
8660 Cons : List_Id;
8662 begin
8663 -- Nothing else to do if no change of representation
8665 if Same_Representation (Operand_Type, Target_Type) then
8666 return;
8668 -- The real change of representation work is done by the assignment
8669 -- statement processing. So if this type conversion is appearing as
8670 -- the expression of an assignment statement, nothing needs to be
8671 -- done to the conversion.
8673 elsif Nkind (Parent (N)) = N_Assignment_Statement then
8674 return;
8676 -- Otherwise we need to generate a temporary variable, and do the
8677 -- change of representation assignment into that temporary variable.
8678 -- The conversion is then replaced by a reference to this variable.
8680 else
8681 Cons := No_List;
8683 -- If type is unconstrained we have to add a constraint, copied
8684 -- from the actual value of the left hand side.
8686 if not Is_Constrained (Target_Type) then
8687 if Has_Discriminants (Operand_Type) then
8688 Disc := First_Discriminant (Operand_Type);
8690 if Disc /= First_Stored_Discriminant (Operand_Type) then
8691 Disc := First_Stored_Discriminant (Operand_Type);
8692 end if;
8694 Cons := New_List;
8695 while Present (Disc) loop
8696 Append_To (Cons,
8697 Make_Selected_Component (Loc,
8698 Prefix =>
8699 Duplicate_Subexpr_Move_Checks (Operand),
8700 Selector_Name =>
8701 Make_Identifier (Loc, Chars (Disc))));
8702 Next_Discriminant (Disc);
8703 end loop;
8705 elsif Is_Array_Type (Operand_Type) then
8706 N_Ix := First_Index (Target_Type);
8707 Cons := New_List;
8709 for J in 1 .. Number_Dimensions (Operand_Type) loop
8711 -- We convert the bounds explicitly. We use an unchecked
8712 -- conversion because bounds checks are done elsewhere.
8714 Append_To (Cons,
8715 Make_Range (Loc,
8716 Low_Bound =>
8717 Unchecked_Convert_To (Etype (N_Ix),
8718 Make_Attribute_Reference (Loc,
8719 Prefix =>
8720 Duplicate_Subexpr_No_Checks
8721 (Operand, Name_Req => True),
8722 Attribute_Name => Name_First,
8723 Expressions => New_List (
8724 Make_Integer_Literal (Loc, J)))),
8726 High_Bound =>
8727 Unchecked_Convert_To (Etype (N_Ix),
8728 Make_Attribute_Reference (Loc,
8729 Prefix =>
8730 Duplicate_Subexpr_No_Checks
8731 (Operand, Name_Req => True),
8732 Attribute_Name => Name_Last,
8733 Expressions => New_List (
8734 Make_Integer_Literal (Loc, J))))));
8736 Next_Index (N_Ix);
8737 end loop;
8738 end if;
8739 end if;
8741 Odef := New_Occurrence_Of (Target_Type, Loc);
8743 if Present (Cons) then
8744 Odef :=
8745 Make_Subtype_Indication (Loc,
8746 Subtype_Mark => Odef,
8747 Constraint =>
8748 Make_Index_Or_Discriminant_Constraint (Loc,
8749 Constraints => Cons));
8750 end if;
8752 Temp := Make_Temporary (Loc, 'C');
8753 Decl :=
8754 Make_Object_Declaration (Loc,
8755 Defining_Identifier => Temp,
8756 Object_Definition => Odef);
8758 Set_No_Initialization (Decl, True);
8760 -- Insert required actions. It is essential to suppress checks
8761 -- since we have suppressed default initialization, which means
8762 -- that the variable we create may have no discriminants.
8764 Insert_Actions (N,
8765 New_List (
8766 Decl,
8767 Make_Assignment_Statement (Loc,
8768 Name => New_Occurrence_Of (Temp, Loc),
8769 Expression => Relocate_Node (N))),
8770 Suppress => All_Checks);
8772 Rewrite (N, New_Occurrence_Of (Temp, Loc));
8773 return;
8774 end if;
8775 end Handle_Changed_Representation;
8777 -------------------------------
8778 -- Raise_Accessibility_Error --
8779 -------------------------------
8781 procedure Raise_Accessibility_Error is
8782 begin
8783 Rewrite (N,
8784 Make_Raise_Program_Error (Sloc (N),
8785 Reason => PE_Accessibility_Check_Failed));
8786 Set_Etype (N, Target_Type);
8788 Error_Msg_N ("?accessibility check failure", N);
8789 Error_Msg_NE
8790 ("\?& will be raised at run time", N, Standard_Program_Error);
8791 end Raise_Accessibility_Error;
8793 ----------------------
8794 -- Real_Range_Check --
8795 ----------------------
8797 -- Case of conversions to floating-point or fixed-point. If range checks
8798 -- are enabled and the target type has a range constraint, we convert:
8800 -- typ (x)
8802 -- to
8804 -- Tnn : typ'Base := typ'Base (x);
8805 -- [constraint_error when Tnn < typ'First or else Tnn > typ'Last]
8806 -- Tnn
8808 -- This is necessary when there is a conversion of integer to float or
8809 -- to fixed-point to ensure that the correct checks are made. It is not
8810 -- necessary for float to float where it is enough to simply set the
8811 -- Do_Range_Check flag.
8813 procedure Real_Range_Check is
8814 Btyp : constant Entity_Id := Base_Type (Target_Type);
8815 Lo : constant Node_Id := Type_Low_Bound (Target_Type);
8816 Hi : constant Node_Id := Type_High_Bound (Target_Type);
8817 Xtyp : constant Entity_Id := Etype (Operand);
8818 Conv : Node_Id;
8819 Tnn : Entity_Id;
8821 begin
8822 -- Nothing to do if conversion was rewritten
8824 if Nkind (N) /= N_Type_Conversion then
8825 return;
8826 end if;
8828 -- Nothing to do if range checks suppressed, or target has the same
8829 -- range as the base type (or is the base type).
8831 if Range_Checks_Suppressed (Target_Type)
8832 or else (Lo = Type_Low_Bound (Btyp)
8833 and then
8834 Hi = Type_High_Bound (Btyp))
8835 then
8836 return;
8837 end if;
8839 -- Nothing to do if expression is an entity on which checks have been
8840 -- suppressed.
8842 if Is_Entity_Name (Operand)
8843 and then Range_Checks_Suppressed (Entity (Operand))
8844 then
8845 return;
8846 end if;
8848 -- Nothing to do if bounds are all static and we can tell that the
8849 -- expression is within the bounds of the target. Note that if the
8850 -- operand is of an unconstrained floating-point type, then we do
8851 -- not trust it to be in range (might be infinite)
8853 declare
8854 S_Lo : constant Node_Id := Type_Low_Bound (Xtyp);
8855 S_Hi : constant Node_Id := Type_High_Bound (Xtyp);
8857 begin
8858 if (not Is_Floating_Point_Type (Xtyp)
8859 or else Is_Constrained (Xtyp))
8860 and then Compile_Time_Known_Value (S_Lo)
8861 and then Compile_Time_Known_Value (S_Hi)
8862 and then Compile_Time_Known_Value (Hi)
8863 and then Compile_Time_Known_Value (Lo)
8864 then
8865 declare
8866 D_Lov : constant Ureal := Expr_Value_R (Lo);
8867 D_Hiv : constant Ureal := Expr_Value_R (Hi);
8868 S_Lov : Ureal;
8869 S_Hiv : Ureal;
8871 begin
8872 if Is_Real_Type (Xtyp) then
8873 S_Lov := Expr_Value_R (S_Lo);
8874 S_Hiv := Expr_Value_R (S_Hi);
8875 else
8876 S_Lov := UR_From_Uint (Expr_Value (S_Lo));
8877 S_Hiv := UR_From_Uint (Expr_Value (S_Hi));
8878 end if;
8880 if D_Hiv > D_Lov
8881 and then S_Lov >= D_Lov
8882 and then S_Hiv <= D_Hiv
8883 then
8884 Set_Do_Range_Check (Operand, False);
8885 return;
8886 end if;
8887 end;
8888 end if;
8889 end;
8891 -- For float to float conversions, we are done
8893 if Is_Floating_Point_Type (Xtyp)
8894 and then
8895 Is_Floating_Point_Type (Btyp)
8896 then
8897 return;
8898 end if;
8900 -- Otherwise rewrite the conversion as described above
8902 Conv := Relocate_Node (N);
8903 Rewrite (Subtype_Mark (Conv), New_Occurrence_Of (Btyp, Loc));
8904 Set_Etype (Conv, Btyp);
8906 -- Enable overflow except for case of integer to float conversions,
8907 -- where it is never required, since we can never have overflow in
8908 -- this case.
8910 if not Is_Integer_Type (Etype (Operand)) then
8911 Enable_Overflow_Check (Conv);
8912 end if;
8914 Tnn := Make_Temporary (Loc, 'T', Conv);
8916 Insert_Actions (N, New_List (
8917 Make_Object_Declaration (Loc,
8918 Defining_Identifier => Tnn,
8919 Object_Definition => New_Occurrence_Of (Btyp, Loc),
8920 Constant_Present => True,
8921 Expression => Conv),
8923 Make_Raise_Constraint_Error (Loc,
8924 Condition =>
8925 Make_Or_Else (Loc,
8926 Left_Opnd =>
8927 Make_Op_Lt (Loc,
8928 Left_Opnd => New_Occurrence_Of (Tnn, Loc),
8929 Right_Opnd =>
8930 Make_Attribute_Reference (Loc,
8931 Attribute_Name => Name_First,
8932 Prefix =>
8933 New_Occurrence_Of (Target_Type, Loc))),
8935 Right_Opnd =>
8936 Make_Op_Gt (Loc,
8937 Left_Opnd => New_Occurrence_Of (Tnn, Loc),
8938 Right_Opnd =>
8939 Make_Attribute_Reference (Loc,
8940 Attribute_Name => Name_Last,
8941 Prefix =>
8942 New_Occurrence_Of (Target_Type, Loc)))),
8943 Reason => CE_Range_Check_Failed)));
8945 Rewrite (N, New_Occurrence_Of (Tnn, Loc));
8946 Analyze_And_Resolve (N, Btyp);
8947 end Real_Range_Check;
8949 -----------------------------
8950 -- Has_Extra_Accessibility --
8951 -----------------------------
8953 -- Returns true for a formal of an anonymous access type or for
8954 -- an Ada 2012-style stand-alone object of an anonymous access type.
8956 function Has_Extra_Accessibility (Id : Entity_Id) return Boolean is
8957 begin
8958 if Is_Formal (Id) or else Ekind_In (Id, E_Constant, E_Variable) then
8959 return Present (Effective_Extra_Accessibility (Id));
8960 else
8961 return False;
8962 end if;
8963 end Has_Extra_Accessibility;
8965 -- Start of processing for Expand_N_Type_Conversion
8967 begin
8968 -- Nothing at all to do if conversion is to the identical type so remove
8969 -- the conversion completely, it is useless, except that it may carry
8970 -- an Assignment_OK attribute, which must be propagated to the operand.
8972 if Operand_Type = Target_Type then
8973 if Assignment_OK (N) then
8974 Set_Assignment_OK (Operand);
8975 end if;
8977 Rewrite (N, Relocate_Node (Operand));
8978 goto Done;
8979 end if;
8981 -- Nothing to do if this is the second argument of read. This is a
8982 -- "backwards" conversion that will be handled by the specialized code
8983 -- in attribute processing.
8985 if Nkind (Parent (N)) = N_Attribute_Reference
8986 and then Attribute_Name (Parent (N)) = Name_Read
8987 and then Next (First (Expressions (Parent (N)))) = N
8988 then
8989 goto Done;
8990 end if;
8992 -- Check for case of converting to a type that has an invariant
8993 -- associated with it. This required an invariant check. We convert
8995 -- typ (expr)
8997 -- into
8999 -- do invariant_check (typ (expr)) in typ (expr);
9001 -- using Duplicate_Subexpr to avoid multiple side effects
9003 -- Note: the Comes_From_Source check, and then the resetting of this
9004 -- flag prevents what would otherwise be an infinite recursion.
9006 if Has_Invariants (Target_Type)
9007 and then Present (Invariant_Procedure (Target_Type))
9008 and then Comes_From_Source (N)
9009 then
9010 Set_Comes_From_Source (N, False);
9011 Rewrite (N,
9012 Make_Expression_With_Actions (Loc,
9013 Actions => New_List (
9014 Make_Invariant_Call (Duplicate_Subexpr (N))),
9015 Expression => Duplicate_Subexpr_No_Checks (N)));
9016 Analyze_And_Resolve (N, Target_Type);
9017 goto Done;
9018 end if;
9020 -- Here if we may need to expand conversion
9022 -- If the operand of the type conversion is an arithmetic operation on
9023 -- signed integers, and the based type of the signed integer type in
9024 -- question is smaller than Standard.Integer, we promote both of the
9025 -- operands to type Integer.
9027 -- For example, if we have
9029 -- target-type (opnd1 + opnd2)
9031 -- and opnd1 and opnd2 are of type short integer, then we rewrite
9032 -- this as:
9034 -- target-type (integer(opnd1) + integer(opnd2))
9036 -- We do this because we are always allowed to compute in a larger type
9037 -- if we do the right thing with the result, and in this case we are
9038 -- going to do a conversion which will do an appropriate check to make
9039 -- sure that things are in range of the target type in any case. This
9040 -- avoids some unnecessary intermediate overflows.
9042 -- We might consider a similar transformation in the case where the
9043 -- target is a real type or a 64-bit integer type, and the operand
9044 -- is an arithmetic operation using a 32-bit integer type. However,
9045 -- we do not bother with this case, because it could cause significant
9046 -- inefficiencies on 32-bit machines. On a 64-bit machine it would be
9047 -- much cheaper, but we don't want different behavior on 32-bit and
9048 -- 64-bit machines. Note that the exclusion of the 64-bit case also
9049 -- handles the configurable run-time cases where 64-bit arithmetic
9050 -- may simply be unavailable.
9052 -- Note: this circuit is partially redundant with respect to the circuit
9053 -- in Checks.Apply_Arithmetic_Overflow_Check, but we catch more cases in
9054 -- the processing here. Also we still need the Checks circuit, since we
9055 -- have to be sure not to generate junk overflow checks in the first
9056 -- place, since it would be trick to remove them here!
9058 if Integer_Promotion_Possible (N) then
9060 -- All conditions met, go ahead with transformation
9062 declare
9063 Opnd : Node_Id;
9064 L, R : Node_Id;
9066 begin
9067 R :=
9068 Make_Type_Conversion (Loc,
9069 Subtype_Mark => New_Reference_To (Standard_Integer, Loc),
9070 Expression => Relocate_Node (Right_Opnd (Operand)));
9072 Opnd := New_Op_Node (Nkind (Operand), Loc);
9073 Set_Right_Opnd (Opnd, R);
9075 if Nkind (Operand) in N_Binary_Op then
9076 L :=
9077 Make_Type_Conversion (Loc,
9078 Subtype_Mark => New_Reference_To (Standard_Integer, Loc),
9079 Expression => Relocate_Node (Left_Opnd (Operand)));
9081 Set_Left_Opnd (Opnd, L);
9082 end if;
9084 Rewrite (N,
9085 Make_Type_Conversion (Loc,
9086 Subtype_Mark => Relocate_Node (Subtype_Mark (N)),
9087 Expression => Opnd));
9089 Analyze_And_Resolve (N, Target_Type);
9090 goto Done;
9091 end;
9092 end if;
9094 -- Do validity check if validity checking operands
9096 if Validity_Checks_On
9097 and then Validity_Check_Operands
9098 then
9099 Ensure_Valid (Operand);
9100 end if;
9102 -- Special case of converting from non-standard boolean type
9104 if Is_Boolean_Type (Operand_Type)
9105 and then (Nonzero_Is_True (Operand_Type))
9106 then
9107 Adjust_Condition (Operand);
9108 Set_Etype (Operand, Standard_Boolean);
9109 Operand_Type := Standard_Boolean;
9110 end if;
9112 -- Case of converting to an access type
9114 if Is_Access_Type (Target_Type) then
9116 -- Apply an accessibility check when the conversion operand is an
9117 -- access parameter (or a renaming thereof), unless conversion was
9118 -- expanded from an Unchecked_ or Unrestricted_Access attribute.
9119 -- Note that other checks may still need to be applied below (such
9120 -- as tagged type checks).
9122 if Is_Entity_Name (Operand)
9123 and then Has_Extra_Accessibility (Entity (Operand))
9124 and then Ekind (Etype (Operand)) = E_Anonymous_Access_Type
9125 and then (Nkind (Original_Node (N)) /= N_Attribute_Reference
9126 or else Attribute_Name (Original_Node (N)) = Name_Access)
9127 then
9128 Apply_Accessibility_Check
9129 (Operand, Target_Type, Insert_Node => Operand);
9131 -- If the level of the operand type is statically deeper than the
9132 -- level of the target type, then force Program_Error. Note that this
9133 -- can only occur for cases where the attribute is within the body of
9134 -- an instantiation (otherwise the conversion will already have been
9135 -- rejected as illegal). Note: warnings are issued by the analyzer
9136 -- for the instance cases.
9138 elsif In_Instance_Body
9139 and then Type_Access_Level (Operand_Type) >
9140 Type_Access_Level (Target_Type)
9141 then
9142 Raise_Accessibility_Error;
9144 -- When the operand is a selected access discriminant the check needs
9145 -- to be made against the level of the object denoted by the prefix
9146 -- of the selected name. Force Program_Error for this case as well
9147 -- (this accessibility violation can only happen if within the body
9148 -- of an instantiation).
9150 elsif In_Instance_Body
9151 and then Ekind (Operand_Type) = E_Anonymous_Access_Type
9152 and then Nkind (Operand) = N_Selected_Component
9153 and then Object_Access_Level (Operand) >
9154 Type_Access_Level (Target_Type)
9155 then
9156 Raise_Accessibility_Error;
9157 goto Done;
9158 end if;
9159 end if;
9161 -- Case of conversions of tagged types and access to tagged types
9163 -- When needed, that is to say when the expression is class-wide, Add
9164 -- runtime a tag check for (strict) downward conversion by using the
9165 -- membership test, generating:
9167 -- [constraint_error when Operand not in Target_Type'Class]
9169 -- or in the access type case
9171 -- [constraint_error
9172 -- when Operand /= null
9173 -- and then Operand.all not in
9174 -- Designated_Type (Target_Type)'Class]
9176 if (Is_Access_Type (Target_Type)
9177 and then Is_Tagged_Type (Designated_Type (Target_Type)))
9178 or else Is_Tagged_Type (Target_Type)
9179 then
9180 -- Do not do any expansion in the access type case if the parent is a
9181 -- renaming, since this is an error situation which will be caught by
9182 -- Sem_Ch8, and the expansion can interfere with this error check.
9184 if Is_Access_Type (Target_Type) and then Is_Renamed_Object (N) then
9185 goto Done;
9186 end if;
9188 -- Otherwise, proceed with processing tagged conversion
9190 Tagged_Conversion : declare
9191 Actual_Op_Typ : Entity_Id;
9192 Actual_Targ_Typ : Entity_Id;
9193 Make_Conversion : Boolean := False;
9194 Root_Op_Typ : Entity_Id;
9196 procedure Make_Tag_Check (Targ_Typ : Entity_Id);
9197 -- Create a membership check to test whether Operand is a member
9198 -- of Targ_Typ. If the original Target_Type is an access, include
9199 -- a test for null value. The check is inserted at N.
9201 --------------------
9202 -- Make_Tag_Check --
9203 --------------------
9205 procedure Make_Tag_Check (Targ_Typ : Entity_Id) is
9206 Cond : Node_Id;
9208 begin
9209 -- Generate:
9210 -- [Constraint_Error
9211 -- when Operand /= null
9212 -- and then Operand.all not in Targ_Typ]
9214 if Is_Access_Type (Target_Type) then
9215 Cond :=
9216 Make_And_Then (Loc,
9217 Left_Opnd =>
9218 Make_Op_Ne (Loc,
9219 Left_Opnd => Duplicate_Subexpr_No_Checks (Operand),
9220 Right_Opnd => Make_Null (Loc)),
9222 Right_Opnd =>
9223 Make_Not_In (Loc,
9224 Left_Opnd =>
9225 Make_Explicit_Dereference (Loc,
9226 Prefix => Duplicate_Subexpr_No_Checks (Operand)),
9227 Right_Opnd => New_Reference_To (Targ_Typ, Loc)));
9229 -- Generate:
9230 -- [Constraint_Error when Operand not in Targ_Typ]
9232 else
9233 Cond :=
9234 Make_Not_In (Loc,
9235 Left_Opnd => Duplicate_Subexpr_No_Checks (Operand),
9236 Right_Opnd => New_Reference_To (Targ_Typ, Loc));
9237 end if;
9239 Insert_Action (N,
9240 Make_Raise_Constraint_Error (Loc,
9241 Condition => Cond,
9242 Reason => CE_Tag_Check_Failed));
9243 end Make_Tag_Check;
9245 -- Start of processing for Tagged_Conversion
9247 begin
9248 -- Handle entities from the limited view
9250 if Is_Access_Type (Operand_Type) then
9251 Actual_Op_Typ :=
9252 Available_View (Designated_Type (Operand_Type));
9253 else
9254 Actual_Op_Typ := Operand_Type;
9255 end if;
9257 if Is_Access_Type (Target_Type) then
9258 Actual_Targ_Typ :=
9259 Available_View (Designated_Type (Target_Type));
9260 else
9261 Actual_Targ_Typ := Target_Type;
9262 end if;
9264 Root_Op_Typ := Root_Type (Actual_Op_Typ);
9266 -- Ada 2005 (AI-251): Handle interface type conversion
9268 if Is_Interface (Actual_Op_Typ) then
9269 Expand_Interface_Conversion (N, Is_Static => False);
9270 goto Done;
9271 end if;
9273 if not Tag_Checks_Suppressed (Actual_Targ_Typ) then
9275 -- Create a runtime tag check for a downward class-wide type
9276 -- conversion.
9278 if Is_Class_Wide_Type (Actual_Op_Typ)
9279 and then Actual_Op_Typ /= Actual_Targ_Typ
9280 and then Root_Op_Typ /= Actual_Targ_Typ
9281 and then Is_Ancestor (Root_Op_Typ, Actual_Targ_Typ,
9282 Use_Full_View => True)
9283 then
9284 Make_Tag_Check (Class_Wide_Type (Actual_Targ_Typ));
9285 Make_Conversion := True;
9286 end if;
9288 -- AI05-0073: If the result subtype of the function is defined
9289 -- by an access_definition designating a specific tagged type
9290 -- T, a check is made that the result value is null or the tag
9291 -- of the object designated by the result value identifies T.
9292 -- Constraint_Error is raised if this check fails.
9294 if Nkind (Parent (N)) = Sinfo.N_Return_Statement then
9295 declare
9296 Func : Entity_Id;
9297 Func_Typ : Entity_Id;
9299 begin
9300 -- Climb scope stack looking for the enclosing function
9302 Func := Current_Scope;
9303 while Present (Func)
9304 and then Ekind (Func) /= E_Function
9305 loop
9306 Func := Scope (Func);
9307 end loop;
9309 -- The function's return subtype must be defined using
9310 -- an access definition.
9312 if Nkind (Result_Definition (Parent (Func))) =
9313 N_Access_Definition
9314 then
9315 Func_Typ := Directly_Designated_Type (Etype (Func));
9317 -- The return subtype denotes a specific tagged type,
9318 -- in other words, a non class-wide type.
9320 if Is_Tagged_Type (Func_Typ)
9321 and then not Is_Class_Wide_Type (Func_Typ)
9322 then
9323 Make_Tag_Check (Actual_Targ_Typ);
9324 Make_Conversion := True;
9325 end if;
9326 end if;
9327 end;
9328 end if;
9330 -- We have generated a tag check for either a class-wide type
9331 -- conversion or for AI05-0073.
9333 if Make_Conversion then
9334 declare
9335 Conv : Node_Id;
9336 begin
9337 Conv :=
9338 Make_Unchecked_Type_Conversion (Loc,
9339 Subtype_Mark => New_Occurrence_Of (Target_Type, Loc),
9340 Expression => Relocate_Node (Expression (N)));
9341 Rewrite (N, Conv);
9342 Analyze_And_Resolve (N, Target_Type);
9343 end;
9344 end if;
9345 end if;
9346 end Tagged_Conversion;
9348 -- Case of other access type conversions
9350 elsif Is_Access_Type (Target_Type) then
9351 Apply_Constraint_Check (Operand, Target_Type);
9353 -- Case of conversions from a fixed-point type
9355 -- These conversions require special expansion and processing, found in
9356 -- the Exp_Fixd package. We ignore cases where Conversion_OK is set,
9357 -- since from a semantic point of view, these are simple integer
9358 -- conversions, which do not need further processing.
9360 elsif Is_Fixed_Point_Type (Operand_Type)
9361 and then not Conversion_OK (N)
9362 then
9363 -- We should never see universal fixed at this case, since the
9364 -- expansion of the constituent divide or multiply should have
9365 -- eliminated the explicit mention of universal fixed.
9367 pragma Assert (Operand_Type /= Universal_Fixed);
9369 -- Check for special case of the conversion to universal real that
9370 -- occurs as a result of the use of a round attribute. In this case,
9371 -- the real type for the conversion is taken from the target type of
9372 -- the Round attribute and the result must be marked as rounded.
9374 if Target_Type = Universal_Real
9375 and then Nkind (Parent (N)) = N_Attribute_Reference
9376 and then Attribute_Name (Parent (N)) = Name_Round
9377 then
9378 Set_Rounded_Result (N);
9379 Set_Etype (N, Etype (Parent (N)));
9380 end if;
9382 -- Otherwise do correct fixed-conversion, but skip these if the
9383 -- Conversion_OK flag is set, because from a semantic point of view
9384 -- these are simple integer conversions needing no further processing
9385 -- (the backend will simply treat them as integers).
9387 if not Conversion_OK (N) then
9388 if Is_Fixed_Point_Type (Etype (N)) then
9389 Expand_Convert_Fixed_To_Fixed (N);
9390 Real_Range_Check;
9392 elsif Is_Integer_Type (Etype (N)) then
9393 Expand_Convert_Fixed_To_Integer (N);
9395 else
9396 pragma Assert (Is_Floating_Point_Type (Etype (N)));
9397 Expand_Convert_Fixed_To_Float (N);
9398 Real_Range_Check;
9399 end if;
9400 end if;
9402 -- Case of conversions to a fixed-point type
9404 -- These conversions require special expansion and processing, found in
9405 -- the Exp_Fixd package. Again, ignore cases where Conversion_OK is set,
9406 -- since from a semantic point of view, these are simple integer
9407 -- conversions, which do not need further processing.
9409 elsif Is_Fixed_Point_Type (Target_Type)
9410 and then not Conversion_OK (N)
9411 then
9412 if Is_Integer_Type (Operand_Type) then
9413 Expand_Convert_Integer_To_Fixed (N);
9414 Real_Range_Check;
9415 else
9416 pragma Assert (Is_Floating_Point_Type (Operand_Type));
9417 Expand_Convert_Float_To_Fixed (N);
9418 Real_Range_Check;
9419 end if;
9421 -- Case of float-to-integer conversions
9423 -- We also handle float-to-fixed conversions with Conversion_OK set
9424 -- since semantically the fixed-point target is treated as though it
9425 -- were an integer in such cases.
9427 elsif Is_Floating_Point_Type (Operand_Type)
9428 and then
9429 (Is_Integer_Type (Target_Type)
9430 or else
9431 (Is_Fixed_Point_Type (Target_Type) and then Conversion_OK (N)))
9432 then
9433 -- One more check here, gcc is still not able to do conversions of
9434 -- this type with proper overflow checking, and so gigi is doing an
9435 -- approximation of what is required by doing floating-point compares
9436 -- with the end-point. But that can lose precision in some cases, and
9437 -- give a wrong result. Converting the operand to Universal_Real is
9438 -- helpful, but still does not catch all cases with 64-bit integers
9439 -- on targets with only 64-bit floats.
9441 -- The above comment seems obsoleted by Apply_Float_Conversion_Check
9442 -- Can this code be removed ???
9444 if Do_Range_Check (Operand) then
9445 Rewrite (Operand,
9446 Make_Type_Conversion (Loc,
9447 Subtype_Mark =>
9448 New_Occurrence_Of (Universal_Real, Loc),
9449 Expression =>
9450 Relocate_Node (Operand)));
9452 Set_Etype (Operand, Universal_Real);
9453 Enable_Range_Check (Operand);
9454 Set_Do_Range_Check (Expression (Operand), False);
9455 end if;
9457 -- Case of array conversions
9459 -- Expansion of array conversions, add required length/range checks but
9460 -- only do this if there is no change of representation. For handling of
9461 -- this case, see Handle_Changed_Representation.
9463 elsif Is_Array_Type (Target_Type) then
9464 if Is_Constrained (Target_Type) then
9465 Apply_Length_Check (Operand, Target_Type);
9466 else
9467 Apply_Range_Check (Operand, Target_Type);
9468 end if;
9470 Handle_Changed_Representation;
9472 -- Case of conversions of discriminated types
9474 -- Add required discriminant checks if target is constrained. Again this
9475 -- change is skipped if we have a change of representation.
9477 elsif Has_Discriminants (Target_Type)
9478 and then Is_Constrained (Target_Type)
9479 then
9480 Apply_Discriminant_Check (Operand, Target_Type);
9481 Handle_Changed_Representation;
9483 -- Case of all other record conversions. The only processing required
9484 -- is to check for a change of representation requiring the special
9485 -- assignment processing.
9487 elsif Is_Record_Type (Target_Type) then
9489 -- Ada 2005 (AI-216): Program_Error is raised when converting from
9490 -- a derived Unchecked_Union type to an unconstrained type that is
9491 -- not Unchecked_Union if the operand lacks inferable discriminants.
9493 if Is_Derived_Type (Operand_Type)
9494 and then Is_Unchecked_Union (Base_Type (Operand_Type))
9495 and then not Is_Constrained (Target_Type)
9496 and then not Is_Unchecked_Union (Base_Type (Target_Type))
9497 and then not Has_Inferable_Discriminants (Operand)
9498 then
9499 -- To prevent Gigi from generating illegal code, we generate a
9500 -- Program_Error node, but we give it the target type of the
9501 -- conversion.
9503 declare
9504 PE : constant Node_Id := Make_Raise_Program_Error (Loc,
9505 Reason => PE_Unchecked_Union_Restriction);
9507 begin
9508 Set_Etype (PE, Target_Type);
9509 Rewrite (N, PE);
9511 end;
9512 else
9513 Handle_Changed_Representation;
9514 end if;
9516 -- Case of conversions of enumeration types
9518 elsif Is_Enumeration_Type (Target_Type) then
9520 -- Special processing is required if there is a change of
9521 -- representation (from enumeration representation clauses).
9523 if not Same_Representation (Target_Type, Operand_Type) then
9525 -- Convert: x(y) to x'val (ytyp'val (y))
9527 Rewrite (N,
9528 Make_Attribute_Reference (Loc,
9529 Prefix => New_Occurrence_Of (Target_Type, Loc),
9530 Attribute_Name => Name_Val,
9531 Expressions => New_List (
9532 Make_Attribute_Reference (Loc,
9533 Prefix => New_Occurrence_Of (Operand_Type, Loc),
9534 Attribute_Name => Name_Pos,
9535 Expressions => New_List (Operand)))));
9537 Analyze_And_Resolve (N, Target_Type);
9538 end if;
9540 -- Case of conversions to floating-point
9542 elsif Is_Floating_Point_Type (Target_Type) then
9543 Real_Range_Check;
9544 end if;
9546 -- At this stage, either the conversion node has been transformed into
9547 -- some other equivalent expression, or left as a conversion that can be
9548 -- handled by Gigi, in the following cases:
9550 -- Conversions with no change of representation or type
9552 -- Numeric conversions involving integer, floating- and fixed-point
9553 -- values. Fixed-point values are allowed only if Conversion_OK is
9554 -- set, i.e. if the fixed-point values are to be treated as integers.
9556 -- No other conversions should be passed to Gigi
9558 -- Check: are these rules stated in sinfo??? if so, why restate here???
9560 -- The only remaining step is to generate a range check if we still have
9561 -- a type conversion at this stage and Do_Range_Check is set. For now we
9562 -- do this only for conversions of discrete types.
9564 if Nkind (N) = N_Type_Conversion
9565 and then Is_Discrete_Type (Etype (N))
9566 then
9567 declare
9568 Expr : constant Node_Id := Expression (N);
9569 Ftyp : Entity_Id;
9570 Ityp : Entity_Id;
9572 begin
9573 if Do_Range_Check (Expr)
9574 and then Is_Discrete_Type (Etype (Expr))
9575 then
9576 Set_Do_Range_Check (Expr, False);
9578 -- Before we do a range check, we have to deal with treating a
9579 -- fixed-point operand as an integer. The way we do this is
9580 -- simply to do an unchecked conversion to an appropriate
9581 -- integer type large enough to hold the result.
9583 -- This code is not active yet, because we are only dealing
9584 -- with discrete types so far ???
9586 if Nkind (Expr) in N_Has_Treat_Fixed_As_Integer
9587 and then Treat_Fixed_As_Integer (Expr)
9588 then
9589 Ftyp := Base_Type (Etype (Expr));
9591 if Esize (Ftyp) >= Esize (Standard_Integer) then
9592 Ityp := Standard_Long_Long_Integer;
9593 else
9594 Ityp := Standard_Integer;
9595 end if;
9597 Rewrite (Expr, Unchecked_Convert_To (Ityp, Expr));
9598 end if;
9600 -- Reset overflow flag, since the range check will include
9601 -- dealing with possible overflow, and generate the check. If
9602 -- Address is either a source type or target type, suppress
9603 -- range check to avoid typing anomalies when it is a visible
9604 -- integer type.
9606 Set_Do_Overflow_Check (N, False);
9607 if not Is_Descendent_Of_Address (Etype (Expr))
9608 and then not Is_Descendent_Of_Address (Target_Type)
9609 then
9610 Generate_Range_Check
9611 (Expr, Target_Type, CE_Range_Check_Failed);
9612 end if;
9613 end if;
9614 end;
9615 end if;
9617 -- Final step, if the result is a type conversion involving Vax_Float
9618 -- types, then it is subject for further special processing.
9620 if Nkind (N) = N_Type_Conversion
9621 and then (Vax_Float (Operand_Type) or else Vax_Float (Target_Type))
9622 then
9623 Expand_Vax_Conversion (N);
9624 goto Done;
9625 end if;
9627 -- Here at end of processing
9629 <<Done>>
9630 -- Apply predicate check if required. Note that we can't just call
9631 -- Apply_Predicate_Check here, because the type looks right after
9632 -- the conversion and it would omit the check. The Comes_From_Source
9633 -- guard is necessary to prevent infinite recursions when we generate
9634 -- internal conversions for the purpose of checking predicates.
9636 if Present (Predicate_Function (Target_Type))
9637 and then Target_Type /= Operand_Type
9638 and then Comes_From_Source (N)
9639 then
9640 declare
9641 New_Expr : constant Node_Id := Duplicate_Subexpr (N);
9643 begin
9644 -- Avoid infinite recursion on the subsequent expansion of
9645 -- of the copy of the original type conversion.
9647 Set_Comes_From_Source (New_Expr, False);
9648 Insert_Action (N, Make_Predicate_Check (Target_Type, New_Expr));
9649 end;
9650 end if;
9651 end Expand_N_Type_Conversion;
9653 -----------------------------------
9654 -- Expand_N_Unchecked_Expression --
9655 -----------------------------------
9657 -- Remove the unchecked expression node from the tree. Its job was simply
9658 -- to make sure that its constituent expression was handled with checks
9659 -- off, and now that that is done, we can remove it from the tree, and
9660 -- indeed must, since Gigi does not expect to see these nodes.
9662 procedure Expand_N_Unchecked_Expression (N : Node_Id) is
9663 Exp : constant Node_Id := Expression (N);
9664 begin
9665 Set_Assignment_OK (Exp, Assignment_OK (N) or else Assignment_OK (Exp));
9666 Rewrite (N, Exp);
9667 end Expand_N_Unchecked_Expression;
9669 ----------------------------------------
9670 -- Expand_N_Unchecked_Type_Conversion --
9671 ----------------------------------------
9673 -- If this cannot be handled by Gigi and we haven't already made a
9674 -- temporary for it, do it now.
9676 procedure Expand_N_Unchecked_Type_Conversion (N : Node_Id) is
9677 Target_Type : constant Entity_Id := Etype (N);
9678 Operand : constant Node_Id := Expression (N);
9679 Operand_Type : constant Entity_Id := Etype (Operand);
9681 begin
9682 -- Nothing at all to do if conversion is to the identical type so remove
9683 -- the conversion completely, it is useless, except that it may carry
9684 -- an Assignment_OK indication which must be propagated to the operand.
9686 if Operand_Type = Target_Type then
9688 -- Code duplicates Expand_N_Unchecked_Expression above, factor???
9690 if Assignment_OK (N) then
9691 Set_Assignment_OK (Operand);
9692 end if;
9694 Rewrite (N, Relocate_Node (Operand));
9695 return;
9696 end if;
9698 -- If we have a conversion of a compile time known value to a target
9699 -- type and the value is in range of the target type, then we can simply
9700 -- replace the construct by an integer literal of the correct type. We
9701 -- only apply this to integer types being converted. Possibly it may
9702 -- apply in other cases, but it is too much trouble to worry about.
9704 -- Note that we do not do this transformation if the Kill_Range_Check
9705 -- flag is set, since then the value may be outside the expected range.
9706 -- This happens in the Normalize_Scalars case.
9708 -- We also skip this if either the target or operand type is biased
9709 -- because in this case, the unchecked conversion is supposed to
9710 -- preserve the bit pattern, not the integer value.
9712 if Is_Integer_Type (Target_Type)
9713 and then not Has_Biased_Representation (Target_Type)
9714 and then Is_Integer_Type (Operand_Type)
9715 and then not Has_Biased_Representation (Operand_Type)
9716 and then Compile_Time_Known_Value (Operand)
9717 and then not Kill_Range_Check (N)
9718 then
9719 declare
9720 Val : constant Uint := Expr_Value (Operand);
9722 begin
9723 if Compile_Time_Known_Value (Type_Low_Bound (Target_Type))
9724 and then
9725 Compile_Time_Known_Value (Type_High_Bound (Target_Type))
9726 and then
9727 Val >= Expr_Value (Type_Low_Bound (Target_Type))
9728 and then
9729 Val <= Expr_Value (Type_High_Bound (Target_Type))
9730 then
9731 Rewrite (N, Make_Integer_Literal (Sloc (N), Val));
9733 -- If Address is the target type, just set the type to avoid a
9734 -- spurious type error on the literal when Address is a visible
9735 -- integer type.
9737 if Is_Descendent_Of_Address (Target_Type) then
9738 Set_Etype (N, Target_Type);
9739 else
9740 Analyze_And_Resolve (N, Target_Type);
9741 end if;
9743 return;
9744 end if;
9745 end;
9746 end if;
9748 -- Nothing to do if conversion is safe
9750 if Safe_Unchecked_Type_Conversion (N) then
9751 return;
9752 end if;
9754 -- Otherwise force evaluation unless Assignment_OK flag is set (this
9755 -- flag indicates ??? -- more comments needed here)
9757 if Assignment_OK (N) then
9758 null;
9759 else
9760 Force_Evaluation (N);
9761 end if;
9762 end Expand_N_Unchecked_Type_Conversion;
9764 ----------------------------
9765 -- Expand_Record_Equality --
9766 ----------------------------
9768 -- For non-variant records, Equality is expanded when needed into:
9770 -- and then Lhs.Discr1 = Rhs.Discr1
9771 -- and then ...
9772 -- and then Lhs.Discrn = Rhs.Discrn
9773 -- and then Lhs.Cmp1 = Rhs.Cmp1
9774 -- and then ...
9775 -- and then Lhs.Cmpn = Rhs.Cmpn
9777 -- The expression is folded by the back-end for adjacent fields. This
9778 -- function is called for tagged record in only one occasion: for imple-
9779 -- menting predefined primitive equality (see Predefined_Primitives_Bodies)
9780 -- otherwise the primitive "=" is used directly.
9782 function Expand_Record_Equality
9783 (Nod : Node_Id;
9784 Typ : Entity_Id;
9785 Lhs : Node_Id;
9786 Rhs : Node_Id;
9787 Bodies : List_Id) return Node_Id
9789 Loc : constant Source_Ptr := Sloc (Nod);
9791 Result : Node_Id;
9792 C : Entity_Id;
9794 First_Time : Boolean := True;
9796 function Suitable_Element (C : Entity_Id) return Entity_Id;
9797 -- Return the first field to compare beginning with C, skipping the
9798 -- inherited components.
9800 ----------------------
9801 -- Suitable_Element --
9802 ----------------------
9804 function Suitable_Element (C : Entity_Id) return Entity_Id is
9805 begin
9806 if No (C) then
9807 return Empty;
9809 elsif Ekind (C) /= E_Discriminant
9810 and then Ekind (C) /= E_Component
9811 then
9812 return Suitable_Element (Next_Entity (C));
9814 elsif Is_Tagged_Type (Typ)
9815 and then C /= Original_Record_Component (C)
9816 then
9817 return Suitable_Element (Next_Entity (C));
9819 elsif Chars (C) = Name_uTag then
9820 return Suitable_Element (Next_Entity (C));
9822 -- The .NET/JVM version of type Root_Controlled contains two fields
9823 -- which should not be considered part of the object. To achieve
9824 -- proper equiality between two controlled objects on .NET/JVM, skip
9825 -- field _parent whenever it is of type Root_Controlled.
9827 elsif Chars (C) = Name_uParent
9828 and then VM_Target /= No_VM
9829 and then Etype (C) = RTE (RE_Root_Controlled)
9830 then
9831 return Suitable_Element (Next_Entity (C));
9833 elsif Is_Interface (Etype (C)) then
9834 return Suitable_Element (Next_Entity (C));
9836 else
9837 return C;
9838 end if;
9839 end Suitable_Element;
9841 -- Start of processing for Expand_Record_Equality
9843 begin
9844 -- Generates the following code: (assuming that Typ has one Discr and
9845 -- component C2 is also a record)
9847 -- True
9848 -- and then Lhs.Discr1 = Rhs.Discr1
9849 -- and then Lhs.C1 = Rhs.C1
9850 -- and then Lhs.C2.C1=Rhs.C2.C1 and then ... Lhs.C2.Cn=Rhs.C2.Cn
9851 -- and then ...
9852 -- and then Lhs.Cmpn = Rhs.Cmpn
9854 Result := New_Reference_To (Standard_True, Loc);
9855 C := Suitable_Element (First_Entity (Typ));
9856 while Present (C) loop
9857 declare
9858 New_Lhs : Node_Id;
9859 New_Rhs : Node_Id;
9860 Check : Node_Id;
9862 begin
9863 if First_Time then
9864 First_Time := False;
9865 New_Lhs := Lhs;
9866 New_Rhs := Rhs;
9867 else
9868 New_Lhs := New_Copy_Tree (Lhs);
9869 New_Rhs := New_Copy_Tree (Rhs);
9870 end if;
9872 Check :=
9873 Expand_Composite_Equality (Nod, Etype (C),
9874 Lhs =>
9875 Make_Selected_Component (Loc,
9876 Prefix => New_Lhs,
9877 Selector_Name => New_Reference_To (C, Loc)),
9878 Rhs =>
9879 Make_Selected_Component (Loc,
9880 Prefix => New_Rhs,
9881 Selector_Name => New_Reference_To (C, Loc)),
9882 Bodies => Bodies);
9884 -- If some (sub)component is an unchecked_union, the whole
9885 -- operation will raise program error.
9887 if Nkind (Check) = N_Raise_Program_Error then
9888 Result := Check;
9889 Set_Etype (Result, Standard_Boolean);
9890 exit;
9891 else
9892 Result :=
9893 Make_And_Then (Loc,
9894 Left_Opnd => Result,
9895 Right_Opnd => Check);
9896 end if;
9897 end;
9899 C := Suitable_Element (Next_Entity (C));
9900 end loop;
9902 return Result;
9903 end Expand_Record_Equality;
9905 ---------------------------
9906 -- Expand_Set_Membership --
9907 ---------------------------
9909 procedure Expand_Set_Membership (N : Node_Id) is
9910 Lop : constant Node_Id := Left_Opnd (N);
9911 Alt : Node_Id;
9912 Res : Node_Id;
9914 function Make_Cond (Alt : Node_Id) return Node_Id;
9915 -- If the alternative is a subtype mark, create a simple membership
9916 -- test. Otherwise create an equality test for it.
9918 ---------------
9919 -- Make_Cond --
9920 ---------------
9922 function Make_Cond (Alt : Node_Id) return Node_Id is
9923 Cond : Node_Id;
9924 L : constant Node_Id := New_Copy (Lop);
9925 R : constant Node_Id := Relocate_Node (Alt);
9927 begin
9928 if (Is_Entity_Name (Alt) and then Is_Type (Entity (Alt)))
9929 or else Nkind (Alt) = N_Range
9930 then
9931 Cond :=
9932 Make_In (Sloc (Alt),
9933 Left_Opnd => L,
9934 Right_Opnd => R);
9935 else
9936 Cond :=
9937 Make_Op_Eq (Sloc (Alt),
9938 Left_Opnd => L,
9939 Right_Opnd => R);
9940 end if;
9942 return Cond;
9943 end Make_Cond;
9945 -- Start of processing for Expand_Set_Membership
9947 begin
9948 Remove_Side_Effects (Lop);
9950 Alt := Last (Alternatives (N));
9951 Res := Make_Cond (Alt);
9953 Prev (Alt);
9954 while Present (Alt) loop
9955 Res :=
9956 Make_Or_Else (Sloc (Alt),
9957 Left_Opnd => Make_Cond (Alt),
9958 Right_Opnd => Res);
9959 Prev (Alt);
9960 end loop;
9962 Rewrite (N, Res);
9963 Analyze_And_Resolve (N, Standard_Boolean);
9964 end Expand_Set_Membership;
9966 -----------------------------------
9967 -- Expand_Short_Circuit_Operator --
9968 -----------------------------------
9970 -- Deal with special expansion if actions are present for the right operand
9971 -- and deal with optimizing case of arguments being True or False. We also
9972 -- deal with the special case of non-standard boolean values.
9974 procedure Expand_Short_Circuit_Operator (N : Node_Id) is
9975 Loc : constant Source_Ptr := Sloc (N);
9976 Typ : constant Entity_Id := Etype (N);
9977 Left : constant Node_Id := Left_Opnd (N);
9978 Right : constant Node_Id := Right_Opnd (N);
9979 LocR : constant Source_Ptr := Sloc (Right);
9980 Actlist : List_Id;
9982 Shortcut_Value : constant Boolean := Nkind (N) = N_Or_Else;
9983 Shortcut_Ent : constant Entity_Id := Boolean_Literals (Shortcut_Value);
9984 -- If Left = Shortcut_Value then Right need not be evaluated
9986 function Make_Test_Expr (Opnd : Node_Id) return Node_Id;
9987 -- For Opnd a boolean expression, return a Boolean expression equivalent
9988 -- to Opnd /= Shortcut_Value.
9990 --------------------
9991 -- Make_Test_Expr --
9992 --------------------
9994 function Make_Test_Expr (Opnd : Node_Id) return Node_Id is
9995 begin
9996 if Shortcut_Value then
9997 return Make_Op_Not (Sloc (Opnd), Opnd);
9998 else
9999 return Opnd;
10000 end if;
10001 end Make_Test_Expr;
10003 Op_Var : Entity_Id;
10004 -- Entity for a temporary variable holding the value of the operator,
10005 -- used for expansion in the case where actions are present.
10007 -- Start of processing for Expand_Short_Circuit_Operator
10009 begin
10010 -- Deal with non-standard booleans
10012 if Is_Boolean_Type (Typ) then
10013 Adjust_Condition (Left);
10014 Adjust_Condition (Right);
10015 Set_Etype (N, Standard_Boolean);
10016 end if;
10018 -- Check for cases where left argument is known to be True or False
10020 if Compile_Time_Known_Value (Left) then
10022 -- Mark SCO for left condition as compile time known
10024 if Generate_SCO and then Comes_From_Source (Left) then
10025 Set_SCO_Condition (Left, Expr_Value_E (Left) = Standard_True);
10026 end if;
10028 -- Rewrite True AND THEN Right / False OR ELSE Right to Right.
10029 -- Any actions associated with Right will be executed unconditionally
10030 -- and can thus be inserted into the tree unconditionally.
10032 if Expr_Value_E (Left) /= Shortcut_Ent then
10033 if Present (Actions (N)) then
10034 Insert_Actions (N, Actions (N));
10035 end if;
10037 Rewrite (N, Right);
10039 -- Rewrite False AND THEN Right / True OR ELSE Right to Left.
10040 -- In this case we can forget the actions associated with Right,
10041 -- since they will never be executed.
10043 else
10044 Kill_Dead_Code (Right);
10045 Kill_Dead_Code (Actions (N));
10046 Rewrite (N, New_Occurrence_Of (Shortcut_Ent, Loc));
10047 end if;
10049 Adjust_Result_Type (N, Typ);
10050 return;
10051 end if;
10053 -- If Actions are present for the right operand, we have to do some
10054 -- special processing. We can't just let these actions filter back into
10055 -- code preceding the short circuit (which is what would have happened
10056 -- if we had not trapped them in the short-circuit form), since they
10057 -- must only be executed if the right operand of the short circuit is
10058 -- executed and not otherwise.
10060 -- the temporary variable C.
10062 if Present (Actions (N)) then
10063 Actlist := Actions (N);
10065 -- The old approach is to expand:
10067 -- left AND THEN right
10069 -- into
10071 -- C : Boolean := False;
10072 -- IF left THEN
10073 -- Actions;
10074 -- IF right THEN
10075 -- C := True;
10076 -- END IF;
10077 -- END IF;
10079 -- and finally rewrite the operator into a reference to C. Similarly
10080 -- for left OR ELSE right, with negated values. Note that this
10081 -- rewrite causes some difficulties for coverage analysis because
10082 -- of the introduction of the new variable C, which obscures the
10083 -- structure of the test.
10085 -- We use this "old approach" if use of N_Expression_With_Actions
10086 -- is False (see description in Opt of when this is or is not set).
10088 if not Use_Expression_With_Actions then
10089 Op_Var := Make_Temporary (Loc, 'C', Related_Node => N);
10091 Insert_Action (N,
10092 Make_Object_Declaration (Loc,
10093 Defining_Identifier =>
10094 Op_Var,
10095 Object_Definition =>
10096 New_Occurrence_Of (Standard_Boolean, Loc),
10097 Expression =>
10098 New_Occurrence_Of (Shortcut_Ent, Loc)));
10100 Append_To (Actlist,
10101 Make_Implicit_If_Statement (Right,
10102 Condition => Make_Test_Expr (Right),
10103 Then_Statements => New_List (
10104 Make_Assignment_Statement (LocR,
10105 Name => New_Occurrence_Of (Op_Var, LocR),
10106 Expression =>
10107 New_Occurrence_Of
10108 (Boolean_Literals (not Shortcut_Value), LocR)))));
10110 Insert_Action (N,
10111 Make_Implicit_If_Statement (Left,
10112 Condition => Make_Test_Expr (Left),
10113 Then_Statements => Actlist));
10115 Rewrite (N, New_Occurrence_Of (Op_Var, Loc));
10116 Analyze_And_Resolve (N, Standard_Boolean);
10118 -- The new approach, activated for now by the use of debug flag
10119 -- -gnatd.X is to use the new Expression_With_Actions node for the
10120 -- right operand of the short-circuit form. This should solve the
10121 -- traceability problems for coverage analysis.
10123 else
10124 Rewrite (Right,
10125 Make_Expression_With_Actions (LocR,
10126 Expression => Relocate_Node (Right),
10127 Actions => Actlist));
10128 Set_Actions (N, No_List);
10129 Analyze_And_Resolve (Right, Standard_Boolean);
10130 end if;
10132 Adjust_Result_Type (N, Typ);
10133 return;
10134 end if;
10136 -- No actions present, check for cases of right argument True/False
10138 if Compile_Time_Known_Value (Right) then
10140 -- Mark SCO for left condition as compile time known
10142 if Generate_SCO and then Comes_From_Source (Right) then
10143 Set_SCO_Condition (Right, Expr_Value_E (Right) = Standard_True);
10144 end if;
10146 -- Change (Left and then True), (Left or else False) to Left.
10147 -- Note that we know there are no actions associated with the right
10148 -- operand, since we just checked for this case above.
10150 if Expr_Value_E (Right) /= Shortcut_Ent then
10151 Rewrite (N, Left);
10153 -- Change (Left and then False), (Left or else True) to Right,
10154 -- making sure to preserve any side effects associated with the Left
10155 -- operand.
10157 else
10158 Remove_Side_Effects (Left);
10159 Rewrite (N, New_Occurrence_Of (Shortcut_Ent, Loc));
10160 end if;
10161 end if;
10163 Adjust_Result_Type (N, Typ);
10164 end Expand_Short_Circuit_Operator;
10166 -------------------------------------
10167 -- Fixup_Universal_Fixed_Operation --
10168 -------------------------------------
10170 procedure Fixup_Universal_Fixed_Operation (N : Node_Id) is
10171 Conv : constant Node_Id := Parent (N);
10173 begin
10174 -- We must have a type conversion immediately above us
10176 pragma Assert (Nkind (Conv) = N_Type_Conversion);
10178 -- Normally the type conversion gives our target type. The exception
10179 -- occurs in the case of the Round attribute, where the conversion
10180 -- will be to universal real, and our real type comes from the Round
10181 -- attribute (as well as an indication that we must round the result)
10183 if Nkind (Parent (Conv)) = N_Attribute_Reference
10184 and then Attribute_Name (Parent (Conv)) = Name_Round
10185 then
10186 Set_Etype (N, Etype (Parent (Conv)));
10187 Set_Rounded_Result (N);
10189 -- Normal case where type comes from conversion above us
10191 else
10192 Set_Etype (N, Etype (Conv));
10193 end if;
10194 end Fixup_Universal_Fixed_Operation;
10196 ---------------------------------
10197 -- Has_Inferable_Discriminants --
10198 ---------------------------------
10200 function Has_Inferable_Discriminants (N : Node_Id) return Boolean is
10202 function Prefix_Is_Formal_Parameter (N : Node_Id) return Boolean;
10203 -- Determines whether the left-most prefix of a selected component is a
10204 -- formal parameter in a subprogram. Assumes N is a selected component.
10206 --------------------------------
10207 -- Prefix_Is_Formal_Parameter --
10208 --------------------------------
10210 function Prefix_Is_Formal_Parameter (N : Node_Id) return Boolean is
10211 Sel_Comp : Node_Id;
10213 begin
10214 -- Move to the left-most prefix by climbing up the tree
10216 Sel_Comp := N;
10217 while Present (Parent (Sel_Comp))
10218 and then Nkind (Parent (Sel_Comp)) = N_Selected_Component
10219 loop
10220 Sel_Comp := Parent (Sel_Comp);
10221 end loop;
10223 return Ekind (Entity (Prefix (Sel_Comp))) in Formal_Kind;
10224 end Prefix_Is_Formal_Parameter;
10226 -- Start of processing for Has_Inferable_Discriminants
10228 begin
10229 -- For selected components, the subtype of the selector must be a
10230 -- constrained Unchecked_Union. If the component is subject to a
10231 -- per-object constraint, then the enclosing object must have inferable
10232 -- discriminants.
10234 if Nkind (N) = N_Selected_Component then
10235 if Has_Per_Object_Constraint (Entity (Selector_Name (N))) then
10237 -- A small hack. If we have a per-object constrained selected
10238 -- component of a formal parameter, return True since we do not
10239 -- know the actual parameter association yet.
10241 if Prefix_Is_Formal_Parameter (N) then
10242 return True;
10244 -- Otherwise, check the enclosing object and the selector
10246 else
10247 return Has_Inferable_Discriminants (Prefix (N))
10248 and then Has_Inferable_Discriminants (Selector_Name (N));
10249 end if;
10251 -- The call to Has_Inferable_Discriminants will determine whether
10252 -- the selector has a constrained Unchecked_Union nominal type.
10254 else
10255 return Has_Inferable_Discriminants (Selector_Name (N));
10256 end if;
10258 -- A qualified expression has inferable discriminants if its subtype
10259 -- mark is a constrained Unchecked_Union subtype.
10261 elsif Nkind (N) = N_Qualified_Expression then
10262 return Is_Unchecked_Union (Etype (Subtype_Mark (N)))
10263 and then Is_Constrained (Etype (Subtype_Mark (N)));
10265 -- For all other names, it is sufficient to have a constrained
10266 -- Unchecked_Union nominal subtype.
10268 else
10269 return Is_Unchecked_Union (Base_Type (Etype (N)))
10270 and then Is_Constrained (Etype (N));
10271 end if;
10272 end Has_Inferable_Discriminants;
10274 -------------------------------
10275 -- Insert_Dereference_Action --
10276 -------------------------------
10278 procedure Insert_Dereference_Action (N : Node_Id) is
10280 function Is_Checked_Storage_Pool (P : Entity_Id) return Boolean;
10281 -- Return true if type of P is derived from Checked_Pool;
10283 -----------------------------
10284 -- Is_Checked_Storage_Pool --
10285 -----------------------------
10287 function Is_Checked_Storage_Pool (P : Entity_Id) return Boolean is
10288 T : Entity_Id;
10290 begin
10291 if No (P) then
10292 return False;
10293 end if;
10295 T := Etype (P);
10296 while T /= Etype (T) loop
10297 if Is_RTE (T, RE_Checked_Pool) then
10298 return True;
10299 else
10300 T := Etype (T);
10301 end if;
10302 end loop;
10304 return False;
10305 end Is_Checked_Storage_Pool;
10307 -- Local variables
10309 Typ : constant Entity_Id := Etype (N);
10310 Desig : constant Entity_Id := Available_View (Designated_Type (Typ));
10311 Loc : constant Source_Ptr := Sloc (N);
10312 Pool : constant Entity_Id := Associated_Storage_Pool (Typ);
10313 Pnod : constant Node_Id := Parent (N);
10315 Addr : Entity_Id;
10316 Alig : Entity_Id;
10317 Deref : Node_Id;
10318 Size : Entity_Id;
10319 Stmt : Node_Id;
10321 -- Start of processing for Insert_Dereference_Action
10323 begin
10324 pragma Assert (Nkind (Pnod) = N_Explicit_Dereference);
10326 -- Do not re-expand a dereference which has already been processed by
10327 -- this routine.
10329 if Has_Dereference_Action (Pnod) then
10330 return;
10332 -- Do not perform this type of expansion for internally-generated
10333 -- dereferences.
10335 elsif not Comes_From_Source (Original_Node (Pnod)) then
10336 return;
10338 -- A dereference action is only applicable to objects which have been
10339 -- allocated on a checked pool.
10341 elsif not Is_Checked_Storage_Pool (Pool) then
10342 return;
10343 end if;
10345 -- Extract the address of the dereferenced object. Generate:
10347 -- Addr : System.Address := <N>'Pool_Address;
10349 Addr := Make_Temporary (Loc, 'P');
10351 Insert_Action (N,
10352 Make_Object_Declaration (Loc,
10353 Defining_Identifier => Addr,
10354 Object_Definition =>
10355 New_Reference_To (RTE (RE_Address), Loc),
10356 Expression =>
10357 Make_Attribute_Reference (Loc,
10358 Prefix => Duplicate_Subexpr_Move_Checks (N),
10359 Attribute_Name => Name_Pool_Address)));
10361 -- Calculate the size of the dereferenced object. Generate:
10363 -- Size : Storage_Count := <N>.all'Size / Storage_Unit;
10365 Deref :=
10366 Make_Explicit_Dereference (Loc,
10367 Prefix => Duplicate_Subexpr_Move_Checks (N));
10368 Set_Has_Dereference_Action (Deref);
10370 Size := Make_Temporary (Loc, 'S');
10372 Insert_Action (N,
10373 Make_Object_Declaration (Loc,
10374 Defining_Identifier => Size,
10376 Object_Definition =>
10377 New_Reference_To (RTE (RE_Storage_Count), Loc),
10379 Expression =>
10380 Make_Op_Divide (Loc,
10381 Left_Opnd =>
10382 Make_Attribute_Reference (Loc,
10383 Prefix => Deref,
10384 Attribute_Name => Name_Size),
10385 Right_Opnd =>
10386 Make_Integer_Literal (Loc, System_Storage_Unit))));
10388 -- Calculate the alignment of the dereferenced object. Generate:
10389 -- Alig : constant Storage_Count := <N>.all'Alignment;
10391 Deref :=
10392 Make_Explicit_Dereference (Loc,
10393 Prefix => Duplicate_Subexpr_Move_Checks (N));
10394 Set_Has_Dereference_Action (Deref);
10396 Alig := Make_Temporary (Loc, 'A');
10398 Insert_Action (N,
10399 Make_Object_Declaration (Loc,
10400 Defining_Identifier => Alig,
10401 Object_Definition =>
10402 New_Reference_To (RTE (RE_Storage_Count), Loc),
10403 Expression =>
10404 Make_Attribute_Reference (Loc,
10405 Prefix => Deref,
10406 Attribute_Name => Name_Alignment)));
10408 -- A dereference of a controlled object requires special processing. The
10409 -- finalization machinery requests additional space from the underlying
10410 -- pool to allocate and hide two pointers. As a result, a checked pool
10411 -- may mark the wrong memory as valid. Since checked pools do not have
10412 -- knowledge of hidden pointers, we have to bring the two pointers back
10413 -- in view in order to restore the original state of the object.
10415 if Needs_Finalization (Desig) then
10417 -- Adjust the address and size of the dereferenced object. Generate:
10418 -- Adjust_Controlled_Dereference (Addr, Size, Alig);
10420 Stmt :=
10421 Make_Procedure_Call_Statement (Loc,
10422 Name =>
10423 New_Reference_To (RTE (RE_Adjust_Controlled_Dereference), Loc),
10424 Parameter_Associations => New_List (
10425 New_Reference_To (Addr, Loc),
10426 New_Reference_To (Size, Loc),
10427 New_Reference_To (Alig, Loc)));
10429 -- Class-wide types complicate things because we cannot determine
10430 -- statically whether the actual object is truly controlled. We must
10431 -- generate a runtime check to detect this property. Generate:
10433 -- if Needs_Finalization (<N>.all'Tag) then
10434 -- <Stmt>;
10435 -- end if;
10437 if Is_Class_Wide_Type (Desig) then
10438 Deref :=
10439 Make_Explicit_Dereference (Loc,
10440 Prefix => Duplicate_Subexpr_Move_Checks (N));
10441 Set_Has_Dereference_Action (Deref);
10443 Stmt :=
10444 Make_If_Statement (Loc,
10445 Condition =>
10446 Make_Function_Call (Loc,
10447 Name =>
10448 New_Reference_To (RTE (RE_Needs_Finalization), Loc),
10449 Parameter_Associations => New_List (
10450 Make_Attribute_Reference (Loc,
10451 Prefix => Deref,
10452 Attribute_Name => Name_Tag))),
10453 Then_Statements => New_List (Stmt));
10454 end if;
10456 Insert_Action (N, Stmt);
10457 end if;
10459 -- Generate:
10460 -- Dereference (Pool, Addr, Size, Alig);
10462 Insert_Action (N,
10463 Make_Procedure_Call_Statement (Loc,
10464 Name =>
10465 New_Reference_To
10466 (Find_Prim_Op (Etype (Pool), Name_Dereference), Loc),
10467 Parameter_Associations => New_List (
10468 New_Reference_To (Pool, Loc),
10469 New_Reference_To (Addr, Loc),
10470 New_Reference_To (Size, Loc),
10471 New_Reference_To (Alig, Loc))));
10473 -- Mark the explicit dereference as processed to avoid potential
10474 -- infinite expansion.
10476 Set_Has_Dereference_Action (Pnod);
10478 exception
10479 when RE_Not_Available =>
10480 return;
10481 end Insert_Dereference_Action;
10483 --------------------------------
10484 -- Integer_Promotion_Possible --
10485 --------------------------------
10487 function Integer_Promotion_Possible (N : Node_Id) return Boolean is
10488 Operand : constant Node_Id := Expression (N);
10489 Operand_Type : constant Entity_Id := Etype (Operand);
10490 Root_Operand_Type : constant Entity_Id := Root_Type (Operand_Type);
10492 begin
10493 pragma Assert (Nkind (N) = N_Type_Conversion);
10495 return
10497 -- We only do the transformation for source constructs. We assume
10498 -- that the expander knows what it is doing when it generates code.
10500 Comes_From_Source (N)
10502 -- If the operand type is Short_Integer or Short_Short_Integer,
10503 -- then we will promote to Integer, which is available on all
10504 -- targets, and is sufficient to ensure no intermediate overflow.
10505 -- Furthermore it is likely to be as efficient or more efficient
10506 -- than using the smaller type for the computation so we do this
10507 -- unconditionally.
10509 and then
10510 (Root_Operand_Type = Base_Type (Standard_Short_Integer)
10511 or else
10512 Root_Operand_Type = Base_Type (Standard_Short_Short_Integer))
10514 -- Test for interesting operation, which includes addition,
10515 -- division, exponentiation, multiplication, subtraction, absolute
10516 -- value and unary negation. Unary "+" is omitted since it is a
10517 -- no-op and thus can't overflow.
10519 and then Nkind_In (Operand, N_Op_Abs,
10520 N_Op_Add,
10521 N_Op_Divide,
10522 N_Op_Expon,
10523 N_Op_Minus,
10524 N_Op_Multiply,
10525 N_Op_Subtract);
10526 end Integer_Promotion_Possible;
10528 ------------------------------
10529 -- Make_Array_Comparison_Op --
10530 ------------------------------
10532 -- This is a hand-coded expansion of the following generic function:
10534 -- generic
10535 -- type elem is (<>);
10536 -- type index is (<>);
10537 -- type a is array (index range <>) of elem;
10539 -- function Gnnn (X : a; Y: a) return boolean is
10540 -- J : index := Y'first;
10542 -- begin
10543 -- if X'length = 0 then
10544 -- return false;
10546 -- elsif Y'length = 0 then
10547 -- return true;
10549 -- else
10550 -- for I in X'range loop
10551 -- if X (I) = Y (J) then
10552 -- if J = Y'last then
10553 -- exit;
10554 -- else
10555 -- J := index'succ (J);
10556 -- end if;
10558 -- else
10559 -- return X (I) > Y (J);
10560 -- end if;
10561 -- end loop;
10563 -- return X'length > Y'length;
10564 -- end if;
10565 -- end Gnnn;
10567 -- Note that since we are essentially doing this expansion by hand, we
10568 -- do not need to generate an actual or formal generic part, just the
10569 -- instantiated function itself.
10571 function Make_Array_Comparison_Op
10572 (Typ : Entity_Id;
10573 Nod : Node_Id) return Node_Id
10575 Loc : constant Source_Ptr := Sloc (Nod);
10577 X : constant Entity_Id := Make_Defining_Identifier (Loc, Name_uX);
10578 Y : constant Entity_Id := Make_Defining_Identifier (Loc, Name_uY);
10579 I : constant Entity_Id := Make_Defining_Identifier (Loc, Name_uI);
10580 J : constant Entity_Id := Make_Defining_Identifier (Loc, Name_uJ);
10582 Index : constant Entity_Id := Base_Type (Etype (First_Index (Typ)));
10584 Loop_Statement : Node_Id;
10585 Loop_Body : Node_Id;
10586 If_Stat : Node_Id;
10587 Inner_If : Node_Id;
10588 Final_Expr : Node_Id;
10589 Func_Body : Node_Id;
10590 Func_Name : Entity_Id;
10591 Formals : List_Id;
10592 Length1 : Node_Id;
10593 Length2 : Node_Id;
10595 begin
10596 -- if J = Y'last then
10597 -- exit;
10598 -- else
10599 -- J := index'succ (J);
10600 -- end if;
10602 Inner_If :=
10603 Make_Implicit_If_Statement (Nod,
10604 Condition =>
10605 Make_Op_Eq (Loc,
10606 Left_Opnd => New_Reference_To (J, Loc),
10607 Right_Opnd =>
10608 Make_Attribute_Reference (Loc,
10609 Prefix => New_Reference_To (Y, Loc),
10610 Attribute_Name => Name_Last)),
10612 Then_Statements => New_List (
10613 Make_Exit_Statement (Loc)),
10615 Else_Statements =>
10616 New_List (
10617 Make_Assignment_Statement (Loc,
10618 Name => New_Reference_To (J, Loc),
10619 Expression =>
10620 Make_Attribute_Reference (Loc,
10621 Prefix => New_Reference_To (Index, Loc),
10622 Attribute_Name => Name_Succ,
10623 Expressions => New_List (New_Reference_To (J, Loc))))));
10625 -- if X (I) = Y (J) then
10626 -- if ... end if;
10627 -- else
10628 -- return X (I) > Y (J);
10629 -- end if;
10631 Loop_Body :=
10632 Make_Implicit_If_Statement (Nod,
10633 Condition =>
10634 Make_Op_Eq (Loc,
10635 Left_Opnd =>
10636 Make_Indexed_Component (Loc,
10637 Prefix => New_Reference_To (X, Loc),
10638 Expressions => New_List (New_Reference_To (I, Loc))),
10640 Right_Opnd =>
10641 Make_Indexed_Component (Loc,
10642 Prefix => New_Reference_To (Y, Loc),
10643 Expressions => New_List (New_Reference_To (J, Loc)))),
10645 Then_Statements => New_List (Inner_If),
10647 Else_Statements => New_List (
10648 Make_Simple_Return_Statement (Loc,
10649 Expression =>
10650 Make_Op_Gt (Loc,
10651 Left_Opnd =>
10652 Make_Indexed_Component (Loc,
10653 Prefix => New_Reference_To (X, Loc),
10654 Expressions => New_List (New_Reference_To (I, Loc))),
10656 Right_Opnd =>
10657 Make_Indexed_Component (Loc,
10658 Prefix => New_Reference_To (Y, Loc),
10659 Expressions => New_List (
10660 New_Reference_To (J, Loc)))))));
10662 -- for I in X'range loop
10663 -- if ... end if;
10664 -- end loop;
10666 Loop_Statement :=
10667 Make_Implicit_Loop_Statement (Nod,
10668 Identifier => Empty,
10670 Iteration_Scheme =>
10671 Make_Iteration_Scheme (Loc,
10672 Loop_Parameter_Specification =>
10673 Make_Loop_Parameter_Specification (Loc,
10674 Defining_Identifier => I,
10675 Discrete_Subtype_Definition =>
10676 Make_Attribute_Reference (Loc,
10677 Prefix => New_Reference_To (X, Loc),
10678 Attribute_Name => Name_Range))),
10680 Statements => New_List (Loop_Body));
10682 -- if X'length = 0 then
10683 -- return false;
10684 -- elsif Y'length = 0 then
10685 -- return true;
10686 -- else
10687 -- for ... loop ... end loop;
10688 -- return X'length > Y'length;
10689 -- end if;
10691 Length1 :=
10692 Make_Attribute_Reference (Loc,
10693 Prefix => New_Reference_To (X, Loc),
10694 Attribute_Name => Name_Length);
10696 Length2 :=
10697 Make_Attribute_Reference (Loc,
10698 Prefix => New_Reference_To (Y, Loc),
10699 Attribute_Name => Name_Length);
10701 Final_Expr :=
10702 Make_Op_Gt (Loc,
10703 Left_Opnd => Length1,
10704 Right_Opnd => Length2);
10706 If_Stat :=
10707 Make_Implicit_If_Statement (Nod,
10708 Condition =>
10709 Make_Op_Eq (Loc,
10710 Left_Opnd =>
10711 Make_Attribute_Reference (Loc,
10712 Prefix => New_Reference_To (X, Loc),
10713 Attribute_Name => Name_Length),
10714 Right_Opnd =>
10715 Make_Integer_Literal (Loc, 0)),
10717 Then_Statements =>
10718 New_List (
10719 Make_Simple_Return_Statement (Loc,
10720 Expression => New_Reference_To (Standard_False, Loc))),
10722 Elsif_Parts => New_List (
10723 Make_Elsif_Part (Loc,
10724 Condition =>
10725 Make_Op_Eq (Loc,
10726 Left_Opnd =>
10727 Make_Attribute_Reference (Loc,
10728 Prefix => New_Reference_To (Y, Loc),
10729 Attribute_Name => Name_Length),
10730 Right_Opnd =>
10731 Make_Integer_Literal (Loc, 0)),
10733 Then_Statements =>
10734 New_List (
10735 Make_Simple_Return_Statement (Loc,
10736 Expression => New_Reference_To (Standard_True, Loc))))),
10738 Else_Statements => New_List (
10739 Loop_Statement,
10740 Make_Simple_Return_Statement (Loc,
10741 Expression => Final_Expr)));
10743 -- (X : a; Y: a)
10745 Formals := New_List (
10746 Make_Parameter_Specification (Loc,
10747 Defining_Identifier => X,
10748 Parameter_Type => New_Reference_To (Typ, Loc)),
10750 Make_Parameter_Specification (Loc,
10751 Defining_Identifier => Y,
10752 Parameter_Type => New_Reference_To (Typ, Loc)));
10754 -- function Gnnn (...) return boolean is
10755 -- J : index := Y'first;
10756 -- begin
10757 -- if ... end if;
10758 -- end Gnnn;
10760 Func_Name := Make_Temporary (Loc, 'G');
10762 Func_Body :=
10763 Make_Subprogram_Body (Loc,
10764 Specification =>
10765 Make_Function_Specification (Loc,
10766 Defining_Unit_Name => Func_Name,
10767 Parameter_Specifications => Formals,
10768 Result_Definition => New_Reference_To (Standard_Boolean, Loc)),
10770 Declarations => New_List (
10771 Make_Object_Declaration (Loc,
10772 Defining_Identifier => J,
10773 Object_Definition => New_Reference_To (Index, Loc),
10774 Expression =>
10775 Make_Attribute_Reference (Loc,
10776 Prefix => New_Reference_To (Y, Loc),
10777 Attribute_Name => Name_First))),
10779 Handled_Statement_Sequence =>
10780 Make_Handled_Sequence_Of_Statements (Loc,
10781 Statements => New_List (If_Stat)));
10783 return Func_Body;
10784 end Make_Array_Comparison_Op;
10786 ---------------------------
10787 -- Make_Boolean_Array_Op --
10788 ---------------------------
10790 -- For logical operations on boolean arrays, expand in line the following,
10791 -- replacing 'and' with 'or' or 'xor' where needed:
10793 -- function Annn (A : typ; B: typ) return typ is
10794 -- C : typ;
10795 -- begin
10796 -- for J in A'range loop
10797 -- C (J) := A (J) op B (J);
10798 -- end loop;
10799 -- return C;
10800 -- end Annn;
10802 -- Here typ is the boolean array type
10804 function Make_Boolean_Array_Op
10805 (Typ : Entity_Id;
10806 N : Node_Id) return Node_Id
10808 Loc : constant Source_Ptr := Sloc (N);
10810 A : constant Entity_Id := Make_Defining_Identifier (Loc, Name_uA);
10811 B : constant Entity_Id := Make_Defining_Identifier (Loc, Name_uB);
10812 C : constant Entity_Id := Make_Defining_Identifier (Loc, Name_uC);
10813 J : constant Entity_Id := Make_Defining_Identifier (Loc, Name_uJ);
10815 A_J : Node_Id;
10816 B_J : Node_Id;
10817 C_J : Node_Id;
10818 Op : Node_Id;
10820 Formals : List_Id;
10821 Func_Name : Entity_Id;
10822 Func_Body : Node_Id;
10823 Loop_Statement : Node_Id;
10825 begin
10826 A_J :=
10827 Make_Indexed_Component (Loc,
10828 Prefix => New_Reference_To (A, Loc),
10829 Expressions => New_List (New_Reference_To (J, Loc)));
10831 B_J :=
10832 Make_Indexed_Component (Loc,
10833 Prefix => New_Reference_To (B, Loc),
10834 Expressions => New_List (New_Reference_To (J, Loc)));
10836 C_J :=
10837 Make_Indexed_Component (Loc,
10838 Prefix => New_Reference_To (C, Loc),
10839 Expressions => New_List (New_Reference_To (J, Loc)));
10841 if Nkind (N) = N_Op_And then
10842 Op :=
10843 Make_Op_And (Loc,
10844 Left_Opnd => A_J,
10845 Right_Opnd => B_J);
10847 elsif Nkind (N) = N_Op_Or then
10848 Op :=
10849 Make_Op_Or (Loc,
10850 Left_Opnd => A_J,
10851 Right_Opnd => B_J);
10853 else
10854 Op :=
10855 Make_Op_Xor (Loc,
10856 Left_Opnd => A_J,
10857 Right_Opnd => B_J);
10858 end if;
10860 Loop_Statement :=
10861 Make_Implicit_Loop_Statement (N,
10862 Identifier => Empty,
10864 Iteration_Scheme =>
10865 Make_Iteration_Scheme (Loc,
10866 Loop_Parameter_Specification =>
10867 Make_Loop_Parameter_Specification (Loc,
10868 Defining_Identifier => J,
10869 Discrete_Subtype_Definition =>
10870 Make_Attribute_Reference (Loc,
10871 Prefix => New_Reference_To (A, Loc),
10872 Attribute_Name => Name_Range))),
10874 Statements => New_List (
10875 Make_Assignment_Statement (Loc,
10876 Name => C_J,
10877 Expression => Op)));
10879 Formals := New_List (
10880 Make_Parameter_Specification (Loc,
10881 Defining_Identifier => A,
10882 Parameter_Type => New_Reference_To (Typ, Loc)),
10884 Make_Parameter_Specification (Loc,
10885 Defining_Identifier => B,
10886 Parameter_Type => New_Reference_To (Typ, Loc)));
10888 Func_Name := Make_Temporary (Loc, 'A');
10889 Set_Is_Inlined (Func_Name);
10891 Func_Body :=
10892 Make_Subprogram_Body (Loc,
10893 Specification =>
10894 Make_Function_Specification (Loc,
10895 Defining_Unit_Name => Func_Name,
10896 Parameter_Specifications => Formals,
10897 Result_Definition => New_Reference_To (Typ, Loc)),
10899 Declarations => New_List (
10900 Make_Object_Declaration (Loc,
10901 Defining_Identifier => C,
10902 Object_Definition => New_Reference_To (Typ, Loc))),
10904 Handled_Statement_Sequence =>
10905 Make_Handled_Sequence_Of_Statements (Loc,
10906 Statements => New_List (
10907 Loop_Statement,
10908 Make_Simple_Return_Statement (Loc,
10909 Expression => New_Reference_To (C, Loc)))));
10911 return Func_Body;
10912 end Make_Boolean_Array_Op;
10914 --------------------------------
10915 -- Optimize_Length_Comparison --
10916 --------------------------------
10918 procedure Optimize_Length_Comparison (N : Node_Id) is
10919 Loc : constant Source_Ptr := Sloc (N);
10920 Typ : constant Entity_Id := Etype (N);
10921 Result : Node_Id;
10923 Left : Node_Id;
10924 Right : Node_Id;
10925 -- First and Last attribute reference nodes, which end up as left and
10926 -- right operands of the optimized result.
10928 Is_Zero : Boolean;
10929 -- True for comparison operand of zero
10931 Comp : Node_Id;
10932 -- Comparison operand, set only if Is_Zero is false
10934 Ent : Entity_Id;
10935 -- Entity whose length is being compared
10937 Index : Node_Id;
10938 -- Integer_Literal node for length attribute expression, or Empty
10939 -- if there is no such expression present.
10941 Ityp : Entity_Id;
10942 -- Type of array index to which 'Length is applied
10944 Op : Node_Kind := Nkind (N);
10945 -- Kind of comparison operator, gets flipped if operands backwards
10947 function Is_Optimizable (N : Node_Id) return Boolean;
10948 -- Tests N to see if it is an optimizable comparison value (defined as
10949 -- constant zero or one, or something else where the value is known to
10950 -- be positive and in the range of 32-bits, and where the corresponding
10951 -- Length value is also known to be 32-bits. If result is true, sets
10952 -- Is_Zero, Ityp, and Comp accordingly.
10954 function Is_Entity_Length (N : Node_Id) return Boolean;
10955 -- Tests if N is a length attribute applied to a simple entity. If so,
10956 -- returns True, and sets Ent to the entity, and Index to the integer
10957 -- literal provided as an attribute expression, or to Empty if none.
10958 -- Also returns True if the expression is a generated type conversion
10959 -- whose expression is of the desired form. This latter case arises
10960 -- when Apply_Universal_Integer_Attribute_Check installs a conversion
10961 -- to check for being in range, which is not needed in this context.
10962 -- Returns False if neither condition holds.
10964 function Prepare_64 (N : Node_Id) return Node_Id;
10965 -- Given a discrete expression, returns a Long_Long_Integer typed
10966 -- expression representing the underlying value of the expression.
10967 -- This is done with an unchecked conversion to the result type. We
10968 -- use unchecked conversion to handle the enumeration type case.
10970 ----------------------
10971 -- Is_Entity_Length --
10972 ----------------------
10974 function Is_Entity_Length (N : Node_Id) return Boolean is
10975 begin
10976 if Nkind (N) = N_Attribute_Reference
10977 and then Attribute_Name (N) = Name_Length
10978 and then Is_Entity_Name (Prefix (N))
10979 then
10980 Ent := Entity (Prefix (N));
10982 if Present (Expressions (N)) then
10983 Index := First (Expressions (N));
10984 else
10985 Index := Empty;
10986 end if;
10988 return True;
10990 elsif Nkind (N) = N_Type_Conversion
10991 and then not Comes_From_Source (N)
10992 then
10993 return Is_Entity_Length (Expression (N));
10995 else
10996 return False;
10997 end if;
10998 end Is_Entity_Length;
11000 --------------------
11001 -- Is_Optimizable --
11002 --------------------
11004 function Is_Optimizable (N : Node_Id) return Boolean is
11005 Val : Uint;
11006 OK : Boolean;
11007 Lo : Uint;
11008 Hi : Uint;
11009 Indx : Node_Id;
11011 begin
11012 if Compile_Time_Known_Value (N) then
11013 Val := Expr_Value (N);
11015 if Val = Uint_0 then
11016 Is_Zero := True;
11017 Comp := Empty;
11018 return True;
11020 elsif Val = Uint_1 then
11021 Is_Zero := False;
11022 Comp := Empty;
11023 return True;
11024 end if;
11025 end if;
11027 -- Here we have to make sure of being within 32-bits
11029 Determine_Range (N, OK, Lo, Hi, Assume_Valid => True);
11031 if not OK
11032 or else Lo < Uint_1
11033 or else Hi > UI_From_Int (Int'Last)
11034 then
11035 return False;
11036 end if;
11038 -- Comparison value was within range, so now we must check the index
11039 -- value to make sure it is also within 32-bits.
11041 Indx := First_Index (Etype (Ent));
11043 if Present (Index) then
11044 for J in 2 .. UI_To_Int (Intval (Index)) loop
11045 Next_Index (Indx);
11046 end loop;
11047 end if;
11049 Ityp := Etype (Indx);
11051 if Esize (Ityp) > 32 then
11052 return False;
11053 end if;
11055 Is_Zero := False;
11056 Comp := N;
11057 return True;
11058 end Is_Optimizable;
11060 ----------------
11061 -- Prepare_64 --
11062 ----------------
11064 function Prepare_64 (N : Node_Id) return Node_Id is
11065 begin
11066 return Unchecked_Convert_To (Standard_Long_Long_Integer, N);
11067 end Prepare_64;
11069 -- Start of processing for Optimize_Length_Comparison
11071 begin
11072 -- Nothing to do if not a comparison
11074 if Op not in N_Op_Compare then
11075 return;
11076 end if;
11078 -- Nothing to do if special -gnatd.P debug flag set
11080 if Debug_Flag_Dot_PP then
11081 return;
11082 end if;
11084 -- Ent'Length op 0/1
11086 if Is_Entity_Length (Left_Opnd (N))
11087 and then Is_Optimizable (Right_Opnd (N))
11088 then
11089 null;
11091 -- 0/1 op Ent'Length
11093 elsif Is_Entity_Length (Right_Opnd (N))
11094 and then Is_Optimizable (Left_Opnd (N))
11095 then
11096 -- Flip comparison to opposite sense
11098 case Op is
11099 when N_Op_Lt => Op := N_Op_Gt;
11100 when N_Op_Le => Op := N_Op_Ge;
11101 when N_Op_Gt => Op := N_Op_Lt;
11102 when N_Op_Ge => Op := N_Op_Le;
11103 when others => null;
11104 end case;
11106 -- Else optimization not possible
11108 else
11109 return;
11110 end if;
11112 -- Fall through if we will do the optimization
11114 -- Cases to handle:
11116 -- X'Length = 0 => X'First > X'Last
11117 -- X'Length = 1 => X'First = X'Last
11118 -- X'Length = n => X'First + (n - 1) = X'Last
11120 -- X'Length /= 0 => X'First <= X'Last
11121 -- X'Length /= 1 => X'First /= X'Last
11122 -- X'Length /= n => X'First + (n - 1) /= X'Last
11124 -- X'Length >= 0 => always true, warn
11125 -- X'Length >= 1 => X'First <= X'Last
11126 -- X'Length >= n => X'First + (n - 1) <= X'Last
11128 -- X'Length > 0 => X'First <= X'Last
11129 -- X'Length > 1 => X'First < X'Last
11130 -- X'Length > n => X'First + (n - 1) < X'Last
11132 -- X'Length <= 0 => X'First > X'Last (warn, could be =)
11133 -- X'Length <= 1 => X'First >= X'Last
11134 -- X'Length <= n => X'First + (n - 1) >= X'Last
11136 -- X'Length < 0 => always false (warn)
11137 -- X'Length < 1 => X'First > X'Last
11138 -- X'Length < n => X'First + (n - 1) > X'Last
11140 -- Note: for the cases of n (not constant 0,1), we require that the
11141 -- corresponding index type be integer or shorter (i.e. not 64-bit),
11142 -- and the same for the comparison value. Then we do the comparison
11143 -- using 64-bit arithmetic (actually long long integer), so that we
11144 -- cannot have overflow intefering with the result.
11146 -- First deal with warning cases
11148 if Is_Zero then
11149 case Op is
11151 -- X'Length >= 0
11153 when N_Op_Ge =>
11154 Rewrite (N,
11155 Convert_To (Typ, New_Occurrence_Of (Standard_True, Loc)));
11156 Analyze_And_Resolve (N, Typ);
11157 Warn_On_Known_Condition (N);
11158 return;
11160 -- X'Length < 0
11162 when N_Op_Lt =>
11163 Rewrite (N,
11164 Convert_To (Typ, New_Occurrence_Of (Standard_False, Loc)));
11165 Analyze_And_Resolve (N, Typ);
11166 Warn_On_Known_Condition (N);
11167 return;
11169 when N_Op_Le =>
11170 if Constant_Condition_Warnings
11171 and then Comes_From_Source (Original_Node (N))
11172 then
11173 Error_Msg_N ("could replace by ""'=""?", N);
11174 end if;
11176 Op := N_Op_Eq;
11178 when others =>
11179 null;
11180 end case;
11181 end if;
11183 -- Build the First reference we will use
11185 Left :=
11186 Make_Attribute_Reference (Loc,
11187 Prefix => New_Occurrence_Of (Ent, Loc),
11188 Attribute_Name => Name_First);
11190 if Present (Index) then
11191 Set_Expressions (Left, New_List (New_Copy (Index)));
11192 end if;
11194 -- If general value case, then do the addition of (n - 1), and
11195 -- also add the needed conversions to type Long_Long_Integer.
11197 if Present (Comp) then
11198 Left :=
11199 Make_Op_Add (Loc,
11200 Left_Opnd => Prepare_64 (Left),
11201 Right_Opnd =>
11202 Make_Op_Subtract (Loc,
11203 Left_Opnd => Prepare_64 (Comp),
11204 Right_Opnd => Make_Integer_Literal (Loc, 1)));
11205 end if;
11207 -- Build the Last reference we will use
11209 Right :=
11210 Make_Attribute_Reference (Loc,
11211 Prefix => New_Occurrence_Of (Ent, Loc),
11212 Attribute_Name => Name_Last);
11214 if Present (Index) then
11215 Set_Expressions (Right, New_List (New_Copy (Index)));
11216 end if;
11218 -- If general operand, convert Last reference to Long_Long_Integer
11220 if Present (Comp) then
11221 Right := Prepare_64 (Right);
11222 end if;
11224 -- Check for cases to optimize
11226 -- X'Length = 0 => X'First > X'Last
11227 -- X'Length < 1 => X'First > X'Last
11228 -- X'Length < n => X'First + (n - 1) > X'Last
11230 if (Is_Zero and then Op = N_Op_Eq)
11231 or else (not Is_Zero and then Op = N_Op_Lt)
11232 then
11233 Result :=
11234 Make_Op_Gt (Loc,
11235 Left_Opnd => Left,
11236 Right_Opnd => Right);
11238 -- X'Length = 1 => X'First = X'Last
11239 -- X'Length = n => X'First + (n - 1) = X'Last
11241 elsif not Is_Zero and then Op = N_Op_Eq then
11242 Result :=
11243 Make_Op_Eq (Loc,
11244 Left_Opnd => Left,
11245 Right_Opnd => Right);
11247 -- X'Length /= 0 => X'First <= X'Last
11248 -- X'Length > 0 => X'First <= X'Last
11250 elsif Is_Zero and (Op = N_Op_Ne or else Op = N_Op_Gt) then
11251 Result :=
11252 Make_Op_Le (Loc,
11253 Left_Opnd => Left,
11254 Right_Opnd => Right);
11256 -- X'Length /= 1 => X'First /= X'Last
11257 -- X'Length /= n => X'First + (n - 1) /= X'Last
11259 elsif not Is_Zero and then Op = N_Op_Ne then
11260 Result :=
11261 Make_Op_Ne (Loc,
11262 Left_Opnd => Left,
11263 Right_Opnd => Right);
11265 -- X'Length >= 1 => X'First <= X'Last
11266 -- X'Length >= n => X'First + (n - 1) <= X'Last
11268 elsif not Is_Zero and then Op = N_Op_Ge then
11269 Result :=
11270 Make_Op_Le (Loc,
11271 Left_Opnd => Left,
11272 Right_Opnd => Right);
11274 -- X'Length > 1 => X'First < X'Last
11275 -- X'Length > n => X'First + (n = 1) < X'Last
11277 elsif not Is_Zero and then Op = N_Op_Gt then
11278 Result :=
11279 Make_Op_Lt (Loc,
11280 Left_Opnd => Left,
11281 Right_Opnd => Right);
11283 -- X'Length <= 1 => X'First >= X'Last
11284 -- X'Length <= n => X'First + (n - 1) >= X'Last
11286 elsif not Is_Zero and then Op = N_Op_Le then
11287 Result :=
11288 Make_Op_Ge (Loc,
11289 Left_Opnd => Left,
11290 Right_Opnd => Right);
11292 -- Should not happen at this stage
11294 else
11295 raise Program_Error;
11296 end if;
11298 -- Rewrite and finish up
11300 Rewrite (N, Result);
11301 Analyze_And_Resolve (N, Typ);
11302 return;
11303 end Optimize_Length_Comparison;
11305 ------------------------
11306 -- Rewrite_Comparison --
11307 ------------------------
11309 procedure Rewrite_Comparison (N : Node_Id) is
11310 Warning_Generated : Boolean := False;
11311 -- Set to True if first pass with Assume_Valid generates a warning in
11312 -- which case we skip the second pass to avoid warning overloaded.
11314 Result : Node_Id;
11315 -- Set to Standard_True or Standard_False
11317 begin
11318 if Nkind (N) = N_Type_Conversion then
11319 Rewrite_Comparison (Expression (N));
11320 return;
11322 elsif Nkind (N) not in N_Op_Compare then
11323 return;
11324 end if;
11326 -- Now start looking at the comparison in detail. We potentially go
11327 -- through this loop twice. The first time, Assume_Valid is set False
11328 -- in the call to Compile_Time_Compare. If this call results in a
11329 -- clear result of always True or Always False, that's decisive and
11330 -- we are done. Otherwise we repeat the processing with Assume_Valid
11331 -- set to True to generate additional warnings. We can skip that step
11332 -- if Constant_Condition_Warnings is False.
11334 for AV in False .. True loop
11335 declare
11336 Typ : constant Entity_Id := Etype (N);
11337 Op1 : constant Node_Id := Left_Opnd (N);
11338 Op2 : constant Node_Id := Right_Opnd (N);
11340 Res : constant Compare_Result :=
11341 Compile_Time_Compare (Op1, Op2, Assume_Valid => AV);
11342 -- Res indicates if compare outcome can be compile time determined
11344 True_Result : Boolean;
11345 False_Result : Boolean;
11347 begin
11348 case N_Op_Compare (Nkind (N)) is
11349 when N_Op_Eq =>
11350 True_Result := Res = EQ;
11351 False_Result := Res = LT or else Res = GT or else Res = NE;
11353 when N_Op_Ge =>
11354 True_Result := Res in Compare_GE;
11355 False_Result := Res = LT;
11357 if Res = LE
11358 and then Constant_Condition_Warnings
11359 and then Comes_From_Source (Original_Node (N))
11360 and then Nkind (Original_Node (N)) = N_Op_Ge
11361 and then not In_Instance
11362 and then Is_Integer_Type (Etype (Left_Opnd (N)))
11363 and then not Has_Warnings_Off (Etype (Left_Opnd (N)))
11364 then
11365 Error_Msg_N
11366 ("can never be greater than, could replace by ""'=""?", N);
11367 Warning_Generated := True;
11368 end if;
11370 when N_Op_Gt =>
11371 True_Result := Res = GT;
11372 False_Result := Res in Compare_LE;
11374 when N_Op_Lt =>
11375 True_Result := Res = LT;
11376 False_Result := Res in Compare_GE;
11378 when N_Op_Le =>
11379 True_Result := Res in Compare_LE;
11380 False_Result := Res = GT;
11382 if Res = GE
11383 and then Constant_Condition_Warnings
11384 and then Comes_From_Source (Original_Node (N))
11385 and then Nkind (Original_Node (N)) = N_Op_Le
11386 and then not In_Instance
11387 and then Is_Integer_Type (Etype (Left_Opnd (N)))
11388 and then not Has_Warnings_Off (Etype (Left_Opnd (N)))
11389 then
11390 Error_Msg_N
11391 ("can never be less than, could replace by ""'=""?", N);
11392 Warning_Generated := True;
11393 end if;
11395 when N_Op_Ne =>
11396 True_Result := Res = NE or else Res = GT or else Res = LT;
11397 False_Result := Res = EQ;
11398 end case;
11400 -- If this is the first iteration, then we actually convert the
11401 -- comparison into True or False, if the result is certain.
11403 if AV = False then
11404 if True_Result or False_Result then
11405 Result := Boolean_Literals (True_Result);
11406 Rewrite (N,
11407 Convert_To (Typ,
11408 New_Occurrence_Of (Result, Sloc (N))));
11409 Analyze_And_Resolve (N, Typ);
11410 Warn_On_Known_Condition (N);
11411 return;
11412 end if;
11414 -- If this is the second iteration (AV = True), and the original
11415 -- node comes from source and we are not in an instance, then give
11416 -- a warning if we know result would be True or False. Note: we
11417 -- know Constant_Condition_Warnings is set if we get here.
11419 elsif Comes_From_Source (Original_Node (N))
11420 and then not In_Instance
11421 then
11422 if True_Result then
11423 Error_Msg_N
11424 ("condition can only be False if invalid values present?",
11426 elsif False_Result then
11427 Error_Msg_N
11428 ("condition can only be True if invalid values present?",
11430 end if;
11431 end if;
11432 end;
11434 -- Skip second iteration if not warning on constant conditions or
11435 -- if the first iteration already generated a warning of some kind or
11436 -- if we are in any case assuming all values are valid (so that the
11437 -- first iteration took care of the valid case).
11439 exit when not Constant_Condition_Warnings;
11440 exit when Warning_Generated;
11441 exit when Assume_No_Invalid_Values;
11442 end loop;
11443 end Rewrite_Comparison;
11445 ----------------------------
11446 -- Safe_In_Place_Array_Op --
11447 ----------------------------
11449 function Safe_In_Place_Array_Op
11450 (Lhs : Node_Id;
11451 Op1 : Node_Id;
11452 Op2 : Node_Id) return Boolean
11454 Target : Entity_Id;
11456 function Is_Safe_Operand (Op : Node_Id) return Boolean;
11457 -- Operand is safe if it cannot overlap part of the target of the
11458 -- operation. If the operand and the target are identical, the operand
11459 -- is safe. The operand can be empty in the case of negation.
11461 function Is_Unaliased (N : Node_Id) return Boolean;
11462 -- Check that N is a stand-alone entity
11464 ------------------
11465 -- Is_Unaliased --
11466 ------------------
11468 function Is_Unaliased (N : Node_Id) return Boolean is
11469 begin
11470 return
11471 Is_Entity_Name (N)
11472 and then No (Address_Clause (Entity (N)))
11473 and then No (Renamed_Object (Entity (N)));
11474 end Is_Unaliased;
11476 ---------------------
11477 -- Is_Safe_Operand --
11478 ---------------------
11480 function Is_Safe_Operand (Op : Node_Id) return Boolean is
11481 begin
11482 if No (Op) then
11483 return True;
11485 elsif Is_Entity_Name (Op) then
11486 return Is_Unaliased (Op);
11488 elsif Nkind_In (Op, N_Indexed_Component, N_Selected_Component) then
11489 return Is_Unaliased (Prefix (Op));
11491 elsif Nkind (Op) = N_Slice then
11492 return
11493 Is_Unaliased (Prefix (Op))
11494 and then Entity (Prefix (Op)) /= Target;
11496 elsif Nkind (Op) = N_Op_Not then
11497 return Is_Safe_Operand (Right_Opnd (Op));
11499 else
11500 return False;
11501 end if;
11502 end Is_Safe_Operand;
11504 -- Start of processing for Is_Safe_In_Place_Array_Op
11506 begin
11507 -- Skip this processing if the component size is different from system
11508 -- storage unit (since at least for NOT this would cause problems).
11510 if Component_Size (Etype (Lhs)) /= System_Storage_Unit then
11511 return False;
11513 -- Cannot do in place stuff on VM_Target since cannot pass addresses
11515 elsif VM_Target /= No_VM then
11516 return False;
11518 -- Cannot do in place stuff if non-standard Boolean representation
11520 elsif Has_Non_Standard_Rep (Component_Type (Etype (Lhs))) then
11521 return False;
11523 elsif not Is_Unaliased (Lhs) then
11524 return False;
11526 else
11527 Target := Entity (Lhs);
11528 return Is_Safe_Operand (Op1) and then Is_Safe_Operand (Op2);
11529 end if;
11530 end Safe_In_Place_Array_Op;
11532 -----------------------
11533 -- Tagged_Membership --
11534 -----------------------
11536 -- There are two different cases to consider depending on whether the right
11537 -- operand is a class-wide type or not. If not we just compare the actual
11538 -- tag of the left expr to the target type tag:
11540 -- Left_Expr.Tag = Right_Type'Tag;
11542 -- If it is a class-wide type we use the RT function CW_Membership which is
11543 -- usually implemented by looking in the ancestor tables contained in the
11544 -- dispatch table pointed by Left_Expr.Tag for Typ'Tag
11546 -- Ada 2005 (AI-251): If it is a class-wide interface type we use the RT
11547 -- function IW_Membership which is usually implemented by looking in the
11548 -- table of abstract interface types plus the ancestor table contained in
11549 -- the dispatch table pointed by Left_Expr.Tag for Typ'Tag
11551 procedure Tagged_Membership
11552 (N : Node_Id;
11553 SCIL_Node : out Node_Id;
11554 Result : out Node_Id)
11556 Left : constant Node_Id := Left_Opnd (N);
11557 Right : constant Node_Id := Right_Opnd (N);
11558 Loc : constant Source_Ptr := Sloc (N);
11560 Full_R_Typ : Entity_Id;
11561 Left_Type : Entity_Id;
11562 New_Node : Node_Id;
11563 Right_Type : Entity_Id;
11564 Obj_Tag : Node_Id;
11566 begin
11567 SCIL_Node := Empty;
11569 -- Handle entities from the limited view
11571 Left_Type := Available_View (Etype (Left));
11572 Right_Type := Available_View (Etype (Right));
11574 -- In the case where the type is an access type, the test is applied
11575 -- using the designated types (needed in Ada 2012 for implicit anonymous
11576 -- access conversions, for AI05-0149).
11578 if Is_Access_Type (Right_Type) then
11579 Left_Type := Designated_Type (Left_Type);
11580 Right_Type := Designated_Type (Right_Type);
11581 end if;
11583 if Is_Class_Wide_Type (Left_Type) then
11584 Left_Type := Root_Type (Left_Type);
11585 end if;
11587 if Is_Class_Wide_Type (Right_Type) then
11588 Full_R_Typ := Underlying_Type (Root_Type (Right_Type));
11589 else
11590 Full_R_Typ := Underlying_Type (Right_Type);
11591 end if;
11593 Obj_Tag :=
11594 Make_Selected_Component (Loc,
11595 Prefix => Relocate_Node (Left),
11596 Selector_Name =>
11597 New_Reference_To (First_Tag_Component (Left_Type), Loc));
11599 if Is_Class_Wide_Type (Right_Type) then
11601 -- No need to issue a run-time check if we statically know that the
11602 -- result of this membership test is always true. For example,
11603 -- considering the following declarations:
11605 -- type Iface is interface;
11606 -- type T is tagged null record;
11607 -- type DT is new T and Iface with null record;
11609 -- Obj1 : T;
11610 -- Obj2 : DT;
11612 -- These membership tests are always true:
11614 -- Obj1 in T'Class
11615 -- Obj2 in T'Class;
11616 -- Obj2 in Iface'Class;
11618 -- We do not need to handle cases where the membership is illegal.
11619 -- For example:
11621 -- Obj1 in DT'Class; -- Compile time error
11622 -- Obj1 in Iface'Class; -- Compile time error
11624 if not Is_Class_Wide_Type (Left_Type)
11625 and then (Is_Ancestor (Etype (Right_Type), Left_Type,
11626 Use_Full_View => True)
11627 or else (Is_Interface (Etype (Right_Type))
11628 and then Interface_Present_In_Ancestor
11629 (Typ => Left_Type,
11630 Iface => Etype (Right_Type))))
11631 then
11632 Result := New_Reference_To (Standard_True, Loc);
11633 return;
11634 end if;
11636 -- Ada 2005 (AI-251): Class-wide applied to interfaces
11638 if Is_Interface (Etype (Class_Wide_Type (Right_Type)))
11640 -- Support to: "Iface_CW_Typ in Typ'Class"
11642 or else Is_Interface (Left_Type)
11643 then
11644 -- Issue error if IW_Membership operation not available in a
11645 -- configurable run time setting.
11647 if not RTE_Available (RE_IW_Membership) then
11648 Error_Msg_CRT
11649 ("dynamic membership test on interface types", N);
11650 Result := Empty;
11651 return;
11652 end if;
11654 Result :=
11655 Make_Function_Call (Loc,
11656 Name => New_Occurrence_Of (RTE (RE_IW_Membership), Loc),
11657 Parameter_Associations => New_List (
11658 Make_Attribute_Reference (Loc,
11659 Prefix => Obj_Tag,
11660 Attribute_Name => Name_Address),
11661 New_Reference_To (
11662 Node (First_Elmt (Access_Disp_Table (Full_R_Typ))),
11663 Loc)));
11665 -- Ada 95: Normal case
11667 else
11668 Build_CW_Membership (Loc,
11669 Obj_Tag_Node => Obj_Tag,
11670 Typ_Tag_Node =>
11671 New_Reference_To (
11672 Node (First_Elmt (Access_Disp_Table (Full_R_Typ))), Loc),
11673 Related_Nod => N,
11674 New_Node => New_Node);
11676 -- Generate the SCIL node for this class-wide membership test.
11677 -- Done here because the previous call to Build_CW_Membership
11678 -- relocates Obj_Tag.
11680 if Generate_SCIL then
11681 SCIL_Node := Make_SCIL_Membership_Test (Sloc (N));
11682 Set_SCIL_Entity (SCIL_Node, Etype (Right_Type));
11683 Set_SCIL_Tag_Value (SCIL_Node, Obj_Tag);
11684 end if;
11686 Result := New_Node;
11687 end if;
11689 -- Right_Type is not a class-wide type
11691 else
11692 -- No need to check the tag of the object if Right_Typ is abstract
11694 if Is_Abstract_Type (Right_Type) then
11695 Result := New_Reference_To (Standard_False, Loc);
11697 else
11698 Result :=
11699 Make_Op_Eq (Loc,
11700 Left_Opnd => Obj_Tag,
11701 Right_Opnd =>
11702 New_Reference_To
11703 (Node (First_Elmt (Access_Disp_Table (Full_R_Typ))), Loc));
11704 end if;
11705 end if;
11706 end Tagged_Membership;
11708 ------------------------------
11709 -- Unary_Op_Validity_Checks --
11710 ------------------------------
11712 procedure Unary_Op_Validity_Checks (N : Node_Id) is
11713 begin
11714 if Validity_Checks_On and Validity_Check_Operands then
11715 Ensure_Valid (Right_Opnd (N));
11716 end if;
11717 end Unary_Op_Validity_Checks;
11719 end Exp_Ch4;