]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/ada/exp_ch4.adb
2017-10-20 Bob Duff <duff@adacore.com>
[thirdparty/gcc.git] / gcc / ada / exp_ch4.adb
CommitLineData
ee6ba406 1------------------------------------------------------------------------------
2-- --
3-- GNAT COMPILER COMPONENTS --
4-- --
5-- E X P _ C H 4 --
d70d22d5 6-- --
ee6ba406 7-- B o d y --
8-- --
fa65ad5e 9-- Copyright (C) 1992-2017, Free Software Foundation, Inc. --
ee6ba406 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- --
80df182a 13-- ware Foundation; either version 3, or (at your option) any later ver- --
ee6ba406 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 --
80df182a 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. --
ee6ba406 20-- --
21-- GNAT was originally developed by the GNAT team at New York University. --
e78e8c8e 22-- Extensive contributions were provided by Ada Core Technologies Inc. --
ee6ba406 23-- --
24------------------------------------------------------------------------------
25
26with Atree; use Atree;
27with Checks; use Checks;
45045496 28with Debug; use Debug;
ee6ba406 29with Einfo; use Einfo;
30with Elists; use Elists;
31with Errout; use Errout;
32with Exp_Aggr; use Exp_Aggr;
99f2248e 33with Exp_Atag; use Exp_Atag;
d071cd96 34with Exp_Ch2; use Exp_Ch2;
ee6ba406 35with Exp_Ch3; use Exp_Ch3;
e8ccec48 36with Exp_Ch6; use Exp_Ch6;
ee6ba406 37with Exp_Ch7; use Exp_Ch7;
38with Exp_Ch9; use Exp_Ch9;
e8ccec48 39with Exp_Disp; use Exp_Disp;
ee6ba406 40with Exp_Fixd; use Exp_Fixd;
9f294c82 41with Exp_Intr; use Exp_Intr;
ee6ba406 42with Exp_Pakd; use Exp_Pakd;
43with Exp_Tss; use Exp_Tss;
44with Exp_Util; use Exp_Util;
38f5559f 45with Freeze; use Freeze;
ee6ba406 46with Inline; use Inline;
914796b1 47with Namet; use Namet;
ee6ba406 48with Nlists; use Nlists;
49with Nmake; use Nmake;
50with Opt; use Opt;
9a4f36a4 51with Par_SCO; use Par_SCO;
99f2248e 52with Restrict; use Restrict;
53with Rident; use Rident;
ee6ba406 54with Rtsfind; use Rtsfind;
55with Sem; use Sem;
d60c9ff7 56with Sem_Aux; use Sem_Aux;
ee6ba406 57with Sem_Cat; use Sem_Cat;
00f91aef 58with Sem_Ch3; use Sem_Ch3;
ee6ba406 59with Sem_Ch13; use Sem_Ch13;
60with Sem_Eval; use Sem_Eval;
61with Sem_Res; use Sem_Res;
62with Sem_Type; use Sem_Type;
63with Sem_Util; use Sem_Util;
f15731c4 64with Sem_Warn; use Sem_Warn;
ee6ba406 65with Sinfo; use Sinfo;
ee6ba406 66with Snames; use Snames;
67with Stand; use Stand;
5a44b136 68with SCIL_LL; use SCIL_LL;
f15731c4 69with Targparm; use Targparm;
ee6ba406 70with Tbuild; use Tbuild;
71with Ttypes; use Ttypes;
72with Uintp; use Uintp;
73with Urealp; use Urealp;
74with Validsw; use Validsw;
75
76package body Exp_Ch4 is
77
5c99c290 78 -----------------------
79 -- Local Subprograms --
80 -----------------------
ee6ba406 81
82 procedure Binary_Op_Validity_Checks (N : Node_Id);
83 pragma Inline (Binary_Op_Validity_Checks);
84 -- Performs validity checks for a binary operator
85
9dfe12ae 86 procedure Build_Boolean_Array_Proc_Call
87 (N : Node_Id;
88 Op1 : Node_Id;
89 Op2 : Node_Id);
1627db8a 90 -- If a boolean array assignment can be done in place, build call to
9dfe12ae 91 -- corresponding library procedure.
92
914796b1 93 procedure Displace_Allocator_Pointer (N : Node_Id);
94 -- Ada 2005 (AI-251): Subsidiary procedure to Expand_N_Allocator and
95 -- Expand_Allocator_Expression. Allocating class-wide interface objects
96 -- this routine displaces the pointer to the allocated object to reference
97 -- the component referencing the corresponding secondary dispatch table.
98
9dfe12ae 99 procedure Expand_Allocator_Expression (N : Node_Id);
100 -- Subsidiary to Expand_N_Allocator, for the case when the expression
101 -- is a qualified expression or an aggregate.
102
ee6ba406 103 procedure Expand_Array_Comparison (N : Node_Id);
104 -- This routine handles expansion of the comparison operators (N_Op_Lt,
105 -- N_Op_Le, N_Op_Gt, N_Op_Ge) when operating on an array type. The basic
106 -- code for these operators is similar, differing only in the details of
9dfe12ae 107 -- the actual comparison call that is made. Special processing (call a
108 -- run-time routine)
ee6ba406 109
110 function Expand_Array_Equality
111 (Nod : Node_Id;
ee6ba406 112 Lhs : Node_Id;
113 Rhs : Node_Id;
80d4fec4 114 Bodies : List_Id;
115 Typ : Entity_Id) return Node_Id;
ee6ba406 116 -- Expand an array equality into a call to a function implementing this
f1e2dcc5 117 -- equality, and a call to it. Loc is the location for the generated nodes.
118 -- Lhs and Rhs are the array expressions to be compared. Bodies is a list
119 -- on which to attach bodies of local functions that are created in the
120 -- process. It is the responsibility of the caller to insert those bodies
121 -- at the right place. Nod provides the Sloc value for the generated code.
122 -- Normally the types used for the generated equality routine are taken
123 -- from Lhs and Rhs. However, in some situations of generated code, the
124 -- Etype fields of Lhs and Rhs are not set yet. In such cases, Typ supplies
125 -- the type to be used for the formal parameters.
ee6ba406 126
127 procedure Expand_Boolean_Operator (N : Node_Id);
f1e2dcc5 128 -- Common expansion processing for Boolean operators (And, Or, Xor) for the
129 -- case of array type arguments.
ee6ba406 130
2a801d20 131 procedure Expand_Nonbinary_Modular_Op (N : Node_Id);
132 -- When generating C code, convert nonbinary modular arithmetic operations
133 -- into code that relies on the front-end expansion of operator Mod. No
134 -- expansion is performed if N is not a nonbinary modular operand.
61b6f3d9 135
3755dbc5 136 procedure Expand_Short_Circuit_Operator (N : Node_Id);
137 -- Common expansion processing for short-circuit boolean operators
138
d94b5da2 139 procedure Expand_Compare_Minimize_Eliminate_Overflow (N : Node_Id);
21a55437 140 -- Deal with comparison in MINIMIZED/ELIMINATED overflow mode. This is
141 -- where we allow comparison of "out of range" values.
d94b5da2 142
ee6ba406 143 function Expand_Composite_Equality
144 (Nod : Node_Id;
145 Typ : Entity_Id;
146 Lhs : Node_Id;
147 Rhs : Node_Id;
752e1833 148 Bodies : List_Id) return Node_Id;
f1e2dcc5 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
718d0d92 151 -- to attach bodies of local functions that are created in the process. It
152 -- is the responsibility of the caller to insert those bodies at the right
153 -- place. Nod provides the Sloc value for generated code. Lhs and Rhs are
154 -- the left and right sides for the comparison, and Typ is the type of the
155 -- objects to compare.
ee6ba406 156
440ec0be 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.
ee6ba406 162
aa4b16cb 163 procedure Expand_Membership_Minimize_Eliminate_Overflow (N : Node_Id);
21a55437 164 -- N is an N_In membership test mode, with the overflow check mode set to
165 -- MINIMIZED or ELIMINATED, and the type of the left operand is a signed
166 -- integer type. This is a case where top level processing is required to
167 -- handle overflow checks in subtrees.
aa4b16cb 168
ee6ba406 169 procedure Fixup_Universal_Fixed_Operation (N : Node_Id);
f1e2dcc5 170 -- N is a N_Op_Divide or N_Op_Multiply node whose result is universal
171 -- fixed. We do not have such a type at runtime, so the purpose of this
172 -- routine is to find the real type by looking up the tree. We also
173 -- determine if the operation must be rounded.
ee6ba406 174
00f91aef 175 function Has_Inferable_Discriminants (N : Node_Id) return Boolean;
176 -- Ada 2005 (AI-216): A view of an Unchecked_Union object has inferable
177 -- discriminants if it has a constrained nominal type, unless the object
178 -- is a component of an enclosing Unchecked_Union object that is subject
179 -- to a per-object constraint and the enclosing object lacks inferable
180 -- discriminants.
181 --
182 -- An expression of an Unchecked_Union type has inferable discriminants
183 -- if it is either a name of an object with inferable discriminants or a
184 -- qualified expression whose subtype mark denotes a constrained subtype.
185
ee6ba406 186 procedure Insert_Dereference_Action (N : Node_Id);
28ed91d4 187 -- N is an expression whose type is an access. When the type of the
188 -- associated storage pool is derived from Checked_Pool, generate a
189 -- call to the 'Dereference' primitive operation.
ee6ba406 190
191 function Make_Array_Comparison_Op
752e1833 192 (Typ : Entity_Id;
193 Nod : Node_Id) return Node_Id;
f1e2dcc5 194 -- Comparisons between arrays are expanded in line. This function produces
195 -- the body of the implementation of (a > b), where a and b are one-
196 -- dimensional arrays of some discrete type. The original node is then
197 -- expanded into the appropriate call to this function. Nod provides the
198 -- Sloc value for the generated code.
ee6ba406 199
200 function Make_Boolean_Array_Op
752e1833 201 (Typ : Entity_Id;
202 N : Node_Id) return Node_Id;
f1e2dcc5 203 -- Boolean operations on boolean arrays are expanded in line. This function
204 -- produce the body for the node N, which is (a and b), (a or b), or (a xor
205 -- b). It is used only the normal case and not the packed case. The type
206 -- involved, Typ, is the Boolean array type, and the logical operations in
207 -- the body are simple boolean operations. Note that Typ is always a
208 -- constrained type (the caller has ensured this by using
209 -- Convert_To_Actual_Subtype if necessary).
ee6ba406 210
f32c377d 211 function Minimized_Eliminated_Overflow_Check (N : Node_Id) return Boolean;
0df9d43f 212 -- For signed arithmetic operations when the current overflow mode is
213 -- MINIMIZED or ELIMINATED, we must call Apply_Arithmetic_Overflow_Checks
214 -- as the first thing we do. We then return. We count on the recursive
215 -- apparatus for overflow checks to call us back with an equivalent
216 -- operation that is in CHECKED mode, avoiding a recursive entry into this
217 -- routine, and that is when we will proceed with the expansion of the
218 -- operator (e.g. converting X+0 to X, or X**2 to X*X). We cannot do
219 -- these optimizations without first making this check, since there may be
220 -- operands further down the tree that are relying on the recursive calls
221 -- triggered by the top level nodes to properly process overflow checking
222 -- and remaining expansion on these nodes. Note that this call back may be
223 -- skipped if the operation is done in Bignum mode but that's fine, since
224 -- the Bignum call takes care of everything.
f32c377d 225
4ecb1318 226 procedure Optimize_Length_Comparison (N : Node_Id);
227 -- Given an expression, if it is of the form X'Length op N (or the other
228 -- way round), where N is known at compile time to be 0 or 1, and X is a
229 -- simple entity, and op is a comparison operator, optimizes it into a
230 -- comparison of First and Last.
231
29d958a7 232 procedure Process_If_Case_Statements (N : Node_Id; Stmts : List_Id);
233 -- Inspect and process statement list Stmt of if or case expression N for
545d732b 234 -- transient objects. If such objects are found, the routine generates code
235 -- to clean them up when the context of the expression is evaluated.
236
237 procedure Process_Transient_In_Expression
238 (Obj_Decl : Node_Id;
239 Expr : Node_Id;
240 Stmts : List_Id);
29d958a7 241 -- Subsidiary routine to the expansion of expression_with_actions, if and
242 -- case expressions. Generate all necessary code to finalize a transient
545d732b 243 -- object when the enclosing context is elaborated or evaluated. Obj_Decl
244 -- denotes the declaration of the transient object, which is usually the
245 -- result of a controlled function call. Expr denotes the expression with
246 -- actions, if expression, or case expression node. Stmts denotes the
247 -- statement list which contains Decl, either at the top level or within a
248 -- nested construct.
1f35ddbe 249
ee6ba406 250 procedure Rewrite_Comparison (N : Node_Id);
e8ccec48 251 -- If N is the node for a comparison whose outcome can be determined at
35c57fc7 252 -- compile time, then the node N can be rewritten with True or False. If
253 -- the outcome cannot be determined at compile time, the call has no
254 -- effect. If N is a type conversion, then this processing is applied to
255 -- its expression. If N is neither comparison nor a type conversion, the
256 -- call has no effect.
ee6ba406 257
3feedf2a 258 procedure Tagged_Membership
259 (N : Node_Id;
260 SCIL_Node : out Node_Id;
261 Result : out Node_Id);
ee6ba406 262 -- Construct the expression corresponding to the tagged membership test.
263 -- Deals with a second operand being (or not) a class-wide type.
264
9dfe12ae 265 function Safe_In_Place_Array_Op
752e1833 266 (Lhs : Node_Id;
267 Op1 : Node_Id;
268 Op2 : Node_Id) return Boolean;
f1e2dcc5 269 -- In the context of an assignment, where the right-hand side is a boolean
270 -- operation on arrays, check whether operation can be performed in place.
9dfe12ae 271
ee6ba406 272 procedure Unary_Op_Validity_Checks (N : Node_Id);
273 pragma Inline (Unary_Op_Validity_Checks);
274 -- Performs validity checks for a unary operator
275
276 -------------------------------
277 -- Binary_Op_Validity_Checks --
278 -------------------------------
279
280 procedure Binary_Op_Validity_Checks (N : Node_Id) is
281 begin
282 if Validity_Checks_On and Validity_Check_Operands then
283 Ensure_Valid (Left_Opnd (N));
284 Ensure_Valid (Right_Opnd (N));
285 end if;
286 end Binary_Op_Validity_Checks;
287
9dfe12ae 288 ------------------------------------
289 -- Build_Boolean_Array_Proc_Call --
290 ------------------------------------
291
292 procedure Build_Boolean_Array_Proc_Call
293 (N : Node_Id;
294 Op1 : Node_Id;
295 Op2 : Node_Id)
296 is
297 Loc : constant Source_Ptr := Sloc (N);
298 Kind : constant Node_Kind := Nkind (Expression (N));
299 Target : constant Node_Id :=
300 Make_Attribute_Reference (Loc,
301 Prefix => Name (N),
302 Attribute_Name => Name_Address);
303
f235fede 304 Arg1 : Node_Id := Op1;
9dfe12ae 305 Arg2 : Node_Id := Op2;
306 Call_Node : Node_Id;
307 Proc_Name : Entity_Id;
308
309 begin
310 if Kind = N_Op_Not then
311 if Nkind (Op1) in N_Binary_Op then
312
f84d3d59 313 -- Use negated version of the binary operators
9dfe12ae 314
315 if Nkind (Op1) = N_Op_And then
316 Proc_Name := RTE (RE_Vector_Nand);
317
318 elsif Nkind (Op1) = N_Op_Or then
319 Proc_Name := RTE (RE_Vector_Nor);
320
321 else pragma Assert (Nkind (Op1) = N_Op_Xor);
322 Proc_Name := RTE (RE_Vector_Xor);
323 end if;
324
325 Call_Node :=
326 Make_Procedure_Call_Statement (Loc,
327 Name => New_Occurrence_Of (Proc_Name, Loc),
328
329 Parameter_Associations => New_List (
330 Target,
331 Make_Attribute_Reference (Loc,
332 Prefix => Left_Opnd (Op1),
333 Attribute_Name => Name_Address),
334
335 Make_Attribute_Reference (Loc,
336 Prefix => Right_Opnd (Op1),
337 Attribute_Name => Name_Address),
338
339 Make_Attribute_Reference (Loc,
340 Prefix => Left_Opnd (Op1),
341 Attribute_Name => Name_Length)));
342
343 else
344 Proc_Name := RTE (RE_Vector_Not);
345
346 Call_Node :=
347 Make_Procedure_Call_Statement (Loc,
348 Name => New_Occurrence_Of (Proc_Name, Loc),
349 Parameter_Associations => New_List (
350 Target,
351
352 Make_Attribute_Reference (Loc,
353 Prefix => Op1,
354 Attribute_Name => Name_Address),
355
356 Make_Attribute_Reference (Loc,
357 Prefix => Op1,
358 Attribute_Name => Name_Length)));
359 end if;
360
361 else
362 -- We use the following equivalences:
363
364 -- (not X) or (not Y) = not (X and Y) = Nand (X, Y)
365 -- (not X) and (not Y) = not (X or Y) = Nor (X, Y)
366 -- (not X) xor (not Y) = X xor Y
367 -- X xor (not Y) = not (X xor Y) = Nxor (X, Y)
368
369 if Nkind (Op1) = N_Op_Not then
f235fede 370 Arg1 := Right_Opnd (Op1);
371 Arg2 := Right_Opnd (Op2);
6f0d10f7 372
9dfe12ae 373 if Kind = N_Op_And then
374 Proc_Name := RTE (RE_Vector_Nor);
9dfe12ae 375 elsif Kind = N_Op_Or then
376 Proc_Name := RTE (RE_Vector_Nand);
9dfe12ae 377 else
378 Proc_Name := RTE (RE_Vector_Xor);
379 end if;
380
381 else
382 if Kind = N_Op_And then
383 Proc_Name := RTE (RE_Vector_And);
9dfe12ae 384 elsif Kind = N_Op_Or then
385 Proc_Name := RTE (RE_Vector_Or);
9dfe12ae 386 elsif Nkind (Op2) = N_Op_Not then
387 Proc_Name := RTE (RE_Vector_Nxor);
388 Arg2 := Right_Opnd (Op2);
9dfe12ae 389 else
390 Proc_Name := RTE (RE_Vector_Xor);
391 end if;
392 end if;
393
394 Call_Node :=
395 Make_Procedure_Call_Statement (Loc,
396 Name => New_Occurrence_Of (Proc_Name, Loc),
397 Parameter_Associations => New_List (
398 Target,
6b73a73b 399 Make_Attribute_Reference (Loc,
400 Prefix => Arg1,
401 Attribute_Name => Name_Address),
402 Make_Attribute_Reference (Loc,
403 Prefix => Arg2,
404 Attribute_Name => Name_Address),
405 Make_Attribute_Reference (Loc,
615f465e 406 Prefix => Arg1,
6b73a73b 407 Attribute_Name => Name_Length)));
9dfe12ae 408 end if;
409
410 Rewrite (N, Call_Node);
411 Analyze (N);
412
413 exception
414 when RE_Not_Available =>
415 return;
416 end Build_Boolean_Array_Proc_Call;
417
914796b1 418 --------------------------------
419 -- Displace_Allocator_Pointer --
420 --------------------------------
421
422 procedure Displace_Allocator_Pointer (N : Node_Id) is
423 Loc : constant Source_Ptr := Sloc (N);
424 Orig_Node : constant Node_Id := Original_Node (N);
425 Dtyp : Entity_Id;
426 Etyp : Entity_Id;
427 PtrT : Entity_Id;
428
429 begin
1627db8a 430 -- Do nothing in case of VM targets: the virtual machine will handle
431 -- interfaces directly.
432
662256db 433 if not Tagged_Type_Expansion then
1627db8a 434 return;
435 end if;
436
914796b1 437 pragma Assert (Nkind (N) = N_Identifier
438 and then Nkind (Orig_Node) = N_Allocator);
439
440 PtrT := Etype (Orig_Node);
b2776257 441 Dtyp := Available_View (Designated_Type (PtrT));
914796b1 442 Etyp := Etype (Expression (Orig_Node));
443
6f0d10f7 444 if Is_Class_Wide_Type (Dtyp) and then Is_Interface (Dtyp) then
445
914796b1 446 -- If the type of the allocator expression is not an interface type
447 -- we can generate code to reference the record component containing
448 -- the pointer to the secondary dispatch table.
449
450 if not Is_Interface (Etyp) then
451 declare
452 Saved_Typ : constant Entity_Id := Etype (Orig_Node);
453
454 begin
455 -- 1) Get access to the allocated object
456
457 Rewrite (N,
d306cbee 458 Make_Explicit_Dereference (Loc, Relocate_Node (N)));
914796b1 459 Set_Etype (N, Etyp);
460 Set_Analyzed (N);
461
462 -- 2) Add the conversion to displace the pointer to reference
463 -- the secondary dispatch table.
464
465 Rewrite (N, Convert_To (Dtyp, Relocate_Node (N)));
466 Analyze_And_Resolve (N, Dtyp);
467
468 -- 3) The 'access to the secondary dispatch table will be used
469 -- as the value returned by the allocator.
470
471 Rewrite (N,
472 Make_Attribute_Reference (Loc,
473 Prefix => Relocate_Node (N),
474 Attribute_Name => Name_Access));
475 Set_Etype (N, Saved_Typ);
476 Set_Analyzed (N);
477 end;
478
479 -- If the type of the allocator expression is an interface type we
480 -- generate a run-time call to displace "this" to reference the
481 -- component containing the pointer to the secondary dispatch table
482 -- or else raise Constraint_Error if the actual object does not
6f0d10f7 483 -- implement the target interface. This case corresponds to the
914796b1 484 -- following example:
485
36b938a3 486 -- function Op (Obj : Iface_1'Class) return access Iface_2'Class is
914796b1 487 -- begin
488 -- return new Iface_2'Class'(Obj);
489 -- end Op;
490
491 else
492 Rewrite (N,
493 Unchecked_Convert_To (PtrT,
494 Make_Function_Call (Loc,
83c6c069 495 Name => New_Occurrence_Of (RTE (RE_Displace), Loc),
914796b1 496 Parameter_Associations => New_List (
497 Unchecked_Convert_To (RTE (RE_Address),
498 Relocate_Node (N)),
499
500 New_Occurrence_Of
501 (Elists.Node
502 (First_Elmt
503 (Access_Disp_Table (Etype (Base_Type (Dtyp))))),
504 Loc)))));
505 Analyze_And_Resolve (N, PtrT);
506 end if;
507 end if;
508 end Displace_Allocator_Pointer;
509
9dfe12ae 510 ---------------------------------
511 -- Expand_Allocator_Expression --
512 ---------------------------------
513
514 procedure Expand_Allocator_Expression (N : Node_Id) is
38f5559f 515 Loc : constant Source_Ptr := Sloc (N);
516 Exp : constant Node_Id := Expression (Expression (N));
38f5559f 517 PtrT : constant Entity_Id := Etype (N);
518 DesigT : constant Entity_Id := Designated_Type (PtrT);
914796b1 519
520 procedure Apply_Accessibility_Check
521 (Ref : Node_Id;
522 Built_In_Place : Boolean := False);
523 -- Ada 2005 (AI-344): For an allocator with a class-wide designated
f1e2dcc5 524 -- type, generate an accessibility check to verify that the level of the
525 -- type of the created object is not deeper than the level of the access
1630f2a9 526 -- type. If the type of the qualified expression is class-wide, then
f1e2dcc5 527 -- always generate the check (except in the case where it is known to be
528 -- unnecessary, see comment below). Otherwise, only generate the check
529 -- if the level of the qualified expression type is statically deeper
530 -- than the access type.
531 --
532 -- Although the static accessibility will generally have been performed
533 -- as a legality check, it won't have been done in cases where the
534 -- allocator appears in generic body, so a run-time check is needed in
535 -- general. One special case is when the access type is declared in the
536 -- same scope as the class-wide allocator, in which case the check can
537 -- never fail, so it need not be generated.
538 --
539 -- As an open issue, there seem to be cases where the static level
540 -- associated with the class-wide object's underlying type is not
541 -- sufficient to perform the proper accessibility check, such as for
542 -- allocators in nested subprograms or accept statements initialized by
543 -- class-wide formals when the actual originates outside at a deeper
544 -- static level. The nested subprogram case might require passing
545 -- accessibility levels along with class-wide parameters, and the task
546 -- case seems to be an actual gap in the language rules that needs to
547 -- be fixed by the ARG. ???
914796b1 548
549 -------------------------------
550 -- Apply_Accessibility_Check --
551 -------------------------------
552
553 procedure Apply_Accessibility_Check
554 (Ref : Node_Id;
555 Built_In_Place : Boolean := False)
556 is
36053850 557 Pool_Id : constant Entity_Id := Associated_Storage_Pool (PtrT);
558 Cond : Node_Id;
559 Fin_Call : Node_Id;
560 Free_Stmt : Node_Id;
561 Obj_Ref : Node_Id;
562 Stmts : List_Id;
914796b1 563
564 begin
de54c5ab 565 if Ada_Version >= Ada_2005
914796b1 566 and then Is_Class_Wide_Type (DesigT)
36ac5fbb 567 and then Tagged_Type_Expansion
fafc6b97 568 and then not Scope_Suppress.Suppress (Accessibility_Check)
914796b1 569 and then
570 (Type_Access_Level (Etype (Exp)) > Type_Access_Level (PtrT)
571 or else
572 (Is_Class_Wide_Type (Etype (Exp))
573 and then Scope (PtrT) /= Current_Scope))
574 then
44e15e2b 575 -- If the allocator was built in place, Ref is already a reference
914796b1 576 -- to the access object initialized to the result of the allocator
44e15e2b 577 -- (see Exp_Ch6.Make_Build_In_Place_Call_In_Allocator). We call
578 -- Remove_Side_Effects for cases where the build-in-place call may
579 -- still be the prefix of the reference (to avoid generating
580 -- duplicate calls). Otherwise, it is the entity associated with
581 -- the object containing the address of the allocated object.
914796b1 582
583 if Built_In_Place then
44e15e2b 584 Remove_Side_Effects (Ref);
36053850 585 Obj_Ref := New_Copy_Tree (Ref);
914796b1 586 else
83c6c069 587 Obj_Ref := New_Occurrence_Of (Ref, Loc);
1630f2a9 588 end if;
589
a7ed0410 590 -- For access to interface types we must generate code to displace
591 -- the pointer to the base of the object since the subsequent code
592 -- references components located in the TSD of the object (which
593 -- is associated with the primary dispatch table --see a-tags.ads)
594 -- and also generates code invoking Free, which requires also a
595 -- reference to the base of the unallocated object.
596
82b93248 597 if Is_Interface (DesigT) and then Tagged_Type_Expansion then
a7ed0410 598 Obj_Ref :=
599 Unchecked_Convert_To (Etype (Obj_Ref),
600 Make_Function_Call (Loc,
c4369687 601 Name =>
602 New_Occurrence_Of (RTE (RE_Base_Address), Loc),
a7ed0410 603 Parameter_Associations => New_List (
604 Unchecked_Convert_To (RTE (RE_Address),
605 New_Copy_Tree (Obj_Ref)))));
606 end if;
607
1630f2a9 608 -- Step 1: Create the object clean up code
609
610 Stmts := New_List;
611
36053850 612 -- Deallocate the object if the accessibility check fails. This
613 -- is done only on targets or profiles that support deallocation.
614
615 -- Free (Obj_Ref);
616
617 if RTE_Available (RE_Free) then
618 Free_Stmt := Make_Free_Statement (Loc, New_Copy_Tree (Obj_Ref));
619 Set_Storage_Pool (Free_Stmt, Pool_Id);
620
621 Append_To (Stmts, Free_Stmt);
622
623 -- The target or profile cannot deallocate objects
624
625 else
626 Free_Stmt := Empty;
627 end if;
628
629 -- Finalize the object if applicable. Generate:
e3796fa2 630
631 -- [Deep_]Finalize (Obj_Ref.all);
632
ceec4f7c 633 if Needs_Finalization (DesigT) then
36053850 634 Fin_Call :=
82b93248 635 Make_Final_Call
636 (Obj_Ref =>
637 Make_Explicit_Dereference (Loc, New_Copy (Obj_Ref)),
638 Typ => DesigT);
36053850 639
fe696bd7 640 -- Guard against a missing [Deep_]Finalize when the designated
641 -- type was not properly frozen.
642
643 if No (Fin_Call) then
644 Fin_Call := Make_Null_Statement (Loc);
645 end if;
646
36053850 647 -- When the target or profile supports deallocation, wrap the
648 -- finalization call in a block to ensure proper deallocation
649 -- even if finalization fails. Generate:
650
651 -- begin
652 -- <Fin_Call>
653 -- exception
654 -- when others =>
655 -- <Free_Stmt>
656 -- raise;
657 -- end;
658
659 if Present (Free_Stmt) then
660 Fin_Call :=
661 Make_Block_Statement (Loc,
662 Handled_Statement_Sequence =>
663 Make_Handled_Sequence_Of_Statements (Loc,
664 Statements => New_List (Fin_Call),
665
666 Exception_Handlers => New_List (
667 Make_Exception_Handler (Loc,
668 Exception_Choices => New_List (
669 Make_Others_Choice (Loc)),
36053850 670 Statements => New_List (
671 New_Copy_Tree (Free_Stmt),
672 Make_Raise_Statement (Loc))))));
673 end if;
674
675 Prepend_To (Stmts, Fin_Call);
79500ea0 676 end if;
677
1630f2a9 678 -- Signal the accessibility failure through a Program_Error
679
680 Append_To (Stmts,
681 Make_Raise_Program_Error (Loc,
83c6c069 682 Condition => New_Occurrence_Of (Standard_True, Loc),
1630f2a9 683 Reason => PE_Accessibility_Check_Failed));
684
685 -- Step 2: Create the accessibility comparison
686
687 -- Generate:
688 -- Ref'Tag
689
a7ed0410 690 Obj_Ref :=
691 Make_Attribute_Reference (Loc,
692 Prefix => Obj_Ref,
693 Attribute_Name => Name_Tag);
79500ea0 694
1630f2a9 695 -- For tagged types, determine the accessibility level by looking
696 -- at the type specific data of the dispatch table. Generate:
697
698 -- Type_Specific_Data (Address (Ref'Tag)).Access_Level
699
79500ea0 700 if Tagged_Type_Expansion then
1630f2a9 701 Cond := Build_Get_Access_Level (Loc, Obj_Ref);
79500ea0 702
1630f2a9 703 -- Use a runtime call to determine the accessibility level when
704 -- compiling on virtual machine targets. Generate:
79500ea0 705
1630f2a9 706 -- Get_Access_Level (Ref'Tag)
79500ea0 707
708 else
1630f2a9 709 Cond :=
710 Make_Function_Call (Loc,
711 Name =>
83c6c069 712 New_Occurrence_Of (RTE (RE_Get_Access_Level), Loc),
1630f2a9 713 Parameter_Associations => New_List (Obj_Ref));
914796b1 714 end if;
715
1630f2a9 716 Cond :=
717 Make_Op_Gt (Loc,
718 Left_Opnd => Cond,
719 Right_Opnd =>
720 Make_Integer_Literal (Loc, Type_Access_Level (PtrT)));
721
722 -- Due to the complexity and side effects of the check, utilize an
723 -- if statement instead of the regular Program_Error circuitry.
724
914796b1 725 Insert_Action (N,
5c72df40 726 Make_Implicit_If_Statement (N,
1630f2a9 727 Condition => Cond,
728 Then_Statements => Stmts));
914796b1 729 end if;
730 end Apply_Accessibility_Check;
731
732 -- Local variables
733
bb3b440a 734 Aggr_In_Place : constant Boolean := Is_Delayed_Aggregate (Exp);
735 Indic : constant Node_Id := Subtype_Mark (Expression (N));
736 T : constant Entity_Id := Entity (Indic);
fe696bd7 737 Adj_Call : Node_Id;
bb3b440a 738 Node : Node_Id;
739 Tag_Assign : Node_Id;
740 Temp : Entity_Id;
741 Temp_Decl : Node_Id;
9dfe12ae 742
35c57fc7 743 TagT : Entity_Id := Empty;
744 -- Type used as source for tag assignment
745
746 TagR : Node_Id := Empty;
747 -- Target reference for tag assignment
748
914796b1 749 -- Start of processing for Expand_Allocator_Expression
750
9dfe12ae 751 begin
693dfc0f 752 -- Handle call to C++ constructor
753
754 if Is_CPP_Constructor_Call (Exp) then
755 Make_CPP_Constructor_Call_In_Allocator
756 (Allocator => N,
757 Function_Call => Exp);
758 return;
759 end if;
760
b2df433c 761 -- In the case of an Ada 2012 allocator whose initial value comes from a
302f6546 762 -- function call, pass "the accessibility level determined by the point
763 -- of call" (AI05-0234) to the function. Conceptually, this belongs in
764 -- Expand_Call but it couldn't be done there (because the Etype of the
765 -- allocator wasn't set then) so we generate the parameter here. See
766 -- the Boolean variable Defer in (a block within) Expand_Call.
767
768 if Ada_Version >= Ada_2012 and then Nkind (Exp) = N_Function_Call then
769 declare
770 Subp : Entity_Id;
771
772 begin
773 if Nkind (Name (Exp)) = N_Explicit_Dereference then
774 Subp := Designated_Type (Etype (Prefix (Name (Exp))));
775 else
776 Subp := Entity (Name (Exp));
777 end if;
778
0c6b5982 779 Subp := Ultimate_Alias (Subp);
780
302f6546 781 if Present (Extra_Accessibility_Of_Result (Subp)) then
782 Add_Extra_Actual_To_Call
783 (Subprogram_Call => Exp,
784 Extra_Formal => Extra_Accessibility_Of_Result (Subp),
785 Extra_Actual => Dynamic_Accessibility_Level (PtrT));
786 end if;
787 end;
788 end if;
789
aa4b16cb 790 -- Case of tagged type or type requiring finalization
302f6546 791
792 if Is_Tagged_Type (T) or else Needs_Finalization (T) then
77378d51 793
f1e2dcc5 794 -- Ada 2005 (AI-318-02): If the initialization expression is a call
795 -- to a build-in-place function, then access to the allocated object
cd24e497 796 -- must be passed to the function.
e8ccec48 797
cd24e497 798 if Is_Build_In_Place_Function_Call (Exp) then
e8ccec48 799 Make_Build_In_Place_Call_In_Allocator (N, Exp);
914796b1 800 Apply_Accessibility_Check (N, Built_In_Place => True);
801 return;
8b3a98b2 802
803 -- Ada 2005 (AI-318-02): Specialization of the previous case for
804 -- expressions containing a build-in-place function call whose
805 -- returned object covers interface types, and Expr has calls to
806 -- Ada.Tags.Displace to displace the pointer to the returned build-
807 -- in-place object to reference the secondary dispatch table of a
808 -- covered interface type.
809
cd24e497 810 elsif Present (Unqual_BIP_Iface_Function_Call (Exp)) then
8b3a98b2 811 Make_Build_In_Place_Iface_Call_In_Allocator (N, Exp);
812 Apply_Accessibility_Check (N, Built_In_Place => True);
813 return;
e8ccec48 814 end if;
815
53c179ea 816 -- Actions inserted before:
817 -- Temp : constant ptr_T := new T'(Expression);
818 -- Temp._tag = T'tag; -- when not class-wide
819 -- [Deep_]Adjust (Temp.all);
9dfe12ae 820
53c179ea 821 -- We analyze by hand the new internal allocator to avoid any
8d11916f 822 -- recursion and inappropriate call to Initialize.
5329ca64 823
e8ccec48 824 -- We don't want to remove side effects when the expression must be
825 -- built in place. In the case of a build-in-place function call,
826 -- that could lead to a duplication of the call, which was already
827 -- substituted for the allocator.
828
914796b1 829 if not Aggr_In_Place then
9dfe12ae 830 Remove_Side_Effects (Exp);
831 end if;
832
55578aa3 833 Temp := Make_Temporary (Loc, 'P', N);
9dfe12ae 834
835 -- For a class wide allocation generate the following code:
836
837 -- type Equiv_Record is record ... end record;
838 -- implicit subtype CW is <Class_Wide_Subytpe>;
839 -- temp : PtrT := new CW'(CW!(expr));
840
841 if Is_Class_Wide_Type (T) then
842 Expand_Subtype_From_Expr (Empty, T, Indic, Exp);
843
914796b1 844 -- Ada 2005 (AI-251): If the expression is a class-wide interface
845 -- object we generate code to move up "this" to reference the
846 -- base of the object before allocating the new object.
847
848 -- Note that Exp'Address is recursively expanded into a call
849 -- to Base_Address (Exp.Tag)
850
851 if Is_Class_Wide_Type (Etype (Exp))
852 and then Is_Interface (Etype (Exp))
662256db 853 and then Tagged_Type_Expansion
914796b1 854 then
855 Set_Expression
856 (Expression (N),
857 Unchecked_Convert_To (Entity (Indic),
858 Make_Explicit_Dereference (Loc,
859 Unchecked_Convert_To (RTE (RE_Tag_Ptr),
860 Make_Attribute_Reference (Loc,
861 Prefix => Exp,
862 Attribute_Name => Name_Address)))));
914796b1 863 else
864 Set_Expression
865 (Expression (N),
866 Unchecked_Convert_To (Entity (Indic), Exp));
867 end if;
9dfe12ae 868
869 Analyze_And_Resolve (Expression (N), Entity (Indic));
870 end if;
871
bb3b440a 872 -- Processing for allocators returning non-interface types
9dfe12ae 873
914796b1 874 if not Is_Interface (Directly_Designated_Type (PtrT)) then
875 if Aggr_In_Place then
bb3b440a 876 Temp_Decl :=
914796b1 877 Make_Object_Declaration (Loc,
878 Defining_Identifier => Temp,
83c6c069 879 Object_Definition => New_Occurrence_Of (PtrT, Loc),
914796b1 880 Expression =>
881 Make_Allocator (Loc,
bb3b440a 882 Expression =>
83c6c069 883 New_Occurrence_Of (Etype (Exp), Loc)));
9dfe12ae 884
19b4517d 885 -- Copy the Comes_From_Source flag for the allocator we just
886 -- built, since logically this allocator is a replacement of
887 -- the original allocator node. This is for proper handling of
888 -- restriction No_Implicit_Heap_Allocations.
889
914796b1 890 Set_Comes_From_Source
bb3b440a 891 (Expression (Temp_Decl), Comes_From_Source (N));
9dfe12ae 892
bb3b440a 893 Set_No_Initialization (Expression (Temp_Decl));
894 Insert_Action (N, Temp_Decl);
9dfe12ae 895
53c179ea 896 Build_Allocate_Deallocate_Proc (Temp_Decl, True);
bb3b440a 897 Convert_Aggr_In_Allocator (N, Temp_Decl, Exp);
19b4517d 898
914796b1 899 else
900 Node := Relocate_Node (N);
901 Set_Analyzed (Node);
bb3b440a 902
903 Temp_Decl :=
914796b1 904 Make_Object_Declaration (Loc,
905 Defining_Identifier => Temp,
906 Constant_Present => True,
83c6c069 907 Object_Definition => New_Occurrence_Of (PtrT, Loc),
bb3b440a 908 Expression => Node);
909
910 Insert_Action (N, Temp_Decl);
53c179ea 911 Build_Allocate_Deallocate_Proc (Temp_Decl, True);
9dfe12ae 912 end if;
913
914796b1 914 -- Ada 2005 (AI-251): Handle allocators whose designated type is an
915 -- interface type. In this case we use the type of the qualified
916 -- expression to allocate the object.
917
9dfe12ae 918 else
914796b1 919 declare
46eb6933 920 Def_Id : constant Entity_Id := Make_Temporary (Loc, 'T');
914796b1 921 New_Decl : Node_Id;
9dfe12ae 922
914796b1 923 begin
924 New_Decl :=
925 Make_Full_Type_Declaration (Loc,
926 Defining_Identifier => Def_Id,
82b93248 927 Type_Definition =>
914796b1 928 Make_Access_To_Object_Definition (Loc,
929 All_Present => True,
930 Null_Exclusion_Present => False,
22631b41 931 Constant_Present =>
932 Is_Access_Constant (Etype (N)),
914796b1 933 Subtype_Indication =>
83c6c069 934 New_Occurrence_Of (Etype (Exp), Loc)));
914796b1 935
936 Insert_Action (N, New_Decl);
937
bb3b440a 938 -- Inherit the allocation-related attributes from the original
939 -- access type.
914796b1 940
ba502e2b 941 Set_Finalization_Master
942 (Def_Id, Finalization_Master (PtrT));
bb3b440a 943
ba502e2b 944 Set_Associated_Storage_Pool
945 (Def_Id, Associated_Storage_Pool (PtrT));
aad6babd 946
914796b1 947 -- Declare the object using the previous type declaration
948
949 if Aggr_In_Place then
bb3b440a 950 Temp_Decl :=
914796b1 951 Make_Object_Declaration (Loc,
952 Defining_Identifier => Temp,
83c6c069 953 Object_Definition => New_Occurrence_Of (Def_Id, Loc),
914796b1 954 Expression =>
955 Make_Allocator (Loc,
83c6c069 956 New_Occurrence_Of (Etype (Exp), Loc)));
914796b1 957
19b4517d 958 -- Copy the Comes_From_Source flag for the allocator we just
959 -- built, since logically this allocator is a replacement of
960 -- the original allocator node. This is for proper handling
961 -- of restriction No_Implicit_Heap_Allocations.
962
914796b1 963 Set_Comes_From_Source
bb3b440a 964 (Expression (Temp_Decl), Comes_From_Source (N));
914796b1 965
bb3b440a 966 Set_No_Initialization (Expression (Temp_Decl));
967 Insert_Action (N, Temp_Decl);
914796b1 968
53c179ea 969 Build_Allocate_Deallocate_Proc (Temp_Decl, True);
bb3b440a 970 Convert_Aggr_In_Allocator (N, Temp_Decl, Exp);
914796b1 971
914796b1 972 else
973 Node := Relocate_Node (N);
974 Set_Analyzed (Node);
bb3b440a 975
976 Temp_Decl :=
914796b1 977 Make_Object_Declaration (Loc,
978 Defining_Identifier => Temp,
979 Constant_Present => True,
83c6c069 980 Object_Definition => New_Occurrence_Of (Def_Id, Loc),
bb3b440a 981 Expression => Node);
982
983 Insert_Action (N, Temp_Decl);
53c179ea 984 Build_Allocate_Deallocate_Proc (Temp_Decl, True);
914796b1 985 end if;
986
987 -- Generate an additional object containing the address of the
988 -- returned object. The type of this second object declaration
f1e2dcc5 989 -- is the correct type required for the common processing that
990 -- is still performed by this subprogram. The displacement of
991 -- this pointer to reference the component associated with the
992 -- interface type will be done at the end of common processing.
914796b1 993
994 New_Decl :=
995 Make_Object_Declaration (Loc,
5e8ac397 996 Defining_Identifier => Make_Temporary (Loc, 'P'),
83c6c069 997 Object_Definition => New_Occurrence_Of (PtrT, Loc),
5e8ac397 998 Expression =>
bb3b440a 999 Unchecked_Convert_To (PtrT,
83c6c069 1000 New_Occurrence_Of (Temp, Loc)));
914796b1 1001
1002 Insert_Action (N, New_Decl);
1003
bb3b440a 1004 Temp_Decl := New_Decl;
1005 Temp := Defining_Identifier (New_Decl);
914796b1 1006 end;
aad6babd 1007 end if;
1008
914796b1 1009 -- Generate the tag assignment
1010
36ac5fbb 1011 -- Suppress the tag assignment for VM targets because VM tags are
914796b1 1012 -- represented implicitly in objects.
1013
662256db 1014 if not Tagged_Type_Expansion then
914796b1 1015 null;
9dfe12ae 1016
914796b1 1017 -- Ada 2005 (AI-251): Suppress the tag assignment with class-wide
1018 -- interface objects because in this case the tag does not change.
35c57fc7 1019
914796b1 1020 elsif Is_Interface (Directly_Designated_Type (Etype (N))) then
1021 pragma Assert (Is_Class_Wide_Type
1022 (Directly_Designated_Type (Etype (N))));
35c57fc7 1023 null;
1024
1025 elsif Is_Tagged_Type (T) and then not Is_Class_Wide_Type (T) then
1026 TagT := T;
83c6c069 1027 TagR := New_Occurrence_Of (Temp, Loc);
35c57fc7 1028
1029 elsif Is_Private_Type (T)
1030 and then Is_Tagged_Type (Underlying_Type (T))
9dfe12ae 1031 then
35c57fc7 1032 TagT := Underlying_Type (T);
ea150575 1033 TagR :=
1034 Unchecked_Convert_To (Underlying_Type (T),
1035 Make_Explicit_Dereference (Loc,
83c6c069 1036 Prefix => New_Occurrence_Of (Temp, Loc)));
35c57fc7 1037 end if;
1038
1039 if Present (TagT) then
23197014 1040 declare
1041 Full_T : constant Entity_Id := Underlying_Type (TagT);
83c6c069 1042
23197014 1043 begin
1044 Tag_Assign :=
1045 Make_Assignment_Statement (Loc,
82b93248 1046 Name =>
23197014 1047 Make_Selected_Component (Loc,
82b93248 1048 Prefix => TagR,
23197014 1049 Selector_Name =>
83c6c069 1050 New_Occurrence_Of
1051 (First_Tag_Component (Full_T), Loc)),
1052
23197014 1053 Expression =>
1054 Unchecked_Convert_To (RTE (RE_Tag),
83c6c069 1055 New_Occurrence_Of
23197014 1056 (Elists.Node
1057 (First_Elmt (Access_Disp_Table (Full_T))), Loc)));
1058 end;
9dfe12ae 1059
1060 -- The previous assignment has to be done in any case
1061
1062 Set_Assignment_OK (Name (Tag_Assign));
1063 Insert_Action (N, Tag_Assign);
9dfe12ae 1064 end if;
1065
9193c101 1066 -- Generate an Adjust call if the object will be moved. In Ada 2005,
1067 -- the object may be inherently limited, in which case there is no
1068 -- Adjust procedure, and the object is built in place. In Ada 95, the
1069 -- object can be limited but not inherently limited if this allocator
1070 -- came from a return statement (we're allocating the result on the
1071 -- secondary stack). In that case, the object will be moved, so we do
cd1a4900 1072 -- want to Adjust. However, if it's a nonlimited build-in-place
1073 -- function call, Adjust is not wanted.
9193c101 1074
1075 if Needs_Finalization (DesigT)
1076 and then Needs_Finalization (T)
1077 and then not Aggr_In_Place
1078 and then not Is_Limited_View (T)
cd1a4900 1079 and then not Alloc_For_BIP_Return (N)
1080 and then not Is_Build_In_Place_Function_Call (Expression (N))
9193c101 1081 then
1082 -- An unchecked conversion is needed in the classwide case because
1083 -- the designated type can be an ancestor of the subtype mark of
1084 -- the allocator.
bb3b440a 1085
fe696bd7 1086 Adj_Call :=
9193c101 1087 Make_Adjust_Call
1088 (Obj_Ref =>
1089 Unchecked_Convert_To (T,
1090 Make_Explicit_Dereference (Loc,
1091 Prefix => New_Occurrence_Of (Temp, Loc))),
fe696bd7 1092 Typ => T);
1093
1094 if Present (Adj_Call) then
1095 Insert_Action (N, Adj_Call);
1096 end if;
9193c101 1097 end if;
9dfe12ae 1098
9193c101 1099 -- Note: the accessibility check must be inserted after the call to
1100 -- [Deep_]Adjust to ensure proper completion of the assignment.
9dfe12ae 1101
9193c101 1102 Apply_Accessibility_Check (Temp);
9dfe12ae 1103
83c6c069 1104 Rewrite (N, New_Occurrence_Of (Temp, Loc));
9dfe12ae 1105 Analyze_And_Resolve (N, PtrT);
1106
f1e2dcc5 1107 -- Ada 2005 (AI-251): Displace the pointer to reference the record
1108 -- component containing the secondary dispatch table of the interface
1109 -- type.
914796b1 1110
1111 if Is_Interface (Directly_Designated_Type (PtrT)) then
1112 Displace_Allocator_Pointer (N);
1113 end if;
1114
b95a77cf 1115 -- Always force the generation of a temporary for aggregates when
1116 -- generating C code, to simplify the work in the code generator.
1117
1118 elsif Aggr_In_Place
b2f0bdaa 1119 or else (Modify_Tree_For_C and then Nkind (Exp) = N_Aggregate)
b95a77cf 1120 then
55578aa3 1121 Temp := Make_Temporary (Loc, 'P', N);
bb3b440a 1122 Temp_Decl :=
9dfe12ae 1123 Make_Object_Declaration (Loc,
1124 Defining_Identifier => Temp,
83c6c069 1125 Object_Definition => New_Occurrence_Of (PtrT, Loc),
bb3b440a 1126 Expression =>
1127 Make_Allocator (Loc,
83c6c069 1128 Expression => New_Occurrence_Of (Etype (Exp), Loc)));
9dfe12ae 1129
19b4517d 1130 -- Copy the Comes_From_Source flag for the allocator we just built,
1131 -- since logically this allocator is a replacement of the original
1132 -- allocator node. This is for proper handling of restriction
1133 -- No_Implicit_Heap_Allocations.
1134
9dfe12ae 1135 Set_Comes_From_Source
bb3b440a 1136 (Expression (Temp_Decl), Comes_From_Source (N));
1137
1138 Set_No_Initialization (Expression (Temp_Decl));
1139 Insert_Action (N, Temp_Decl);
1140
53c179ea 1141 Build_Allocate_Deallocate_Proc (Temp_Decl, True);
bb3b440a 1142 Convert_Aggr_In_Allocator (N, Temp_Decl, Exp);
9dfe12ae 1143
83c6c069 1144 Rewrite (N, New_Occurrence_Of (Temp, Loc));
9dfe12ae 1145 Analyze_And_Resolve (N, PtrT);
1146
6f0d10f7 1147 elsif Is_Access_Type (T) and then Can_Never_Be_Null (T) then
9cba1736 1148 Install_Null_Excluding_Check (Exp);
1149
38f5559f 1150 elsif Is_Access_Type (DesigT)
9dfe12ae 1151 and then Nkind (Exp) = N_Allocator
1152 and then Nkind (Expression (Exp)) /= N_Qualified_Expression
1153 then
80d4fec4 1154 -- Apply constraint to designated subtype indication
9dfe12ae 1155
82b93248 1156 Apply_Constraint_Check
1157 (Expression (Exp), Designated_Type (DesigT), No_Sliding => True);
9dfe12ae 1158
1159 if Nkind (Expression (Exp)) = N_Raise_Constraint_Error then
1160
1161 -- Propagate constraint_error to enclosing allocator
1162
1163 Rewrite (Exp, New_Copy (Expression (Exp)));
1164 end if;
1dceb63e 1165
9dfe12ae 1166 else
9b2f616e 1167 Build_Allocate_Deallocate_Proc (N, True);
1168
395f8e2e 1169 -- If we have:
1170 -- type A is access T1;
1171 -- X : A := new T2'(...);
1172 -- T1 and T2 can be different subtypes, and we might need to check
1173 -- both constraints. First check against the type of the qualified
1174 -- expression.
1175
1176 Apply_Constraint_Check (Exp, T, No_Sliding => True);
9dfe12ae 1177
a9b57347 1178 if Do_Range_Check (Exp) then
a9b57347 1179 Generate_Range_Check (Exp, DesigT, CE_Range_Check_Failed);
1180 end if;
1181
f1e2dcc5 1182 -- A check is also needed in cases where the designated subtype is
1183 -- constrained and differs from the subtype given in the qualified
1184 -- expression. Note that the check on the qualified expression does
1185 -- not allow sliding, but this check does (a relaxation from Ada 83).
9dfe12ae 1186
38f5559f 1187 if Is_Constrained (DesigT)
51f2eb44 1188 and then not Subtypes_Statically_Match (T, DesigT)
9dfe12ae 1189 then
1190 Apply_Constraint_Check
38f5559f 1191 (Exp, DesigT, No_Sliding => False);
a9b57347 1192
1193 if Do_Range_Check (Exp) then
a9b57347 1194 Generate_Range_Check (Exp, DesigT, CE_Range_Check_Failed);
1195 end if;
38f5559f 1196 end if;
1197
f1e2dcc5 1198 -- For an access to unconstrained packed array, GIGI needs to see an
1199 -- expression with a constrained subtype in order to compute the
1200 -- proper size for the allocator.
38f5559f 1201
1202 if Is_Array_Type (T)
1203 and then not Is_Constrained (T)
1204 and then Is_Packed (T)
1205 then
1206 declare
46eb6933 1207 ConstrT : constant Entity_Id := Make_Temporary (Loc, 'A');
38f5559f 1208 Internal_Exp : constant Node_Id := Relocate_Node (Exp);
1209 begin
1210 Insert_Action (Exp,
1211 Make_Subtype_Declaration (Loc,
1212 Defining_Identifier => ConstrT,
8ef30a23 1213 Subtype_Indication =>
1214 Make_Subtype_From_Expr (Internal_Exp, T)));
38f5559f 1215 Freeze_Itype (ConstrT, Exp);
1216 Rewrite (Exp, OK_Convert_To (ConstrT, Internal_Exp));
1217 end;
9dfe12ae 1218 end if;
38f5559f 1219
f1e2dcc5 1220 -- Ada 2005 (AI-318-02): If the initialization expression is a call
1221 -- to a build-in-place function, then access to the allocated object
cd24e497 1222 -- must be passed to the function.
e8ccec48 1223
cd24e497 1224 if Is_Build_In_Place_Function_Call (Exp) then
e8ccec48 1225 Make_Build_In_Place_Call_In_Allocator (N, Exp);
1226 end if;
9dfe12ae 1227 end if;
1228
1229 exception
1230 when RE_Not_Available =>
1231 return;
1232 end Expand_Allocator_Expression;
1233
ee6ba406 1234 -----------------------------
1235 -- Expand_Array_Comparison --
1236 -----------------------------
1237
f1e2dcc5 1238 -- Expansion is only required in the case of array types. For the unpacked
1239 -- case, an appropriate runtime routine is called. For packed cases, and
1240 -- also in some other cases where a runtime routine cannot be called, the
1241 -- form of the expansion is:
ee6ba406 1242
1243 -- [body for greater_nn; boolean_expression]
1244
1245 -- The body is built by Make_Array_Comparison_Op, and the form of the
1246 -- Boolean expression depends on the operator involved.
1247
1248 procedure Expand_Array_Comparison (N : Node_Id) is
1249 Loc : constant Source_Ptr := Sloc (N);
1250 Op1 : Node_Id := Left_Opnd (N);
1251 Op2 : Node_Id := Right_Opnd (N);
1252 Typ1 : constant Entity_Id := Base_Type (Etype (Op1));
9dfe12ae 1253 Ctyp : constant Entity_Id := Component_Type (Typ1);
ee6ba406 1254
1255 Expr : Node_Id;
1256 Func_Body : Node_Id;
1257 Func_Name : Entity_Id;
1258
9dfe12ae 1259 Comp : RE_Id;
1260
0914a918 1261 Byte_Addressable : constant Boolean := System_Storage_Unit = Byte'Size;
1262 -- True for byte addressable target
5c61a0ff 1263
9dfe12ae 1264 function Length_Less_Than_4 (Opnd : Node_Id) return Boolean;
f1e2dcc5 1265 -- Returns True if the length of the given operand is known to be less
1266 -- than 4. Returns False if this length is known to be four or greater
1267 -- or is not known at compile time.
9dfe12ae 1268
1269 ------------------------
1270 -- Length_Less_Than_4 --
1271 ------------------------
1272
1273 function Length_Less_Than_4 (Opnd : Node_Id) return Boolean is
1274 Otyp : constant Entity_Id := Etype (Opnd);
1275
1276 begin
1277 if Ekind (Otyp) = E_String_Literal_Subtype then
1278 return String_Literal_Length (Otyp) < 4;
1279
1280 else
1281 declare
1282 Ityp : constant Entity_Id := Etype (First_Index (Otyp));
1283 Lo : constant Node_Id := Type_Low_Bound (Ityp);
1284 Hi : constant Node_Id := Type_High_Bound (Ityp);
1285 Lov : Uint;
1286 Hiv : Uint;
1287
1288 begin
1289 if Compile_Time_Known_Value (Lo) then
1290 Lov := Expr_Value (Lo);
1291 else
1292 return False;
1293 end if;
1294
1295 if Compile_Time_Known_Value (Hi) then
1296 Hiv := Expr_Value (Hi);
1297 else
1298 return False;
1299 end if;
1300
1301 return Hiv < Lov + 3;
1302 end;
1303 end if;
1304 end Length_Less_Than_4;
1305
1306 -- Start of processing for Expand_Array_Comparison
1307
ee6ba406 1308 begin
9dfe12ae 1309 -- Deal first with unpacked case, where we can call a runtime routine
1310 -- except that we avoid this for targets for which are not addressable
36ac5fbb 1311 -- by bytes.
9dfe12ae 1312
1313 if not Is_Bit_Packed_Array (Typ1)
0914a918 1314 and then Byte_Addressable
9dfe12ae 1315 then
1316 -- The call we generate is:
1317
1318 -- Compare_Array_xn[_Unaligned]
1319 -- (left'address, right'address, left'length, right'length) <op> 0
1320
1321 -- x = U for unsigned, S for signed
1322 -- n = 8,16,32,64 for component size
1323 -- Add _Unaligned if length < 4 and component size is 8.
1324 -- <op> is the standard comparison operator
1325
1326 if Component_Size (Typ1) = 8 then
1327 if Length_Less_Than_4 (Op1)
1328 or else
1329 Length_Less_Than_4 (Op2)
1330 then
1331 if Is_Unsigned_Type (Ctyp) then
1332 Comp := RE_Compare_Array_U8_Unaligned;
1333 else
1334 Comp := RE_Compare_Array_S8_Unaligned;
1335 end if;
1336
1337 else
1338 if Is_Unsigned_Type (Ctyp) then
1339 Comp := RE_Compare_Array_U8;
1340 else
1341 Comp := RE_Compare_Array_S8;
1342 end if;
1343 end if;
1344
1345 elsif Component_Size (Typ1) = 16 then
1346 if Is_Unsigned_Type (Ctyp) then
1347 Comp := RE_Compare_Array_U16;
1348 else
1349 Comp := RE_Compare_Array_S16;
1350 end if;
1351
1352 elsif Component_Size (Typ1) = 32 then
1353 if Is_Unsigned_Type (Ctyp) then
1354 Comp := RE_Compare_Array_U32;
1355 else
1356 Comp := RE_Compare_Array_S32;
1357 end if;
1358
1359 else pragma Assert (Component_Size (Typ1) = 64);
1360 if Is_Unsigned_Type (Ctyp) then
1361 Comp := RE_Compare_Array_U64;
1362 else
1363 Comp := RE_Compare_Array_S64;
1364 end if;
1365 end if;
1366
b8eacb12 1367 if RTE_Available (Comp) then
9dfe12ae 1368
b8eacb12 1369 -- Expand to a call only if the runtime function is available,
0c30cda1 1370 -- otherwise fall back to inline code.
9dfe12ae 1371
b8eacb12 1372 Remove_Side_Effects (Op1, Name_Req => True);
1373 Remove_Side_Effects (Op2, Name_Req => True);
9dfe12ae 1374
b8eacb12 1375 Rewrite (Op1,
1376 Make_Function_Call (Sloc (Op1),
1377 Name => New_Occurrence_Of (RTE (Comp), Loc),
9dfe12ae 1378
b8eacb12 1379 Parameter_Associations => New_List (
1380 Make_Attribute_Reference (Loc,
1381 Prefix => Relocate_Node (Op1),
1382 Attribute_Name => Name_Address),
9dfe12ae 1383
b8eacb12 1384 Make_Attribute_Reference (Loc,
1385 Prefix => Relocate_Node (Op2),
1386 Attribute_Name => Name_Address),
9dfe12ae 1387
b8eacb12 1388 Make_Attribute_Reference (Loc,
1389 Prefix => Relocate_Node (Op1),
1390 Attribute_Name => Name_Length),
9dfe12ae 1391
b8eacb12 1392 Make_Attribute_Reference (Loc,
1393 Prefix => Relocate_Node (Op2),
1394 Attribute_Name => Name_Length))));
1395
1396 Rewrite (Op2,
1397 Make_Integer_Literal (Sloc (Op2),
1398 Intval => Uint_0));
1399
1400 Analyze_And_Resolve (Op1, Standard_Integer);
1401 Analyze_And_Resolve (Op2, Standard_Integer);
1402 return;
1403 end if;
9dfe12ae 1404 end if;
1405
1406 -- Cases where we cannot make runtime call
1407
ee6ba406 1408 -- For (a <= b) we convert to not (a > b)
1409
1410 if Chars (N) = Name_Op_Le then
1411 Rewrite (N,
1412 Make_Op_Not (Loc,
1413 Right_Opnd =>
1414 Make_Op_Gt (Loc,
1415 Left_Opnd => Op1,
1416 Right_Opnd => Op2)));
1417 Analyze_And_Resolve (N, Standard_Boolean);
1418 return;
1419
1420 -- For < the Boolean expression is
1421 -- greater__nn (op2, op1)
1422
1423 elsif Chars (N) = Name_Op_Lt then
1424 Func_Body := Make_Array_Comparison_Op (Typ1, N);
1425
1426 -- Switch operands
1427
1428 Op1 := Right_Opnd (N);
1429 Op2 := Left_Opnd (N);
1430
1431 -- For (a >= b) we convert to not (a < b)
1432
1433 elsif Chars (N) = Name_Op_Ge then
1434 Rewrite (N,
1435 Make_Op_Not (Loc,
1436 Right_Opnd =>
1437 Make_Op_Lt (Loc,
1438 Left_Opnd => Op1,
1439 Right_Opnd => Op2)));
1440 Analyze_And_Resolve (N, Standard_Boolean);
1441 return;
1442
1443 -- For > the Boolean expression is
1444 -- greater__nn (op1, op2)
1445
1446 else
1447 pragma Assert (Chars (N) = Name_Op_Gt);
1448 Func_Body := Make_Array_Comparison_Op (Typ1, N);
1449 end if;
1450
1451 Func_Name := Defining_Unit_Name (Specification (Func_Body));
1452 Expr :=
1453 Make_Function_Call (Loc,
83c6c069 1454 Name => New_Occurrence_Of (Func_Name, Loc),
ee6ba406 1455 Parameter_Associations => New_List (Op1, Op2));
1456
1457 Insert_Action (N, Func_Body);
1458 Rewrite (N, Expr);
1459 Analyze_And_Resolve (N, Standard_Boolean);
ee6ba406 1460 end Expand_Array_Comparison;
1461
1462 ---------------------------
1463 -- Expand_Array_Equality --
1464 ---------------------------
1465
f1e2dcc5 1466 -- Expand an equality function for multi-dimensional arrays. Here is an
1467 -- example of such a function for Nb_Dimension = 2
ee6ba406 1468
80d4fec4 1469 -- function Enn (A : atyp; B : btyp) return boolean is
ee6ba406 1470 -- begin
9dfe12ae 1471 -- if (A'length (1) = 0 or else A'length (2) = 0)
1472 -- and then
1473 -- (B'length (1) = 0 or else B'length (2) = 0)
1474 -- then
1475 -- return True; -- RM 4.5.2(22)
1476 -- end if;
80d4fec4 1477
9dfe12ae 1478 -- if A'length (1) /= B'length (1)
1479 -- or else
1480 -- A'length (2) /= B'length (2)
1481 -- then
1482 -- return False; -- RM 4.5.2(23)
1483 -- end if;
80d4fec4 1484
9dfe12ae 1485 -- declare
8f71d067 1486 -- A1 : Index_T1 := A'first (1);
1487 -- B1 : Index_T1 := B'first (1);
9dfe12ae 1488 -- begin
8f71d067 1489 -- loop
9dfe12ae 1490 -- declare
8f71d067 1491 -- A2 : Index_T2 := A'first (2);
1492 -- B2 : Index_T2 := B'first (2);
9dfe12ae 1493 -- begin
8f71d067 1494 -- loop
9dfe12ae 1495 -- if A (A1, A2) /= B (B1, B2) then
1496 -- return False;
ee6ba406 1497 -- end if;
80d4fec4 1498
8f71d067 1499 -- exit when A2 = A'last (2);
1500 -- A2 := Index_T2'succ (A2);
80d4fec4 1501 -- B2 := Index_T2'succ (B2);
ee6ba406 1502 -- end loop;
9dfe12ae 1503 -- end;
80d4fec4 1504
8f71d067 1505 -- exit when A1 = A'last (1);
1506 -- A1 := Index_T1'succ (A1);
80d4fec4 1507 -- B1 := Index_T1'succ (B1);
ee6ba406 1508 -- end loop;
9dfe12ae 1509 -- end;
80d4fec4 1510
ee6ba406 1511 -- return true;
1512 -- end Enn;
1513
f1e2dcc5 1514 -- Note on the formal types used (atyp and btyp). If either of the arrays
1515 -- is of a private type, we use the underlying type, and do an unchecked
1516 -- conversion of the actual. If either of the arrays has a bound depending
1517 -- on a discriminant, then we use the base type since otherwise we have an
1518 -- escaped discriminant in the function.
80d4fec4 1519
f1e2dcc5 1520 -- If both arrays are constrained and have the same bounds, we can generate
1521 -- a loop with an explicit iteration scheme using a 'Range attribute over
1522 -- the first array.
8f71d067 1523
ee6ba406 1524 function Expand_Array_Equality
1525 (Nod : Node_Id;
ee6ba406 1526 Lhs : Node_Id;
1527 Rhs : Node_Id;
80d4fec4 1528 Bodies : List_Id;
1529 Typ : Entity_Id) return Node_Id
ee6ba406 1530 is
1531 Loc : constant Source_Ptr := Sloc (Nod);
9dfe12ae 1532 Decls : constant List_Id := New_List;
1533 Index_List1 : constant List_Id := New_List;
1534 Index_List2 : constant List_Id := New_List;
1535
1536 Actuals : List_Id;
1537 Formals : List_Id;
1538 Func_Name : Entity_Id;
1539 Func_Body : Node_Id;
ee6ba406 1540
1541 A : constant Entity_Id := Make_Defining_Identifier (Loc, Name_uA);
1542 B : constant Entity_Id := Make_Defining_Identifier (Loc, Name_uB);
1543
80d4fec4 1544 Ltyp : Entity_Id;
1545 Rtyp : Entity_Id;
1546 -- The parameter types to be used for the formals
1547
9dfe12ae 1548 function Arr_Attr
1549 (Arr : Entity_Id;
1550 Nam : Name_Id;
752e1833 1551 Num : Int) return Node_Id;
f84d3d59 1552 -- This builds the attribute reference Arr'Nam (Expr)
9dfe12ae 1553
ee6ba406 1554 function Component_Equality (Typ : Entity_Id) return Node_Id;
f1e2dcc5 1555 -- Create one statement to compare corresponding components, designated
1d00a8ce 1556 -- by a full set of indexes.
ee6ba406 1557
80d4fec4 1558 function Get_Arg_Type (N : Node_Id) return Entity_Id;
f1e2dcc5 1559 -- Given one of the arguments, computes the appropriate type to be used
1560 -- for that argument in the corresponding function formal
80d4fec4 1561
9dfe12ae 1562 function Handle_One_Dimension
ee6ba406 1563 (N : Int;
752e1833 1564 Index : Node_Id) return Node_Id;
80d4fec4 1565 -- This procedure returns the following code
9dfe12ae 1566 --
1567 -- declare
8f71d067 1568 -- Bn : Index_T := B'First (N);
9dfe12ae 1569 -- begin
8f71d067 1570 -- loop
9dfe12ae 1571 -- xxx
8f71d067 1572 -- exit when An = A'Last (N);
1573 -- An := Index_T'Succ (An)
80d4fec4 1574 -- Bn := Index_T'Succ (Bn)
9dfe12ae 1575 -- end loop;
1576 -- end;
1577 --
1d00a8ce 1578 -- If both indexes are constrained and identical, the procedure
8f71d067 1579 -- returns a simpler loop:
1580 --
1581 -- for An in A'Range (N) loop
1582 -- xxx
1583 -- end loop
80d4fec4 1584 --
8f71d067 1585 -- N is the dimension for which we are generating a loop. Index is the
f1e2dcc5 1586 -- N'th index node, whose Etype is Index_Type_n in the above code. The
1587 -- xxx statement is either the loop or declare for the next dimension
1588 -- or if this is the last dimension the comparison of corresponding
1589 -- components of the arrays.
9dfe12ae 1590 --
f1e2dcc5 1591 -- The actual way the code works is to return the comparison of
39a0c1d3 1592 -- corresponding components for the N+1 call. That's neater.
9dfe12ae 1593
1594 function Test_Empty_Arrays return Node_Id;
1595 -- This function constructs the test for both arrays being empty
1596 -- (A'length (1) = 0 or else A'length (2) = 0 or else ...)
1597 -- and then
1598 -- (B'length (1) = 0 or else B'length (2) = 0 or else ...)
1599
1600 function Test_Lengths_Correspond return Node_Id;
f1e2dcc5 1601 -- This function constructs the test for arrays having different lengths
1602 -- in at least one index position, in which case the resulting code is:
9dfe12ae 1603
1604 -- A'length (1) /= B'length (1)
1605 -- or else
1606 -- A'length (2) /= B'length (2)
1607 -- or else
1608 -- ...
1609
1610 --------------
1611 -- Arr_Attr --
1612 --------------
1613
1614 function Arr_Attr
1615 (Arr : Entity_Id;
1616 Nam : Name_Id;
752e1833 1617 Num : Int) return Node_Id
9dfe12ae 1618 is
1619 begin
1620 return
1621 Make_Attribute_Reference (Loc,
82b93248 1622 Attribute_Name => Nam,
1623 Prefix => New_Occurrence_Of (Arr, Loc),
1624 Expressions => New_List (Make_Integer_Literal (Loc, Num)));
9dfe12ae 1625 end Arr_Attr;
ee6ba406 1626
1627 ------------------------
1628 -- Component_Equality --
1629 ------------------------
1630
1631 function Component_Equality (Typ : Entity_Id) return Node_Id is
1632 Test : Node_Id;
1633 L, R : Node_Id;
1634
1635 begin
1636 -- if a(i1...) /= b(j1...) then return false; end if;
1637
1638 L :=
1639 Make_Indexed_Component (Loc,
55868293 1640 Prefix => Make_Identifier (Loc, Chars (A)),
ee6ba406 1641 Expressions => Index_List1);
1642
1643 R :=
1644 Make_Indexed_Component (Loc,
55868293 1645 Prefix => Make_Identifier (Loc, Chars (B)),
ee6ba406 1646 Expressions => Index_List2);
1647
1648 Test := Expand_Composite_Equality
1649 (Nod, Component_Type (Typ), L, R, Decls);
1650
4660e715 1651 -- If some (sub)component is an unchecked_union, the whole operation
1652 -- will raise program error.
b374288a 1653
1654 if Nkind (Test) = N_Raise_Program_Error then
4660e715 1655
1656 -- This node is going to be inserted at a location where a
f1e2dcc5 1657 -- statement is expected: clear its Etype so analysis will set
1658 -- it to the expected Standard_Void_Type.
4660e715 1659
1660 Set_Etype (Test, Empty);
b374288a 1661 return Test;
1662
1663 else
1664 return
1665 Make_Implicit_If_Statement (Nod,
82b93248 1666 Condition => Make_Op_Not (Loc, Right_Opnd => Test),
b374288a 1667 Then_Statements => New_List (
a3e461ac 1668 Make_Simple_Return_Statement (Loc,
b374288a 1669 Expression => New_Occurrence_Of (Standard_False, Loc))));
1670 end if;
ee6ba406 1671 end Component_Equality;
1672
80d4fec4 1673 ------------------
1674 -- Get_Arg_Type --
1675 ------------------
1676
1677 function Get_Arg_Type (N : Node_Id) return Entity_Id is
1678 T : Entity_Id;
1679 X : Node_Id;
1680
1681 begin
1682 T := Etype (N);
1683
1684 if No (T) then
1685 return Typ;
1686
1687 else
1688 T := Underlying_Type (T);
1689
1690 X := First_Index (T);
1691 while Present (X) loop
cf04d13c 1692 if Denotes_Discriminant (Type_Low_Bound (Etype (X)))
1693 or else
1694 Denotes_Discriminant (Type_High_Bound (Etype (X)))
80d4fec4 1695 then
1696 T := Base_Type (T);
1697 exit;
1698 end if;
1699
1700 Next_Index (X);
1701 end loop;
1702
1703 return T;
1704 end if;
1705 end Get_Arg_Type;
1706
9dfe12ae 1707 --------------------------
1708 -- Handle_One_Dimension --
1709 ---------------------------
ee6ba406 1710
9dfe12ae 1711 function Handle_One_Dimension
ee6ba406 1712 (N : Int;
752e1833 1713 Index : Node_Id) return Node_Id
ee6ba406 1714 is
80d4fec4 1715 Need_Separate_Indexes : constant Boolean :=
cf04d13c 1716 Ltyp /= Rtyp or else not Is_Constrained (Ltyp);
80d4fec4 1717 -- If the index types are identical, and we are working with
f1e2dcc5 1718 -- constrained types, then we can use the same index for both
1719 -- of the arrays.
80d4fec4 1720
46eb6933 1721 An : constant Entity_Id := Make_Temporary (Loc, 'A');
80d4fec4 1722
1723 Bn : Entity_Id;
1724 Index_T : Entity_Id;
1725 Stm_List : List_Id;
1726 Loop_Stm : Node_Id;
ee6ba406 1727
1728 begin
80d4fec4 1729 if N > Number_Dimensions (Ltyp) then
1730 return Component_Equality (Ltyp);
9dfe12ae 1731 end if;
ee6ba406 1732
80d4fec4 1733 -- Case where we generate a loop
1734
1735 Index_T := Base_Type (Etype (Index));
1736
1737 if Need_Separate_Indexes then
46eb6933 1738 Bn := Make_Temporary (Loc, 'B');
80d4fec4 1739 else
1740 Bn := An;
1741 end if;
ee6ba406 1742
83c6c069 1743 Append (New_Occurrence_Of (An, Loc), Index_List1);
1744 Append (New_Occurrence_Of (Bn, Loc), Index_List2);
ee6ba406 1745
80d4fec4 1746 Stm_List := New_List (
1747 Handle_One_Dimension (N + 1, Next_Index (Index)));
ee6ba406 1748
80d4fec4 1749 if Need_Separate_Indexes then
4660e715 1750
1d00a8ce 1751 -- Generate guard for loop, followed by increments of indexes
8f71d067 1752
1753 Append_To (Stm_List,
1754 Make_Exit_Statement (Loc,
1755 Condition =>
1756 Make_Op_Eq (Loc,
82b93248 1757 Left_Opnd => New_Occurrence_Of (An, Loc),
8f71d067 1758 Right_Opnd => Arr_Attr (A, Name_Last, N))));
1759
1760 Append_To (Stm_List,
1761 Make_Assignment_Statement (Loc,
83c6c069 1762 Name => New_Occurrence_Of (An, Loc),
8f71d067 1763 Expression =>
1764 Make_Attribute_Reference (Loc,
83c6c069 1765 Prefix => New_Occurrence_Of (Index_T, Loc),
8f71d067 1766 Attribute_Name => Name_Succ,
83c6c069 1767 Expressions => New_List (
1768 New_Occurrence_Of (An, Loc)))));
8f71d067 1769
80d4fec4 1770 Append_To (Stm_List,
1771 Make_Assignment_Statement (Loc,
83c6c069 1772 Name => New_Occurrence_Of (Bn, Loc),
80d4fec4 1773 Expression =>
1774 Make_Attribute_Reference (Loc,
83c6c069 1775 Prefix => New_Occurrence_Of (Index_T, Loc),
80d4fec4 1776 Attribute_Name => Name_Succ,
83c6c069 1777 Expressions => New_List (
1778 New_Occurrence_Of (Bn, Loc)))));
80d4fec4 1779 end if;
1780
4660e715 1781 -- If separate indexes, we need a declare block for An and Bn, and a
1782 -- loop without an iteration scheme.
80d4fec4 1783
1784 if Need_Separate_Indexes then
8f71d067 1785 Loop_Stm :=
1786 Make_Implicit_Loop_Statement (Nod, Statements => Stm_List);
1787
80d4fec4 1788 return
1789 Make_Block_Statement (Loc,
1790 Declarations => New_List (
8f71d067 1791 Make_Object_Declaration (Loc,
1792 Defining_Identifier => An,
83c6c069 1793 Object_Definition => New_Occurrence_Of (Index_T, Loc),
8f71d067 1794 Expression => Arr_Attr (A, Name_First, N)),
1795
80d4fec4 1796 Make_Object_Declaration (Loc,
1797 Defining_Identifier => Bn,
83c6c069 1798 Object_Definition => New_Occurrence_Of (Index_T, Loc),
80d4fec4 1799 Expression => Arr_Attr (B, Name_First, N))),
8f71d067 1800
80d4fec4 1801 Handled_Statement_Sequence =>
1802 Make_Handled_Sequence_Of_Statements (Loc,
1803 Statements => New_List (Loop_Stm)));
1804
8f71d067 1805 -- If no separate indexes, return loop statement with explicit
1806 -- iteration scheme on its own
80d4fec4 1807
1808 else
8f71d067 1809 Loop_Stm :=
1810 Make_Implicit_Loop_Statement (Nod,
1811 Statements => Stm_List,
1812 Iteration_Scheme =>
1813 Make_Iteration_Scheme (Loc,
1814 Loop_Parameter_Specification =>
1815 Make_Loop_Parameter_Specification (Loc,
1816 Defining_Identifier => An,
1817 Discrete_Subtype_Definition =>
1818 Arr_Attr (A, Name_Range, N))));
80d4fec4 1819 return Loop_Stm;
1820 end if;
9dfe12ae 1821 end Handle_One_Dimension;
1822
1823 -----------------------
1824 -- Test_Empty_Arrays --
1825 -----------------------
1826
1827 function Test_Empty_Arrays return Node_Id is
1828 Alist : Node_Id;
1829 Blist : Node_Id;
1830
1831 Atest : Node_Id;
1832 Btest : Node_Id;
ee6ba406 1833
9dfe12ae 1834 begin
1835 Alist := Empty;
1836 Blist := Empty;
80d4fec4 1837 for J in 1 .. Number_Dimensions (Ltyp) loop
9dfe12ae 1838 Atest :=
1839 Make_Op_Eq (Loc,
1840 Left_Opnd => Arr_Attr (A, Name_Length, J),
1841 Right_Opnd => Make_Integer_Literal (Loc, 0));
1842
1843 Btest :=
1844 Make_Op_Eq (Loc,
1845 Left_Opnd => Arr_Attr (B, Name_Length, J),
1846 Right_Opnd => Make_Integer_Literal (Loc, 0));
1847
1848 if No (Alist) then
1849 Alist := Atest;
1850 Blist := Btest;
ee6ba406 1851
9dfe12ae 1852 else
1853 Alist :=
1854 Make_Or_Else (Loc,
1855 Left_Opnd => Relocate_Node (Alist),
1856 Right_Opnd => Atest);
1857
1858 Blist :=
1859 Make_Or_Else (Loc,
1860 Left_Opnd => Relocate_Node (Blist),
1861 Right_Opnd => Btest);
1862 end if;
1863 end loop;
ee6ba406 1864
9dfe12ae 1865 return
1866 Make_And_Then (Loc,
1867 Left_Opnd => Alist,
1868 Right_Opnd => Blist);
1869 end Test_Empty_Arrays;
ee6ba406 1870
9dfe12ae 1871 -----------------------------
1872 -- Test_Lengths_Correspond --
1873 -----------------------------
ee6ba406 1874
9dfe12ae 1875 function Test_Lengths_Correspond return Node_Id is
1876 Result : Node_Id;
1877 Rtest : Node_Id;
1878
1879 begin
1880 Result := Empty;
80d4fec4 1881 for J in 1 .. Number_Dimensions (Ltyp) loop
9dfe12ae 1882 Rtest :=
1883 Make_Op_Ne (Loc,
1884 Left_Opnd => Arr_Attr (A, Name_Length, J),
1885 Right_Opnd => Arr_Attr (B, Name_Length, J));
1886
1887 if No (Result) then
1888 Result := Rtest;
1889 else
1890 Result :=
1891 Make_Or_Else (Loc,
1892 Left_Opnd => Relocate_Node (Result),
1893 Right_Opnd => Rtest);
1894 end if;
1895 end loop;
1896
1897 return Result;
1898 end Test_Lengths_Correspond;
ee6ba406 1899
1900 -- Start of processing for Expand_Array_Equality
1901
1902 begin
80d4fec4 1903 Ltyp := Get_Arg_Type (Lhs);
1904 Rtyp := Get_Arg_Type (Rhs);
1905
f1e2dcc5 1906 -- For now, if the argument types are not the same, go to the base type,
1907 -- since the code assumes that the formals have the same type. This is
1908 -- fixable in future ???
80d4fec4 1909
1910 if Ltyp /= Rtyp then
1911 Ltyp := Base_Type (Ltyp);
1912 Rtyp := Base_Type (Rtyp);
1913 pragma Assert (Ltyp = Rtyp);
1914 end if;
1915
1916 -- Build list of formals for function
1917
ee6ba406 1918 Formals := New_List (
1919 Make_Parameter_Specification (Loc,
1920 Defining_Identifier => A,
83c6c069 1921 Parameter_Type => New_Occurrence_Of (Ltyp, Loc)),
ee6ba406 1922
1923 Make_Parameter_Specification (Loc,
1924 Defining_Identifier => B,
83c6c069 1925 Parameter_Type => New_Occurrence_Of (Rtyp, Loc)));
ee6ba406 1926
46eb6933 1927 Func_Name := Make_Temporary (Loc, 'E');
ee6ba406 1928
9dfe12ae 1929 -- Build statement sequence for function
ee6ba406 1930
1931 Func_Body :=
1932 Make_Subprogram_Body (Loc,
1933 Specification =>
1934 Make_Function_Specification (Loc,
1935 Defining_Unit_Name => Func_Name,
1936 Parameter_Specifications => Formals,
83c6c069 1937 Result_Definition => New_Occurrence_Of (Standard_Boolean, Loc)),
9dfe12ae 1938
1939 Declarations => Decls,
1940
ee6ba406 1941 Handled_Statement_Sequence =>
1942 Make_Handled_Sequence_Of_Statements (Loc,
1943 Statements => New_List (
9dfe12ae 1944
1945 Make_Implicit_If_Statement (Nod,
82b93248 1946 Condition => Test_Empty_Arrays,
9dfe12ae 1947 Then_Statements => New_List (
a3e461ac 1948 Make_Simple_Return_Statement (Loc,
9dfe12ae 1949 Expression =>
1950 New_Occurrence_Of (Standard_True, Loc)))),
1951
1952 Make_Implicit_If_Statement (Nod,
82b93248 1953 Condition => Test_Lengths_Correspond,
9dfe12ae 1954 Then_Statements => New_List (
a3e461ac 1955 Make_Simple_Return_Statement (Loc,
82b93248 1956 Expression => New_Occurrence_Of (Standard_False, Loc)))),
9dfe12ae 1957
80d4fec4 1958 Handle_One_Dimension (1, First_Index (Ltyp)),
9dfe12ae 1959
a3e461ac 1960 Make_Simple_Return_Statement (Loc,
ee6ba406 1961 Expression => New_Occurrence_Of (Standard_True, Loc)))));
1962
1963 Set_Has_Completion (Func_Name, True);
80d4fec4 1964 Set_Is_Inlined (Func_Name);
ee6ba406 1965
f1e2dcc5 1966 -- If the array type is distinct from the type of the arguments, it
1967 -- is the full view of a private type. Apply an unchecked conversion
1968 -- to insure that analysis of the call succeeds.
ee6ba406 1969
80d4fec4 1970 declare
1971 L, R : Node_Id;
1972
1973 begin
1974 L := Lhs;
1975 R := Rhs;
1976
1977 if No (Etype (Lhs))
1978 or else Base_Type (Etype (Lhs)) /= Base_Type (Ltyp)
1979 then
1980 L := OK_Convert_To (Ltyp, Lhs);
1981 end if;
1982
1983 if No (Etype (Rhs))
1984 or else Base_Type (Etype (Rhs)) /= Base_Type (Rtyp)
1985 then
1986 R := OK_Convert_To (Rtyp, Rhs);
1987 end if;
1988
1989 Actuals := New_List (L, R);
1990 end;
ee6ba406 1991
1992 Append_To (Bodies, Func_Body);
1993
1994 return
1995 Make_Function_Call (Loc,
83c6c069 1996 Name => New_Occurrence_Of (Func_Name, Loc),
ee6ba406 1997 Parameter_Associations => Actuals);
1998 end Expand_Array_Equality;
1999
2000 -----------------------------
2001 -- Expand_Boolean_Operator --
2002 -----------------------------
2003
f1e2dcc5 2004 -- Note that we first get the actual subtypes of the operands, since we
2005 -- always want to deal with types that have bounds.
ee6ba406 2006
2007 procedure Expand_Boolean_Operator (N : Node_Id) is
9dfe12ae 2008 Typ : constant Entity_Id := Etype (N);
ee6ba406 2009
2010 begin
f1e2dcc5 2011 -- Special case of bit packed array where both operands are known to be
2012 -- properly aligned. In this case we use an efficient run time routine
2013 -- to carry out the operation (see System.Bit_Ops).
4660e715 2014
2015 if Is_Bit_Packed_Array (Typ)
2016 and then not Is_Possibly_Unaligned_Object (Left_Opnd (N))
2017 and then not Is_Possibly_Unaligned_Object (Right_Opnd (N))
2018 then
ee6ba406 2019 Expand_Packed_Boolean_Operator (N);
4660e715 2020 return;
2021 end if;
ee6ba406 2022
4660e715 2023 -- For the normal non-packed case, the general expansion is to build
2024 -- function for carrying out the comparison (use Make_Boolean_Array_Op)
2025 -- and then inserting it into the tree. The original operator node is
2026 -- then rewritten as a call to this function. We also use this in the
2027 -- packed case if either operand is a possibly unaligned object.
ee6ba406 2028
4660e715 2029 declare
2030 Loc : constant Source_Ptr := Sloc (N);
2031 L : constant Node_Id := Relocate_Node (Left_Opnd (N));
2032 R : constant Node_Id := Relocate_Node (Right_Opnd (N));
2033 Func_Body : Node_Id;
2034 Func_Name : Entity_Id;
9dfe12ae 2035
4660e715 2036 begin
2037 Convert_To_Actual_Subtype (L);
2038 Convert_To_Actual_Subtype (R);
2039 Ensure_Defined (Etype (L), N);
2040 Ensure_Defined (Etype (R), N);
2041 Apply_Length_Check (R, Etype (L));
2042
40a5a4cb 2043 if Nkind (N) = N_Op_Xor then
2044 Silly_Boolean_Array_Xor_Test (N, Etype (L));
2045 end if;
2046
4660e715 2047 if Nkind (Parent (N)) = N_Assignment_Statement
2048 and then Safe_In_Place_Array_Op (Name (Parent (N)), L, R)
2049 then
2050 Build_Boolean_Array_Proc_Call (Parent (N), L, R);
9dfe12ae 2051
4660e715 2052 elsif Nkind (Parent (N)) = N_Op_Not
2053 and then Nkind (N) = N_Op_And
f4f2bf51 2054 and then Nkind (Parent (Parent (N))) = N_Assignment_Statement
82b93248 2055 and then Safe_In_Place_Array_Op (Name (Parent (Parent (N))), L, R)
4660e715 2056 then
2057 return;
2058 else
9dfe12ae 2059
4660e715 2060 Func_Body := Make_Boolean_Array_Op (Etype (L), N);
2061 Func_Name := Defining_Unit_Name (Specification (Func_Body));
2062 Insert_Action (N, Func_Body);
ee6ba406 2063
4660e715 2064 -- Now rewrite the expression with a call
ee6ba406 2065
4660e715 2066 Rewrite (N,
2067 Make_Function_Call (Loc,
83c6c069 2068 Name => New_Occurrence_Of (Func_Name, Loc),
4660e715 2069 Parameter_Associations =>
2070 New_List (
2071 L,
2072 Make_Type_Conversion
83c6c069 2073 (Loc, New_Occurrence_Of (Etype (L), Loc), R))));
ee6ba406 2074
4660e715 2075 Analyze_And_Resolve (N, Typ);
2076 end if;
2077 end;
ee6ba406 2078 end Expand_Boolean_Operator;
2079
d94b5da2 2080 ------------------------------------------------
2081 -- Expand_Compare_Minimize_Eliminate_Overflow --
2082 ------------------------------------------------
2083
2084 procedure Expand_Compare_Minimize_Eliminate_Overflow (N : Node_Id) is
2085 Loc : constant Source_Ptr := Sloc (N);
2086
b8a17a21 2087 Result_Type : constant Entity_Id := Etype (N);
2088 -- Capture result type (could be a derived boolean type)
2089
d94b5da2 2090 Llo, Lhi : Uint;
2091 Rlo, Rhi : Uint;
2092
2093 LLIB : constant Entity_Id := Base_Type (Standard_Long_Long_Integer);
2094 -- Entity for Long_Long_Integer'Base
2095
db415383 2096 Check : constant Overflow_Mode_Type := Overflow_Check_Mode;
0df9d43f 2097 -- Current overflow checking mode
d94b5da2 2098
2099 procedure Set_True;
2100 procedure Set_False;
2101 -- These procedures rewrite N with an occurrence of Standard_True or
2102 -- Standard_False, and then makes a call to Warn_On_Known_Condition.
2103
2104 ---------------
2105 -- Set_False --
2106 ---------------
2107
2108 procedure Set_False is
2109 begin
2110 Rewrite (N, New_Occurrence_Of (Standard_False, Loc));
2111 Warn_On_Known_Condition (N);
2112 end Set_False;
2113
2114 --------------
2115 -- Set_True --
2116 --------------
2117
2118 procedure Set_True is
2119 begin
2120 Rewrite (N, New_Occurrence_Of (Standard_True, Loc));
2121 Warn_On_Known_Condition (N);
2122 end Set_True;
2123
2124 -- Start of processing for Expand_Compare_Minimize_Eliminate_Overflow
2125
2126 begin
2127 -- Nothing to do unless we have a comparison operator with operands
2128 -- that are signed integer types, and we are operating in either
2129 -- MINIMIZED or ELIMINATED overflow checking mode.
2130
2131 if Nkind (N) not in N_Op_Compare
2132 or else Check not in Minimized_Or_Eliminated
2133 or else not Is_Signed_Integer_Type (Etype (Left_Opnd (N)))
2134 then
2135 return;
2136 end if;
2137
2138 -- OK, this is the case we are interested in. First step is to process
2139 -- our operands using the Minimize_Eliminate circuitry which applies
2140 -- this processing to the two operand subtrees.
2141
0df9d43f 2142 Minimize_Eliminate_Overflows
61016a7a 2143 (Left_Opnd (N), Llo, Lhi, Top_Level => False);
0df9d43f 2144 Minimize_Eliminate_Overflows
61016a7a 2145 (Right_Opnd (N), Rlo, Rhi, Top_Level => False);
d94b5da2 2146
0f4a8308 2147 -- See if the range information decides the result of the comparison.
2148 -- We can only do this if we in fact have full range information (which
2149 -- won't be the case if either operand is bignum at this stage).
d94b5da2 2150
0f4a8308 2151 if Llo /= No_Uint and then Rlo /= No_Uint then
2152 case N_Op_Compare (Nkind (N)) is
99378362 2153 when N_Op_Eq =>
2154 if Llo = Lhi and then Rlo = Rhi and then Llo = Rlo then
2155 Set_True;
2156 elsif Llo > Rhi or else Lhi < Rlo then
2157 Set_False;
2158 end if;
d94b5da2 2159
99378362 2160 when N_Op_Ge =>
2161 if Llo >= Rhi then
2162 Set_True;
2163 elsif Lhi < Rlo then
2164 Set_False;
2165 end if;
d94b5da2 2166
99378362 2167 when N_Op_Gt =>
2168 if Llo > Rhi then
2169 Set_True;
2170 elsif Lhi <= Rlo then
2171 Set_False;
2172 end if;
d94b5da2 2173
99378362 2174 when N_Op_Le =>
2175 if Llo > Rhi then
2176 Set_False;
2177 elsif Lhi <= Rlo then
2178 Set_True;
2179 end if;
d94b5da2 2180
99378362 2181 when N_Op_Lt =>
2182 if Llo >= Rhi then
2183 Set_False;
2184 elsif Lhi < Rlo then
2185 Set_True;
2186 end if;
d94b5da2 2187
99378362 2188 when N_Op_Ne =>
2189 if Llo = Lhi and then Rlo = Rhi and then Llo = Rlo then
2190 Set_False;
2191 elsif Llo > Rhi or else Lhi < Rlo then
2192 Set_True;
2193 end if;
0f4a8308 2194 end case;
d94b5da2 2195
0f4a8308 2196 -- All done if we did the rewrite
d94b5da2 2197
0f4a8308 2198 if Nkind (N) not in N_Op_Compare then
2199 return;
2200 end if;
d94b5da2 2201 end if;
2202
2203 -- Otherwise, time to do the comparison
2204
2205 declare
2206 Ltype : constant Entity_Id := Etype (Left_Opnd (N));
2207 Rtype : constant Entity_Id := Etype (Right_Opnd (N));
2208
2209 begin
2210 -- If the two operands have the same signed integer type we are
2211 -- all set, nothing more to do. This is the case where either
2212 -- both operands were unchanged, or we rewrote both of them to
2213 -- be Long_Long_Integer.
2214
2215 -- Note: Entity for the comparison may be wrong, but it's not worth
2216 -- the effort to change it, since the back end does not use it.
2217
2218 if Is_Signed_Integer_Type (Ltype)
2219 and then Base_Type (Ltype) = Base_Type (Rtype)
2220 then
2221 return;
2222
2223 -- Here if bignums are involved (can only happen in ELIMINATED mode)
2224
2225 elsif Is_RTE (Ltype, RE_Bignum) or else Is_RTE (Rtype, RE_Bignum) then
2226 declare
2227 Left : Node_Id := Left_Opnd (N);
2228 Right : Node_Id := Right_Opnd (N);
2229 -- Bignum references for left and right operands
2230
2231 begin
2232 if not Is_RTE (Ltype, RE_Bignum) then
2233 Left := Convert_To_Bignum (Left);
2234 elsif not Is_RTE (Rtype, RE_Bignum) then
2235 Right := Convert_To_Bignum (Right);
2236 end if;
2237
b8a17a21 2238 -- We rewrite our node with:
d94b5da2 2239
b8a17a21 2240 -- do
2241 -- Bnn : Result_Type;
2242 -- declare
2243 -- M : Mark_Id := SS_Mark;
2244 -- begin
2245 -- Bnn := Big_xx (Left, Right); (xx = EQ, NT etc)
2246 -- SS_Release (M);
2247 -- end;
2248 -- in
2249 -- Bnn
2250 -- end
d94b5da2 2251
2252 declare
b8a17a21 2253 Blk : constant Node_Id := Make_Bignum_Block (Loc);
d94b5da2 2254 Bnn : constant Entity_Id := Make_Temporary (Loc, 'B', N);
2255 Ent : RE_Id;
2256
2257 begin
2258 case N_Op_Compare (Nkind (N)) is
2259 when N_Op_Eq => Ent := RE_Big_EQ;
2260 when N_Op_Ge => Ent := RE_Big_GE;
2261 when N_Op_Gt => Ent := RE_Big_GT;
2262 when N_Op_Le => Ent := RE_Big_LE;
2263 when N_Op_Lt => Ent := RE_Big_LT;
2264 when N_Op_Ne => Ent := RE_Big_NE;
2265 end case;
2266
b8a17a21 2267 -- Insert assignment to Bnn into the bignum block
d94b5da2 2268
2269 Insert_Before
2270 (First (Statements (Handled_Statement_Sequence (Blk))),
2271 Make_Assignment_Statement (Loc,
2272 Name => New_Occurrence_Of (Bnn, Loc),
2273 Expression =>
2274 Make_Function_Call (Loc,
2275 Name =>
2276 New_Occurrence_Of (RTE (Ent), Loc),
2277 Parameter_Associations => New_List (Left, Right))));
2278
b8a17a21 2279 -- Now do the rewrite with expression actions
2280
2281 Rewrite (N,
2282 Make_Expression_With_Actions (Loc,
2283 Actions => New_List (
2284 Make_Object_Declaration (Loc,
2285 Defining_Identifier => Bnn,
2286 Object_Definition =>
2287 New_Occurrence_Of (Result_Type, Loc)),
2288 Blk),
2289 Expression => New_Occurrence_Of (Bnn, Loc)));
2290 Analyze_And_Resolve (N, Result_Type);
d94b5da2 2291 end;
2292 end;
2293
2294 -- No bignums involved, but types are different, so we must have
2295 -- rewritten one of the operands as a Long_Long_Integer but not
2296 -- the other one.
2297
2298 -- If left operand is Long_Long_Integer, convert right operand
2299 -- and we are done (with a comparison of two Long_Long_Integers).
2300
2301 elsif Ltype = LLIB then
2302 Convert_To_And_Rewrite (LLIB, Right_Opnd (N));
2303 Analyze_And_Resolve (Right_Opnd (N), LLIB, Suppress => All_Checks);
2304 return;
2305
2306 -- If right operand is Long_Long_Integer, convert left operand
2307 -- and we are done (with a comparison of two Long_Long_Integers).
2308
2309 -- This is the only remaining possibility
2310
2311 else pragma Assert (Rtype = LLIB);
2312 Convert_To_And_Rewrite (LLIB, Left_Opnd (N));
2313 Analyze_And_Resolve (Left_Opnd (N), LLIB, Suppress => All_Checks);
2314 return;
2315 end if;
2316 end;
2317 end Expand_Compare_Minimize_Eliminate_Overflow;
2318
ee6ba406 2319 -------------------------------
2320 -- Expand_Composite_Equality --
2321 -------------------------------
2322
2323 -- This function is only called for comparing internal fields of composite
2324 -- types when these fields are themselves composites. This is a special
2325 -- case because it is not possible to respect normal Ada visibility rules.
2326
2327 function Expand_Composite_Equality
2328 (Nod : Node_Id;
2329 Typ : Entity_Id;
2330 Lhs : Node_Id;
2331 Rhs : Node_Id;
752e1833 2332 Bodies : List_Id) return Node_Id
ee6ba406 2333 is
2334 Loc : constant Source_Ptr := Sloc (Nod);
2335 Full_Type : Entity_Id;
2336 Prim : Elmt_Id;
2337 Eq_Op : Entity_Id;
2338
1aeb2140 2339 function Find_Primitive_Eq return Node_Id;
2340 -- AI05-0123: Locate primitive equality for type if it exists, and
2341 -- build the corresponding call. If operation is abstract, replace
2342 -- call with an explicit raise. Return Empty if there is no primitive.
2343
2344 -----------------------
2345 -- Find_Primitive_Eq --
2346 -----------------------
2347
2348 function Find_Primitive_Eq return Node_Id is
2349 Prim_E : Elmt_Id;
2350 Prim : Node_Id;
2351
2352 begin
2353 Prim_E := First_Elmt (Collect_Primitive_Operations (Typ));
2354 while Present (Prim_E) loop
2355 Prim := Node (Prim_E);
2356
2357 -- Locate primitive equality with the right signature
2358
2359 if Chars (Prim) = Name_Op_Eq
2360 and then Etype (First_Formal (Prim)) =
9d747a29 2361 Etype (Next_Formal (First_Formal (Prim)))
1aeb2140 2362 and then Etype (Prim) = Standard_Boolean
2363 then
2364 if Is_Abstract_Subprogram (Prim) then
2365 return
2366 Make_Raise_Program_Error (Loc,
2367 Reason => PE_Explicit_Raise);
2368
2369 else
2370 return
2371 Make_Function_Call (Loc,
83c6c069 2372 Name => New_Occurrence_Of (Prim, Loc),
1aeb2140 2373 Parameter_Associations => New_List (Lhs, Rhs));
2374 end if;
2375 end if;
2376
2377 Next_Elmt (Prim_E);
2378 end loop;
2379
2380 -- If not found, predefined operation will be used
2381
2382 return Empty;
2383 end Find_Primitive_Eq;
2384
2385 -- Start of processing for Expand_Composite_Equality
2386
ee6ba406 2387 begin
2388 if Is_Private_Type (Typ) then
2389 Full_Type := Underlying_Type (Typ);
2390 else
2391 Full_Type := Typ;
2392 end if;
2393
f0c20d90 2394 -- If the private type has no completion the context may be the
2395 -- expansion of a composite equality for a composite type with some
2396 -- still incomplete components. The expression will not be analyzed
2397 -- until the enclosing type is completed, at which point this will be
2398 -- properly expanded, unless there is a bona fide completion error.
ee6ba406 2399
2400 if No (Full_Type) then
f0c20d90 2401 return Make_Op_Eq (Loc, Left_Opnd => Lhs, Right_Opnd => Rhs);
ee6ba406 2402 end if;
2403
2404 Full_Type := Base_Type (Full_Type);
2405
e04a8646 2406 -- When the base type itself is private, use the full view to expand
2407 -- the composite equality.
2408
2409 if Is_Private_Type (Full_Type) then
2410 Full_Type := Underlying_Type (Full_Type);
2411 end if;
2412
d4e8ab94 2413 -- Case of array types
2414
ee6ba406 2415 if Is_Array_Type (Full_Type) then
2416
2417 -- If the operand is an elementary type other than a floating-point
2418 -- type, then we can simply use the built-in block bitwise equality,
2419 -- since the predefined equality operators always apply and bitwise
2420 -- equality is fine for all these cases.
2421
2422 if Is_Elementary_Type (Component_Type (Full_Type))
2423 and then not Is_Floating_Point_Type (Component_Type (Full_Type))
2424 then
9d747a29 2425 return Make_Op_Eq (Loc, Left_Opnd => Lhs, Right_Opnd => Rhs);
ee6ba406 2426
f1e2dcc5 2427 -- For composite component types, and floating-point types, use the
2428 -- expansion. This deals with tagged component types (where we use
2429 -- the applicable equality routine) and floating-point, (where we
2430 -- need to worry about negative zeroes), and also the case of any
2431 -- composite type recursively containing such fields.
ee6ba406 2432
2433 else
80d4fec4 2434 return Expand_Array_Equality (Nod, Lhs, Rhs, Bodies, Full_Type);
ee6ba406 2435 end if;
2436
d4e8ab94 2437 -- Case of tagged record types
2438
ee6ba406 2439 elsif Is_Tagged_Type (Full_Type) then
2440
2441 -- Call the primitive operation "=" of this type
2442
2443 if Is_Class_Wide_Type (Full_Type) then
2444 Full_Type := Root_Type (Full_Type);
2445 end if;
2446
f1e2dcc5 2447 -- If this is derived from an untagged private type completed with a
2448 -- tagged type, it does not have a full view, so we use the primitive
2449 -- operations of the private type. This check should no longer be
2450 -- necessary when these types receive their full views ???
ee6ba406 2451
2452 if Is_Private_Type (Typ)
2453 and then not Is_Tagged_Type (Typ)
2454 and then not Is_Controlled (Typ)
2455 and then Is_Derived_Type (Typ)
2456 and then No (Full_View (Typ))
2457 then
2458 Prim := First_Elmt (Collect_Primitive_Operations (Typ));
2459 else
2460 Prim := First_Elmt (Primitive_Operations (Full_Type));
2461 end if;
2462
2463 loop
2464 Eq_Op := Node (Prim);
2465 exit when Chars (Eq_Op) = Name_Op_Eq
2466 and then Etype (First_Formal (Eq_Op)) =
28ed91d4 2467 Etype (Next_Formal (First_Formal (Eq_Op)))
2468 and then Base_Type (Etype (Eq_Op)) = Standard_Boolean;
ee6ba406 2469 Next_Elmt (Prim);
2470 pragma Assert (Present (Prim));
2471 end loop;
2472
2473 Eq_Op := Node (Prim);
2474
2475 return
2476 Make_Function_Call (Loc,
83c6c069 2477 Name => New_Occurrence_Of (Eq_Op, Loc),
ee6ba406 2478 Parameter_Associations =>
2479 New_List
2480 (Unchecked_Convert_To (Etype (First_Formal (Eq_Op)), Lhs),
2481 Unchecked_Convert_To (Etype (First_Formal (Eq_Op)), Rhs)));
2482
d4e8ab94 2483 -- Case of untagged record types
2484
ee6ba406 2485 elsif Is_Record_Type (Full_Type) then
9dfe12ae 2486 Eq_Op := TSS (Full_Type, TSS_Composite_Equality);
ee6ba406 2487
2488 if Present (Eq_Op) then
2489 if Etype (First_Formal (Eq_Op)) /= Full_Type then
2490
f1e2dcc5 2491 -- Inherited equality from parent type. Convert the actuals to
2492 -- match signature of operation.
ee6ba406 2493
2494 declare
9dfe12ae 2495 T : constant Entity_Id := Etype (First_Formal (Eq_Op));
ee6ba406 2496
2497 begin
2498 return
2499 Make_Function_Call (Loc,
83c6c069 2500 Name => New_Occurrence_Of (Eq_Op, Loc),
9d747a29 2501 Parameter_Associations => New_List (
2502 OK_Convert_To (T, Lhs),
2503 OK_Convert_To (T, Rhs)));
ee6ba406 2504 end;
2505
2506 else
00f91aef 2507 -- Comparison between Unchecked_Union components
2508
2509 if Is_Unchecked_Union (Full_Type) then
2510 declare
2511 Lhs_Type : Node_Id := Full_Type;
2512 Rhs_Type : Node_Id := Full_Type;
2513 Lhs_Discr_Val : Node_Id;
2514 Rhs_Discr_Val : Node_Id;
2515
2516 begin
2517 -- Lhs subtype
2518
2519 if Nkind (Lhs) = N_Selected_Component then
2520 Lhs_Type := Etype (Entity (Selector_Name (Lhs)));
2521 end if;
2522
2523 -- Rhs subtype
2524
2525 if Nkind (Rhs) = N_Selected_Component then
2526 Rhs_Type := Etype (Entity (Selector_Name (Rhs)));
2527 end if;
2528
2529 -- Lhs of the composite equality
2530
2531 if Is_Constrained (Lhs_Type) then
2532
f1e2dcc5 2533 -- Since the enclosing record type can never be an
00f91aef 2534 -- Unchecked_Union (this code is executed for records
2535 -- that do not have variants), we may reference its
2536 -- discriminant(s).
2537
2538 if Nkind (Lhs) = N_Selected_Component
6f0d10f7 2539 and then Has_Per_Object_Constraint
2540 (Entity (Selector_Name (Lhs)))
00f91aef 2541 then
2542 Lhs_Discr_Val :=
2543 Make_Selected_Component (Loc,
9d747a29 2544 Prefix => Prefix (Lhs),
00f91aef 2545 Selector_Name =>
9d747a29 2546 New_Copy
2547 (Get_Discriminant_Value
2548 (First_Discriminant (Lhs_Type),
2549 Lhs_Type,
2550 Stored_Constraint (Lhs_Type))));
00f91aef 2551
2552 else
9d747a29 2553 Lhs_Discr_Val :=
2554 New_Copy
2555 (Get_Discriminant_Value
2556 (First_Discriminant (Lhs_Type),
2557 Lhs_Type,
2558 Stored_Constraint (Lhs_Type)));
00f91aef 2559
2560 end if;
2561 else
2562 -- It is not possible to infer the discriminant since
2563 -- the subtype is not constrained.
2564
b374288a 2565 return
00f91aef 2566 Make_Raise_Program_Error (Loc,
b374288a 2567 Reason => PE_Unchecked_Union_Restriction);
00f91aef 2568 end if;
2569
2570 -- Rhs of the composite equality
2571
2572 if Is_Constrained (Rhs_Type) then
2573 if Nkind (Rhs) = N_Selected_Component
9d747a29 2574 and then Has_Per_Object_Constraint
2575 (Entity (Selector_Name (Rhs)))
00f91aef 2576 then
2577 Rhs_Discr_Val :=
2578 Make_Selected_Component (Loc,
9d747a29 2579 Prefix => Prefix (Rhs),
00f91aef 2580 Selector_Name =>
9d747a29 2581 New_Copy
2582 (Get_Discriminant_Value
2583 (First_Discriminant (Rhs_Type),
2584 Rhs_Type,
2585 Stored_Constraint (Rhs_Type))));
00f91aef 2586
2587 else
9d747a29 2588 Rhs_Discr_Val :=
2589 New_Copy
2590 (Get_Discriminant_Value
2591 (First_Discriminant (Rhs_Type),
2592 Rhs_Type,
2593 Stored_Constraint (Rhs_Type)));
00f91aef 2594
2595 end if;
2596 else
b374288a 2597 return
00f91aef 2598 Make_Raise_Program_Error (Loc,
b374288a 2599 Reason => PE_Unchecked_Union_Restriction);
00f91aef 2600 end if;
2601
2602 -- Call the TSS equality function with the inferred
2603 -- discriminant values.
2604
2605 return
2606 Make_Function_Call (Loc,
83c6c069 2607 Name => New_Occurrence_Of (Eq_Op, Loc),
00f91aef 2608 Parameter_Associations => New_List (
2609 Lhs,
2610 Rhs,
2611 Lhs_Discr_Val,
2612 Rhs_Discr_Val));
2613 end;
ff6293ec 2614
c9b6c9b1 2615 -- All cases other than comparing Unchecked_Union types
2616
ff6293ec 2617 else
5145ea08 2618 declare
2619 T : constant Entity_Id := Etype (First_Formal (Eq_Op));
5145ea08 2620 begin
2621 return
2622 Make_Function_Call (Loc,
c9b6c9b1 2623 Name =>
2624 New_Occurrence_Of (Eq_Op, Loc),
5145ea08 2625 Parameter_Associations => New_List (
2626 OK_Convert_To (T, Lhs),
2627 OK_Convert_To (T, Rhs)));
2628 end;
00f91aef 2629 end if;
ff6293ec 2630 end if;
00f91aef 2631
de4993fc 2632 -- Equality composes in Ada 2012 for untagged record types. It also
2633 -- composes for bounded strings, because they are part of the
2634 -- predefined environment. We could make it compose for bounded
2635 -- strings by making them tagged, or by making sure all subcomponents
2636 -- are set to the same value, even when not used. Instead, we have
2637 -- this special case in the compiler, because it's more efficient.
2638
2639 elsif Ada_Version >= Ada_2012 or else Is_Bounded_String (Typ) then
00f91aef 2640
aab75e08 2641 -- If no TSS has been created for the type, check whether there is
1aeb2140 2642 -- a primitive equality declared for it.
ff6293ec 2643
2644 declare
de4993fc 2645 Op : constant Node_Id := Find_Primitive_Eq;
ff6293ec 2646
2647 begin
385d80fe 2648 -- Use user-defined primitive if it exists, otherwise use
2649 -- predefined equality.
2650
de4993fc 2651 if Present (Op) then
2652 return Op;
1aeb2140 2653 else
1aeb2140 2654 return Make_Op_Eq (Loc, Lhs, Rhs);
2655 end if;
ff6293ec 2656 end;
2657
ee6ba406 2658 else
2659 return Expand_Record_Equality (Nod, Full_Type, Lhs, Rhs, Bodies);
2660 end if;
2661
d4e8ab94 2662 -- Non-composite types (always use predefined equality)
ee6ba406 2663
d4e8ab94 2664 else
ee6ba406 2665 return Make_Op_Eq (Loc, Left_Opnd => Lhs, Right_Opnd => Rhs);
2666 end if;
2667 end Expand_Composite_Equality;
2668
440ec0be 2669 ------------------------
2670 -- Expand_Concatenate --
2671 ------------------------
ee6ba406 2672
440ec0be 2673 procedure Expand_Concatenate (Cnode : Node_Id; Opnds : List_Id) is
2674 Loc : constant Source_Ptr := Sloc (Cnode);
ee6ba406 2675
440ec0be 2676 Atyp : constant Entity_Id := Base_Type (Etype (Cnode));
2677 -- Result type of concatenation
ee6ba406 2678
440ec0be 2679 Ctyp : constant Entity_Id := Base_Type (Component_Type (Etype (Cnode)));
2680 -- Component type. Elements of this component type can appear as one
2681 -- of the operands of concatenation as well as arrays.
ee6ba406 2682
107ec33e 2683 Istyp : constant Entity_Id := Etype (First_Index (Atyp));
2684 -- Index subtype
2685
2686 Ityp : constant Entity_Id := Base_Type (Istyp);
2687 -- Index type. This is the base type of the index subtype, and is used
2688 -- for all computed bounds (which may be out of range of Istyp in the
2689 -- case of null ranges).
ee6ba406 2690
e92a2f27 2691 Artyp : Entity_Id;
440ec0be 2692 -- This is the type we use to do arithmetic to compute the bounds and
2693 -- lengths of operands. The choice of this type is a little subtle and
2694 -- is discussed in a separate section at the start of the body code.
ee6ba406 2695
440ec0be 2696 Concatenation_Error : exception;
2697 -- Raised if concatenation is sure to raise a CE
ee6ba406 2698
aab73971 2699 Result_May_Be_Null : Boolean := True;
2700 -- Reset to False if at least one operand is encountered which is known
2701 -- at compile time to be non-null. Used for handling the special case
2702 -- of setting the high bound to the last operand high bound for a null
2703 -- result, thus ensuring a proper high bound in the super-flat case.
2704
e37ded63 2705 N : constant Nat := List_Length (Opnds);
440ec0be 2706 -- Number of concatenation operands including possibly null operands
e37ded63 2707
2708 NN : Nat := 0;
0a5976bd 2709 -- Number of operands excluding any known to be null, except that the
2710 -- last operand is always retained, in case it provides the bounds for
2711 -- a null result.
2712
16149377 2713 Opnd : Node_Id := Empty;
0a5976bd 2714 -- Current operand being processed in the loop through operands. After
2715 -- this loop is complete, always contains the last operand (which is not
2716 -- the same as Operands (NN), since null operands are skipped).
e37ded63 2717
2718 -- Arrays describing the operands, only the first NN entries of each
2719 -- array are set (NN < N when we exclude known null operands).
2720
2721 Is_Fixed_Length : array (1 .. N) of Boolean;
2722 -- True if length of corresponding operand known at compile time
2723
2724 Operands : array (1 .. N) of Node_Id;
0a5976bd 2725 -- Set to the corresponding entry in the Opnds list (but note that null
2726 -- operands are excluded, so not all entries in the list are stored).
e37ded63 2727
2728 Fixed_Length : array (1 .. N) of Uint;
440ec0be 2729 -- Set to length of operand. Entries in this array are set only if the
2730 -- corresponding entry in Is_Fixed_Length is True.
e37ded63 2731
aab73971 2732 Opnd_Low_Bound : array (1 .. N) of Node_Id;
2733 -- Set to lower bound of operand. Either an integer literal in the case
2734 -- where the bound is known at compile time, else actual lower bound.
2735 -- The operand low bound is of type Ityp.
2736
e37ded63 2737 Var_Length : array (1 .. N) of Entity_Id;
2738 -- Set to an entity of type Natural that contains the length of an
2739 -- operand whose length is not known at compile time. Entries in this
2740 -- array are set only if the corresponding entry in Is_Fixed_Length
e92a2f27 2741 -- is False. The entity is of type Artyp.
e37ded63 2742
2743 Aggr_Length : array (0 .. N) of Node_Id;
440ec0be 2744 -- The J'th entry in an expression node that represents the total length
2745 -- of operands 1 through J. It is either an integer literal node, or a
2746 -- reference to a constant entity with the right value, so it is fine
2747 -- to just do a Copy_Node to get an appropriate copy. The extra zero'th
e92a2f27 2748 -- entry always is set to zero. The length is of type Artyp.
e37ded63 2749
2750 Low_Bound : Node_Id;
aab73971 2751 -- A tree node representing the low bound of the result (of type Ityp).
2752 -- This is either an integer literal node, or an identifier reference to
2753 -- a constant entity initialized to the appropriate value.
2754
16149377 2755 Last_Opnd_Low_Bound : Node_Id := Empty;
362e5ece 2756 -- A tree node representing the low bound of the last operand. This
2757 -- need only be set if the result could be null. It is used for the
2758 -- special case of setting the right low bound for a null result.
2759 -- This is of type Ityp.
2760
16149377 2761 Last_Opnd_High_Bound : Node_Id := Empty;
0a5976bd 2762 -- A tree node representing the high bound of the last operand. This
2763 -- need only be set if the result could be null. It is used for the
2764 -- special case of setting the right high bound for a null result.
2765 -- This is of type Ityp.
2766
aab73971 2767 High_Bound : Node_Id;
2768 -- A tree node representing the high bound of the result (of type Ityp)
e37ded63 2769
2770 Result : Node_Id;
aab73971 2771 -- Result of the concatenation (of type Ityp)
e37ded63 2772
2b4d7555 2773 Actions : constant List_Id := New_List;
c19abba7 2774 -- Collect actions to be inserted
2b4d7555 2775
b6772205 2776 Known_Non_Null_Operand_Seen : Boolean;
6fb3c314 2777 -- Set True during generation of the assignments of operands into
b6772205 2778 -- result once an operand known to be non-null has been seen.
2779
4685dd6f 2780 function Library_Level_Target return Boolean;
2781 -- Return True if the concatenation is within the expression of the
2782 -- declaration of a library-level object.
2783
b6772205 2784 function Make_Artyp_Literal (Val : Nat) return Node_Id;
2785 -- This function makes an N_Integer_Literal node that is returned in
2786 -- analyzed form with the type set to Artyp. Importantly this literal
2787 -- is not flagged as static, so that if we do computations with it that
2788 -- result in statically detected out of range conditions, we will not
2789 -- generate error messages but instead warning messages.
2790
e92a2f27 2791 function To_Artyp (X : Node_Id) return Node_Id;
440ec0be 2792 -- Given a node of type Ityp, returns the corresponding value of type
a50e85e5 2793 -- Artyp. For non-enumeration types, this is a plain integer conversion.
2794 -- For enum types, the Pos of the value is returned.
440ec0be 2795
2796 function To_Ityp (X : Node_Id) return Node_Id;
aab73971 2797 -- The inverse function (uses Val in the case of enumeration types)
440ec0be 2798
4685dd6f 2799 --------------------------
2800 -- Library_Level_Target --
2801 --------------------------
2802
2803 function Library_Level_Target return Boolean is
2804 P : Node_Id := Parent (Cnode);
2805
2806 begin
2807 while Present (P) loop
2808 if Nkind (P) = N_Object_Declaration then
2809 return Is_Library_Level_Entity (Defining_Identifier (P));
2810
2811 -- Prevent the search from going too far
2812
2813 elsif Is_Body_Or_Package_Declaration (P) then
2814 return False;
2815 end if;
2816
2817 P := Parent (P);
2818 end loop;
2819
2820 return False;
2821 end Library_Level_Target;
2822
b6772205 2823 ------------------------
2824 -- Make_Artyp_Literal --
2825 ------------------------
2826
2827 function Make_Artyp_Literal (Val : Nat) return Node_Id is
2828 Result : constant Node_Id := Make_Integer_Literal (Loc, Val);
2829 begin
2830 Set_Etype (Result, Artyp);
2831 Set_Analyzed (Result, True);
2832 Set_Is_Static_Expression (Result, False);
2833 return Result;
2834 end Make_Artyp_Literal;
a50e85e5 2835
440ec0be 2836 --------------
e92a2f27 2837 -- To_Artyp --
440ec0be 2838 --------------
2839
e92a2f27 2840 function To_Artyp (X : Node_Id) return Node_Id is
440ec0be 2841 begin
e92a2f27 2842 if Ityp = Base_Type (Artyp) then
440ec0be 2843 return X;
2844
2845 elsif Is_Enumeration_Type (Ityp) then
2846 return
2847 Make_Attribute_Reference (Loc,
2848 Prefix => New_Occurrence_Of (Ityp, Loc),
2849 Attribute_Name => Name_Pos,
2850 Expressions => New_List (X));
2851
2852 else
e92a2f27 2853 return Convert_To (Artyp, X);
440ec0be 2854 end if;
e92a2f27 2855 end To_Artyp;
440ec0be 2856
2857 -------------
2858 -- To_Ityp --
2859 -------------
2860
2861 function To_Ityp (X : Node_Id) return Node_Id is
2862 begin
769e3ade 2863 if Is_Enumeration_Type (Ityp) then
440ec0be 2864 return
2865 Make_Attribute_Reference (Loc,
2866 Prefix => New_Occurrence_Of (Ityp, Loc),
2867 Attribute_Name => Name_Val,
2868 Expressions => New_List (X));
2869
2870 -- Case where we will do a type conversion
2871
2872 else
a50e85e5 2873 if Ityp = Base_Type (Artyp) then
2874 return X;
440ec0be 2875 else
a50e85e5 2876 return Convert_To (Ityp, X);
440ec0be 2877 end if;
2878 end if;
2879 end To_Ityp;
2880
2881 -- Local Declarations
2882
aab73971 2883 Opnd_Typ : Entity_Id;
2884 Ent : Entity_Id;
2885 Len : Uint;
2886 J : Nat;
2887 Clen : Node_Id;
2888 Set : Boolean;
ee6ba406 2889
79500ea0 2890 -- Start of processing for Expand_Concatenate
2891
ee6ba406 2892 begin
440ec0be 2893 -- Choose an appropriate computational type
2894
2895 -- We will be doing calculations of lengths and bounds in this routine
2896 -- and computing one from the other in some cases, e.g. getting the high
2897 -- bound by adding the length-1 to the low bound.
2898
2899 -- We can't just use the index type, or even its base type for this
2900 -- purpose for two reasons. First it might be an enumeration type which
6fb3c314 2901 -- is not suitable for computations of any kind, and second it may
2902 -- simply not have enough range. For example if the index type is
2903 -- -128..+127 then lengths can be up to 256, which is out of range of
2904 -- the type.
440ec0be 2905
2906 -- For enumeration types, we can simply use Standard_Integer, this is
2907 -- sufficient since the actual number of enumeration literals cannot
2908 -- possibly exceed the range of integer (remember we will be doing the
aab73971 2909 -- arithmetic with POS values, not representation values).
440ec0be 2910
2911 if Is_Enumeration_Type (Ityp) then
e92a2f27 2912 Artyp := Standard_Integer;
440ec0be 2913
d70d22d5 2914 -- If index type is Positive, we use the standard unsigned type, to give
2915 -- more room on the top of the range, obviating the need for an overflow
2916 -- check when creating the upper bound. This is needed to avoid junk
2917 -- overflow checks in the common case of String types.
2918
2919 -- ??? Disabled for now
2920
2921 -- elsif Istyp = Standard_Positive then
2922 -- Artyp := Standard_Unsigned;
2923
769e3ade 2924 -- For modular types, we use a 32-bit modular type for types whose size
2925 -- is in the range 1-31 bits. For 32-bit unsigned types, we use the
2926 -- identity type, and for larger unsigned types we use 64-bits.
440ec0be 2927
769e3ade 2928 elsif Is_Modular_Integer_Type (Ityp) then
107ec33e 2929 if RM_Size (Ityp) < RM_Size (Standard_Unsigned) then
e92a2f27 2930 Artyp := Standard_Unsigned;
107ec33e 2931 elsif RM_Size (Ityp) = RM_Size (Standard_Unsigned) then
e92a2f27 2932 Artyp := Ityp;
440ec0be 2933 else
e92a2f27 2934 Artyp := RTE (RE_Long_Long_Unsigned);
440ec0be 2935 end if;
2936
769e3ade 2937 -- Similar treatment for signed types
440ec0be 2938
2939 else
107ec33e 2940 if RM_Size (Ityp) < RM_Size (Standard_Integer) then
e92a2f27 2941 Artyp := Standard_Integer;
107ec33e 2942 elsif RM_Size (Ityp) = RM_Size (Standard_Integer) then
e92a2f27 2943 Artyp := Ityp;
440ec0be 2944 else
e92a2f27 2945 Artyp := Standard_Long_Long_Integer;
440ec0be 2946 end if;
2947 end if;
2948
b6772205 2949 -- Supply dummy entry at start of length array
2950
2951 Aggr_Length (0) := Make_Artyp_Literal (0);
2952
440ec0be 2953 -- Go through operands setting up the above arrays
ee6ba406 2954
e37ded63 2955 J := 1;
2956 while J <= N loop
2957 Opnd := Remove_Head (Opnds);
aab73971 2958 Opnd_Typ := Etype (Opnd);
440ec0be 2959
2960 -- The parent got messed up when we put the operands in a list,
5b990e08 2961 -- so now put back the proper parent for the saved operand, that
2962 -- is to say the concatenation node, to make sure that each operand
2963 -- is seen as a subexpression, e.g. if actions must be inserted.
440ec0be 2964
5b990e08 2965 Set_Parent (Opnd, Cnode);
440ec0be 2966
2967 -- Set will be True when we have setup one entry in the array
2968
e37ded63 2969 Set := False;
2970
440ec0be 2971 -- Singleton element (or character literal) case
e37ded63 2972
aab73971 2973 if Base_Type (Opnd_Typ) = Ctyp then
e37ded63 2974 NN := NN + 1;
2975 Operands (NN) := Opnd;
2976 Is_Fixed_Length (NN) := True;
2977 Fixed_Length (NN) := Uint_1;
aab73971 2978 Result_May_Be_Null := False;
440ec0be 2979
0a5976bd 2980 -- Set low bound of operand (no need to set Last_Opnd_High_Bound
2981 -- since we know that the result cannot be null).
440ec0be 2982
aab73971 2983 Opnd_Low_Bound (NN) :=
2984 Make_Attribute_Reference (Loc,
83c6c069 2985 Prefix => New_Occurrence_Of (Istyp, Loc),
aab73971 2986 Attribute_Name => Name_First);
2987
e37ded63 2988 Set := True;
2989
440ec0be 2990 -- String literal case (can only occur for strings of course)
e37ded63 2991
2992 elsif Nkind (Opnd) = N_String_Literal then
aab73971 2993 Len := String_Literal_Length (Opnd_Typ);
e37ded63 2994
0a5976bd 2995 if Len /= 0 then
2996 Result_May_Be_Null := False;
2997 end if;
2998
362e5ece 2999 -- Capture last operand low and high bound if result could be null
0a5976bd 3000
3001 if J = N and then Result_May_Be_Null then
362e5ece 3002 Last_Opnd_Low_Bound :=
3003 New_Copy_Tree (String_Literal_Low_Bound (Opnd_Typ));
3004
0a5976bd 3005 Last_Opnd_High_Bound :=
362e5ece 3006 Make_Op_Subtract (Loc,
0a5976bd 3007 Left_Opnd =>
3008 New_Copy_Tree (String_Literal_Low_Bound (Opnd_Typ)),
d70d22d5 3009 Right_Opnd => Make_Integer_Literal (Loc, 1));
0a5976bd 3010 end if;
3011
3012 -- Skip null string literal
440ec0be 3013
aab73971 3014 if J < N and then Len = 0 then
e37ded63 3015 goto Continue;
3016 end if;
3017
3018 NN := NN + 1;
3019 Operands (NN) := Opnd;
3020 Is_Fixed_Length (NN) := True;
aab73971 3021
3022 -- Set length and bounds
3023
e37ded63 3024 Fixed_Length (NN) := Len;
aab73971 3025
3026 Opnd_Low_Bound (NN) :=
3027 New_Copy_Tree (String_Literal_Low_Bound (Opnd_Typ));
3028
e37ded63 3029 Set := True;
3030
3031 -- All other cases
3032
3033 else
3034 -- Check constrained case with known bounds
3035
aab73971 3036 if Is_Constrained (Opnd_Typ) then
e37ded63 3037 declare
e37ded63 3038 Index : constant Node_Id := First_Index (Opnd_Typ);
3039 Indx_Typ : constant Entity_Id := Etype (Index);
3040 Lo : constant Node_Id := Type_Low_Bound (Indx_Typ);
3041 Hi : constant Node_Id := Type_High_Bound (Indx_Typ);
3042
3043 begin
440ec0be 3044 -- Fixed length constrained array type with known at compile
3045 -- time bounds is last case of fixed length operand.
e37ded63 3046
3047 if Compile_Time_Known_Value (Lo)
3048 and then
3049 Compile_Time_Known_Value (Hi)
3050 then
3051 declare
3052 Loval : constant Uint := Expr_Value (Lo);
3053 Hival : constant Uint := Expr_Value (Hi);
3054 Len : constant Uint :=
3055 UI_Max (Hival - Loval + 1, Uint_0);
3056
3057 begin
aab73971 3058 if Len > 0 then
3059 Result_May_Be_Null := False;
e37ded63 3060 end if;
aab73971 3061
362e5ece 3062 -- Capture last operand bounds if result could be null
0a5976bd 3063
3064 if J = N and then Result_May_Be_Null then
362e5ece 3065 Last_Opnd_Low_Bound :=
3066 Convert_To (Ityp,
3067 Make_Integer_Literal (Loc, Expr_Value (Lo)));
3068
0a5976bd 3069 Last_Opnd_High_Bound :=
3070 Convert_To (Ityp,
9d747a29 3071 Make_Integer_Literal (Loc, Expr_Value (Hi)));
0a5976bd 3072 end if;
3073
3074 -- Exclude null length case unless last operand
aab73971 3075
0a5976bd 3076 if J < N and then Len = 0 then
aab73971 3077 goto Continue;
3078 end if;
3079
3080 NN := NN + 1;
3081 Operands (NN) := Opnd;
3082 Is_Fixed_Length (NN) := True;
3083 Fixed_Length (NN) := Len;
3084
9d747a29 3085 Opnd_Low_Bound (NN) :=
3086 To_Ityp
3087 (Make_Integer_Literal (Loc, Expr_Value (Lo)));
aab73971 3088 Set := True;
e37ded63 3089 end;
3090 end if;
3091 end;
3092 end if;
3093
aab73971 3094 -- All cases where the length is not known at compile time, or the
3095 -- special case of an operand which is known to be null but has a
3096 -- lower bound other than 1 or is other than a string type.
e37ded63 3097
3098 if not Set then
3099 NN := NN + 1;
aab73971 3100
3101 -- Capture operand bounds
3102
3103 Opnd_Low_Bound (NN) :=
3104 Make_Attribute_Reference (Loc,
3105 Prefix =>
3106 Duplicate_Subexpr (Opnd, Name_Req => True),
3107 Attribute_Name => Name_First);
3108
362e5ece 3109 -- Capture last operand bounds if result could be null
3110
0a5976bd 3111 if J = N and Result_May_Be_Null then
362e5ece 3112 Last_Opnd_Low_Bound :=
3113 Convert_To (Ityp,
3114 Make_Attribute_Reference (Loc,
3115 Prefix =>
3116 Duplicate_Subexpr (Opnd, Name_Req => True),
3117 Attribute_Name => Name_First));
3118
0a5976bd 3119 Last_Opnd_High_Bound :=
3120 Convert_To (Ityp,
3121 Make_Attribute_Reference (Loc,
3122 Prefix =>
3123 Duplicate_Subexpr (Opnd, Name_Req => True),
3124 Attribute_Name => Name_Last));
3125 end if;
aab73971 3126
3127 -- Capture length of operand in entity
3128
e37ded63 3129 Operands (NN) := Opnd;
3130 Is_Fixed_Length (NN) := False;
3131
46eb6933 3132 Var_Length (NN) := Make_Temporary (Loc, 'L');
e37ded63 3133
2b4d7555 3134 Append_To (Actions,
e37ded63 3135 Make_Object_Declaration (Loc,
3136 Defining_Identifier => Var_Length (NN),
3137 Constant_Present => True,
9d747a29 3138 Object_Definition => New_Occurrence_Of (Artyp, Loc),
e37ded63 3139 Expression =>
3140 Make_Attribute_Reference (Loc,
3141 Prefix =>
3142 Duplicate_Subexpr (Opnd, Name_Req => True),
2b4d7555 3143 Attribute_Name => Name_Length)));
e37ded63 3144 end if;
3145 end if;
3146
3147 -- Set next entry in aggregate length array
3148
3149 -- For first entry, make either integer literal for fixed length
aab73971 3150 -- or a reference to the saved length for variable length.
e37ded63 3151
3152 if NN = 1 then
3153 if Is_Fixed_Length (1) then
9d747a29 3154 Aggr_Length (1) := Make_Integer_Literal (Loc, Fixed_Length (1));
e37ded63 3155 else
83c6c069 3156 Aggr_Length (1) := New_Occurrence_Of (Var_Length (1), Loc);
e37ded63 3157 end if;
3158
3159 -- If entry is fixed length and only fixed lengths so far, make
3160 -- appropriate new integer literal adding new length.
3161
3162 elsif Is_Fixed_Length (NN)
3163 and then Nkind (Aggr_Length (NN - 1)) = N_Integer_Literal
3164 then
3165 Aggr_Length (NN) :=
3166 Make_Integer_Literal (Loc,
3167 Intval => Fixed_Length (NN) + Intval (Aggr_Length (NN - 1)));
3168
2b4d7555 3169 -- All other cases, construct an addition node for the length and
3170 -- create an entity initialized to this length.
e37ded63 3171
3172 else
46eb6933 3173 Ent := Make_Temporary (Loc, 'L');
e37ded63 3174
3175 if Is_Fixed_Length (NN) then
3176 Clen := Make_Integer_Literal (Loc, Fixed_Length (NN));
3177 else
83c6c069 3178 Clen := New_Occurrence_Of (Var_Length (NN), Loc);
e37ded63 3179 end if;
3180
2b4d7555 3181 Append_To (Actions,
e37ded63 3182 Make_Object_Declaration (Loc,
3183 Defining_Identifier => Ent,
3184 Constant_Present => True,
9d747a29 3185 Object_Definition => New_Occurrence_Of (Artyp, Loc),
e37ded63 3186 Expression =>
3187 Make_Op_Add (Loc,
4cb8adff 3188 Left_Opnd => New_Copy_Tree (Aggr_Length (NN - 1)),
2b4d7555 3189 Right_Opnd => Clen)));
e37ded63 3190
a50e85e5 3191 Aggr_Length (NN) := Make_Identifier (Loc, Chars => Chars (Ent));
e37ded63 3192 end if;
3193
3194 <<Continue>>
3195 J := J + 1;
3196 end loop;
3197
0a5976bd 3198 -- If we have only skipped null operands, return the last operand
e37ded63 3199
3200 if NN = 0 then
0a5976bd 3201 Result := Opnd;
e37ded63 3202 goto Done;
3203 end if;
3204
3205 -- If we have only one non-null operand, return it and we are done.
3206 -- There is one case in which this cannot be done, and that is when
440ec0be 3207 -- the sole operand is of the element type, in which case it must be
3208 -- converted to an array, and the easiest way of doing that is to go
e37ded63 3209 -- through the normal general circuit.
3210
6f0d10f7 3211 if NN = 1 and then Base_Type (Etype (Operands (1))) /= Ctyp then
e37ded63 3212 Result := Operands (1);
3213 goto Done;
3214 end if;
3215
3216 -- Cases where we have a real concatenation
3217
440ec0be 3218 -- Next step is to find the low bound for the result array that we
3219 -- will allocate. The rules for this are in (RM 4.5.6(5-7)).
3220
3221 -- If the ultimate ancestor of the index subtype is a constrained array
3222 -- definition, then the lower bound is that of the index subtype as
3223 -- specified by (RM 4.5.3(6)).
3224
3225 -- The right test here is to go to the root type, and then the ultimate
3226 -- ancestor is the first subtype of this root type.
3227
3228 if Is_Constrained (First_Subtype (Root_Type (Atyp))) then
aab73971 3229 Low_Bound :=
440ec0be 3230 Make_Attribute_Reference (Loc,
3231 Prefix =>
3232 New_Occurrence_Of (First_Subtype (Root_Type (Atyp)), Loc),
aab73971 3233 Attribute_Name => Name_First);
e37ded63 3234
3235 -- If the first operand in the list has known length we know that
3236 -- the lower bound of the result is the lower bound of this operand.
3237
440ec0be 3238 elsif Is_Fixed_Length (1) then
aab73971 3239 Low_Bound := Opnd_Low_Bound (1);
e37ded63 3240
3241 -- OK, we don't know the lower bound, we have to build a horrible
92f1631f 3242 -- if expression node of the form
e37ded63 3243
3244 -- if Cond1'Length /= 0 then
aab73971 3245 -- Opnd1 low bound
e37ded63 3246 -- else
3247 -- if Opnd2'Length /= 0 then
aab73971 3248 -- Opnd2 low bound
e37ded63 3249 -- else
3250 -- ...
3251
3252 -- The nesting ends either when we hit an operand whose length is known
3253 -- at compile time, or on reaching the last operand, whose low bound we
3254 -- take unconditionally whether or not it is null. It's easiest to do
3255 -- this with a recursive procedure:
3256
3257 else
3258 declare
3259 function Get_Known_Bound (J : Nat) return Node_Id;
3260 -- Returns the lower bound determined by operands J .. NN
3261
3262 ---------------------
3263 -- Get_Known_Bound --
3264 ---------------------
3265
3266 function Get_Known_Bound (J : Nat) return Node_Id is
e37ded63 3267 begin
aab73971 3268 if Is_Fixed_Length (J) or else J = NN then
4cb8adff 3269 return New_Copy_Tree (Opnd_Low_Bound (J));
ee6ba406 3270
3271 else
e37ded63 3272 return
92f1631f 3273 Make_If_Expression (Loc,
e37ded63 3274 Expressions => New_List (
3275
3276 Make_Op_Ne (Loc,
83c6c069 3277 Left_Opnd =>
3278 New_Occurrence_Of (Var_Length (J), Loc),
3279 Right_Opnd =>
3280 Make_Integer_Literal (Loc, 0)),
e37ded63 3281
4cb8adff 3282 New_Copy_Tree (Opnd_Low_Bound (J)),
e37ded63 3283 Get_Known_Bound (J + 1)));
ee6ba406 3284 end if;
e37ded63 3285 end Get_Known_Bound;
ee6ba406 3286
e37ded63 3287 begin
46eb6933 3288 Ent := Make_Temporary (Loc, 'L');
e37ded63 3289
2b4d7555 3290 Append_To (Actions,
e37ded63 3291 Make_Object_Declaration (Loc,
3292 Defining_Identifier => Ent,
3293 Constant_Present => True,
aab73971 3294 Object_Definition => New_Occurrence_Of (Ityp, Loc),
2b4d7555 3295 Expression => Get_Known_Bound (1)));
e37ded63 3296
83c6c069 3297 Low_Bound := New_Occurrence_Of (Ent, Loc);
e37ded63 3298 end;
3299 end if;
ee6ba406 3300
a50e85e5 3301 -- Now we can safely compute the upper bound, normally
3302 -- Low_Bound + Length - 1.
aab73971 3303
3304 High_Bound :=
82b93248 3305 To_Ityp
3306 (Make_Op_Add (Loc,
4cb8adff 3307 Left_Opnd => To_Artyp (New_Copy_Tree (Low_Bound)),
82b93248 3308 Right_Opnd =>
3309 Make_Op_Subtract (Loc,
4cb8adff 3310 Left_Opnd => New_Copy_Tree (Aggr_Length (NN)),
82b93248 3311 Right_Opnd => Make_Artyp_Literal (1))));
aab73971 3312
d70d22d5 3313 -- Note that calculation of the high bound may cause overflow in some
45045496 3314 -- very weird cases, so in the general case we need an overflow check on
3315 -- the high bound. We can avoid this for the common case of string types
3316 -- and other types whose index is Positive, since we chose a wider range
b3defed3 3317 -- for the arithmetic type. If checks are suppressed we do not set the
3318 -- flag, and possibly superfluous warnings will be omitted.
a50e85e5 3319
b3defed3 3320 if Istyp /= Standard_Positive
3321 and then not Overflow_Checks_Suppressed (Istyp)
3322 then
d70d22d5 3323 Activate_Overflow_Check (High_Bound);
3324 end if;
a50e85e5 3325
3326 -- Handle the exceptional case where the result is null, in which case
0a5976bd 3327 -- case the bounds come from the last operand (so that we get the proper
3328 -- bounds if the last operand is super-flat).
3329
aab73971 3330 if Result_May_Be_Null then
362e5ece 3331 Low_Bound :=
92f1631f 3332 Make_If_Expression (Loc,
362e5ece 3333 Expressions => New_List (
3334 Make_Op_Eq (Loc,
4cb8adff 3335 Left_Opnd => New_Copy_Tree (Aggr_Length (NN)),
362e5ece 3336 Right_Opnd => Make_Artyp_Literal (0)),
3337 Last_Opnd_Low_Bound,
3338 Low_Bound));
3339
aab73971 3340 High_Bound :=
92f1631f 3341 Make_If_Expression (Loc,
aab73971 3342 Expressions => New_List (
3343 Make_Op_Eq (Loc,
4cb8adff 3344 Left_Opnd => New_Copy_Tree (Aggr_Length (NN)),
b6772205 3345 Right_Opnd => Make_Artyp_Literal (0)),
0a5976bd 3346 Last_Opnd_High_Bound,
aab73971 3347 High_Bound));
3348 end if;
3349
2b4d7555 3350 -- Here is where we insert the saved up actions
3351
3352 Insert_Actions (Cnode, Actions, Suppress => All_Checks);
3353
bbc7bed2 3354 -- Now we construct an array object with appropriate bounds. We mark
3355 -- the target as internal to prevent useless initialization when
4a473cb9 3356 -- Initialize_Scalars is enabled. Also since this is the actual result
3357 -- entity, we make sure we have debug information for the result.
ee6ba406 3358
46eb6933 3359 Ent := Make_Temporary (Loc, 'S');
70be2d3a 3360 Set_Is_Internal (Ent);
4a473cb9 3361 Set_Needs_Debug_Info (Ent);
ee6ba406 3362
a50e85e5 3363 -- If the bound is statically known to be out of range, we do not want
b6772205 3364 -- to abort, we want a warning and a runtime constraint error. Note that
3365 -- we have arranged that the result will not be treated as a static
3366 -- constant, so we won't get an illegality during this insertion.
a50e85e5 3367
e37ded63 3368 Insert_Action (Cnode,
3369 Make_Object_Declaration (Loc,
3370 Defining_Identifier => Ent,
e37ded63 3371 Object_Definition =>
3372 Make_Subtype_Indication (Loc,
440ec0be 3373 Subtype_Mark => New_Occurrence_Of (Atyp, Loc),
e37ded63 3374 Constraint =>
3375 Make_Index_Or_Discriminant_Constraint (Loc,
3376 Constraints => New_List (
3377 Make_Range (Loc,
aab73971 3378 Low_Bound => Low_Bound,
3379 High_Bound => High_Bound))))),
e37ded63 3380 Suppress => All_Checks);
3381
148b2476 3382 -- If the result of the concatenation appears as the initializing
3383 -- expression of an object declaration, we can just rename the
3384 -- result, rather than copying it.
3385
3386 Set_OK_To_Rename (Ent);
3387
a50e85e5 3388 -- Catch the static out of range case now
3389
3390 if Raises_Constraint_Error (High_Bound) then
3391 raise Concatenation_Error;
3392 end if;
3393
e37ded63 3394 -- Now we will generate the assignments to do the actual concatenation
3395
45045496 3396 -- There is one case in which we will not do this, namely when all the
3397 -- following conditions are met:
3398
3399 -- The result type is Standard.String
3400
3401 -- There are nine or fewer retained (non-null) operands
3402
4685dd6f 3403 -- The optimization level is -O0 or the debug flag gnatd.C is set,
3404 -- and the debug flag gnatd.c is not set.
45045496 3405
3406 -- The corresponding System.Concat_n.Str_Concat_n routine is
3407 -- available in the run time.
3408
45045496 3409 -- If all these conditions are met then we generate a call to the
3410 -- relevant concatenation routine. The purpose of this is to avoid
3411 -- undesirable code bloat at -O0.
3412
4685dd6f 3413 -- If the concatenation is within the declaration of a library-level
3414 -- object, we call the built-in concatenation routines to prevent code
3415 -- bloat, regardless of the optimization level. This is space efficient
3416 -- and prevents linking problems when units are compiled with different
3417 -- optimization levels.
3418
45045496 3419 if Atyp = Standard_String
3420 and then NN in 2 .. 9
4685dd6f 3421 and then (((Optimization_Level = 0 or else Debug_Flag_Dot_CC)
3422 and then not Debug_Flag_Dot_C)
3423 or else Library_Level_Target)
45045496 3424 then
3425 declare
3426 RR : constant array (Nat range 2 .. 9) of RE_Id :=
3427 (RE_Str_Concat_2,
3428 RE_Str_Concat_3,
3429 RE_Str_Concat_4,
3430 RE_Str_Concat_5,
3431 RE_Str_Concat_6,
3432 RE_Str_Concat_7,
3433 RE_Str_Concat_8,
3434 RE_Str_Concat_9);
3435
3436 begin
3437 if RTE_Available (RR (NN)) then
3438 declare
3439 Opnds : constant List_Id :=
3440 New_List (New_Occurrence_Of (Ent, Loc));
3441
3442 begin
3443 for J in 1 .. NN loop
3444 if Is_List_Member (Operands (J)) then
3445 Remove (Operands (J));
3446 end if;
3447
3448 if Base_Type (Etype (Operands (J))) = Ctyp then
3449 Append_To (Opnds,
3450 Make_Aggregate (Loc,
3451 Component_Associations => New_List (
3452 Make_Component_Association (Loc,
3453 Choices => New_List (
3454 Make_Integer_Literal (Loc, 1)),
3455 Expression => Operands (J)))));
3456
3457 else
3458 Append_To (Opnds, Operands (J));
3459 end if;
3460 end loop;
3461
3462 Insert_Action (Cnode,
3463 Make_Procedure_Call_Statement (Loc,
83c6c069 3464 Name => New_Occurrence_Of (RTE (RR (NN)), Loc),
45045496 3465 Parameter_Associations => Opnds));
3466
83c6c069 3467 Result := New_Occurrence_Of (Ent, Loc);
45045496 3468 goto Done;
3469 end;
3470 end if;
3471 end;
3472 end if;
3473
3474 -- Not special case so generate the assignments
3475
a50e85e5 3476 Known_Non_Null_Operand_Seen := False;
3477
e37ded63 3478 for J in 1 .. NN loop
3479 declare
3480 Lo : constant Node_Id :=
3481 Make_Op_Add (Loc,
4cb8adff 3482 Left_Opnd => To_Artyp (New_Copy_Tree (Low_Bound)),
e37ded63 3483 Right_Opnd => Aggr_Length (J - 1));
3484
3485 Hi : constant Node_Id :=
3486 Make_Op_Add (Loc,
4cb8adff 3487 Left_Opnd => To_Artyp (New_Copy_Tree (Low_Bound)),
e37ded63 3488 Right_Opnd =>
3489 Make_Op_Subtract (Loc,
3490 Left_Opnd => Aggr_Length (J),
b6772205 3491 Right_Opnd => Make_Artyp_Literal (1)));
ee6ba406 3492
e37ded63 3493 begin
440ec0be 3494 -- Singleton case, simple assignment
3495
3496 if Base_Type (Etype (Operands (J))) = Ctyp then
a50e85e5 3497 Known_Non_Null_Operand_Seen := True;
e37ded63 3498 Insert_Action (Cnode,
3499 Make_Assignment_Statement (Loc,
3500 Name =>
3501 Make_Indexed_Component (Loc,
3502 Prefix => New_Occurrence_Of (Ent, Loc),
440ec0be 3503 Expressions => New_List (To_Ityp (Lo))),
e37ded63 3504 Expression => Operands (J)),
3505 Suppress => All_Checks);
ee6ba406 3506
a50e85e5 3507 -- Array case, slice assignment, skipped when argument is fixed
3508 -- length and known to be null.
440ec0be 3509
a50e85e5 3510 elsif (not Is_Fixed_Length (J)) or else (Fixed_Length (J) > 0) then
3511 declare
3512 Assign : Node_Id :=
3513 Make_Assignment_Statement (Loc,
3514 Name =>
3515 Make_Slice (Loc,
3516 Prefix =>
3517 New_Occurrence_Of (Ent, Loc),
3518 Discrete_Range =>
3519 Make_Range (Loc,
3520 Low_Bound => To_Ityp (Lo),
3521 High_Bound => To_Ityp (Hi))),
3522 Expression => Operands (J));
3523 begin
3524 if Is_Fixed_Length (J) then
3525 Known_Non_Null_Operand_Seen := True;
3526
3527 elsif not Known_Non_Null_Operand_Seen then
3528
3529 -- Here if operand length is not statically known and no
3530 -- operand known to be non-null has been processed yet.
3531 -- If operand length is 0, we do not need to perform the
3532 -- assignment, and we must avoid the evaluation of the
3533 -- high bound of the slice, since it may underflow if the
3534 -- low bound is Ityp'First.
3535
3536 Assign :=
3537 Make_Implicit_If_Statement (Cnode,
9d747a29 3538 Condition =>
a50e85e5 3539 Make_Op_Ne (Loc,
9d747a29 3540 Left_Opnd =>
a50e85e5 3541 New_Occurrence_Of (Var_Length (J), Loc),
3542 Right_Opnd => Make_Integer_Literal (Loc, 0)),
9d747a29 3543 Then_Statements => New_List (Assign));
a50e85e5 3544 end if;
b6772205 3545
a50e85e5 3546 Insert_Action (Cnode, Assign, Suppress => All_Checks);
3547 end;
e37ded63 3548 end if;
3549 end;
3550 end loop;
ee6ba406 3551
aab73971 3552 -- Finally we build the result, which is a reference to the array object
3553
83c6c069 3554 Result := New_Occurrence_Of (Ent, Loc);
ee6ba406 3555
e37ded63 3556 <<Done>>
3557 Rewrite (Cnode, Result);
440ec0be 3558 Analyze_And_Resolve (Cnode, Atyp);
3559
3560 exception
3561 when Concatenation_Error =>
a50e85e5 3562
3563 -- Kill warning generated for the declaration of the static out of
3564 -- range high bound, and instead generate a Constraint_Error with
3565 -- an appropriate specific message.
3566
3567 Kill_Dead_Code (Declaration_Node (Entity (High_Bound)));
3568 Apply_Compile_Time_Constraint_Error
3569 (N => Cnode,
6e9f198b 3570 Msg => "concatenation result upper bound out of range??",
a50e85e5 3571 Reason => CE_Range_Check_Failed);
440ec0be 3572 end Expand_Concatenate;
ee6ba406 3573
aa4b16cb 3574 ---------------------------------------------------
3575 -- Expand_Membership_Minimize_Eliminate_Overflow --
3576 ---------------------------------------------------
3577
3578 procedure Expand_Membership_Minimize_Eliminate_Overflow (N : Node_Id) is
3579 pragma Assert (Nkind (N) = N_In);
3580 -- Despite the name, this routine applies only to N_In, not to
3581 -- N_Not_In. The latter is always rewritten as not (X in Y).
3582
b8a17a21 3583 Result_Type : constant Entity_Id := Etype (N);
3584 -- Capture result type, may be a derived boolean type
3585
f32c377d 3586 Loc : constant Source_Ptr := Sloc (N);
3587 Lop : constant Node_Id := Left_Opnd (N);
3588 Rop : constant Node_Id := Right_Opnd (N);
3589
3590 -- Note: there are many referencs to Etype (Lop) and Etype (Rop). It
3591 -- is thus tempting to capture these values, but due to the rewrites
3592 -- that occur as a result of overflow checking, these values change
3593 -- as we go along, and it is safe just to always use Etype explicitly.
aa4b16cb 3594
3595 Restype : constant Entity_Id := Etype (N);
3596 -- Save result type
3597
3598 Lo, Hi : Uint;
4e72eb91 3599 -- Bounds in Minimize calls, not used currently
aa4b16cb 3600
3601 LLIB : constant Entity_Id := Base_Type (Standard_Long_Long_Integer);
3602 -- Entity for Long_Long_Integer'Base (Standard should export this???)
3603
3604 begin
0df9d43f 3605 Minimize_Eliminate_Overflows (Lop, Lo, Hi, Top_Level => False);
aa4b16cb 3606
3607 -- If right operand is a subtype name, and the subtype name has no
3608 -- predicate, then we can just replace the right operand with an
3609 -- explicit range T'First .. T'Last, and use the explicit range code.
3610
f32c377d 3611 if Nkind (Rop) /= N_Range
3612 and then No (Predicate_Function (Etype (Rop)))
3613 then
3614 declare
3615 Rtyp : constant Entity_Id := Etype (Rop);
3616 begin
3617 Rewrite (Rop,
3618 Make_Range (Loc,
82b93248 3619 Low_Bound =>
f32c377d 3620 Make_Attribute_Reference (Loc,
3621 Attribute_Name => Name_First,
83c6c069 3622 Prefix => New_Occurrence_Of (Rtyp, Loc)),
f32c377d 3623 High_Bound =>
3624 Make_Attribute_Reference (Loc,
3625 Attribute_Name => Name_Last,
83c6c069 3626 Prefix => New_Occurrence_Of (Rtyp, Loc))));
f32c377d 3627 Analyze_And_Resolve (Rop, Rtyp, Suppress => All_Checks);
3628 end;
aa4b16cb 3629 end if;
3630
3631 -- Here for the explicit range case. Note that the bounds of the range
3632 -- have not been processed for minimized or eliminated checks.
3633
3634 if Nkind (Rop) = N_Range then
0df9d43f 3635 Minimize_Eliminate_Overflows
f32c377d 3636 (Low_Bound (Rop), Lo, Hi, Top_Level => False);
0df9d43f 3637 Minimize_Eliminate_Overflows
61016a7a 3638 (High_Bound (Rop), Lo, Hi, Top_Level => False);
aa4b16cb 3639
3640 -- We have A in B .. C, treated as A >= B and then A <= C
3641
3642 -- Bignum case
3643
f32c377d 3644 if Is_RTE (Etype (Lop), RE_Bignum)
aa4b16cb 3645 or else Is_RTE (Etype (Low_Bound (Rop)), RE_Bignum)
3646 or else Is_RTE (Etype (High_Bound (Rop)), RE_Bignum)
3647 then
3648 declare
3649 Blk : constant Node_Id := Make_Bignum_Block (Loc);
3650 Bnn : constant Entity_Id := Make_Temporary (Loc, 'B', N);
b8a17a21 3651 L : constant Entity_Id :=
3652 Make_Defining_Identifier (Loc, Name_uL);
aa4b16cb 3653 Lopnd : constant Node_Id := Convert_To_Bignum (Lop);
3654 Lbound : constant Node_Id :=
3655 Convert_To_Bignum (Low_Bound (Rop));
3656 Hbound : constant Node_Id :=
3657 Convert_To_Bignum (High_Bound (Rop));
3658
b8a17a21 3659 -- Now we rewrite the membership test node to look like
3660
3661 -- do
3662 -- Bnn : Result_Type;
3663 -- declare
3664 -- M : Mark_Id := SS_Mark;
3665 -- L : Bignum := Lopnd;
3666 -- begin
3667 -- Bnn := Big_GE (L, Lbound) and then Big_LE (L, Hbound)
3668 -- SS_Release (M);
3669 -- end;
3670 -- in
3671 -- Bnn
3672 -- end
aa4b16cb 3673
3674 begin
b8a17a21 3675 -- Insert declaration of L into declarations of bignum block
3676
aa4b16cb 3677 Insert_After
3678 (Last (Declarations (Blk)),
3679 Make_Object_Declaration (Loc,
b8a17a21 3680 Defining_Identifier => L,
aa4b16cb 3681 Object_Definition =>
3682 New_Occurrence_Of (RTE (RE_Bignum), Loc),
3683 Expression => Lopnd));
3684
b8a17a21 3685 -- Insert assignment to Bnn into expressions of bignum block
3686
aa4b16cb 3687 Insert_Before
3688 (First (Statements (Handled_Statement_Sequence (Blk))),
3689 Make_Assignment_Statement (Loc,
3690 Name => New_Occurrence_Of (Bnn, Loc),
3691 Expression =>
3692 Make_And_Then (Loc,
82b93248 3693 Left_Opnd =>
aa4b16cb 3694 Make_Function_Call (Loc,
3695 Name =>
3696 New_Occurrence_Of (RTE (RE_Big_GE), Loc),
b8a17a21 3697 Parameter_Associations => New_List (
3698 New_Occurrence_Of (L, Loc),
3699 Lbound)),
82b93248 3700
aa4b16cb 3701 Right_Opnd =>
3702 Make_Function_Call (Loc,
3703 Name =>
b8a17a21 3704 New_Occurrence_Of (RTE (RE_Big_LE), Loc),
3705 Parameter_Associations => New_List (
3706 New_Occurrence_Of (L, Loc),
3707 Hbound)))));
aa4b16cb 3708
b8a17a21 3709 -- Now rewrite the node
aa4b16cb 3710
b8a17a21 3711 Rewrite (N,
3712 Make_Expression_With_Actions (Loc,
3713 Actions => New_List (
3714 Make_Object_Declaration (Loc,
3715 Defining_Identifier => Bnn,
3716 Object_Definition =>
3717 New_Occurrence_Of (Result_Type, Loc)),
3718 Blk),
3719 Expression => New_Occurrence_Of (Bnn, Loc)));
3720 Analyze_And_Resolve (N, Result_Type);
aa4b16cb 3721 return;
3722 end;
3723
3724 -- Here if no bignums around
3725
3726 else
3727 -- Case where types are all the same
3728
f32c377d 3729 if Base_Type (Etype (Lop)) = Base_Type (Etype (Low_Bound (Rop)))
aa4b16cb 3730 and then
f32c377d 3731 Base_Type (Etype (Lop)) = Base_Type (Etype (High_Bound (Rop)))
aa4b16cb 3732 then
3733 null;
3734
3735 -- If types are not all the same, it means that we have rewritten
3736 -- at least one of them to be of type Long_Long_Integer, and we
3737 -- will convert the other operands to Long_Long_Integer.
3738
3739 else
3740 Convert_To_And_Rewrite (LLIB, Lop);
b8a17a21 3741 Set_Analyzed (Lop, False);
3742 Analyze_And_Resolve (Lop, LLIB);
3743
3744 -- For the right operand, avoid unnecessary recursion into
3745 -- this routine, we know that overflow is not possible.
aa4b16cb 3746
3747 Convert_To_And_Rewrite (LLIB, Low_Bound (Rop));
3748 Convert_To_And_Rewrite (LLIB, High_Bound (Rop));
3749 Set_Analyzed (Rop, False);
b8a17a21 3750 Analyze_And_Resolve (Rop, LLIB, Suppress => Overflow_Check);
aa4b16cb 3751 end if;
3752
3753 -- Now the three operands are of the same signed integer type,
f32c377d 3754 -- so we can use the normal expansion routine for membership,
3755 -- setting the flag to prevent recursion into this procedure.
aa4b16cb 3756
3757 Set_No_Minimize_Eliminate (N);
3758 Expand_N_In (N);
3759 end if;
3760
3761 -- Right operand is a subtype name and the subtype has a predicate. We
70a2dff4 3762 -- have to make sure the predicate is checked, and for that we need to
3763 -- use the standard N_In circuitry with appropriate types.
aa4b16cb 3764
3765 else
f32c377d 3766 pragma Assert (Present (Predicate_Function (Etype (Rop))));
aa4b16cb 3767
3768 -- If types are "right", just call Expand_N_In preventing recursion
3769
f32c377d 3770 if Base_Type (Etype (Lop)) = Base_Type (Etype (Rop)) then
aa4b16cb 3771 Set_No_Minimize_Eliminate (N);
3772 Expand_N_In (N);
3773
3774 -- Bignum case
3775
f32c377d 3776 elsif Is_RTE (Etype (Lop), RE_Bignum) then
aa4b16cb 3777
b8a17a21 3778 -- For X in T, we want to rewrite our node as
aa4b16cb 3779
b8a17a21 3780 -- do
3781 -- Bnn : Result_Type;
aa4b16cb 3782
b8a17a21 3783 -- declare
3784 -- M : Mark_Id := SS_Mark;
3785 -- Lnn : Long_Long_Integer'Base
3786 -- Nnn : Bignum;
aa4b16cb 3787
b8a17a21 3788 -- begin
3789 -- Nnn := X;
3790
3791 -- if not Bignum_In_LLI_Range (Nnn) then
3792 -- Bnn := False;
3793 -- else
3794 -- Lnn := From_Bignum (Nnn);
3795 -- Bnn :=
3796 -- Lnn in LLIB (T'Base'First) .. LLIB (T'Base'Last)
3797 -- and then T'Base (Lnn) in T;
3798 -- end if;
82b93248 3799
3800 -- SS_Release (M);
b8a17a21 3801 -- end
3802 -- in
3803 -- Bnn
3804 -- end
aa4b16cb 3805
70a2dff4 3806 -- A bit gruesome, but there doesn't seem to be a simpler way
aa4b16cb 3807
3808 declare
f32c377d 3809 Blk : constant Node_Id := Make_Bignum_Block (Loc);
3810 Bnn : constant Entity_Id := Make_Temporary (Loc, 'B', N);
3811 Lnn : constant Entity_Id := Make_Temporary (Loc, 'L', N);
3812 Nnn : constant Entity_Id := Make_Temporary (Loc, 'N', N);
b8a17a21 3813 T : constant Entity_Id := Etype (Rop);
3814 TB : constant Entity_Id := Base_Type (T);
f32c377d 3815 Nin : Node_Id;
aa4b16cb 3816
3817 begin
b8a17a21 3818 -- Mark the last membership operation to prevent recursion
aa4b16cb 3819
3820 Nin :=
3821 Make_In (Loc,
70a2dff4 3822 Left_Opnd => Convert_To (TB, New_Occurrence_Of (Lnn, Loc)),
3823 Right_Opnd => New_Occurrence_Of (T, Loc));
aa4b16cb 3824 Set_No_Minimize_Eliminate (Nin);
3825
3826 -- Now decorate the block
3827
3828 Insert_After
3829 (Last (Declarations (Blk)),
3830 Make_Object_Declaration (Loc,
3831 Defining_Identifier => Lnn,
3832 Object_Definition => New_Occurrence_Of (LLIB, Loc)));
3833
3834 Insert_After
3835 (Last (Declarations (Blk)),
3836 Make_Object_Declaration (Loc,
3837 Defining_Identifier => Nnn,
3838 Object_Definition =>
3839 New_Occurrence_Of (RTE (RE_Bignum), Loc)));
3840
3841 Insert_List_Before
3842 (First (Statements (Handled_Statement_Sequence (Blk))),
3843 New_List (
3844 Make_Assignment_Statement (Loc,
3845 Name => New_Occurrence_Of (Nnn, Loc),
3846 Expression => Relocate_Node (Lop)),
3847
5c72df40 3848 Make_Implicit_If_Statement (N,
aa4b16cb 3849 Condition =>
b8a17a21 3850 Make_Op_Not (Loc,
3851 Right_Opnd =>
3852 Make_Function_Call (Loc,
3853 Name =>
3854 New_Occurrence_Of
3855 (RTE (RE_Bignum_In_LLI_Range), Loc),
3856 Parameter_Associations => New_List (
3857 New_Occurrence_Of (Nnn, Loc)))),
aa4b16cb 3858
3859 Then_Statements => New_List (
3860 Make_Assignment_Statement (Loc,
3861 Name => New_Occurrence_Of (Bnn, Loc),
3862 Expression =>
3863 New_Occurrence_Of (Standard_False, Loc))),
3864
3865 Else_Statements => New_List (
3866 Make_Assignment_Statement (Loc,
3867 Name => New_Occurrence_Of (Lnn, Loc),
3868 Expression =>
3869 Make_Function_Call (Loc,
3870 Name =>
3871 New_Occurrence_Of (RTE (RE_From_Bignum), Loc),
3872 Parameter_Associations => New_List (
3873 New_Occurrence_Of (Nnn, Loc)))),
3874
3875 Make_Assignment_Statement (Loc,
b8a17a21 3876 Name => New_Occurrence_Of (Bnn, Loc),
aa4b16cb 3877 Expression =>
3878 Make_And_Then (Loc,
b8a17a21 3879 Left_Opnd =>
aa4b16cb 3880 Make_In (Loc,
b8a17a21 3881 Left_Opnd => New_Occurrence_Of (Lnn, Loc),
aa4b16cb 3882 Right_Opnd =>
b8a17a21 3883 Make_Range (Loc,
3884 Low_Bound =>
3885 Convert_To (LLIB,
3886 Make_Attribute_Reference (Loc,
3887 Attribute_Name => Name_First,
3888 Prefix =>
3889 New_Occurrence_Of (TB, Loc))),
3890
3891 High_Bound =>
3892 Convert_To (LLIB,
3893 Make_Attribute_Reference (Loc,
3894 Attribute_Name => Name_Last,
3895 Prefix =>
3896 New_Occurrence_Of (TB, Loc))))),
3897
aa4b16cb 3898 Right_Opnd => Nin))))));
3899
b8a17a21 3900 -- Now we can do the rewrite
aa4b16cb 3901
b8a17a21 3902 Rewrite (N,
3903 Make_Expression_With_Actions (Loc,
3904 Actions => New_List (
3905 Make_Object_Declaration (Loc,
3906 Defining_Identifier => Bnn,
3907 Object_Definition =>
3908 New_Occurrence_Of (Result_Type, Loc)),
3909 Blk),
3910 Expression => New_Occurrence_Of (Bnn, Loc)));
3911 Analyze_And_Resolve (N, Result_Type);
aa4b16cb 3912 return;
3913 end;
3914
3915 -- Not bignum case, but types don't match (this means we rewrote the
f32c377d 3916 -- left operand to be Long_Long_Integer).
aa4b16cb 3917
3918 else
f32c377d 3919 pragma Assert (Base_Type (Etype (Lop)) = LLIB);
aa4b16cb 3920
b8a17a21 3921 -- We rewrite the membership test as (where T is the type with
3922 -- the predicate, i.e. the type of the right operand)
aa4b16cb 3923
b8a17a21 3924 -- Lop in LLIB (T'Base'First) .. LLIB (T'Base'Last)
3925 -- and then T'Base (Lop) in T
aa4b16cb 3926
3927 declare
b8a17a21 3928 T : constant Entity_Id := Etype (Rop);
3929 TB : constant Entity_Id := Base_Type (T);
aa4b16cb 3930 Nin : Node_Id;
3931
3932 begin
3933 -- The last membership test is marked to prevent recursion
3934
3935 Nin :=
3936 Make_In (Loc,
b8a17a21 3937 Left_Opnd => Convert_To (TB, Duplicate_Subexpr (Lop)),
3938 Right_Opnd => New_Occurrence_Of (T, Loc));
aa4b16cb 3939 Set_No_Minimize_Eliminate (Nin);
3940
3941 -- Now do the rewrite
3942
3943 Rewrite (N,
3944 Make_And_Then (Loc,
b8a17a21 3945 Left_Opnd =>
aa4b16cb 3946 Make_In (Loc,
3947 Left_Opnd => Lop,
3948 Right_Opnd =>
b8a17a21 3949 Make_Range (Loc,
3950 Low_Bound =>
3951 Convert_To (LLIB,
3952 Make_Attribute_Reference (Loc,
3953 Attribute_Name => Name_First,
82b93248 3954 Prefix =>
3955 New_Occurrence_Of (TB, Loc))),
b8a17a21 3956 High_Bound =>
3957 Convert_To (LLIB,
3958 Make_Attribute_Reference (Loc,
3959 Attribute_Name => Name_Last,
82b93248 3960 Prefix =>
3961 New_Occurrence_Of (TB, Loc))))),
aa4b16cb 3962 Right_Opnd => Nin));
b8a17a21 3963 Set_Analyzed (N, False);
3964 Analyze_And_Resolve (N, Restype);
aa4b16cb 3965 end;
3966 end if;
3967 end if;
3968 end Expand_Membership_Minimize_Eliminate_Overflow;
3969
2a801d20 3970 ---------------------------------
3971 -- Expand_Nonbinary_Modular_Op --
3972 ---------------------------------
61b6f3d9 3973
2a801d20 3974 procedure Expand_Nonbinary_Modular_Op (N : Node_Id) is
61b6f3d9 3975 Loc : constant Source_Ptr := Sloc (N);
3976 Typ : constant Entity_Id := Etype (N);
3977
3978 procedure Expand_Modular_Addition;
2a801d20 3979 -- Expand the modular addition, handling the special case of adding a
61b6f3d9 3980 -- constant.
3981
3982 procedure Expand_Modular_Op;
3983 -- Compute the general rule: (lhs OP rhs) mod Modulus
3984
3985 procedure Expand_Modular_Subtraction;
2a801d20 3986 -- Expand the modular addition, handling the special case of subtracting
61b6f3d9 3987 -- a constant.
3988
3989 -----------------------------
3990 -- Expand_Modular_Addition --
3991 -----------------------------
3992
3993 procedure Expand_Modular_Addition is
3994 begin
3995 -- If this is not the addition of a constant then compute it using
3996 -- the general rule: (lhs + rhs) mod Modulus
3997
3998 if Nkind (Right_Opnd (N)) /= N_Integer_Literal then
3999 Expand_Modular_Op;
4000
4001 -- If this is an addition of a constant, convert it to a subtraction
4002 -- plus a conditional expression since we can compute it faster than
4003 -- computing the modulus.
4004
4005 -- modMinusRhs = Modulus - rhs
4006 -- if lhs < modMinusRhs then lhs + rhs
4007 -- else lhs - modMinusRhs
4008
4009 else
4010 declare
4011 Mod_Minus_Right : constant Uint :=
4012 Modulus (Typ) - Intval (Right_Opnd (N));
4013
4014 Exprs : constant List_Id := New_List;
4015 Cond_Expr : constant Node_Id := New_Op_Node (N_Op_Lt, Loc);
4016 Then_Expr : constant Node_Id := New_Op_Node (N_Op_Add, Loc);
4017 Else_Expr : constant Node_Id := New_Op_Node (N_Op_Subtract,
4018 Loc);
4019 begin
4020 Set_Left_Opnd (Cond_Expr,
4021 New_Copy_Tree (Left_Opnd (N)));
4022 Set_Right_Opnd (Cond_Expr,
4023 Make_Integer_Literal (Loc, Mod_Minus_Right));
4024 Append_To (Exprs, Cond_Expr);
4025
4026 Set_Left_Opnd (Then_Expr,
4027 Unchecked_Convert_To (Standard_Unsigned,
4028 New_Copy_Tree (Left_Opnd (N))));
4029 Set_Right_Opnd (Then_Expr,
4030 Make_Integer_Literal (Loc, Intval (Right_Opnd (N))));
4031 Append_To (Exprs, Then_Expr);
4032
4033 Set_Left_Opnd (Else_Expr,
4034 Unchecked_Convert_To (Standard_Unsigned,
4035 New_Copy_Tree (Left_Opnd (N))));
4036 Set_Right_Opnd (Else_Expr,
4037 Make_Integer_Literal (Loc, Mod_Minus_Right));
4038 Append_To (Exprs, Else_Expr);
4039
4040 Rewrite (N,
4041 Unchecked_Convert_To (Typ,
4042 Make_If_Expression (Loc, Expressions => Exprs)));
4043 end;
4044 end if;
4045 end Expand_Modular_Addition;
4046
4047 -----------------------
4048 -- Expand_Modular_Op --
4049 -----------------------
4050
4051 procedure Expand_Modular_Op is
4052 Op_Expr : constant Node_Id := New_Op_Node (Nkind (N), Loc);
4053 Mod_Expr : constant Node_Id := New_Op_Node (N_Op_Mod, Loc);
4054
4055 begin
2a801d20 4056 -- Convert nonbinary modular type operands into integer values. Thus
4057 -- we avoid never-ending loops expanding them, and we also ensure
4058 -- the back end never receives nonbinary modular type expressions.
61b6f3d9 4059
4060 if Nkind_In (Nkind (N), N_Op_And, N_Op_Or) then
4061 Set_Left_Opnd (Op_Expr,
4062 Unchecked_Convert_To (Standard_Unsigned,
4063 New_Copy_Tree (Left_Opnd (N))));
4064 Set_Right_Opnd (Op_Expr,
4065 Unchecked_Convert_To (Standard_Unsigned,
4066 New_Copy_Tree (Right_Opnd (N))));
4067 Set_Left_Opnd (Mod_Expr,
4068 Unchecked_Convert_To (Standard_Integer, Op_Expr));
87a108bc 4069
61b6f3d9 4070 else
4071 Set_Left_Opnd (Op_Expr,
4072 Unchecked_Convert_To (Standard_Integer,
4073 New_Copy_Tree (Left_Opnd (N))));
4074 Set_Right_Opnd (Op_Expr,
4075 Unchecked_Convert_To (Standard_Integer,
4076 New_Copy_Tree (Right_Opnd (N))));
8ae779b8 4077
4078 -- Link this node to the tree to analyze it
4079
a740d7fa 4080 -- If the parent node is an expression with actions we link it to
4081 -- N since otherwise Force_Evaluation cannot identify if this node
4082 -- comes from the Expression and rejects generating the temporary.
8ae779b8 4083
4084 if Nkind (Parent (N)) = N_Expression_With_Actions then
4085 Set_Parent (Op_Expr, N);
4086
4087 -- Common case
4088
4089 else
4090 Set_Parent (Op_Expr, Parent (N));
4091 end if;
4092
4093 Analyze (Op_Expr);
4094
4095 -- Force generating a temporary because in the expansion of this
4096 -- expression we may generate code that performs this computation
4097 -- several times.
4098
4099 Force_Evaluation (Op_Expr, Mode => Strict);
4100
61b6f3d9 4101 Set_Left_Opnd (Mod_Expr, Op_Expr);
4102 end if;
4103
4104 Set_Right_Opnd (Mod_Expr,
4105 Make_Integer_Literal (Loc, Modulus (Typ)));
4106
4107 Rewrite (N,
4108 Unchecked_Convert_To (Typ, Mod_Expr));
4109 end Expand_Modular_Op;
4110
4111 --------------------------------
4112 -- Expand_Modular_Subtraction --
4113 --------------------------------
4114
4115 procedure Expand_Modular_Subtraction is
4116 begin
4117 -- If this is not the addition of a constant then compute it using
4118 -- the general rule: (lhs + rhs) mod Modulus
4119
4120 if Nkind (Right_Opnd (N)) /= N_Integer_Literal then
4121 Expand_Modular_Op;
4122
4123 -- If this is an addition of a constant, convert it to a subtraction
4124 -- plus a conditional expression since we can compute it faster than
4125 -- computing the modulus.
4126
4127 -- modMinusRhs = Modulus - rhs
4128 -- if lhs < rhs then lhs + modMinusRhs
4129 -- else lhs - rhs
4130
4131 else
4132 declare
4133 Mod_Minus_Right : constant Uint :=
4134 Modulus (Typ) - Intval (Right_Opnd (N));
4135
4136 Exprs : constant List_Id := New_List;
4137 Cond_Expr : constant Node_Id := New_Op_Node (N_Op_Lt, Loc);
4138 Then_Expr : constant Node_Id := New_Op_Node (N_Op_Add, Loc);
4139 Else_Expr : constant Node_Id := New_Op_Node (N_Op_Subtract,
4140 Loc);
4141 begin
4142 Set_Left_Opnd (Cond_Expr,
4143 New_Copy_Tree (Left_Opnd (N)));
4144 Set_Right_Opnd (Cond_Expr,
4145 Make_Integer_Literal (Loc, Intval (Right_Opnd (N))));
4146 Append_To (Exprs, Cond_Expr);
4147
4148 Set_Left_Opnd (Then_Expr,
4149 Unchecked_Convert_To (Standard_Unsigned,
4150 New_Copy_Tree (Left_Opnd (N))));
4151 Set_Right_Opnd (Then_Expr,
4152 Make_Integer_Literal (Loc, Mod_Minus_Right));
4153 Append_To (Exprs, Then_Expr);
4154
4155 Set_Left_Opnd (Else_Expr,
4156 Unchecked_Convert_To (Standard_Unsigned,
4157 New_Copy_Tree (Left_Opnd (N))));
4158 Set_Right_Opnd (Else_Expr,
4159 Unchecked_Convert_To (Standard_Unsigned,
4160 New_Copy_Tree (Right_Opnd (N))));
4161 Append_To (Exprs, Else_Expr);
4162
4163 Rewrite (N,
4164 Unchecked_Convert_To (Typ,
4165 Make_If_Expression (Loc, Expressions => Exprs)));
4166 end;
4167 end if;
4168 end Expand_Modular_Subtraction;
4169
2a801d20 4170 -- Start of processing for Expand_Nonbinary_Modular_Op
61b6f3d9 4171
4172 begin
2a801d20 4173 -- No action needed if we are not generating C code for a nonbinary
61b6f3d9 4174 -- modular operand.
4175
4176 if not Modify_Tree_For_C
4177 or else not Non_Binary_Modulus (Typ)
4178 then
4179 return;
4180 end if;
4181
4182 case Nkind (N) is
4183 when N_Op_Add =>
4184 Expand_Modular_Addition;
4185
4186 when N_Op_Subtract =>
4187 Expand_Modular_Subtraction;
4188
4189 when N_Op_Minus =>
87a108bc 4190
61b6f3d9 4191 -- Expand -expr into (0 - expr)
4192
4193 Rewrite (N,
4194 Make_Op_Subtract (Loc,
4195 Left_Opnd => Make_Integer_Literal (Loc, 0),
4196 Right_Opnd => Right_Opnd (N)));
4197 Analyze_And_Resolve (N, Typ);
4198
4199 when others =>
4200 Expand_Modular_Op;
4201 end case;
4202
4203 Analyze_And_Resolve (N, Typ);
2a801d20 4204 end Expand_Nonbinary_Modular_Op;
61b6f3d9 4205
ee6ba406 4206 ------------------------
4207 -- Expand_N_Allocator --
4208 ------------------------
4209
4210 procedure Expand_N_Allocator (N : Node_Id) is
5c72df40 4211 Etyp : constant Entity_Id := Etype (Expression (N));
4212 Loc : constant Source_Ptr := Sloc (N);
4213 PtrT : constant Entity_Id := Etype (N);
ee6ba406 4214
914796b1 4215 procedure Rewrite_Coextension (N : Node_Id);
4216 -- Static coextensions have the same lifetime as the entity they
36b938a3 4217 -- constrain. Such occurrences can be rewritten as aliased objects
914796b1 4218 -- and their unrestricted access used instead of the coextension.
99f2248e 4219
c970afb7 4220 function Size_In_Storage_Elements (E : Entity_Id) return Node_Id;
cd8ac304 4221 -- Given a constrained array type E, returns a node representing the
4222 -- code to compute the size in storage elements for the given type.
bb8d99b2 4223 -- This is done without using the attribute (which malfunctions for
cd8ac304 4224 -- large sizes ???)
c970afb7 4225
914796b1 4226 -------------------------
4227 -- Rewrite_Coextension --
4228 -------------------------
4229
4230 procedure Rewrite_Coextension (N : Node_Id) is
504c14e8 4231 Temp_Id : constant Node_Id := Make_Temporary (Loc, 'C');
4232 Temp_Decl : Node_Id;
914796b1 4233
bb3b440a 4234 begin
914796b1 4235 -- Generate:
4236 -- Cnn : aliased Etyp;
4237
bb3b440a 4238 Temp_Decl :=
4239 Make_Object_Declaration (Loc,
4240 Defining_Identifier => Temp_Id,
5e8ac397 4241 Aliased_Present => True,
4242 Object_Definition => New_Occurrence_Of (Etyp, Loc));
914796b1 4243
914796b1 4244 if Nkind (Expression (N)) = N_Qualified_Expression then
bb3b440a 4245 Set_Expression (Temp_Decl, Expression (Expression (N)));
99f2248e 4246 end if;
914796b1 4247
504c14e8 4248 Insert_Action (N, Temp_Decl);
914796b1 4249 Rewrite (N,
4250 Make_Attribute_Reference (Loc,
5e8ac397 4251 Prefix => New_Occurrence_Of (Temp_Id, Loc),
914796b1 4252 Attribute_Name => Name_Unrestricted_Access));
4253
4254 Analyze_And_Resolve (N, PtrT);
4255 end Rewrite_Coextension;
99f2248e 4256
c970afb7 4257 ------------------------------
4258 -- Size_In_Storage_Elements --
4259 ------------------------------
4260
4261 function Size_In_Storage_Elements (E : Entity_Id) return Node_Id is
4262 begin
4263 -- Logically this just returns E'Max_Size_In_Storage_Elements.
4264 -- However, the reason for the existence of this function is
4265 -- to construct a test for sizes too large, which means near the
4266 -- 32-bit limit on a 32-bit machine, and precisely the trouble
4267 -- is that we get overflows when sizes are greater than 2**31.
4268
cd8ac304 4269 -- So what we end up doing for array types is to use the expression:
c970afb7 4270
4271 -- number-of-elements * component_type'Max_Size_In_Storage_Elements
4272
9ee7df75 4273 -- which avoids this problem. All this is a bit bogus, but it does
c970afb7 4274 -- mean we catch common cases of trying to allocate arrays that
4275 -- are too large, and which in the absence of a check results in
4276 -- undetected chaos ???
4277
c9f84db7 4278 -- Note in particular that this is a pessimistic estimate in the
4279 -- case of packed array types, where an array element might occupy
4280 -- just a fraction of a storage element???
4281
cd8ac304 4282 declare
4283 Len : Node_Id;
4284 Res : Node_Id;
16149377 4285 pragma Warnings (Off, Res);
c970afb7 4286
cd8ac304 4287 begin
4288 for J in 1 .. Number_Dimensions (E) loop
4289 Len :=
4290 Make_Attribute_Reference (Loc,
4291 Prefix => New_Occurrence_Of (E, Loc),
4292 Attribute_Name => Name_Length,
5e8ac397 4293 Expressions => New_List (Make_Integer_Literal (Loc, J)));
c970afb7 4294
cd8ac304 4295 if J = 1 then
4296 Res := Len;
c970afb7 4297
cd8ac304 4298 else
4299 Res :=
4300 Make_Op_Multiply (Loc,
4301 Left_Opnd => Res,
4302 Right_Opnd => Len);
4303 end if;
4304 end loop;
c970afb7 4305
c970afb7 4306 return
cd8ac304 4307 Make_Op_Multiply (Loc,
4308 Left_Opnd => Len,
4309 Right_Opnd =>
4310 Make_Attribute_Reference (Loc,
4311 Prefix => New_Occurrence_Of (Component_Type (E), Loc),
4312 Attribute_Name => Name_Max_Size_In_Storage_Elements));
4313 end;
c970afb7 4314 end Size_In_Storage_Elements;
4315
5c72df40 4316 -- Local variables
4317
0a184e47 4318 Dtyp : constant Entity_Id := Available_View (Designated_Type (PtrT));
5c72df40 4319 Desig : Entity_Id;
4320 Nod : Node_Id;
4321 Pool : Entity_Id;
4322 Rel_Typ : Entity_Id;
4323 Temp : Entity_Id;
4324
99f2248e 4325 -- Start of processing for Expand_N_Allocator
4326
ee6ba406 4327 begin
4328 -- RM E.2.3(22). We enforce that the expected type of an allocator
4329 -- shall not be a remote access-to-class-wide-limited-private type
4330
4331 -- Why is this being done at expansion time, seems clearly wrong ???
4332
4333 Validate_Remote_Access_To_Class_Wide_Type (N);
4334
53c179ea 4335 -- Processing for anonymous access-to-controlled types. These access
4336 -- types receive a special finalization master which appears in the
4337 -- declarations of the enclosing semantic unit. This expansion is done
9ef23ec9 4338 -- now to ensure that any additional types generated by this routine or
4339 -- Expand_Allocator_Expression inherit the proper type attributes.
53c179ea 4340
9ef23ec9 4341 if (Ekind (PtrT) = E_Anonymous_Access_Type
6f0d10f7 4342 or else (Is_Itype (PtrT) and then No (Finalization_Master (PtrT))))
53c179ea 4343 and then Needs_Finalization (Dtyp)
4344 then
5c72df40 4345 -- Detect the allocation of an anonymous controlled object where the
4346 -- type of the context is named. For example:
4347
4348 -- procedure Proc (Ptr : Named_Access_Typ);
4349 -- Proc (new Designated_Typ);
4350
4351 -- Regardless of the anonymous-to-named access type conversion, the
4352 -- lifetime of the object must be associated with the named access
d1eda9b3 4353 -- type. Use the finalization-related attributes of this type.
5c72df40 4354
4355 if Nkind_In (Parent (N), N_Type_Conversion,
4356 N_Unchecked_Type_Conversion)
4357 and then Ekind_In (Etype (Parent (N)), E_Access_Subtype,
4358 E_Access_Type,
4359 E_General_Access_Type)
4360 then
4361 Rel_Typ := Etype (Parent (N));
4362 else
4363 Rel_Typ := Empty;
4364 end if;
4365
2a829294 4366 -- Anonymous access-to-controlled types allocate on the global pool.
36ac5fbb 4367 -- Note that this is a "root type only" attribute.
53c179ea 4368
36ac5fbb 4369 if No (Associated_Storage_Pool (PtrT)) then
5c72df40 4370 if Present (Rel_Typ) then
e9b26a1d 4371 Set_Associated_Storage_Pool
ba502e2b 4372 (Root_Type (PtrT), Associated_Storage_Pool (Rel_Typ));
5c72df40 4373 else
e9b26a1d 4374 Set_Associated_Storage_Pool
ba502e2b 4375 (Root_Type (PtrT), RTE (RE_Global_Pool_Object));
5c72df40 4376 end if;
53c179ea 4377 end if;
4378
4379 -- The finalization master must be inserted and analyzed as part of
8a075a7e 4380 -- the current semantic unit. Note that the master is updated when
ba502e2b 4381 -- analysis changes current units. Note that this is a "root type
4382 -- only" attribute.
53c179ea 4383
8a075a7e 4384 if Present (Rel_Typ) then
ba502e2b 4385 Set_Finalization_Master
4386 (Root_Type (PtrT), Finalization_Master (Rel_Typ));
8a075a7e 4387 else
f74a102b 4388 Build_Anonymous_Master (Root_Type (PtrT));
53c179ea 4389 end if;
4390 end if;
4391
4392 -- Set the storage pool and find the appropriate version of Allocate to
3295b1fa 4393 -- call. Do not overwrite the storage pool if it is already set, which
4394 -- can happen for build-in-place function returns (see
52b3bcf2 4395 -- Exp_Ch4.Expand_N_Extended_Return_Statement).
ee6ba406 4396
52b3bcf2 4397 if No (Storage_Pool (N)) then
4398 Pool := Associated_Storage_Pool (Root_Type (PtrT));
ee6ba406 4399
52b3bcf2 4400 if Present (Pool) then
4401 Set_Storage_Pool (N, Pool);
9dfe12ae 4402
52b3bcf2 4403 if Is_RTE (Pool, RE_SS_Pool) then
36ac5fbb 4404 Set_Procedure_To_Call (N, RTE (RE_SS_Allocate));
9dfe12ae 4405
b55f7641 4406 -- In the case of an allocator for a simple storage pool, locate
4407 -- and save a reference to the pool type's Allocate routine.
4408
4409 elsif Present (Get_Rep_Pragma
b15003c3 4410 (Etype (Pool), Name_Simple_Storage_Pool_Type))
b55f7641 4411 then
4412 declare
b55f7641 4413 Pool_Type : constant Entity_Id := Base_Type (Etype (Pool));
09ad6da2 4414 Alloc_Op : Entity_Id;
b55f7641 4415 begin
09ad6da2 4416 Alloc_Op := Get_Name_Entity_Id (Name_Allocate);
b55f7641 4417 while Present (Alloc_Op) loop
4418 if Scope (Alloc_Op) = Scope (Pool_Type)
4419 and then Present (First_Formal (Alloc_Op))
4420 and then Etype (First_Formal (Alloc_Op)) = Pool_Type
4421 then
4422 Set_Procedure_To_Call (N, Alloc_Op);
b55f7641 4423 exit;
09ad6da2 4424 else
4425 Alloc_Op := Homonym (Alloc_Op);
b55f7641 4426 end if;
b55f7641 4427 end loop;
4428 end;
4429
52b3bcf2 4430 elsif Is_Class_Wide_Type (Etype (Pool)) then
4431 Set_Procedure_To_Call (N, RTE (RE_Allocate_Any));
4432
4433 else
4434 Set_Procedure_To_Call (N,
4435 Find_Prim_Op (Etype (Pool), Name_Allocate));
4436 end if;
ee6ba406 4437 end if;
4438 end if;
4439
f1e2dcc5 4440 -- Under certain circumstances we can replace an allocator by an access
4441 -- to statically allocated storage. The conditions, as noted in AARM
4442 -- 3.10 (10c) are as follows:
ee6ba406 4443
4444 -- Size and initial value is known at compile time
4445 -- Access type is access-to-constant
4446
9dfe12ae 4447 -- The allocator is not part of a constraint on a record component,
4448 -- because in that case the inserted actions are delayed until the
4449 -- record declaration is fully analyzed, which is too late for the
4450 -- analysis of the rewritten allocator.
4451
ee6ba406 4452 if Is_Access_Constant (PtrT)
4453 and then Nkind (Expression (N)) = N_Qualified_Expression
4454 and then Compile_Time_Known_Value (Expression (Expression (N)))
5e8ac397 4455 and then Size_Known_At_Compile_Time
4456 (Etype (Expression (Expression (N))))
9dfe12ae 4457 and then not Is_Record_Type (Current_Scope)
ee6ba406 4458 then
4459 -- Here we can do the optimization. For the allocator
4460
4461 -- new x'(y)
4462
4463 -- We insert an object declaration
4464
4465 -- Tnn : aliased x := y;
4466
f1e2dcc5 4467 -- and replace the allocator by Tnn'Unrestricted_Access. Tnn is
4468 -- marked as requiring static allocation.
ee6ba406 4469
bb3b440a 4470 Temp := Make_Temporary (Loc, 'T', Expression (Expression (N)));
ee6ba406 4471 Desig := Subtype_Mark (Expression (N));
4472
4473 -- If context is constrained, use constrained subtype directly,
36b938a3 4474 -- so that the constant is not labelled as having a nominally
ee6ba406 4475 -- unconstrained subtype.
4476
80d4fec4 4477 if Entity (Desig) = Base_Type (Dtyp) then
4478 Desig := New_Occurrence_Of (Dtyp, Loc);
ee6ba406 4479 end if;
4480
4481 Insert_Action (N,
4482 Make_Object_Declaration (Loc,
4483 Defining_Identifier => Temp,
4484 Aliased_Present => True,
4485 Constant_Present => Is_Access_Constant (PtrT),
4486 Object_Definition => Desig,
4487 Expression => Expression (Expression (N))));
4488
4489 Rewrite (N,
4490 Make_Attribute_Reference (Loc,
5e8ac397 4491 Prefix => New_Occurrence_Of (Temp, Loc),
ee6ba406 4492 Attribute_Name => Name_Unrestricted_Access));
4493
4494 Analyze_And_Resolve (N, PtrT);
4495
f1e2dcc5 4496 -- We set the variable as statically allocated, since we don't want
39a0c1d3 4497 -- it going on the stack of the current procedure.
ee6ba406 4498
4499 Set_Is_Statically_Allocated (Temp);
4500 return;
4501 end if;
4502
99f2248e 4503 -- Same if the allocator is an access discriminant for a local object:
4504 -- instead of an allocator we create a local value and constrain the
6fb3c314 4505 -- enclosing object with the corresponding access attribute.
99f2248e 4506
914796b1 4507 if Is_Static_Coextension (N) then
4508 Rewrite_Coextension (N);
99f2248e 4509 return;
4510 end if;
4511
c970afb7 4512 -- Check for size too large, we do this because the back end misses
4513 -- proper checks here and can generate rubbish allocation calls when
4514 -- we are near the limit. We only do this for the 32-bit address case
4515 -- since that is from a practical point of view where we see a problem.
4516
4517 if System_Address_Size = 32
4518 and then not Storage_Checks_Suppressed (PtrT)
4519 and then not Storage_Checks_Suppressed (Dtyp)
4520 and then not Storage_Checks_Suppressed (Etyp)
4521 then
4522 -- The check we want to generate should look like
4523
4524 -- if Etyp'Max_Size_In_Storage_Elements > 3.5 gigabytes then
4525 -- raise Storage_Error;
4526 -- end if;
4527
6fb3c314 4528 -- where 3.5 gigabytes is a constant large enough to accommodate any
cd8ac304 4529 -- reasonable request for. But we can't do it this way because at
4530 -- least at the moment we don't compute this attribute right, and
4531 -- can silently give wrong results when the result gets large. Since
4532 -- this is all about large results, that's bad, so instead we only
bb8d99b2 4533 -- apply the check for constrained arrays, and manually compute the
cd8ac304 4534 -- value of the attribute ???
c970afb7 4535
cd8ac304 4536 if Is_Array_Type (Etyp) and then Is_Constrained (Etyp) then
4537 Insert_Action (N,
4538 Make_Raise_Storage_Error (Loc,
4539 Condition =>
4540 Make_Op_Gt (Loc,
4541 Left_Opnd => Size_In_Storage_Elements (Etyp),
4542 Right_Opnd =>
5e8ac397 4543 Make_Integer_Literal (Loc, Uint_7 * (Uint_2 ** 29))),
cd8ac304 4544 Reason => SE_Object_Too_Large));
4545 end if;
c970afb7 4546 end if;
4547
addd4a7e 4548 -- If no storage pool has been specified and we have the restriction
4549 -- No_Standard_Allocators_After_Elaboration is present, then generate
4550 -- a call to Elaboration_Allocators.Check_Standard_Allocator.
4551
4552 if Nkind (N) = N_Allocator
4553 and then No (Storage_Pool (N))
4554 and then Restriction_Active (No_Standard_Allocators_After_Elaboration)
4555 then
4556 Insert_Action (N,
4557 Make_Procedure_Call_Statement (Loc,
4558 Name =>
4559 New_Occurrence_Of (RTE (RE_Check_Standard_Allocator), Loc)));
4560 end if;
4561
80d4fec4 4562 -- Handle case of qualified expression (other than optimization above)
6b2d409e 4563 -- First apply constraint checks, because the bounds or discriminants
4564 -- in the aggregate might not match the subtype mark in the allocator.
80d4fec4 4565
ee6ba406 4566 if Nkind (Expression (N)) = N_Qualified_Expression then
964f334d 4567 declare
71d4161f 4568 Exp : constant Node_Id := Expression (Expression (N));
964f334d 4569 Typ : constant Entity_Id := Etype (Expression (N));
71d4161f 4570
964f334d 4571 begin
4572 Apply_Constraint_Check (Exp, Typ);
4573 Apply_Predicate_Check (Exp, Typ);
4574 end;
6b2d409e 4575
9dfe12ae 4576 Expand_Allocator_Expression (N);
914796b1 4577 return;
4578 end if;
9dfe12ae 4579
914796b1 4580 -- If the allocator is for a type which requires initialization, and
4581 -- there is no initial value (i.e. operand is a subtype indication
f1e2dcc5 4582 -- rather than a qualified expression), then we must generate a call to
4583 -- the initialization routine using an expressions action node:
ee6ba406 4584
914796b1 4585 -- [Pnnn : constant ptr_T := new (T); Init (Pnnn.all,...); Pnnn]
ee6ba406 4586
914796b1 4587 -- Here ptr_T is the pointer type for the allocator, and T is the
4588 -- subtype of the allocator. A special case arises if the designated
4589 -- type of the access type is a task or contains tasks. In this case
4590 -- the call to Init (Temp.all ...) is replaced by code that ensures
4591 -- that tasks get activated (see Exp_Ch9.Build_Task_Allocate_Block
a0c3eeb9 4592 -- for details). In addition, if the type T is a task type, then the
914796b1 4593 -- first argument to Init must be converted to the task record type.
ee6ba406 4594
914796b1 4595 declare
bb3b440a 4596 T : constant Entity_Id := Entity (Expression (N));
4597 Args : List_Id;
4598 Decls : List_Id;
4599 Decl : Node_Id;
4600 Discr : Elmt_Id;
4601 Init : Entity_Id;
4602 Init_Arg1 : Node_Id;
fe696bd7 4603 Init_Call : Node_Id;
bb3b440a 4604 Temp_Decl : Node_Id;
4605 Temp_Type : Entity_Id;
ee6ba406 4606
914796b1 4607 begin
4608 if No_Initialization (N) then
bb3b440a 4609
4610 -- Even though this might be a simple allocation, create a custom
36ac5fbb 4611 -- Allocate if the context requires it.
bb3b440a 4612
36ac5fbb 4613 if Present (Finalization_Master (PtrT)) then
bb3b440a 4614 Build_Allocate_Deallocate_Proc
53c179ea 4615 (N => N,
bb3b440a 4616 Is_Allocate => True);
4617 end if;
ee6ba406 4618
914796b1 4619 -- Case of no initialization procedure present
ee6ba406 4620
914796b1 4621 elsif not Has_Non_Null_Base_Init_Proc (T) then
ee6ba406 4622
914796b1 4623 -- Case of simple initialization required
ee6ba406 4624
914796b1 4625 if Needs_Simple_Initialization (T) then
40a5a4cb 4626 Check_Restriction (No_Default_Initialization, N);
914796b1 4627 Rewrite (Expression (N),
4628 Make_Qualified_Expression (Loc,
4629 Subtype_Mark => New_Occurrence_Of (T, Loc),
40a5a4cb 4630 Expression => Get_Simple_Init_Val (T, N)));
ee6ba406 4631
914796b1 4632 Analyze_And_Resolve (Expression (Expression (N)), T);
4633 Analyze_And_Resolve (Expression (N), T);
4634 Set_Paren_Count (Expression (Expression (N)), 1);
4635 Expand_N_Allocator (N);
ee6ba406 4636
914796b1 4637 -- No initialization required
ee6ba406 4638
4639 else
58a61b0f 4640 Build_Allocate_Deallocate_Proc
4641 (N => N,
4642 Is_Allocate => True);
914796b1 4643 end if;
ee6ba406 4644
914796b1 4645 -- Case of initialization procedure present, must be called
ee6ba406 4646
914796b1 4647 else
40a5a4cb 4648 Check_Restriction (No_Default_Initialization, N);
ee6ba406 4649
40a5a4cb 4650 if not Restriction_Active (No_Default_Initialization) then
4651 Init := Base_Init_Proc (T);
4652 Nod := N;
46eb6933 4653 Temp := Make_Temporary (Loc, 'P');
ee6ba406 4654
40a5a4cb 4655 -- Construct argument list for the initialization routine call
ee6ba406 4656
bb3b440a 4657 Init_Arg1 :=
40a5a4cb 4658 Make_Explicit_Dereference (Loc,
bb3b440a 4659 Prefix =>
83c6c069 4660 New_Occurrence_Of (Temp, Loc));
bb3b440a 4661
4662 Set_Assignment_OK (Init_Arg1);
40a5a4cb 4663 Temp_Type := PtrT;
914796b1 4664
40a5a4cb 4665 -- The initialization procedure expects a specific type. if the
4666 -- context is access to class wide, indicate that the object
4667 -- being allocated has the right specific type.
ee6ba406 4668
40a5a4cb 4669 if Is_Class_Wide_Type (Dtyp) then
bb3b440a 4670 Init_Arg1 := Unchecked_Convert_To (T, Init_Arg1);
40a5a4cb 4671 end if;
ee6ba406 4672
40a5a4cb 4673 -- If designated type is a concurrent type or if it is private
4674 -- type whose definition is a concurrent type, the first
4675 -- argument in the Init routine has to be unchecked conversion
4676 -- to the corresponding record type. If the designated type is
5e8ac397 4677 -- a derived type, also convert the argument to its root type.
e8ccec48 4678
40a5a4cb 4679 if Is_Concurrent_Type (T) then
bb3b440a 4680 Init_Arg1 :=
4681 Unchecked_Convert_To (
4682 Corresponding_Record_Type (T), Init_Arg1);
ee6ba406 4683
40a5a4cb 4684 elsif Is_Private_Type (T)
4685 and then Present (Full_View (T))
4686 and then Is_Concurrent_Type (Full_View (T))
4687 then
bb3b440a 4688 Init_Arg1 :=
40a5a4cb 4689 Unchecked_Convert_To
bb3b440a 4690 (Corresponding_Record_Type (Full_View (T)), Init_Arg1);
ee6ba406 4691
40a5a4cb 4692 elsif Etype (First_Formal (Init)) /= Base_Type (T) then
4693 declare
4694 Ftyp : constant Entity_Id := Etype (First_Formal (Init));
bb3b440a 4695
40a5a4cb 4696 begin
bb3b440a 4697 Init_Arg1 := OK_Convert_To (Etype (Ftyp), Init_Arg1);
4698 Set_Etype (Init_Arg1, Ftyp);
40a5a4cb 4699 end;
4700 end if;
ee6ba406 4701
bb3b440a 4702 Args := New_List (Init_Arg1);
ee6ba406 4703
40a5a4cb 4704 -- For the task case, pass the Master_Id of the access type as
4705 -- the value of the _Master parameter, and _Chain as the value
4706 -- of the _Chain parameter (_Chain will be defined as part of
4707 -- the generated code for the allocator).
ee6ba406 4708
40a5a4cb 4709 -- In Ada 2005, the context may be a function that returns an
4710 -- anonymous access type. In that case the Master_Id has been
4711 -- created when expanding the function declaration.
ee6ba406 4712
40a5a4cb 4713 if Has_Task (T) then
4714 if No (Master_Id (Base_Type (PtrT))) then
ee6ba406 4715
40a5a4cb 4716 -- The designated type was an incomplete type, and the
4717 -- access type did not get expanded. Salvage it now.
ee6ba406 4718
ba0453b4 4719 if not Restriction_Active (No_Task_Hierarchy) then
8d4059a5 4720 if Present (Parent (Base_Type (PtrT))) then
4721 Expand_N_Full_Type_Declaration
4722 (Parent (Base_Type (PtrT)));
4723
64cc9e5d 4724 -- The only other possibility is an itype. For this
4725 -- case, the master must exist in the context. This is
4726 -- the case when the allocator initializes an access
4727 -- component in an init-proc.
8d4059a5 4728
64cc9e5d 4729 else
8d4059a5 4730 pragma Assert (Is_Itype (PtrT));
4731 Build_Master_Renaming (PtrT, N);
4732 end if;
ba0453b4 4733 end if;
40a5a4cb 4734 end if;
ee6ba406 4735
40a5a4cb 4736 -- If the context of the allocator is a declaration or an
4737 -- assignment, we can generate a meaningful image for it,
4738 -- even though subsequent assignments might remove the
4739 -- connection between task and entity. We build this image
4740 -- when the left-hand side is a simple variable, a simple
4741 -- indexed assignment or a simple selected component.
4742
4743 if Nkind (Parent (N)) = N_Assignment_Statement then
4744 declare
4745 Nam : constant Node_Id := Name (Parent (N));
4746
4747 begin
4748 if Is_Entity_Name (Nam) then
4749 Decls :=
4750 Build_Task_Image_Decls
4751 (Loc,
4752 New_Occurrence_Of
4753 (Entity (Nam), Sloc (Nam)), T);
4754
5e8ac397 4755 elsif Nkind_In (Nam, N_Indexed_Component,
4756 N_Selected_Component)
40a5a4cb 4757 and then Is_Entity_Name (Prefix (Nam))
4758 then
4759 Decls :=
4760 Build_Task_Image_Decls
4761 (Loc, Nam, Etype (Prefix (Nam)));
4762 else
4763 Decls := Build_Task_Image_Decls (Loc, T, T);
4764 end if;
4765 end;
ee6ba406 4766
40a5a4cb 4767 elsif Nkind (Parent (N)) = N_Object_Declaration then
4768 Decls :=
4769 Build_Task_Image_Decls
4770 (Loc, Defining_Identifier (Parent (N)), T);
ee6ba406 4771
40a5a4cb 4772 else
4773 Decls := Build_Task_Image_Decls (Loc, T, T);
4774 end if;
914796b1 4775
925c2ba1 4776 if Restriction_Active (No_Task_Hierarchy) then
11bd2f46 4777 Append_To (Args,
4778 New_Occurrence_Of (RTE (RE_Library_Task_Level), Loc));
925c2ba1 4779 else
4780 Append_To (Args,
83c6c069 4781 New_Occurrence_Of
925c2ba1 4782 (Master_Id (Base_Type (Root_Type (PtrT))), Loc));
4783 end if;
4784
40a5a4cb 4785 Append_To (Args, Make_Identifier (Loc, Name_uChain));
914796b1 4786
40a5a4cb 4787 Decl := Last (Decls);
4788 Append_To (Args,
4789 New_Occurrence_Of (Defining_Identifier (Decl), Loc));
914796b1 4790
925c2ba1 4791 -- Has_Task is false, Decls not used
914796b1 4792
40a5a4cb 4793 else
4794 Decls := No_List;
914796b1 4795 end if;
4796
40a5a4cb 4797 -- Add discriminants if discriminated type
4798
4799 declare
4800 Dis : Boolean := False;
4801 Typ : Entity_Id;
4802
4803 begin
4804 if Has_Discriminants (T) then
4805 Dis := True;
4806 Typ := T;
4807
8f2fccfb 4808 -- Type may be a private type with no visible discriminants
4809 -- in which case check full view if in scope, or the
4810 -- underlying_full_view if dealing with a type whose full
4811 -- view may be derived from a private type whose own full
4812 -- view has discriminants.
4813
4814 elsif Is_Private_Type (T) then
4815 if Present (Full_View (T))
4816 and then Has_Discriminants (Full_View (T))
4817 then
4818 Dis := True;
4819 Typ := Full_View (T);
4820
4821 elsif Present (Underlying_Full_View (T))
4822 and then Has_Discriminants (Underlying_Full_View (T))
4823 then
4824 Dis := True;
4825 Typ := Underlying_Full_View (T);
4826 end if;
e8ccec48 4827 end if;
ee6ba406 4828
40a5a4cb 4829 if Dis then
914796b1 4830
40a5a4cb 4831 -- If the allocated object will be constrained by the
f1e2dcc5 4832 -- default values for discriminants, then build a subtype
4833 -- with those defaults, and change the allocated subtype
4834 -- to that. Note that this happens in fewer cases in Ada
4835 -- 2005 (AI-363).
914796b1 4836
40a5a4cb 4837 if not Is_Constrained (Typ)
4838 and then Present (Discriminant_Default_Value
bb3b440a 4839 (First_Discriminant (Typ)))
de54c5ab 4840 and then (Ada_Version < Ada_2005
ff7a92d3 4841 or else not
0d78d2d4 4842 Object_Type_Has_Constrained_Partial_View
4843 (Typ, Current_Scope))
e8ccec48 4844 then
40a5a4cb 4845 Typ := Build_Default_Subtype (Typ, N);
83c6c069 4846 Set_Expression (N, New_Occurrence_Of (Typ, Loc));
e8ccec48 4847 end if;
4848
40a5a4cb 4849 Discr := First_Elmt (Discriminant_Constraint (Typ));
4850 while Present (Discr) loop
4851 Nod := Node (Discr);
4852 Append (New_Copy_Tree (Node (Discr)), Args);
e8ccec48 4853
40a5a4cb 4854 -- AI-416: when the discriminant constraint is an
4855 -- anonymous access type make sure an accessibility
4856 -- check is inserted if necessary (3.10.2(22.q/2))
e8ccec48 4857
de54c5ab 4858 if Ada_Version >= Ada_2005
40a5a4cb 4859 and then
4860 Ekind (Etype (Nod)) = E_Anonymous_Access_Type
4861 then
55dc6dc2 4862 Apply_Accessibility_Check
4863 (Nod, Typ, Insert_Node => Nod);
40a5a4cb 4864 end if;
e8ccec48 4865
40a5a4cb 4866 Next_Elmt (Discr);
4867 end loop;
4868 end if;
4869 end;
ee6ba406 4870
d5be9f38 4871 -- We set the allocator as analyzed so that when we analyze
92f1631f 4872 -- the if expression node, we do not get an unwanted recursive
4873 -- expansion of the allocator expression.
ee6ba406 4874
40a5a4cb 4875 Set_Analyzed (N, True);
4876 Nod := Relocate_Node (N);
ee6ba406 4877
40a5a4cb 4878 -- Here is the transformation:
53c179ea 4879 -- input: new Ctrl_Typ
4880 -- output: Temp : constant Ctrl_Typ_Ptr := new Ctrl_Typ;
4881 -- Ctrl_TypIP (Temp.all, ...);
4882 -- [Deep_]Initialize (Temp.all);
ee6ba406 4883
53c179ea 4884 -- Here Ctrl_Typ_Ptr is the pointer type for the allocator, and
4885 -- is the subtype of the allocator.
ee6ba406 4886
40a5a4cb 4887 Temp_Decl :=
4888 Make_Object_Declaration (Loc,
4889 Defining_Identifier => Temp,
4890 Constant_Present => True,
83c6c069 4891 Object_Definition => New_Occurrence_Of (Temp_Type, Loc),
40a5a4cb 4892 Expression => Nod);
ee6ba406 4893
40a5a4cb 4894 Set_Assignment_OK (Temp_Decl);
4895 Insert_Action (N, Temp_Decl, Suppress => All_Checks);
ee6ba406 4896
53c179ea 4897 Build_Allocate_Deallocate_Proc (Temp_Decl, True);
bb3b440a 4898
40a5a4cb 4899 -- If the designated type is a task type or contains tasks,
4900 -- create block to activate created tasks, and insert
4901 -- declaration for Task_Image variable ahead of call.
ee6ba406 4902
40a5a4cb 4903 if Has_Task (T) then
4904 declare
4905 L : constant List_Id := New_List;
4906 Blk : Node_Id;
4907 begin
4908 Build_Task_Allocate_Block (L, Nod, Args);
4909 Blk := Last (L);
4910 Insert_List_Before (First (Declarations (Blk)), Decls);
4911 Insert_Actions (N, L);
4912 end;
ee6ba406 4913
40a5a4cb 4914 else
4915 Insert_Action (N,
4916 Make_Procedure_Call_Statement (Loc,
83c6c069 4917 Name => New_Occurrence_Of (Init, Loc),
40a5a4cb 4918 Parameter_Associations => Args));
4919 end if;
ee6ba406 4920
45851103 4921 if Needs_Finalization (T) then
ee6ba406 4922
bb3b440a 4923 -- Generate:
4924 -- [Deep_]Initialize (Init_Arg1);
ee6ba406 4925
fe696bd7 4926 Init_Call :=
5e8ac397 4927 Make_Init_Call
4928 (Obj_Ref => New_Copy_Tree (Init_Arg1),
fe696bd7 4929 Typ => T);
4930
4931 -- Guard against a missing [Deep_]Initialize when the
4932 -- designated type was not properly frozen.
4933
4934 if Present (Init_Call) then
4935 Insert_Action (N, Init_Call);
4936 end if;
ee6ba406 4937 end if;
4938
83c6c069 4939 Rewrite (N, New_Occurrence_Of (Temp, Loc));
40a5a4cb 4940 Analyze_And_Resolve (N, PtrT);
4941 end if;
914796b1 4942 end if;
4943 end;
0cba9418 4944
914796b1 4945 -- Ada 2005 (AI-251): If the allocator is for a class-wide interface
4946 -- object that has been rewritten as a reference, we displace "this"
4947 -- to reference properly its secondary dispatch table.
4948
6f0d10f7 4949 if Nkind (N) = N_Identifier and then Is_Interface (Dtyp) then
914796b1 4950 Displace_Allocator_Pointer (N);
0cba9418 4951 end if;
4952
9dfe12ae 4953 exception
4954 when RE_Not_Available =>
4955 return;
ee6ba406 4956 end Expand_N_Allocator;
4957
4958 -----------------------
4959 -- Expand_N_And_Then --
4960 -----------------------
4961
3755dbc5 4962 procedure Expand_N_And_Then (N : Node_Id)
4963 renames Expand_Short_Circuit_Operator;
ee6ba406 4964
e977c0cf 4965 ------------------------------
4966 -- Expand_N_Case_Expression --
4967 ------------------------------
4968
4969 procedure Expand_N_Case_Expression (N : Node_Id) is
2b4f2458 4970
7f4577a3 4971 function Is_Copy_Type (Typ : Entity_Id) return Boolean;
4972 -- Return True if we can copy objects of this type when expanding a case
4973 -- expression.
4974
4975 ------------------
4976 -- Is_Copy_Type --
4977 ------------------
4978
4979 function Is_Copy_Type (Typ : Entity_Id) return Boolean is
4980 begin
2b4f2458 4981 -- If Minimize_Expression_With_Actions is True, we can afford to copy
7f4577a3 4982 -- large objects, as long as they are constrained and not limited.
4983
4984 return
4985 Is_Elementary_Type (Underlying_Type (Typ))
4986 or else
4987 (Minimize_Expression_With_Actions
4988 and then Is_Constrained (Underlying_Type (Typ))
4989 and then not Is_Limited_View (Underlying_Type (Typ)));
4990 end Is_Copy_Type;
4991
4992 -- Local variables
4993
4994 Loc : constant Source_Ptr := Sloc (N);
4995 Par : constant Node_Id := Parent (N);
4996 Typ : constant Entity_Id := Etype (N);
4997
29d958a7 4998 Acts : List_Id;
4999 Alt : Node_Id;
5000 Case_Stmt : Node_Id;
5001 Decl : Node_Id;
5002 Expr : Node_Id;
5003 Target : Entity_Id;
5004 Target_Typ : Entity_Id;
5005
5006 In_Predicate : Boolean := False;
5007 -- Flag set when the case expression appears within a predicate
5008
97d14ea2 5009 Optimize_Return_Stmt : Boolean := False;
29d958a7 5010 -- Flag set when the case expression can be optimized in the context of
5011 -- a simple return statement.
e977c0cf 5012
7f4577a3 5013 -- Start of processing for Expand_N_Case_Expression
5014
e977c0cf 5015 begin
f32c377d 5016 -- Check for MINIMIZED/ELIMINATED overflow mode
5017
5018 if Minimized_Eliminated_Overflow_Check (N) then
0326b4d4 5019 Apply_Arithmetic_Overflow_Check (N);
5020 return;
5021 end if;
5022
5655be8a 5023 -- If the case expression is a predicate specification, and the type
5024 -- to which it applies has a static predicate aspect, do not expand,
5025 -- because it will be converted to the proper predicate form later.
639c3741 5026
5027 if Ekind_In (Current_Scope, E_Function, E_Procedure)
5028 and then Is_Predicate_Function (Current_Scope)
5029 then
97d14ea2 5030 In_Predicate := True;
5031
5032 if Has_Static_Predicate_Aspect (Etype (First_Entity (Current_Scope)))
5033 then
5034 return;
5035 end if;
639c3741 5036 end if;
5037
29d958a7 5038 -- When the type of the case expression is elementary, expand
e977c0cf 5039
29d958a7 5040 -- (case X is when A => AX, when B => BX ...)
e977c0cf 5041
29d958a7 5042 -- into
e977c0cf 5043
5044 -- do
29d958a7 5045 -- Target : Typ;
e977c0cf 5046 -- case X is
5047 -- when A =>
97d14ea2 5048 -- Target := AX;
e977c0cf 5049 -- when B =>
97d14ea2 5050 -- Target := BX;
e977c0cf 5051 -- ...
5052 -- end case;
97d14ea2 5053 -- in Target end;
5054
29d958a7 5055 -- In all other cases expand into
e977c0cf 5056
5057 -- do
29d958a7 5058 -- type Ptr_Typ is access all Typ;
97d14ea2 5059 -- Target : Ptr_Typ;
e977c0cf 5060 -- case X is
5061 -- when A =>
97d14ea2 5062 -- Target := AX'Unrestricted_Access;
e977c0cf 5063 -- when B =>
97d14ea2 5064 -- Target := BX'Unrestricted_Access;
e977c0cf 5065 -- ...
5066 -- end case;
97d14ea2 5067 -- in Target.all end;
e977c0cf 5068
29d958a7 5069 -- This approach avoids extra copies of potentially large objects. It
5070 -- also allows handling of values of limited or unconstrained types.
2b4f2458 5071 -- Note that we do the copy also for constrained, nonlimited types
7f4577a3 5072 -- when minimizing expressions with actions (e.g. when generating C
5073 -- code) since it allows us to do the optimization below in more cases.
29d958a7 5074
5075 -- Small optimization: when the case expression appears in the context
5076 -- of a simple return statement, expand into
5077
5078 -- case X is
5079 -- when A =>
5080 -- return AX;
5081 -- when B =>
5082 -- return BX;
5083 -- ...
5084 -- end case;
5085
97d14ea2 5086 Case_Stmt :=
e977c0cf 5087 Make_Case_Statement (Loc,
5088 Expression => Expression (N),
5089 Alternatives => New_List);
5090
cf580b1d 5091 -- Preserve the original context for which the case statement is being
5092 -- generated. This is needed by the finalization machinery to prevent
5093 -- the premature finalization of controlled objects found within the
5094 -- case statement.
5095
97d14ea2 5096 Set_From_Conditional_Expression (Case_Stmt);
5097 Acts := New_List;
e977c0cf 5098
7f4577a3 5099 -- Scalar/Copy case
e977c0cf 5100
7f4577a3 5101 if Is_Copy_Type (Typ) then
97d14ea2 5102 Target_Typ := Typ;
5103
5104 -- ??? Do not perform the optimization when the return statement is
2b4f2458 5105 -- within a predicate function, as this causes spurious errors. Could
29d958a7 5106 -- this be a possible mismatch in handling this case somewhere else
5107 -- in semantic analysis?
97d14ea2 5108
29d958a7 5109 Optimize_Return_Stmt :=
5110 Nkind (Par) = N_Simple_Return_Statement and then not In_Predicate;
5111
5112 -- Otherwise create an access type to handle the general case using
5113 -- 'Unrestricted_Access.
5114
5115 -- Generate:
5116 -- type Ptr_Typ is access all Typ;
e977c0cf 5117
5118 else
e77f7735 5119 if Generate_C_Code then
5120
0ae9270b 5121 -- We cannot ensure that correct C code will be generated if any
5122 -- temporary is created down the line (to e.g. handle checks or
5123 -- capture values) since we might end up with dangling references
5124 -- to local variables, so better be safe and reject the construct.
e77f7735 5125
5126 Error_Msg_N
5127 ("case expression too complex, use case statement instead", N);
5128 end if;
5129
29d958a7 5130 Target_Typ := Make_Temporary (Loc, 'P');
5131
97d14ea2 5132 Append_To (Acts,
e977c0cf 5133 Make_Full_Type_Declaration (Loc,
29d958a7 5134 Defining_Identifier => Target_Typ,
f4623c89 5135 Type_Definition =>
e977c0cf 5136 Make_Access_To_Object_Definition (Loc,
f4623c89 5137 All_Present => True,
83c6c069 5138 Subtype_Indication => New_Occurrence_Of (Typ, Loc))));
e977c0cf 5139 end if;
5140
29d958a7 5141 -- Create the declaration of the target which captures the value of the
5142 -- expression.
5143
5144 -- Generate:
5145 -- Target : [Ptr_]Typ;
5146
97d14ea2 5147 if not Optimize_Return_Stmt then
5148 Target := Make_Temporary (Loc, 'T');
588e7f97 5149
97d14ea2 5150 Decl :=
5151 Make_Object_Declaration (Loc,
5152 Defining_Identifier => Target,
5153 Object_Definition => New_Occurrence_Of (Target_Typ, Loc));
5154 Set_No_Initialization (Decl);
29d958a7 5155
97d14ea2 5156 Append_To (Acts, Decl);
5157 end if;
e977c0cf 5158
29d958a7 5159 -- Process the alternatives
e977c0cf 5160
5161 Alt := First (Alternatives (N));
5162 while Present (Alt) loop
5163 declare
97d14ea2 5164 Alt_Expr : Node_Id := Expression (Alt);
5165 Alt_Loc : constant Source_Ptr := Sloc (Alt_Expr);
5166 Stmts : List_Id;
e977c0cf 5167
5168 begin
29d958a7 5169 -- Take the unrestricted access of the expression value for non-
5170 -- scalar types. This approach avoids big copies and covers the
5171 -- limited and unconstrained cases.
5172
5173 -- Generate:
5174 -- AX'Unrestricted_Access
62616039 5175
7f4577a3 5176 if not Is_Copy_Type (Typ) then
97d14ea2 5177 Alt_Expr :=
5178 Make_Attribute_Reference (Alt_Loc,
5179 Prefix => Relocate_Node (Alt_Expr),
e977c0cf 5180 Attribute_Name => Name_Unrestricted_Access);
5181 end if;
5182
29d958a7 5183 -- Generate:
5184 -- return AX['Unrestricted_Access];
5185
97d14ea2 5186 if Optimize_Return_Stmt then
5187 Stmts := New_List (
5188 Make_Simple_Return_Statement (Alt_Loc,
5189 Expression => Alt_Expr));
29d958a7 5190
5191 -- Generate:
5192 -- Target := AX['Unrestricted_Access];
5193
97d14ea2 5194 else
5195 Stmts := New_List (
5196 Make_Assignment_Statement (Alt_Loc,
5197 Name => New_Occurrence_Of (Target, Loc),
5198 Expression => Alt_Expr));
5199 end if;
cb39358d 5200
5201 -- Propagate declarations inserted in the node by Insert_Actions
5202 -- (for example, temporaries generated to remove side effects).
5203 -- These actions must remain attached to the alternative, given
5204 -- that they are generated by the corresponding expression.
5205
97d14ea2 5206 if Present (Actions (Alt)) then
5207 Prepend_List (Actions (Alt), Stmts);
cb39358d 5208 end if;
5209
545d732b 5210 -- Finalize any transient objects on exit from the alternative.
5211 -- This is done only in the return optimization case because
5212 -- otherwise the case expression is converted into an expression
5213 -- with actions which already contains this form of processing.
29d958a7 5214
5215 if Optimize_Return_Stmt then
5216 Process_If_Case_Statements (N, Stmts);
5217 end if;
5218
e977c0cf 5219 Append_To
97d14ea2 5220 (Alternatives (Case_Stmt),
e977c0cf 5221 Make_Case_Statement_Alternative (Sloc (Alt),
5222 Discrete_Choices => Discrete_Choices (Alt),
97d14ea2 5223 Statements => Stmts));
e977c0cf 5224 end;
5225
5226 Next (Alt);
5227 end loop;
5228
29d958a7 5229 -- Rewrite the parent return statement as a case statement
97d14ea2 5230
5231 if Optimize_Return_Stmt then
97d14ea2 5232 Rewrite (Par, Case_Stmt);
5233 Analyze (Par);
97d14ea2 5234
29d958a7 5235 -- Otherwise convert the case expression into an expression with actions
e977c0cf 5236
e977c0cf 5237 else
29d958a7 5238 Append_To (Acts, Case_Stmt);
e977c0cf 5239
7f4577a3 5240 if Is_Copy_Type (Typ) then
29d958a7 5241 Expr := New_Occurrence_Of (Target, Loc);
e977c0cf 5242
29d958a7 5243 else
5244 Expr :=
5245 Make_Explicit_Dereference (Loc,
5246 Prefix => New_Occurrence_Of (Target, Loc));
5247 end if;
5248
5249 -- Generate:
5250 -- do
5251 -- ...
5252 -- in Target[.all] end;
5253
5254 Rewrite (N,
5255 Make_Expression_With_Actions (Loc,
5256 Expression => Expr,
5257 Actions => Acts));
5258
5259 Analyze_And_Resolve (N, Typ);
5260 end if;
e977c0cf 5261 end Expand_N_Case_Expression;
5262
92f1631f 5263 -----------------------------------
5264 -- Expand_N_Explicit_Dereference --
5265 -----------------------------------
5266
5267 procedure Expand_N_Explicit_Dereference (N : Node_Id) is
5268 begin
5269 -- Insert explicit dereference call for the checked storage pool case
5270
5271 Insert_Dereference_Action (Prefix (N));
5272
5273 -- If the type is an Atomic type for which Atomic_Sync is enabled, then
5274 -- we set the atomic sync flag.
5275
5276 if Is_Atomic (Etype (N))
5277 and then not Atomic_Synchronization_Disabled (Etype (N))
5278 then
5279 Activate_Atomic_Synchronization (N);
5280 end if;
5281 end Expand_N_Explicit_Dereference;
5282
5283 --------------------------------------
5284 -- Expand_N_Expression_With_Actions --
5285 --------------------------------------
5286
5287 procedure Expand_N_Expression_With_Actions (N : Node_Id) is
6958c62c 5288 Acts : constant List_Id := Actions (N);
5289
5290 procedure Force_Boolean_Evaluation (Expr : Node_Id);
5291 -- Force the evaluation of Boolean expression Expr
5292
66fbfcda 5293 function Process_Action (Act : Node_Id) return Traverse_Result;
1f35ddbe 5294 -- Inspect and process a single action of an expression_with_actions for
545d732b 5295 -- transient objects. If such objects are found, the routine generates
5296 -- code to clean them up when the context of the expression is evaluated
5297 -- or elaborated.
92f1631f 5298
6958c62c 5299 ------------------------------
5300 -- Force_Boolean_Evaluation --
5301 ------------------------------
5302
5303 procedure Force_Boolean_Evaluation (Expr : Node_Id) is
5304 Loc : constant Source_Ptr := Sloc (N);
5305 Flag_Decl : Node_Id;
5306 Flag_Id : Entity_Id;
5307
5308 begin
5309 -- Relocate the expression to the actions list by capturing its value
5310 -- in a Boolean flag. Generate:
5311 -- Flag : constant Boolean := Expr;
5312
5313 Flag_Id := Make_Temporary (Loc, 'F');
5314
5315 Flag_Decl :=
5316 Make_Object_Declaration (Loc,
5317 Defining_Identifier => Flag_Id,
5318 Constant_Present => True,
5319 Object_Definition => New_Occurrence_Of (Standard_Boolean, Loc),
5320 Expression => Relocate_Node (Expr));
5321
5322 Append (Flag_Decl, Acts);
5323 Analyze (Flag_Decl);
5324
5325 -- Replace the expression with a reference to the flag
5326
5327 Rewrite (Expression (N), New_Occurrence_Of (Flag_Id, Loc));
5328 Analyze (Expression (N));
5329 end Force_Boolean_Evaluation;
5330
66fbfcda 5331 --------------------
5332 -- Process_Action --
5333 --------------------
5334
5335 function Process_Action (Act : Node_Id) return Traverse_Result is
66fbfcda 5336 begin
5337 if Nkind (Act) = N_Object_Declaration
5338 and then Is_Finalizable_Transient (Act, N)
5339 then
545d732b 5340 Process_Transient_In_Expression (Act, N, Acts);
1f35ddbe 5341 return Abandon;
92f1631f 5342
66fbfcda 5343 -- Avoid processing temporary function results multiple times when
5344 -- dealing with nested expression_with_actions.
92f1631f 5345
66fbfcda 5346 elsif Nkind (Act) = N_Expression_With_Actions then
5347 return Abandon;
5348
1f35ddbe 5349 -- Do not process temporary function results in loops. This is done
5350 -- by Expand_N_Loop_Statement and Build_Finalizer.
66fbfcda 5351
5352 elsif Nkind (Act) = N_Loop_Statement then
5353 return Abandon;
92f1631f 5354 end if;
5355
66fbfcda 5356 return OK;
5357 end Process_Action;
92f1631f 5358
66fbfcda 5359 procedure Process_Single_Action is new Traverse_Proc (Process_Action);
92f1631f 5360
5361 -- Local variables
5362
6958c62c 5363 Act : Node_Id;
92f1631f 5364
5365 -- Start of processing for Expand_N_Expression_With_Actions
5366
5367 begin
cf8fe84b 5368 -- Do not evaluate the expression when it denotes an entity because the
5369 -- expression_with_actions node will be replaced by the reference.
5370
6958c62c 5371 if Is_Entity_Name (Expression (N)) then
cf8fe84b 5372 null;
5373
5374 -- Do not evaluate the expression when there are no actions because the
5375 -- expression_with_actions node will be replaced by the expression.
5376
5377 elsif No (Acts) or else Is_Empty_List (Acts) then
5378 null;
5379
5380 -- Force the evaluation of the expression by capturing its value in a
545d732b 5381 -- temporary. This ensures that aliases of transient objects do not leak
5382 -- to the expression of the expression_with_actions node:
cf8fe84b 5383
5384 -- do
fdbdf68c 5385 -- Trans_Id : Ctrl_Typ := ...;
cf8fe84b 5386 -- Alias : ... := Trans_Id;
5387 -- in ... Alias ... end;
5388
5389 -- In the example above, Trans_Id cannot be finalized at the end of the
5390 -- actions list because this may affect the alias and the final value of
5391 -- the expression_with_actions. Forcing the evaluation encapsulates the
5392 -- reference to the Alias within the actions list:
5393
5394 -- do
fdbdf68c 5395 -- Trans_Id : Ctrl_Typ := ...;
cf8fe84b 5396 -- Alias : ... := Trans_Id;
5397 -- Val : constant Boolean := ... Alias ...;
5398 -- <finalize Trans_Id>
5399 -- in Val end;
389062c9 5400
6958c62c 5401 -- Once this transformation is performed, it is safe to finalize the
545d732b 5402 -- transient object at the end of the actions list.
6958c62c 5403
5404 -- Note that Force_Evaluation does not remove side effects in operators
5405 -- because it assumes that all operands are evaluated and side effect
5406 -- free. This is not the case when an operand depends implicitly on the
545d732b 5407 -- transient object through the use of access types.
6958c62c 5408
5409 elsif Is_Boolean_Type (Etype (Expression (N))) then
5410 Force_Boolean_Evaluation (Expression (N));
5411
2f7de3db 5412 -- The expression of an expression_with_actions node may not necessarily
6958c62c 5413 -- be Boolean when the node appears in an if expression. In this case do
5414 -- the usual forced evaluation to encapsulate potential aliasing.
cf8fe84b 5415
5416 else
6958c62c 5417 Force_Evaluation (Expression (N));
cf8fe84b 5418 end if;
5419
545d732b 5420 -- Process all transient objects found within the actions of the EWA
5421 -- node.
cf8fe84b 5422
5423 Act := First (Acts);
389062c9 5424 while Present (Act) loop
5425 Process_Single_Action (Act);
5426 Next (Act);
5427 end loop;
5428
8c784c07 5429 -- Deal with case where there are no actions. In this case we simply
008ad8b8 5430 -- rewrite the node with its expression since we don't need the actions
8c784c07 5431 -- and the specification of this node does not allow a null action list.
5432
008ad8b8 5433 -- Note: we use Rewrite instead of Replace, because Codepeer is using
5434 -- the expanded tree and relying on being able to retrieve the original
5435 -- tree in cases like this. This raises a whole lot of issues of whether
5436 -- we have problems elsewhere, which will be addressed in the future???
5437
cf8fe84b 5438 if Is_Empty_List (Acts) then
008ad8b8 5439 Rewrite (N, Relocate_Node (Expression (N)));
8c784c07 5440 end if;
92f1631f 5441 end Expand_N_Expression_With_Actions;
5442
5443 ----------------------------
5444 -- Expand_N_If_Expression --
5445 ----------------------------
ee6ba406 5446
d5be9f38 5447 -- Deal with limited types and condition actions
ee6ba406 5448
92f1631f 5449 procedure Expand_N_If_Expression (N : Node_Id) is
29d958a7 5450 Cond : constant Node_Id := First (Expressions (N));
5451 Loc : constant Source_Ptr := Sloc (N);
5452 Thenx : constant Node_Id := Next (Cond);
5453 Elsex : constant Node_Id := Next (Thenx);
5454 Typ : constant Entity_Id := Etype (N);
8d6d2396 5455
714e7f2d 5456 Actions : List_Id;
bbc7bed2 5457 Decl : Node_Id;
714e7f2d 5458 Expr : Node_Id;
bbc7bed2 5459 New_If : Node_Id;
5460 New_N : Node_Id;
ee6ba406 5461
5462 begin
f32c377d 5463 -- Check for MINIMIZED/ELIMINATED overflow mode
5464
5465 if Minimized_Eliminated_Overflow_Check (N) then
5466 Apply_Arithmetic_Overflow_Check (N);
5467 return;
5468 end if;
5469
bbc7bed2 5470 -- Fold at compile time if condition known. We have already folded
92f1631f 5471 -- static if expressions, but it is possible to fold any case in which
5472 -- the condition is known at compile time, even though the result is
5473 -- non-static.
bbc7bed2 5474
5475 -- Note that we don't do the fold of such cases in Sem_Elab because
5476 -- it can cause infinite loops with the expander adding a conditional
5477 -- expression, and Sem_Elab circuitry removing it repeatedly.
5478
5479 if Compile_Time_Known_Value (Cond) then
9c890dc4 5480 declare
5481 function Fold_Known_Value (Cond : Node_Id) return Boolean;
29d958a7 5482 -- Fold at compile time. Assumes condition known. Return True if
5483 -- folding occurred, meaning we're done.
bbc7bed2 5484
9c890dc4 5485 ----------------------
5486 -- Fold_Known_Value --
5487 ----------------------
fc690413 5488
9c890dc4 5489 function Fold_Known_Value (Cond : Node_Id) return Boolean is
5490 begin
5491 if Is_True (Expr_Value (Cond)) then
5492 Expr := Thenx;
5493 Actions := Then_Actions (N);
5494 else
5495 Expr := Elsex;
5496 Actions := Else_Actions (N);
5497 end if;
bbc7bed2 5498
9c890dc4 5499 Remove (Expr);
bbc7bed2 5500
9c890dc4 5501 if Present (Actions) then
5502
d4706d04 5503 -- To minimize the use of Expression_With_Actions, just skip
5504 -- the optimization as it is not critical for correctness.
9c890dc4 5505
5506 if Minimize_Expression_With_Actions then
5507 return False;
5508 end if;
5509
5510 Rewrite (N,
5511 Make_Expression_With_Actions (Loc,
5512 Expression => Relocate_Node (Expr),
5513 Actions => Actions));
5514 Analyze_And_Resolve (N, Typ);
5515
5516 else
5517 Rewrite (N, Relocate_Node (Expr));
5518 end if;
5519
5520 -- Note that the result is never static (legitimate cases of
5521 -- static if expressions were folded in Sem_Eval).
5522
5523 Set_Is_Static_Expression (N, False);
5524 return True;
5525 end Fold_Known_Value;
5526
5527 begin
5528 if Fold_Known_Value (Cond) then
5529 return;
5530 end if;
5531 end;
bbc7bed2 5532 end if;
5533
2a36a1cc 5534 -- If the type is limited, and the back end does not handle limited
5535 -- types, then we expand as follows to avoid the possibility of
5536 -- improper copying.
7b31b357 5537
8d6d2396 5538 -- type Ptr is access all Typ;
5539 -- Cnn : Ptr;
7b31b357 5540 -- if cond then
5541 -- <<then actions>>
5542 -- Cnn := then-expr'Unrestricted_Access;
5543 -- else
5544 -- <<else actions>>
5545 -- Cnn := else-expr'Unrestricted_Access;
5546 -- end if;
5547
92f1631f 5548 -- and replace the if expression by a reference to Cnn.all.
7b31b357 5549
c9e3ee19 5550 -- This special case can be skipped if the back end handles limited
5551 -- types properly and ensures that no incorrect copies are made.
5552
5553 if Is_By_Reference_Type (Typ)
5554 and then not Back_End_Handles_Limited_Types
5555 then
1f35ddbe 5556 -- When the "then" or "else" expressions involve controlled function
5557 -- calls, generated temporaries are chained on the corresponding list
5558 -- of actions. These temporaries need to be finalized after the if
5559 -- expression is evaluated.
714e7f2d 5560
29d958a7 5561 Process_If_Case_Statements (N, Then_Actions (N));
5562 Process_If_Case_Statements (N, Else_Actions (N));
714e7f2d 5563
e0e76328 5564 declare
5565 Cnn : constant Entity_Id := Make_Temporary (Loc, 'C', N);
5566 Ptr_Typ : constant Entity_Id := Make_Temporary (Loc, 'A');
5567 begin
5568 -- Generate:
5569 -- type Ann is access all Typ;
714e7f2d 5570
e0e76328 5571 Insert_Action (N,
5572 Make_Full_Type_Declaration (Loc,
5573 Defining_Identifier => Ptr_Typ,
5574 Type_Definition =>
5575 Make_Access_To_Object_Definition (Loc,
5576 All_Present => True,
5577 Subtype_Indication => New_Occurrence_Of (Typ, Loc))));
714e7f2d 5578
e0e76328 5579 -- Generate:
5580 -- Cnn : Ann;
714e7f2d 5581
e0e76328 5582 Decl :=
5583 Make_Object_Declaration (Loc,
5584 Defining_Identifier => Cnn,
5585 Object_Definition => New_Occurrence_Of (Ptr_Typ, Loc));
714e7f2d 5586
e0e76328 5587 -- Generate:
5588 -- if Cond then
5589 -- Cnn := <Thenx>'Unrestricted_Access;
5590 -- else
5591 -- Cnn := <Elsex>'Unrestricted_Access;
5592 -- end if;
714e7f2d 5593
e0e76328 5594 New_If :=
5595 Make_Implicit_If_Statement (N,
5596 Condition => Relocate_Node (Cond),
5597 Then_Statements => New_List (
5598 Make_Assignment_Statement (Sloc (Thenx),
5599 Name => New_Occurrence_Of (Cnn, Sloc (Thenx)),
5600 Expression =>
5601 Make_Attribute_Reference (Loc,
5602 Prefix => Relocate_Node (Thenx),
5603 Attribute_Name => Name_Unrestricted_Access))),
714e7f2d 5604
e0e76328 5605 Else_Statements => New_List (
5606 Make_Assignment_Statement (Sloc (Elsex),
5607 Name => New_Occurrence_Of (Cnn, Sloc (Elsex)),
5608 Expression =>
5609 Make_Attribute_Reference (Loc,
5610 Prefix => Relocate_Node (Elsex),
5611 Attribute_Name => Name_Unrestricted_Access))));
5612
5613 -- Preserve the original context for which the if statement is
5614 -- being generated. This is needed by the finalization machinery
5615 -- to prevent the premature finalization of controlled objects
5616 -- found within the if statement.
5617
5618 Set_From_Conditional_Expression (New_If);
5619
5620 New_N :=
5621 Make_Explicit_Dereference (Loc,
5622 Prefix => New_Occurrence_Of (Cnn, Loc));
5623 end;
b2316500 5624
2a36a1cc 5625 -- If the result is an unconstrained array and the if expression is in a
5626 -- context other than the initializing expression of the declaration of
5627 -- an object, then we pull out the if expression as follows:
5628
5629 -- Cnn : constant typ := if-expression
5630
5631 -- and then replace the if expression with an occurrence of Cnn. This
5632 -- avoids the need in the back end to create on-the-fly variable length
5633 -- temporaries (which it cannot do!)
5634
5635 -- Note that the test for being in an object declaration avoids doing an
5636 -- unnecessary expansion, and also avoids infinite recursion.
5637
5638 elsif Is_Array_Type (Typ) and then not Is_Constrained (Typ)
5639 and then (Nkind (Parent (N)) /= N_Object_Declaration
5640 or else Expression (Parent (N)) /= N)
5641 then
5642 declare
5643 Cnn : constant Node_Id := Make_Temporary (Loc, 'C', N);
5644 begin
5645 Insert_Action (N,
5646 Make_Object_Declaration (Loc,
5647 Defining_Identifier => Cnn,
5648 Constant_Present => True,
5649 Object_Definition => New_Occurrence_Of (Typ, Loc),
5650 Expression => Relocate_Node (N),
5651 Has_Init_Expression => True));
5652
5653 Rewrite (N, New_Occurrence_Of (Cnn, Loc));
5654 return;
5655 end;
5656
8d6d2396 5657 -- For other types, we only need to expand if there are other actions
5658 -- associated with either branch.
5659
5660 elsif Present (Then_Actions (N)) or else Present (Else_Actions (N)) then
8d6d2396 5661
f6f7b3f4 5662 -- We now wrap the actions into the appropriate expression
b2316500 5663
b379e58c 5664 if Minimize_Expression_With_Actions
5665 and then (Is_Elementary_Type (Underlying_Type (Typ))
5666 or else Is_Constrained (Underlying_Type (Typ)))
5667 then
9c890dc4 5668 -- If we can't use N_Expression_With_Actions nodes, then we insert
5669 -- the following sequence of actions (using Insert_Actions):
c9e3ee19 5670
9c890dc4 5671 -- Cnn : typ;
5672 -- if cond then
5673 -- <<then actions>>
5674 -- Cnn := then-expr;
5675 -- else
5676 -- <<else actions>>
5677 -- Cnn := else-expr
5678 -- end if;
1f35ddbe 5679
9c890dc4 5680 -- and replace the if expression by a reference to Cnn
c9e3ee19 5681
e0e76328 5682 declare
5683 Cnn : constant Node_Id := Make_Temporary (Loc, 'C', N);
5684 begin
5685 Decl :=
5686 Make_Object_Declaration (Loc,
5687 Defining_Identifier => Cnn,
5688 Object_Definition => New_Occurrence_Of (Typ, Loc));
9c890dc4 5689
e0e76328 5690 New_If :=
5691 Make_Implicit_If_Statement (N,
5692 Condition => Relocate_Node (Cond),
9c890dc4 5693
e0e76328 5694 Then_Statements => New_List (
5695 Make_Assignment_Statement (Sloc (Thenx),
5696 Name => New_Occurrence_Of (Cnn, Sloc (Thenx)),
5697 Expression => Relocate_Node (Thenx))),
9c890dc4 5698
e0e76328 5699 Else_Statements => New_List (
5700 Make_Assignment_Statement (Sloc (Elsex),
5701 Name => New_Occurrence_Of (Cnn, Sloc (Elsex)),
5702 Expression => Relocate_Node (Elsex))));
9c890dc4 5703
e0e76328 5704 Set_Assignment_OK (Name (First (Then_Statements (New_If))));
5705 Set_Assignment_OK (Name (First (Else_Statements (New_If))));
9c890dc4 5706
e0e76328 5707 New_N := New_Occurrence_Of (Cnn, Loc);
5708 end;
9c890dc4 5709
5710 -- Regular path using Expression_With_Actions
5711
5712 else
5713 if Present (Then_Actions (N)) then
5714 Rewrite (Thenx,
5715 Make_Expression_With_Actions (Sloc (Thenx),
5716 Actions => Then_Actions (N),
5717 Expression => Relocate_Node (Thenx)));
5718
5719 Set_Then_Actions (N, No_List);
5720 Analyze_And_Resolve (Thenx, Typ);
5721 end if;
5722
5723 if Present (Else_Actions (N)) then
5724 Rewrite (Elsex,
5725 Make_Expression_With_Actions (Sloc (Elsex),
5726 Actions => Else_Actions (N),
5727 Expression => Relocate_Node (Elsex)));
5728
5729 Set_Else_Actions (N, No_List);
5730 Analyze_And_Resolve (Elsex, Typ);
5731 end if;
5732
5733 return;
5734 end if;
f6f7b3f4 5735
1f35ddbe 5736 -- If no actions then no expansion needed, gigi will handle it using the
5737 -- same approach as a C conditional expression.
c9e3ee19 5738
5739 else
8d6d2396 5740 return;
5741 end if;
5742
c9e3ee19 5743 -- Fall through here for either the limited expansion, or the case of
2b4f2458 5744 -- inserting actions for nonlimited types. In both these cases, we must
c9e3ee19 5745 -- move the SLOC of the parent If statement to the newly created one and
be5e6450 5746 -- change it to the SLOC of the expression which, after expansion, will
5747 -- correspond to what is being evaluated.
8d6d2396 5748
6f0d10f7 5749 if Present (Parent (N)) and then Nkind (Parent (N)) = N_If_Statement then
8d6d2396 5750 Set_Sloc (New_If, Sloc (Parent (N)));
5751 Set_Sloc (Parent (N), Loc);
5752 end if;
ee6ba406 5753
be5e6450 5754 -- Make sure Then_Actions and Else_Actions are appropriately moved
5755 -- to the new if statement.
5756
8d6d2396 5757 if Present (Then_Actions (N)) then
5758 Insert_List_Before
5759 (First (Then_Statements (New_If)), Then_Actions (N));
ee6ba406 5760 end if;
8d6d2396 5761
5762 if Present (Else_Actions (N)) then
5763 Insert_List_Before
5764 (First (Else_Statements (New_If)), Else_Actions (N));
5765 end if;
5766
5767 Insert_Action (N, Decl);
5768 Insert_Action (N, New_If);
5769 Rewrite (N, New_N);
5770 Analyze_And_Resolve (N, Typ);
92f1631f 5771 end Expand_N_If_Expression;
008ad845 5772
ee6ba406 5773 -----------------
5774 -- Expand_N_In --
5775 -----------------
5776
5777 procedure Expand_N_In (N : Node_Id) is
5329ca64 5778 Loc : constant Source_Ptr := Sloc (N);
4aed5405 5779 Restyp : constant Entity_Id := Etype (N);
5329ca64 5780 Lop : constant Node_Id := Left_Opnd (N);
5781 Rop : constant Node_Id := Right_Opnd (N);
5782 Static : constant Boolean := Is_OK_Static_Expression (N);
ee6ba406 5783
4dcc60e5 5784 procedure Substitute_Valid_Check;
5785 -- Replaces node N by Lop'Valid. This is done when we have an explicit
5786 -- test for the left operand being in range of its subtype.
5787
5788 ----------------------------
5789 -- Substitute_Valid_Check --
5790 ----------------------------
5791
5792 procedure Substitute_Valid_Check is
83d2f9bc 5793 function Is_OK_Object_Reference (Nod : Node_Id) return Boolean;
5794 -- Determine whether arbitrary node Nod denotes a source object that
5795 -- may safely act as prefix of attribute 'Valid.
5796
5797 ----------------------------
5798 -- Is_OK_Object_Reference --
5799 ----------------------------
5800
5801 function Is_OK_Object_Reference (Nod : Node_Id) return Boolean is
5802 Obj_Ref : Node_Id;
5803
5804 begin
5805 -- Inspect the original operand
5806
5807 Obj_Ref := Original_Node (Nod);
5808
5809 -- The object reference must be a source construct, otherwise the
5810 -- codefix suggestion may refer to nonexistent code from a user
5811 -- perspective.
5812
5813 if Comes_From_Source (Obj_Ref) then
5814
5815 -- Recover the actual object reference. There may be more cases
5816 -- to consider???
5817
5818 loop
5819 if Nkind_In (Obj_Ref, N_Type_Conversion,
5820 N_Unchecked_Type_Conversion)
5821 then
5822 Obj_Ref := Expression (Obj_Ref);
5823 else
5824 exit;
5825 end if;
5826 end loop;
5827
5828 return Is_Object_Reference (Obj_Ref);
5829 end if;
5830
5831 return False;
5832 end Is_OK_Object_Reference;
5833
5834 -- Start of processing for Substitute_Valid_Check
5835
4dcc60e5 5836 begin
55e8372b 5837 Rewrite (N,
5838 Make_Attribute_Reference (Loc,
5839 Prefix => Relocate_Node (Lop),
5840 Attribute_Name => Name_Valid));
4dcc60e5 5841
55e8372b 5842 Analyze_And_Resolve (N, Restyp);
4dcc60e5 5843
83d2f9bc 5844 -- Emit a warning when the left-hand operand of the membership test
5845 -- is a source object, otherwise the use of attribute 'Valid would be
5846 -- illegal. The warning is not given when overflow checking is either
5847 -- MINIMIZED or ELIMINATED, as the danger of optimization has been
5848 -- eliminated above.
3cce7f32 5849
83d2f9bc 5850 if Is_OK_Object_Reference (Lop)
5851 and then Overflow_Check_Mode not in Minimized_Or_Eliminated
5852 then
6e9f198b 5853 Error_Msg_N
5854 ("??explicit membership test may be optimized away", N);
3cce7f32 5855 Error_Msg_N -- CODEFIX
6e9f198b 5856 ("\??use ''Valid attribute instead", N);
3cce7f32 5857 end if;
4dcc60e5 5858 end Substitute_Valid_Check;
5859
83d2f9bc 5860 -- Local variables
5861
5862 Ltyp : Entity_Id;
5863 Rtyp : Entity_Id;
5864
4dcc60e5 5865 -- Start of processing for Expand_N_In
5866
ee6ba406 5867 begin
6fb3c314 5868 -- If set membership case, expand with separate procedure
4aed5405 5869
5d6b98f6 5870 if Present (Alternatives (N)) then
9765de15 5871 Expand_Set_Membership (N);
5d6b98f6 5872 return;
5873 end if;
5874
4aed5405 5875 -- Not set membership, proceed with expansion
5876
5877 Ltyp := Etype (Left_Opnd (N));
5878 Rtyp := Etype (Right_Opnd (N));
5879
21a55437 5880 -- If MINIMIZED/ELIMINATED overflow mode and type is a signed integer
aa4b16cb 5881 -- type, then expand with a separate procedure. Note the use of the
5882 -- flag No_Minimize_Eliminate to prevent infinite recursion.
5883
0df9d43f 5884 if Overflow_Check_Mode in Minimized_Or_Eliminated
aa4b16cb 5885 and then Is_Signed_Integer_Type (Ltyp)
5886 and then not No_Minimize_Eliminate (N)
5887 then
5888 Expand_Membership_Minimize_Eliminate_Overflow (N);
5889 return;
5890 end if;
5891
4dcc60e5 5892 -- Check case of explicit test for an expression in range of its
5893 -- subtype. This is suspicious usage and we replace it with a 'Valid
f32c377d 5894 -- test and give a warning for scalar types.
4dcc60e5 5895
4aed5405 5896 if Is_Scalar_Type (Ltyp)
f32c377d 5897
5898 -- Only relevant for source comparisons
5899
5900 and then Comes_From_Source (N)
5901
5902 -- In floating-point this is a standard way to check for finite values
5903 -- and using 'Valid would typically be a pessimization.
5904
4aed5405 5905 and then not Is_Floating_Point_Type (Ltyp)
f32c377d 5906
5907 -- Don't give the message unless right operand is a type entity and
5908 -- the type of the left operand matches this type. Note that this
5909 -- eliminates the cases where MINIMIZED/ELIMINATED mode overflow
5910 -- checks have changed the type of the left operand.
5911
4dcc60e5 5912 and then Nkind (Rop) in N_Has_Entity
4aed5405 5913 and then Ltyp = Entity (Rop)
f32c377d 5914
f32c377d 5915 -- Skip this for predicated types, where such expressions are a
5916 -- reasonable way of testing if something meets the predicate.
5917
aae8e592 5918 and then not Present (Predicate_Function (Ltyp))
4dcc60e5 5919 then
5920 Substitute_Valid_Check;
5921 return;
5922 end if;
5923
e8ccec48 5924 -- Do validity check on operands
5925
5926 if Validity_Checks_On and Validity_Check_Operands then
5927 Ensure_Valid (Left_Opnd (N));
5928 Validity_Check_Range (Right_Opnd (N));
5929 end if;
5930
4dcc60e5 5931 -- Case of explicit range
9dfe12ae 5932
5933 if Nkind (Rop) = N_Range then
5934 declare
4dcc60e5 5935 Lo : constant Node_Id := Low_Bound (Rop);
5936 Hi : constant Node_Id := High_Bound (Rop);
5937
5938 Lo_Orig : constant Node_Id := Original_Node (Lo);
5939 Hi_Orig : constant Node_Id := Original_Node (Hi);
5940
9c486805 5941 Lcheck : Compare_Result;
5942 Ucheck : Compare_Result;
9dfe12ae 5943
a3e461ac 5944 Warn1 : constant Boolean :=
5945 Constant_Condition_Warnings
9c486805 5946 and then Comes_From_Source (N)
5947 and then not In_Instance;
a3e461ac 5948 -- This must be true for any of the optimization warnings, we
31c85ce5 5949 -- clearly want to give them only for source with the flag on. We
5950 -- also skip these warnings in an instance since it may be the
5951 -- case that different instantiations have different ranges.
a3e461ac 5952
5953 Warn2 : constant Boolean :=
5954 Warn1
5955 and then Nkind (Original_Node (Rop)) = N_Range
5956 and then Is_Integer_Type (Etype (Lo));
5957 -- For the case where only one bound warning is elided, we also
5958 -- insist on an explicit range and an integer type. The reason is
5959 -- that the use of enumeration ranges including an end point is
31c85ce5 5960 -- common, as is the use of a subtype name, one of whose bounds is
5961 -- the same as the type of the expression.
a3e461ac 5962
9dfe12ae 5963 begin
d03ada96 5964 -- If test is explicit x'First .. x'Last, replace by valid check
4dcc60e5 5965
5b5df4a9 5966 -- Could use some individual comments for this complex test ???
5967
a3e461ac 5968 if Is_Scalar_Type (Ltyp)
f32c377d 5969
5970 -- And left operand is X'First where X matches left operand
5971 -- type (this eliminates cases of type mismatch, including
5972 -- the cases where ELIMINATED/MINIMIZED mode has changed the
5973 -- type of the left operand.
5974
4dcc60e5 5975 and then Nkind (Lo_Orig) = N_Attribute_Reference
5976 and then Attribute_Name (Lo_Orig) = Name_First
5977 and then Nkind (Prefix (Lo_Orig)) in N_Has_Entity
a3e461ac 5978 and then Entity (Prefix (Lo_Orig)) = Ltyp
f32c377d 5979
82b93248 5980 -- Same tests for right operand
f32c377d 5981
4dcc60e5 5982 and then Nkind (Hi_Orig) = N_Attribute_Reference
5983 and then Attribute_Name (Hi_Orig) = Name_Last
5984 and then Nkind (Prefix (Hi_Orig)) in N_Has_Entity
a3e461ac 5985 and then Entity (Prefix (Hi_Orig)) = Ltyp
f32c377d 5986
5987 -- Relevant only for source cases
5988
4dcc60e5 5989 and then Comes_From_Source (N)
5990 then
5991 Substitute_Valid_Check;
4aed5405 5992 goto Leave;
4dcc60e5 5993 end if;
5994
a3e461ac 5995 -- If bounds of type are known at compile time, and the end points
5996 -- are known at compile time and identical, this is another case
5997 -- for substituting a valid test. We only do this for discrete
5998 -- types, since it won't arise in practice for float types.
5999
6000 if Comes_From_Source (N)
6001 and then Is_Discrete_Type (Ltyp)
6002 and then Compile_Time_Known_Value (Type_High_Bound (Ltyp))
6003 and then Compile_Time_Known_Value (Type_Low_Bound (Ltyp))
6004 and then Compile_Time_Known_Value (Lo)
6005 and then Compile_Time_Known_Value (Hi)
6006 and then Expr_Value (Type_High_Bound (Ltyp)) = Expr_Value (Hi)
6007 and then Expr_Value (Type_Low_Bound (Ltyp)) = Expr_Value (Lo)
0a5994cb 6008
aa4b16cb 6009 -- Kill warnings in instances, since they may be cases where we
6010 -- have a test in the generic that makes sense with some types
6011 -- and not with other types.
0a5994cb 6012
6013 and then not In_Instance
a3e461ac 6014 then
6015 Substitute_Valid_Check;
4aed5405 6016 goto Leave;
a3e461ac 6017 end if;
6018
31c85ce5 6019 -- If we have an explicit range, do a bit of optimization based on
6020 -- range analysis (we may be able to kill one or both checks).
4dcc60e5 6021
9c486805 6022 Lcheck := Compile_Time_Compare (Lop, Lo, Assume_Valid => False);
6023 Ucheck := Compile_Time_Compare (Lop, Hi, Assume_Valid => False);
6024
4dcc60e5 6025 -- If either check is known to fail, replace result by False since
6026 -- the other check does not matter. Preserve the static flag for
6027 -- legality checks, because we are constant-folding beyond RM 4.9.
9dfe12ae 6028
6029 if Lcheck = LT or else Ucheck = GT then
9c486805 6030 if Warn1 then
cb97ae5c 6031 Error_Msg_N ("?c?range test optimized away", N);
6032 Error_Msg_N ("\?c?value is known to be out of range", N);
a3e461ac 6033 end if;
6034
83c6c069 6035 Rewrite (N, New_Occurrence_Of (Standard_False, Loc));
4aed5405 6036 Analyze_And_Resolve (N, Restyp);
5329ca64 6037 Set_Is_Static_Expression (N, Static);
4aed5405 6038 goto Leave;
9dfe12ae 6039
f1e2dcc5 6040 -- If both checks are known to succeed, replace result by True,
6041 -- since we know we are in range.
9dfe12ae 6042
6043 elsif Lcheck in Compare_GE and then Ucheck in Compare_LE then
9c486805 6044 if Warn1 then
cb97ae5c 6045 Error_Msg_N ("?c?range test optimized away", N);
6046 Error_Msg_N ("\?c?value is known to be in range", N);
a3e461ac 6047 end if;
6048
83c6c069 6049 Rewrite (N, New_Occurrence_Of (Standard_True, Loc));
4aed5405 6050 Analyze_And_Resolve (N, Restyp);
5329ca64 6051 Set_Is_Static_Expression (N, Static);
4aed5405 6052 goto Leave;
9dfe12ae 6053
a3e461ac 6054 -- If lower bound check succeeds and upper bound check is not
6055 -- known to succeed or fail, then replace the range check with
6056 -- a comparison against the upper bound.
9dfe12ae 6057
6058 elsif Lcheck in Compare_GE then
0a5994cb 6059 if Warn2 and then not In_Instance then
6e9f198b 6060 Error_Msg_N ("??lower bound test optimized away", Lo);
6061 Error_Msg_N ("\??value is known to be in range", Lo);
a3e461ac 6062 end if;
6063
9dfe12ae 6064 Rewrite (N,
6065 Make_Op_Le (Loc,
6066 Left_Opnd => Lop,
6067 Right_Opnd => High_Bound (Rop)));
4aed5405 6068 Analyze_And_Resolve (N, Restyp);
6069 goto Leave;
9dfe12ae 6070
a3e461ac 6071 -- If upper bound check succeeds and lower bound check is not
6072 -- known to succeed or fail, then replace the range check with
6073 -- a comparison against the lower bound.
9dfe12ae 6074
6075 elsif Ucheck in Compare_LE then
0a5994cb 6076 if Warn2 and then not In_Instance then
6e9f198b 6077 Error_Msg_N ("??upper bound test optimized away", Hi);
6078 Error_Msg_N ("\??value is known to be in range", Hi);
a3e461ac 6079 end if;
6080
9dfe12ae 6081 Rewrite (N,
6082 Make_Op_Ge (Loc,
6083 Left_Opnd => Lop,
6084 Right_Opnd => Low_Bound (Rop)));
4aed5405 6085 Analyze_And_Resolve (N, Restyp);
6086 goto Leave;
9dfe12ae 6087 end if;
9c486805 6088
6089 -- We couldn't optimize away the range check, but there is one
6090 -- more issue. If we are checking constant conditionals, then we
6091 -- see if we can determine the outcome assuming everything is
6092 -- valid, and if so give an appropriate warning.
6093
6094 if Warn1 and then not Assume_No_Invalid_Values then
6095 Lcheck := Compile_Time_Compare (Lop, Lo, Assume_Valid => True);
6096 Ucheck := Compile_Time_Compare (Lop, Hi, Assume_Valid => True);
6097
6098 -- Result is out of range for valid value
6099
6100 if Lcheck = LT or else Ucheck = GT then
503f7fd3 6101 Error_Msg_N
cb97ae5c 6102 ("?c?value can only be in range if it is invalid", N);
9c486805 6103
6104 -- Result is in range for valid value
6105
6106 elsif Lcheck in Compare_GE and then Ucheck in Compare_LE then
503f7fd3 6107 Error_Msg_N
cb97ae5c 6108 ("?c?value can only be out of range if it is invalid", N);
9c486805 6109
6110 -- Lower bound check succeeds if value is valid
6111
6112 elsif Warn2 and then Lcheck in Compare_GE then
503f7fd3 6113 Error_Msg_N
cb97ae5c 6114 ("?c?lower bound check only fails if it is invalid", Lo);
9c486805 6115
6116 -- Upper bound check succeeds if value is valid
6117
6118 elsif Warn2 and then Ucheck in Compare_LE then
503f7fd3 6119 Error_Msg_N
cb97ae5c 6120 ("?c?upper bound check only fails for invalid values", Hi);
9c486805 6121 end if;
6122 end if;
9dfe12ae 6123 end;
6124
6125 -- For all other cases of an explicit range, nothing to be done
ee6ba406 6126
4aed5405 6127 goto Leave;
ee6ba406 6128
6129 -- Here right operand is a subtype mark
6130
6131 else
6132 declare
3feedf2a 6133 Typ : Entity_Id := Etype (Rop);
6134 Is_Acc : constant Boolean := Is_Access_Type (Typ);
6135 Cond : Node_Id := Empty;
6136 New_N : Node_Id;
6137 Obj : Node_Id := Lop;
6138 SCIL_Node : Node_Id;
ee6ba406 6139
6140 begin
6141 Remove_Side_Effects (Obj);
6142
6143 -- For tagged type, do tagged membership operation
6144
6145 if Is_Tagged_Type (Typ) then
9dfe12ae 6146
36ac5fbb 6147 -- No expansion will be performed for VM targets, as the VM
2a801d20 6148 -- back ends will handle the membership tests directly.
ee6ba406 6149
662256db 6150 if Tagged_Type_Expansion then
3feedf2a 6151 Tagged_Membership (N, SCIL_Node, New_N);
6152 Rewrite (N, New_N);
ed7fd418 6153 Analyze_And_Resolve (N, Restyp, Suppress => All_Checks);
3feedf2a 6154
6155 -- Update decoration of relocated node referenced by the
6156 -- SCIL node.
6157
31c85ce5 6158 if Generate_SCIL and then Present (SCIL_Node) then
5a44b136 6159 Set_SCIL_Node (N, SCIL_Node);
3feedf2a 6160 end if;
ee6ba406 6161 end if;
6162
4aed5405 6163 goto Leave;
ee6ba406 6164
d03ada96 6165 -- If type is scalar type, rewrite as x in t'First .. t'Last.
ee6ba406 6166 -- This reason we do this is that the bounds may have the wrong
9c486805 6167 -- type if they come from the original type definition. Also this
6168 -- way we get all the processing above for an explicit range.
ee6ba406 6169
aa4b16cb 6170 -- Don't do this for predicated types, since in this case we
39a0c1d3 6171 -- want to check the predicate.
6a7bc898 6172
55e8372b 6173 elsif Is_Scalar_Type (Typ) then
6174 if No (Predicate_Function (Typ)) then
6175 Rewrite (Rop,
6176 Make_Range (Loc,
6177 Low_Bound =>
6178 Make_Attribute_Reference (Loc,
6179 Attribute_Name => Name_First,
83c6c069 6180 Prefix => New_Occurrence_Of (Typ, Loc)),
55e8372b 6181
6182 High_Bound =>
6183 Make_Attribute_Reference (Loc,
6184 Attribute_Name => Name_Last,
83c6c069 6185 Prefix => New_Occurrence_Of (Typ, Loc))));
55e8372b 6186 Analyze_And_Resolve (N, Restyp);
6187 end if;
ee6ba406 6188
4aed5405 6189 goto Leave;
00f91aef 6190
6191 -- Ada 2005 (AI-216): Program_Error is raised when evaluating
6192 -- a membership test if the subtype mark denotes a constrained
6193 -- Unchecked_Union subtype and the expression lacks inferable
6194 -- discriminants.
6195
6196 elsif Is_Unchecked_Union (Base_Type (Typ))
6197 and then Is_Constrained (Typ)
6198 and then not Has_Inferable_Discriminants (Lop)
6199 then
6200 Insert_Action (N,
6201 Make_Raise_Program_Error (Loc,
6202 Reason => PE_Unchecked_Union_Restriction));
6203
31c85ce5 6204 -- Prevent Gigi from generating incorrect code by rewriting the
aa4b16cb 6205 -- test as False. What is this undocumented thing about ???
00f91aef 6206
31c85ce5 6207 Rewrite (N, New_Occurrence_Of (Standard_False, Loc));
4aed5405 6208 goto Leave;
ee6ba406 6209 end if;
6210
9dfe12ae 6211 -- Here we have a non-scalar type
6212
ee6ba406 6213 if Is_Acc then
6214 Typ := Designated_Type (Typ);
6215 end if;
6216
6217 if not Is_Constrained (Typ) then
83c6c069 6218 Rewrite (N, New_Occurrence_Of (Standard_True, Loc));
4aed5405 6219 Analyze_And_Resolve (N, Restyp);
ee6ba406 6220
f1e2dcc5 6221 -- For the constrained array case, we have to check the subscripts
6222 -- for an exact match if the lengths are non-zero (the lengths
6223 -- must match in any case).
ee6ba406 6224
6225 elsif Is_Array_Type (Typ) then
9dfe12ae 6226 Check_Subscripts : declare
31c85ce5 6227 function Build_Attribute_Reference
752e1833 6228 (E : Node_Id;
6229 Nam : Name_Id;
6230 Dim : Nat) return Node_Id;
31c85ce5 6231 -- Build attribute reference E'Nam (Dim)
ee6ba406 6232
31c85ce5 6233 -------------------------------
6234 -- Build_Attribute_Reference --
6235 -------------------------------
9dfe12ae 6236
31c85ce5 6237 function Build_Attribute_Reference
752e1833 6238 (E : Node_Id;
6239 Nam : Name_Id;
6240 Dim : Nat) return Node_Id
ee6ba406 6241 is
6242 begin
6243 return
6244 Make_Attribute_Reference (Loc,
31c85ce5 6245 Prefix => E,
ee6ba406 6246 Attribute_Name => Nam,
31c85ce5 6247 Expressions => New_List (
ee6ba406 6248 Make_Integer_Literal (Loc, Dim)));
31c85ce5 6249 end Build_Attribute_Reference;
ee6ba406 6250
19b4517d 6251 -- Start of processing for Check_Subscripts
9dfe12ae 6252
ee6ba406 6253 begin
6254 for J in 1 .. Number_Dimensions (Typ) loop
6255 Evolve_And_Then (Cond,
6256 Make_Op_Eq (Loc,
6257 Left_Opnd =>
31c85ce5 6258 Build_Attribute_Reference
9dfe12ae 6259 (Duplicate_Subexpr_No_Checks (Obj),
6260 Name_First, J),
ee6ba406 6261 Right_Opnd =>
31c85ce5 6262 Build_Attribute_Reference
ee6ba406 6263 (New_Occurrence_Of (Typ, Loc), Name_First, J)));
6264
6265 Evolve_And_Then (Cond,
6266 Make_Op_Eq (Loc,
6267 Left_Opnd =>
31c85ce5 6268 Build_Attribute_Reference
9dfe12ae 6269 (Duplicate_Subexpr_No_Checks (Obj),
6270 Name_Last, J),
ee6ba406 6271 Right_Opnd =>
31c85ce5 6272 Build_Attribute_Reference
ee6ba406 6273 (New_Occurrence_Of (Typ, Loc), Name_Last, J)));
6274 end loop;
6275
6276 if Is_Acc then
9dfe12ae 6277 Cond :=
6278 Make_Or_Else (Loc,
82b93248 6279 Left_Opnd =>
9dfe12ae 6280 Make_Op_Eq (Loc,
6281 Left_Opnd => Obj,
6282 Right_Opnd => Make_Null (Loc)),
6283 Right_Opnd => Cond);
ee6ba406 6284 end if;
6285
6286 Rewrite (N, Cond);
4aed5405 6287 Analyze_And_Resolve (N, Restyp);
9dfe12ae 6288 end Check_Subscripts;
ee6ba406 6289
f1e2dcc5 6290 -- These are the cases where constraint checks may be required,
6291 -- e.g. records with possible discriminants
ee6ba406 6292
6293 else
6294 -- Expand the test into a series of discriminant comparisons.
f1e2dcc5 6295 -- The expression that is built is the negation of the one that
6296 -- is used for checking discriminant constraints.
ee6ba406 6297
6298 Obj := Relocate_Node (Left_Opnd (N));
6299
6300 if Has_Discriminants (Typ) then
6301 Cond := Make_Op_Not (Loc,
6302 Right_Opnd => Build_Discriminant_Checks (Obj, Typ));
6303
6304 if Is_Acc then
6305 Cond := Make_Or_Else (Loc,
82b93248 6306 Left_Opnd =>
ee6ba406 6307 Make_Op_Eq (Loc,
6308 Left_Opnd => Obj,
6309 Right_Opnd => Make_Null (Loc)),
6310 Right_Opnd => Cond);
6311 end if;
6312
6313 else
6314 Cond := New_Occurrence_Of (Standard_True, Loc);
6315 end if;
6316
6317 Rewrite (N, Cond);
4aed5405 6318 Analyze_And_Resolve (N, Restyp);
ee6ba406 6319 end if;
d071cd96 6320
6321 -- Ada 2012 (AI05-0149): Handle membership tests applied to an
6322 -- expression of an anonymous access type. This can involve an
6323 -- accessibility test and a tagged type membership test in the
6324 -- case of tagged designated types.
6325
6326 if Ada_Version >= Ada_2012
6327 and then Is_Acc
6328 and then Ekind (Ltyp) = E_Anonymous_Access_Type
6329 then
6330 declare
6331 Expr_Entity : Entity_Id := Empty;
6332 New_N : Node_Id;
6333 Param_Level : Node_Id;
6334 Type_Level : Node_Id;
1a9cc6cd 6335
d071cd96 6336 begin
6337 if Is_Entity_Name (Lop) then
6338 Expr_Entity := Param_Entity (Lop);
1a9cc6cd 6339
d071cd96 6340 if not Present (Expr_Entity) then
6341 Expr_Entity := Entity (Lop);
6342 end if;
6343 end if;
6344
6345 -- If a conversion of the anonymous access value to the
6346 -- tested type would be illegal, then the result is False.
6347
6348 if not Valid_Conversion
6349 (Lop, Rtyp, Lop, Report_Errs => False)
6350 then
6351 Rewrite (N, New_Occurrence_Of (Standard_False, Loc));
6352 Analyze_And_Resolve (N, Restyp);
6353
6354 -- Apply an accessibility check if the access object has an
6355 -- associated access level and when the level of the type is
6356 -- less deep than the level of the access parameter. This
6357 -- only occur for access parameters and stand-alone objects
6358 -- of an anonymous access type.
6359
6360 else
6361 if Present (Expr_Entity)
1a9cc6cd 6362 and then
6363 Present
6364 (Effective_Extra_Accessibility (Expr_Entity))
6365 and then UI_Gt (Object_Access_Level (Lop),
6366 Type_Access_Level (Rtyp))
d071cd96 6367 then
6368 Param_Level :=
6369 New_Occurrence_Of
47d210a3 6370 (Effective_Extra_Accessibility (Expr_Entity), Loc);
d071cd96 6371
6372 Type_Level :=
6373 Make_Integer_Literal (Loc, Type_Access_Level (Rtyp));
6374
6375 -- Return True only if the accessibility level of the
6376 -- expression entity is not deeper than the level of
6377 -- the tested access type.
6378
6379 Rewrite (N,
6380 Make_And_Then (Loc,
6381 Left_Opnd => Relocate_Node (N),
6382 Right_Opnd => Make_Op_Le (Loc,
6383 Left_Opnd => Param_Level,
6384 Right_Opnd => Type_Level)));
6385
6386 Analyze_And_Resolve (N);
6387 end if;
6388
6389 -- If the designated type is tagged, do tagged membership
6390 -- operation.
6391
6392 -- *** NOTE: we have to check not null before doing the
6393 -- tagged membership test (but maybe that can be done
6394 -- inside Tagged_Membership?).
6395
6396 if Is_Tagged_Type (Typ) then
6397 Rewrite (N,
6398 Make_And_Then (Loc,
6399 Left_Opnd => Relocate_Node (N),
6400 Right_Opnd =>
6401 Make_Op_Ne (Loc,
6402 Left_Opnd => Obj,
6403 Right_Opnd => Make_Null (Loc))));
6404
36ac5fbb 6405 -- No expansion will be performed for VM targets, as
2a801d20 6406 -- the VM back ends will handle the membership tests
d748ef42 6407 -- directly.
d071cd96 6408
6409 if Tagged_Type_Expansion then
6410
6411 -- Note that we have to pass Original_Node, because
6412 -- the membership test might already have been
6413 -- rewritten by earlier parts of membership test.
6414
6415 Tagged_Membership
6416 (Original_Node (N), SCIL_Node, New_N);
6417
6418 -- Update decoration of relocated node referenced
6419 -- by the SCIL node.
6420
6421 if Generate_SCIL and then Present (SCIL_Node) then
6422 Set_SCIL_Node (New_N, SCIL_Node);
6423 end if;
6424
6425 Rewrite (N,
6426 Make_And_Then (Loc,
6427 Left_Opnd => Relocate_Node (N),
6428 Right_Opnd => New_N));
6429
6430 Analyze_And_Resolve (N, Restyp);
6431 end if;
6432 end if;
6433 end if;
6434 end;
6435 end if;
ee6ba406 6436 end;
6437 end if;
4aed5405 6438
6439 -- At this point, we have done the processing required for the basic
6440 -- membership test, but not yet dealt with the predicate.
6441
6442 <<Leave>>
6443
55e8372b 6444 -- If a predicate is present, then we do the predicate test, but we
6445 -- most certainly want to omit this if we are within the predicate
39a0c1d3 6446 -- function itself, since otherwise we have an infinite recursion.
aae8e592 6447 -- The check should also not be emitted when testing against a range
6448 -- (the check is only done when the right operand is a subtype; see
6449 -- RM12-4.5.2 (28.1/3-30/3)).
4aed5405 6450
e7402fda 6451 Predicate_Check : declare
6452 function In_Range_Check return Boolean;
6453 -- Within an expanded range check that may raise Constraint_Error do
6454 -- not generate a predicate check as well. It is redundant because
6455 -- the context will add an explicit predicate check, and it will
6456 -- raise the wrong exception if it fails.
6457
6458 --------------------
6459 -- In_Range_Check --
6460 --------------------
6461
6462 function In_Range_Check return Boolean is
6463 P : Node_Id;
6464 begin
6465 P := Parent (N);
6466 while Present (P) loop
6467 if Nkind (P) = N_Raise_Constraint_Error then
6468 return True;
6469
6470 elsif Nkind (P) in N_Statement_Other_Than_Procedure_Call
6471 or else Nkind (P) = N_Procedure_Call_Statement
6472 or else Nkind (P) in N_Declaration
6473 then
6474 return False;
6475 end if;
6476
6477 P := Parent (P);
6478 end loop;
6479
6480 return False;
6481 end In_Range_Check;
6482
6483 -- Local variables
6484
55e8372b 6485 PFunc : constant Entity_Id := Predicate_Function (Rtyp);
e7402fda 6486 R_Op : Node_Id;
6487
6488 -- Start of processing for Predicate_Check
4aed5405 6489
55e8372b 6490 begin
6491 if Present (PFunc)
6492 and then Current_Scope /= PFunc
aae8e592 6493 and then Nkind (Rop) /= N_Range
55e8372b 6494 then
e7402fda 6495 if not In_Range_Check then
6496 R_Op := Make_Predicate_Call (Rtyp, Lop, Mem => True);
6497 else
6498 R_Op := New_Occurrence_Of (Standard_True, Loc);
6499 end if;
6500
55e8372b 6501 Rewrite (N,
6502 Make_And_Then (Loc,
6503 Left_Opnd => Relocate_Node (N),
e7402fda 6504 Right_Opnd => R_Op));
4aed5405 6505
55e8372b 6506 -- Analyze new expression, mark left operand as analyzed to
798afddc 6507 -- avoid infinite recursion adding predicate calls. Similarly,
6508 -- suppress further range checks on the call.
4aed5405 6509
55e8372b 6510 Set_Analyzed (Left_Opnd (N));
798afddc 6511 Analyze_And_Resolve (N, Standard_Boolean, Suppress => All_Checks);
4aed5405 6512
55e8372b 6513 -- All done, skip attempt at compile time determination of result
6514
6515 return;
6516 end if;
e7402fda 6517 end Predicate_Check;
ee6ba406 6518 end Expand_N_In;
6519
6520 --------------------------------
6521 -- Expand_N_Indexed_Component --
6522 --------------------------------
6523
6524 procedure Expand_N_Indexed_Component (N : Node_Id) is
6525 Loc : constant Source_Ptr := Sloc (N);
6526 Typ : constant Entity_Id := Etype (N);
6527 P : constant Node_Id := Prefix (N);
6528 T : constant Entity_Id := Etype (P);
d306cbee 6529 Atp : Entity_Id;
ee6ba406 6530
6531 begin
f1e2dcc5 6532 -- A special optimization, if we have an indexed component that is
6533 -- selecting from a slice, then we can eliminate the slice, since, for
6534 -- example, x (i .. j)(k) is identical to x(k). The only difference is
6535 -- the range check required by the slice. The range check for the slice
6536 -- itself has already been generated. The range check for the
6537 -- subscripting operation is ensured by converting the subject to
6538 -- the subtype of the slice.
6539
6540 -- This optimization not only generates better code, avoiding slice
6541 -- messing especially in the packed case, but more importantly bypasses
6542 -- some problems in handling this peculiar case, for example, the issue
6543 -- of dealing specially with object renamings.
ee6ba406 6544
2fac8a3a 6545 if Nkind (P) = N_Slice
6546
6547 -- This optimization is disabled for CodePeer because it can transform
6548 -- an index-check constraint_error into a range-check constraint_error
6549 -- and CodePeer cares about that distinction.
6550
6551 and then not CodePeer_Mode
6552 then
ee6ba406 6553 Rewrite (N,
6554 Make_Indexed_Component (Loc,
82b93248 6555 Prefix => Prefix (P),
ee6ba406 6556 Expressions => New_List (
6557 Convert_To
6558 (Etype (First_Index (Etype (P))),
6559 First (Expressions (N))))));
6560 Analyze_And_Resolve (N, Typ);
6561 return;
6562 end if;
6563
40a5a4cb 6564 -- Ada 2005 (AI-318-02): If the prefix is a call to a build-in-place
6565 -- function, then additional actuals must be passed.
6566
cd24e497 6567 if Is_Build_In_Place_Function_Call (P) then
40a5a4cb 6568 Make_Build_In_Place_Call_In_Anonymous_Context (P);
8b3a98b2 6569
6570 -- Ada 2005 (AI-318-02): Specialization of the previous case for prefix
6571 -- containing build-in-place function calls whose returned object covers
6572 -- interface types.
6573
cd24e497 6574 elsif Present (Unqual_BIP_Iface_Function_Call (P)) then
8b3a98b2 6575 Make_Build_In_Place_Iface_Call_In_Anonymous_Context (P);
40a5a4cb 6576 end if;
6577
f1e2dcc5 6578 -- If the prefix is an access type, then we unconditionally rewrite if
eae1d4d1 6579 -- as an explicit dereference. This simplifies processing for several
f1e2dcc5 6580 -- cases, including packed array cases and certain cases in which checks
6581 -- must be generated. We used to try to do this only when it was
6582 -- necessary, but it cleans up the code to do it all the time.
ee6ba406 6583
6584 if Is_Access_Type (T) then
aae50ddd 6585 Insert_Explicit_Dereference (P);
ee6ba406 6586 Analyze_And_Resolve (P, Designated_Type (T));
d306cbee 6587 Atp := Designated_Type (T);
6588 else
6589 Atp := T;
ee6ba406 6590 end if;
6591
9dfe12ae 6592 -- Generate index and validity checks
6593
6594 Generate_Index_Checks (N);
6595
ee6ba406 6596 if Validity_Checks_On and then Validity_Check_Subscripts then
6597 Apply_Subscript_Validity_Checks (N);
6598 end if;
6599
d306cbee 6600 -- If selecting from an array with atomic components, and atomic sync
6601 -- is not suppressed for this array type, set atomic sync flag.
6602
6603 if (Has_Atomic_Components (Atp)
6604 and then not Atomic_Synchronization_Disabled (Atp))
6605 or else (Is_Atomic (Typ)
6606 and then not Atomic_Synchronization_Disabled (Typ))
e0c0515d 6607 or else (Is_Entity_Name (P)
6608 and then Has_Atomic_Components (Entity (P))
6609 and then not Atomic_Synchronization_Disabled (Entity (P)))
d306cbee 6610 then
b444f81d 6611 Activate_Atomic_Synchronization (N);
d306cbee 6612 end if;
6613
7214e56d 6614 -- All done if the prefix is not a packed array implemented specially
ee6ba406 6615
7214e56d 6616 if not (Is_Packed (Etype (Prefix (N)))
6617 and then Present (Packed_Array_Impl_Type (Etype (Prefix (N)))))
6618 then
ee6ba406 6619 return;
6620 end if;
6621
6622 -- For packed arrays that are not bit-packed (i.e. the case of an array
36b938a3 6623 -- with one or more index types with a non-contiguous enumeration type),
ee6ba406 6624 -- we can always use the normal packed element get circuit.
6625
6626 if not Is_Bit_Packed_Array (Etype (Prefix (N))) then
6627 Expand_Packed_Element_Reference (N);
6628 return;
6629 end if;
6630
a88a5773 6631 -- For a reference to a component of a bit packed array, we convert it
6632 -- to a reference to the corresponding Packed_Array_Impl_Type. We only
6633 -- want to do this for simple references, and not for:
ee6ba406 6634
f1e2dcc5 6635 -- Left side of assignment, or prefix of left side of assignment, or
6636 -- prefix of the prefix, to handle packed arrays of packed arrays,
ee6ba406 6637 -- This case is handled in Exp_Ch5.Expand_N_Assignment_Statement
6638
6639 -- Renaming objects in renaming associations
6640 -- This case is handled when a use of the renamed variable occurs
6641
6642 -- Actual parameters for a procedure call
6643 -- This case is handled in Exp_Ch6.Expand_Actuals
6644
6645 -- The second expression in a 'Read attribute reference
6646
5c182b3b 6647 -- The prefix of an address or bit or size attribute reference
ee6ba406 6648
3f716509 6649 -- The following circuit detects these exceptions. Note that we need to
6650 -- deal with implicit dereferences when climbing up the parent chain,
6651 -- with the additional difficulty that the type of parents may have yet
6652 -- to be resolved since prefixes are usually resolved first.
ee6ba406 6653
6654 declare
6655 Child : Node_Id := N;
6656 Parnt : Node_Id := Parent (N);
6657
6658 begin
6659 loop
6660 if Nkind (Parnt) = N_Unchecked_Expression then
6661 null;
6662
1627db8a 6663 elsif Nkind_In (Parnt, N_Object_Renaming_Declaration,
6664 N_Procedure_Call_Statement)
ee6ba406 6665 or else (Nkind (Parnt) = N_Parameter_Association
6666 and then
2060fafe 6667 Nkind (Parent (Parnt)) = N_Procedure_Call_Statement)
ee6ba406 6668 then
6669 return;
6670
6671 elsif Nkind (Parnt) = N_Attribute_Reference
18393965 6672 and then Nam_In (Attribute_Name (Parnt), Name_Address,
6673 Name_Bit,
6674 Name_Size)
ee6ba406 6675 and then Prefix (Parnt) = Child
6676 then
6677 return;
6678
6679 elsif Nkind (Parnt) = N_Assignment_Statement
6680 and then Name (Parnt) = Child
6681 then
6682 return;
6683
f1e2dcc5 6684 -- If the expression is an index of an indexed component, it must
6685 -- be expanded regardless of context.
9dfe12ae 6686
6687 elsif Nkind (Parnt) = N_Indexed_Component
6688 and then Child /= Prefix (Parnt)
6689 then
6690 Expand_Packed_Element_Reference (N);
6691 return;
6692
6693 elsif Nkind (Parent (Parnt)) = N_Assignment_Statement
6694 and then Name (Parent (Parnt)) = Parnt
6695 then
6696 return;
6697
ee6ba406 6698 elsif Nkind (Parnt) = N_Attribute_Reference
6699 and then Attribute_Name (Parnt) = Name_Read
6700 and then Next (First (Expressions (Parnt))) = Child
6701 then
6702 return;
6703
3f716509 6704 elsif Nkind (Parnt) = N_Indexed_Component
6705 and then Prefix (Parnt) = Child
6706 then
6707 null;
6708
6709 elsif Nkind (Parnt) = N_Selected_Component
6f0d10f7 6710 and then Prefix (Parnt) = Child
3f716509 6711 and then not (Present (Etype (Selector_Name (Parnt)))
6712 and then
6713 Is_Access_Type (Etype (Selector_Name (Parnt))))
ee6ba406 6714 then
6715 null;
6716
3f716509 6717 -- If the parent is a dereference, either implicit or explicit,
6718 -- then the packed reference needs to be expanded.
6719
ee6ba406 6720 else
6721 Expand_Packed_Element_Reference (N);
6722 return;
6723 end if;
6724
f1e2dcc5 6725 -- Keep looking up tree for unchecked expression, or if we are the
6726 -- prefix of a possible assignment left side.
ee6ba406 6727
6728 Child := Parnt;
6729 Parnt := Parent (Child);
6730 end loop;
6731 end;
ee6ba406 6732 end Expand_N_Indexed_Component;
6733
6734 ---------------------
6735 -- Expand_N_Not_In --
6736 ---------------------
6737
6738 -- Replace a not in b by not (a in b) so that the expansions for (a in b)
6739 -- can be done. This avoids needing to duplicate this expansion code.
6740
6741 procedure Expand_N_Not_In (N : Node_Id) is
4dcc60e5 6742 Loc : constant Source_Ptr := Sloc (N);
6743 Typ : constant Entity_Id := Etype (N);
6744 Cfs : constant Boolean := Comes_From_Source (N);
ee6ba406 6745
6746 begin
6747 Rewrite (N,
6748 Make_Op_Not (Loc,
6749 Right_Opnd =>
6750 Make_In (Loc,
6751 Left_Opnd => Left_Opnd (N),
a3e461ac 6752 Right_Opnd => Right_Opnd (N))));
4dcc60e5 6753
5d6b98f6 6754 -- If this is a set membership, preserve list of alternatives
6755
6756 Set_Alternatives (Right_Opnd (N), Alternatives (Original_Node (N)));
6757
a3e461ac 6758 -- We want this to appear as coming from source if original does (see
36b938a3 6759 -- transformations in Expand_N_In).
4dcc60e5 6760
6761 Set_Comes_From_Source (N, Cfs);
6762 Set_Comes_From_Source (Right_Opnd (N), Cfs);
6763
36b938a3 6764 -- Now analyze transformed node
4dcc60e5 6765
ee6ba406 6766 Analyze_And_Resolve (N, Typ);
6767 end Expand_N_Not_In;
6768
6769 -------------------
6770 -- Expand_N_Null --
6771 -------------------
6772
b77e4501 6773 -- The only replacement required is for the case of a null of a type that
6774 -- is an access to protected subprogram, or a subtype thereof. We represent
6775 -- such access values as a record, and so we must replace the occurrence of
6776 -- null by the equivalent record (with a null address and a null pointer in
2a801d20 6777 -- it), so that the back end creates the proper value.
ee6ba406 6778
6779 procedure Expand_N_Null (N : Node_Id) is
6780 Loc : constant Source_Ptr := Sloc (N);
b77e4501 6781 Typ : constant Entity_Id := Base_Type (Etype (N));
ee6ba406 6782 Agg : Node_Id;
6783
6784 begin
914796b1 6785 if Is_Access_Protected_Subprogram_Type (Typ) then
ee6ba406 6786 Agg :=
6787 Make_Aggregate (Loc,
6788 Expressions => New_List (
6789 New_Occurrence_Of (RTE (RE_Null_Address), Loc),
6790 Make_Null (Loc)));
6791
6792 Rewrite (N, Agg);
6793 Analyze_And_Resolve (N, Equivalent_Type (Typ));
6794
f1e2dcc5 6795 -- For subsequent semantic analysis, the node must retain its type.
6796 -- Gigi in any case replaces this type by the corresponding record
6797 -- type before processing the node.
ee6ba406 6798
6799 Set_Etype (N, Typ);
6800 end if;
9dfe12ae 6801
6802 exception
6803 when RE_Not_Available =>
6804 return;
ee6ba406 6805 end Expand_N_Null;
6806
6807 ---------------------
6808 -- Expand_N_Op_Abs --
6809 ---------------------
6810
6811 procedure Expand_N_Op_Abs (N : Node_Id) is
6812 Loc : constant Source_Ptr := Sloc (N);
82b93248 6813 Expr : constant Node_Id := Right_Opnd (N);
ee6ba406 6814
6815 begin
6816 Unary_Op_Validity_Checks (N);
6817
f32c377d 6818 -- Check for MINIMIZED/ELIMINATED overflow mode
6819
6820 if Minimized_Eliminated_Overflow_Check (N) then
6821 Apply_Arithmetic_Overflow_Check (N);
6822 return;
6823 end if;
6824
ee6ba406 6825 -- Deal with software overflow checking
6826
f15731c4 6827 if not Backend_Overflow_Checks_On_Target
6f0d10f7 6828 and then Is_Signed_Integer_Type (Etype (N))
6829 and then Do_Overflow_Check (N)
ee6ba406 6830 then
f1e2dcc5 6831 -- The only case to worry about is when the argument is equal to the
6832 -- largest negative number, so what we do is to insert the check:
ee6ba406 6833
9dfe12ae 6834 -- [constraint_error when Expr = typ'Base'First]
ee6ba406 6835
6836 -- with the usual Duplicate_Subexpr use coding for expr
6837
9dfe12ae 6838 Insert_Action (N,
6839 Make_Raise_Constraint_Error (Loc,
6840 Condition =>
6841 Make_Op_Eq (Loc,
ee6ba406 6842 Left_Opnd => Duplicate_Subexpr (Expr),
9dfe12ae 6843 Right_Opnd =>
6844 Make_Attribute_Reference (Loc,
82b93248 6845 Prefix =>
9dfe12ae 6846 New_Occurrence_Of (Base_Type (Etype (Expr)), Loc),
6847 Attribute_Name => Name_First)),
6848 Reason => CE_Overflow_Check_Failed));
6849 end if;
ee6ba406 6850 end Expand_N_Op_Abs;
6851
6852 ---------------------
6853 -- Expand_N_Op_Add --
6854 ---------------------
6855
6856 procedure Expand_N_Op_Add (N : Node_Id) is
6857 Typ : constant Entity_Id := Etype (N);
6858
6859 begin
6860 Binary_Op_Validity_Checks (N);
6861
f32c377d 6862 -- Check for MINIMIZED/ELIMINATED overflow mode
6863
6864 if Minimized_Eliminated_Overflow_Check (N) then
6865 Apply_Arithmetic_Overflow_Check (N);
6866 return;
6867 end if;
6868
ee6ba406 6869 -- N + 0 = 0 + N = N for integer types
6870
6871 if Is_Integer_Type (Typ) then
6872 if Compile_Time_Known_Value (Right_Opnd (N))
6873 and then Expr_Value (Right_Opnd (N)) = Uint_0
6874 then
6875 Rewrite (N, Left_Opnd (N));
6876 return;
6877
6878 elsif Compile_Time_Known_Value (Left_Opnd (N))
6879 and then Expr_Value (Left_Opnd (N)) = Uint_0
6880 then
6881 Rewrite (N, Right_Opnd (N));
6882 return;
6883 end if;
6884 end if;
6885
9dfe12ae 6886 -- Arithmetic overflow checks for signed integer/fixed point types
ee6ba406 6887
cf04d13c 6888 if Is_Signed_Integer_Type (Typ) or else Is_Fixed_Point_Type (Typ) then
ee6ba406 6889 Apply_Arithmetic_Overflow_Check (N);
6890 return;
ee6ba406 6891 end if;
54d549ff 6892
6893 -- Overflow checks for floating-point if -gnateF mode active
6894
6895 Check_Float_Op_Overflow (N);
61b6f3d9 6896
2a801d20 6897 -- When generating C code, convert nonbinary modular additions into code
6898 -- that relies on the front-end expansion of operator Mod.
61b6f3d9 6899
6900 if Modify_Tree_For_C then
2a801d20 6901 Expand_Nonbinary_Modular_Op (N);
61b6f3d9 6902 end if;
ee6ba406 6903 end Expand_N_Op_Add;
6904
6905 ---------------------
6906 -- Expand_N_Op_And --
6907 ---------------------
6908
6909 procedure Expand_N_Op_And (N : Node_Id) is
6910 Typ : constant Entity_Id := Etype (N);
6911
6912 begin
6913 Binary_Op_Validity_Checks (N);
6914
6915 if Is_Array_Type (Etype (N)) then
6916 Expand_Boolean_Operator (N);
6917
6918 elsif Is_Boolean_Type (Etype (N)) then
0033d60c 6919 Adjust_Condition (Left_Opnd (N));
6920 Adjust_Condition (Right_Opnd (N));
6921 Set_Etype (N, Standard_Boolean);
6922 Adjust_Result_Type (N, Typ);
9f294c82 6923
6924 elsif Is_Intrinsic_Subprogram (Entity (N)) then
6925 Expand_Intrinsic_Call (N, Entity (N));
61b6f3d9 6926 end if;
6927
2a801d20 6928 -- When generating C code, convert nonbinary modular operators into code
6929 -- that relies on the front-end expansion of operator Mod.
9f294c82 6930
61b6f3d9 6931 if Modify_Tree_For_C then
2a801d20 6932 Expand_Nonbinary_Modular_Op (N);
ee6ba406 6933 end if;
6934 end Expand_N_Op_And;
6935
6936 ------------------------
6937 -- Expand_N_Op_Concat --
6938 ------------------------
6939
6940 procedure Expand_N_Op_Concat (N : Node_Id) is
ee6ba406 6941 Opnds : List_Id;
6942 -- List of operands to be concatenated
6943
ee6ba406 6944 Cnode : Node_Id;
f1e2dcc5 6945 -- Node which is to be replaced by the result of concatenating the nodes
6946 -- in the list Opnds.
ee6ba406 6947
ee6ba406 6948 begin
9dfe12ae 6949 -- Ensure validity of both operands
6950
ee6ba406 6951 Binary_Op_Validity_Checks (N);
6952
f1e2dcc5 6953 -- If we are the left operand of a concatenation higher up the tree,
6954 -- then do nothing for now, since we want to deal with a series of
6955 -- concatenations as a unit.
ee6ba406 6956
6957 if Nkind (Parent (N)) = N_Op_Concat
6958 and then N = Left_Opnd (Parent (N))
6959 then
6960 return;
6961 end if;
6962
6963 -- We get here with a concatenation whose left operand may be a
6964 -- concatenation itself with a consistent type. We need to process
6965 -- these concatenation operands from left to right, which means
6966 -- from the deepest node in the tree to the highest node.
6967
6968 Cnode := N;
6969 while Nkind (Left_Opnd (Cnode)) = N_Op_Concat loop
6970 Cnode := Left_Opnd (Cnode);
6971 end loop;
6972
34d59716 6973 -- Now Cnode is the deepest concatenation, and its parents are the
6974 -- concatenation nodes above, so now we process bottom up, doing the
34d59716 6975 -- operands.
ee6ba406 6976
e37ded63 6977 -- The outer loop runs more than once if more than one concatenation
6978 -- type is involved.
ee6ba406 6979
6980 Outer : loop
6981 Opnds := New_List (Left_Opnd (Cnode), Right_Opnd (Cnode));
6982 Set_Parent (Opnds, N);
6983
e37ded63 6984 -- The inner loop gathers concatenation operands
ee6ba406 6985
6986 Inner : while Cnode /= N
ee6ba406 6987 and then Base_Type (Etype (Cnode)) =
6988 Base_Type (Etype (Parent (Cnode)))
6989 loop
6990 Cnode := Parent (Cnode);
6991 Append (Right_Opnd (Cnode), Opnds);
6992 end loop Inner;
6993
30ab103b 6994 -- Note: The following code is a temporary workaround for N731-034
6995 -- and N829-028 and will be kept until the general issue of internal
6996 -- symbol serialization is addressed. The workaround is kept under a
6997 -- debug switch to avoid permiating into the general case.
6998
6999 -- Wrap the node to concatenate into an expression actions node to
7000 -- keep it nicely packaged. This is useful in the case of an assert
7001 -- pragma with a concatenation where we want to be able to delete
7002 -- the concatenation and all its expansion stuff.
7003
7004 if Debug_Flag_Dot_H then
7005 declare
4cb8adff 7006 Cnod : constant Node_Id := New_Copy_Tree (Cnode);
30ab103b 7007 Typ : constant Entity_Id := Base_Type (Etype (Cnode));
7008
7009 begin
7010 -- Note: use Rewrite rather than Replace here, so that for
7011 -- example Why_Not_Static can find the original concatenation
7012 -- node OK!
7013
7014 Rewrite (Cnode,
7015 Make_Expression_With_Actions (Sloc (Cnode),
7016 Actions => New_List (Make_Null_Statement (Sloc (Cnode))),
7017 Expression => Cnod));
7018
7019 Expand_Concatenate (Cnod, Opnds);
7020 Analyze_And_Resolve (Cnode, Typ);
7021 end;
7022
7023 -- Default case
7024
7025 else
7026 Expand_Concatenate (Cnode, Opnds);
7027 end if;
ee6ba406 7028
7029 exit Outer when Cnode = N;
7030 Cnode := Parent (Cnode);
7031 end loop Outer;
7032 end Expand_N_Op_Concat;
7033
7034 ------------------------
7035 -- Expand_N_Op_Divide --
7036 ------------------------
7037
7038 procedure Expand_N_Op_Divide (N : Node_Id) is
0cba9418 7039 Loc : constant Source_Ptr := Sloc (N);
7040 Lopnd : constant Node_Id := Left_Opnd (N);
7041 Ropnd : constant Node_Id := Right_Opnd (N);
7042 Ltyp : constant Entity_Id := Etype (Lopnd);
7043 Rtyp : constant Entity_Id := Etype (Ropnd);
7044 Typ : Entity_Id := Etype (N);
7045 Rknow : constant Boolean := Is_Integer_Type (Typ)
7046 and then
7047 Compile_Time_Known_Value (Ropnd);
7048 Rval : Uint;
ee6ba406 7049
7050 begin
7051 Binary_Op_Validity_Checks (N);
7052
f32c377d 7053 -- Check for MINIMIZED/ELIMINATED overflow mode
7054
7055 if Minimized_Eliminated_Overflow_Check (N) then
7056 Apply_Arithmetic_Overflow_Check (N);
7057 return;
7058 end if;
7059
7060 -- Otherwise proceed with expansion of division
7061
0cba9418 7062 if Rknow then
7063 Rval := Expr_Value (Ropnd);
7064 end if;
7065
ee6ba406 7066 -- N / 1 = N for integer types
7067
0cba9418 7068 if Rknow and then Rval = Uint_1 then
7069 Rewrite (N, Lopnd);
ee6ba406 7070 return;
7071 end if;
7072
7073 -- Convert x / 2 ** y to Shift_Right (x, y). Note that the fact that
7074 -- Is_Power_Of_2_For_Shift is set means that we know that our left
7075 -- operand is an unsigned integer, as required for this to work.
7076
0cba9418 7077 if Nkind (Ropnd) = N_Op_Expon
7078 and then Is_Power_Of_2_For_Shift (Ropnd)
9dfe12ae 7079
7080 -- We cannot do this transformation in configurable run time mode if we
006b904a 7081 -- have 64-bit integers and long shifts are not available.
9dfe12ae 7082
cf04d13c 7083 and then (Esize (Ltyp) <= 32 or else Support_Long_Shifts_On_Target)
ee6ba406 7084 then
7085 Rewrite (N,
7086 Make_Op_Shift_Right (Loc,
0cba9418 7087 Left_Opnd => Lopnd,
ee6ba406 7088 Right_Opnd =>
0cba9418 7089 Convert_To (Standard_Natural, Right_Opnd (Ropnd))));
ee6ba406 7090 Analyze_And_Resolve (N, Typ);
7091 return;
7092 end if;
7093
7094 -- Do required fixup of universal fixed operation
7095
7096 if Typ = Universal_Fixed then
7097 Fixup_Universal_Fixed_Operation (N);
7098 Typ := Etype (N);
7099 end if;
7100
7101 -- Divisions with fixed-point results
7102
7103 if Is_Fixed_Point_Type (Typ) then
7104
d89314ba 7105 -- No special processing if Treat_Fixed_As_Integer is set, since
7106 -- from a semantic point of view such operations are simply integer
7107 -- operations and will be treated that way.
7108
7109 if not Treat_Fixed_As_Integer (N) then
7110 if Is_Integer_Type (Rtyp) then
7111 Expand_Divide_Fixed_By_Integer_Giving_Fixed (N);
7112 else
7113 Expand_Divide_Fixed_By_Fixed_Giving_Fixed (N);
7114 end if;
7115 end if;
7116
b5b66286 7117 -- Deal with divide-by-zero check if back end cannot handle them
7118 -- and the flag is set indicating that we need such a check. Note
7119 -- that we don't need to bother here with the case of mixed-mode
7120 -- (Right operand an integer type), since these will be rewritten
7121 -- with conversions to a divide with a fixed-point right operand.
7122
d89314ba 7123 if Nkind (N) = N_Op_Divide
7124 and then Do_Division_Check (N)
b5b66286 7125 and then not Backend_Divide_Checks_On_Target
7126 and then not Is_Integer_Type (Rtyp)
7127 then
7128 Set_Do_Division_Check (N, False);
7129 Insert_Action (N,
7130 Make_Raise_Constraint_Error (Loc,
7131 Condition =>
7132 Make_Op_Eq (Loc,
7133 Left_Opnd => Duplicate_Subexpr_Move_Checks (Ropnd),
7134 Right_Opnd => Make_Real_Literal (Loc, Ureal_0)),
7135 Reason => CE_Divide_By_Zero));
7136 end if;
7137
f1e2dcc5 7138 -- Other cases of division of fixed-point operands. Again we exclude the
7139 -- case where Treat_Fixed_As_Integer is set.
ee6ba406 7140
cf04d13c 7141 elsif (Is_Fixed_Point_Type (Ltyp) or else Is_Fixed_Point_Type (Rtyp))
ee6ba406 7142 and then not Treat_Fixed_As_Integer (N)
7143 then
7144 if Is_Integer_Type (Typ) then
7145 Expand_Divide_Fixed_By_Fixed_Giving_Integer (N);
7146 else
7147 pragma Assert (Is_Floating_Point_Type (Typ));
7148 Expand_Divide_Fixed_By_Fixed_Giving_Float (N);
7149 end if;
7150
f1e2dcc5 7151 -- Mixed-mode operations can appear in a non-static universal context,
7152 -- in which case the integer argument must be converted explicitly.
ee6ba406 7153
6f0d10f7 7154 elsif Typ = Universal_Real and then Is_Integer_Type (Rtyp) then
0cba9418 7155 Rewrite (Ropnd,
7156 Convert_To (Universal_Real, Relocate_Node (Ropnd)));
ee6ba406 7157
0cba9418 7158 Analyze_And_Resolve (Ropnd, Universal_Real);
ee6ba406 7159
6f0d10f7 7160 elsif Typ = Universal_Real and then Is_Integer_Type (Ltyp) then
0cba9418 7161 Rewrite (Lopnd,
7162 Convert_To (Universal_Real, Relocate_Node (Lopnd)));
ee6ba406 7163
0cba9418 7164 Analyze_And_Resolve (Lopnd, Universal_Real);
ee6ba406 7165
38f5559f 7166 -- Non-fixed point cases, do integer zero divide and overflow checks
ee6ba406 7167
7168 elsif Is_Integer_Type (Typ) then
2fe22c69 7169 Apply_Divide_Checks (N);
ee6ba406 7170 end if;
54d549ff 7171
7172 -- Overflow checks for floating-point if -gnateF mode active
7173
7174 Check_Float_Op_Overflow (N);
61b6f3d9 7175
2a801d20 7176 -- When generating C code, convert nonbinary modular divisions into code
7177 -- that relies on the front-end expansion of operator Mod.
61b6f3d9 7178
7179 if Modify_Tree_For_C then
2a801d20 7180 Expand_Nonbinary_Modular_Op (N);
61b6f3d9 7181 end if;
ee6ba406 7182 end Expand_N_Op_Divide;
7183
7184 --------------------
7185 -- Expand_N_Op_Eq --
7186 --------------------
7187
7188 procedure Expand_N_Op_Eq (N : Node_Id) is
9dfe12ae 7189 Loc : constant Source_Ptr := Sloc (N);
7190 Typ : constant Entity_Id := Etype (N);
7191 Lhs : constant Node_Id := Left_Opnd (N);
7192 Rhs : constant Node_Id := Right_Opnd (N);
7193 Bodies : constant List_Id := New_List;
7194 A_Typ : constant Entity_Id := Etype (Lhs);
7195
ee6ba406 7196 Typl : Entity_Id := A_Typ;
7197 Op_Name : Entity_Id;
7198 Prim : Elmt_Id;
ee6ba406 7199
7200 procedure Build_Equality_Call (Eq : Entity_Id);
7201 -- If a constructed equality exists for the type or for its parent,
7202 -- build and analyze call, adding conversions if the operation is
7203 -- inherited.
7204
00f91aef 7205 function Has_Unconstrained_UU_Component (Typ : Node_Id) return Boolean;
36b938a3 7206 -- Determines whether a type has a subcomponent of an unconstrained
00f91aef 7207 -- Unchecked_Union subtype. Typ is a record type.
7208
ee6ba406 7209 -------------------------
7210 -- Build_Equality_Call --
7211 -------------------------
7212
7213 procedure Build_Equality_Call (Eq : Entity_Id) is
7214 Op_Type : constant Entity_Id := Etype (First_Formal (Eq));
82b93248 7215 L_Exp : Node_Id := Relocate_Node (Lhs);
7216 R_Exp : Node_Id := Relocate_Node (Rhs);
ee6ba406 7217
7218 begin
48680a09 7219 -- Adjust operands if necessary to comparison type
7220
ee6ba406 7221 if Base_Type (Op_Type) /= Base_Type (A_Typ)
7222 and then not Is_Class_Wide_Type (A_Typ)
7223 then
7224 L_Exp := OK_Convert_To (Op_Type, L_Exp);
7225 R_Exp := OK_Convert_To (Op_Type, R_Exp);
7226 end if;
7227
00f91aef 7228 -- If we have an Unchecked_Union, we need to add the inferred
7229 -- discriminant values as actuals in the function call. At this
7230 -- point, the expansion has determined that both operands have
7231 -- inferable discriminants.
7232
7233 if Is_Unchecked_Union (Op_Type) then
7234 declare
e502f26d 7235 Lhs_Type : constant Node_Id := Etype (L_Exp);
7236 Rhs_Type : constant Node_Id := Etype (R_Exp);
7237
7238 Lhs_Discr_Vals : Elist_Id;
7239 -- List of inferred discriminant values for left operand.
7240
7241 Rhs_Discr_Vals : Elist_Id;
7242 -- List of inferred discriminant values for right operand.
7243
7244 Discr : Entity_Id;
00f91aef 7245
7246 begin
e502f26d 7247 Lhs_Discr_Vals := New_Elmt_List;
7248 Rhs_Discr_Vals := New_Elmt_List;
7249
00f91aef 7250 -- Per-object constrained selected components require special
7251 -- attention. If the enclosing scope of the component is an
38f5559f 7252 -- Unchecked_Union, we cannot reference its discriminants
e502f26d 7253 -- directly. This is why we use the extra parameters of the
7254 -- equality function of the enclosing Unchecked_Union.
00f91aef 7255
7256 -- type UU_Type (Discr : Integer := 0) is
7257 -- . . .
7258 -- end record;
7259 -- pragma Unchecked_Union (UU_Type);
7260
7261 -- 1. Unchecked_Union enclosing record:
7262
7263 -- type Enclosing_UU_Type (Discr : Integer := 0) is record
7264 -- . . .
7265 -- Comp : UU_Type (Discr);
7266 -- . . .
7267 -- end Enclosing_UU_Type;
7268 -- pragma Unchecked_Union (Enclosing_UU_Type);
7269
7270 -- Obj1 : Enclosing_UU_Type;
7271 -- Obj2 : Enclosing_UU_Type (1);
7272
aae50ddd 7273 -- [. . .] Obj1 = Obj2 [. . .]
00f91aef 7274
7275 -- Generated code:
7276
7277 -- if not (uu_typeEQ (obj1.comp, obj2.comp, a, b)) then
7278
7279 -- A and B are the formal parameters of the equality function
7280 -- of Enclosing_UU_Type. The function always has two extra
e502f26d 7281 -- formals to capture the inferred discriminant values for
7282 -- each discriminant of the type.
00f91aef 7283
7284 -- 2. Non-Unchecked_Union enclosing record:
7285
7286 -- type
7287 -- Enclosing_Non_UU_Type (Discr : Integer := 0)
7288 -- is record
7289 -- . . .
7290 -- Comp : UU_Type (Discr);
7291 -- . . .
7292 -- end Enclosing_Non_UU_Type;
7293
7294 -- Obj1 : Enclosing_Non_UU_Type;
7295 -- Obj2 : Enclosing_Non_UU_Type (1);
7296
4dcc60e5 7297 -- ... Obj1 = Obj2 ...
00f91aef 7298
7299 -- Generated code:
7300
7301 -- if not (uu_typeEQ (obj1.comp, obj2.comp,
7302 -- obj1.discr, obj2.discr)) then
7303
7304 -- In this case we can directly reference the discriminants of
7305 -- the enclosing record.
7306
e502f26d 7307 -- Process left operand of equality
00f91aef 7308
7309 if Nkind (Lhs) = N_Selected_Component
6f0d10f7 7310 and then
7311 Has_Per_Object_Constraint (Entity (Selector_Name (Lhs)))
00f91aef 7312 then
e502f26d 7313 -- If enclosing record is an Unchecked_Union, use formals
7314 -- corresponding to each discriminant. The name of the
7315 -- formal is that of the discriminant, with added suffix,
7316 -- see Exp_Ch3.Build_Record_Equality for details.
00f91aef 7317
48680a09 7318 if Is_Unchecked_Union (Scope (Entity (Selector_Name (Lhs))))
00f91aef 7319 then
e502f26d 7320 Discr :=
7321 First_Discriminant
7322 (Scope (Entity (Selector_Name (Lhs))));
7323 while Present (Discr) loop
82b93248 7324 Append_Elmt
7325 (Make_Identifier (Loc,
7326 Chars => New_External_Name (Chars (Discr), 'A')),
7327 To => Lhs_Discr_Vals);
e502f26d 7328 Next_Discriminant (Discr);
7329 end loop;
00f91aef 7330
e502f26d 7331 -- If enclosing record is of a non-Unchecked_Union type, it
7332 -- is possible to reference its discriminants directly.
00f91aef 7333
7334 else
e502f26d 7335 Discr := First_Discriminant (Lhs_Type);
7336 while Present (Discr) loop
82b93248 7337 Append_Elmt
7338 (Make_Selected_Component (Loc,
7339 Prefix => Prefix (Lhs),
7340 Selector_Name =>
7341 New_Copy
7342 (Get_Discriminant_Value (Discr,
7343 Lhs_Type,
7344 Stored_Constraint (Lhs_Type)))),
7345 To => Lhs_Discr_Vals);
e502f26d 7346 Next_Discriminant (Discr);
7347 end loop;
00f91aef 7348 end if;
7349
e502f26d 7350 -- Otherwise operand is on object with a constrained type.
7351 -- Infer the discriminant values from the constraint.
00f91aef 7352
7353 else
e502f26d 7354
7355 Discr := First_Discriminant (Lhs_Type);
7356 while Present (Discr) loop
82b93248 7357 Append_Elmt
7358 (New_Copy
7359 (Get_Discriminant_Value (Discr,
e502f26d 7360 Lhs_Type,
7361 Stored_Constraint (Lhs_Type))),
82b93248 7362 To => Lhs_Discr_Vals);
e502f26d 7363 Next_Discriminant (Discr);
7364 end loop;
00f91aef 7365 end if;
7366
e502f26d 7367 -- Similar processing for right operand of equality
00f91aef 7368
7369 if Nkind (Rhs) = N_Selected_Component
6f0d10f7 7370 and then
7371 Has_Per_Object_Constraint (Entity (Selector_Name (Rhs)))
00f91aef 7372 then
f84d3d59 7373 if Is_Unchecked_Union
82b93248 7374 (Scope (Entity (Selector_Name (Rhs))))
00f91aef 7375 then
e502f26d 7376 Discr :=
7377 First_Discriminant
7378 (Scope (Entity (Selector_Name (Rhs))));
7379 while Present (Discr) loop
82b93248 7380 Append_Elmt
7381 (Make_Identifier (Loc,
7382 Chars => New_External_Name (Chars (Discr), 'B')),
7383 To => Rhs_Discr_Vals);
e502f26d 7384 Next_Discriminant (Discr);
7385 end loop;
00f91aef 7386
7387 else
e502f26d 7388 Discr := First_Discriminant (Rhs_Type);
7389 while Present (Discr) loop
82b93248 7390 Append_Elmt
7391 (Make_Selected_Component (Loc,
7392 Prefix => Prefix (Rhs),
7393 Selector_Name =>
7394 New_Copy (Get_Discriminant_Value
7395 (Discr,
7396 Rhs_Type,
7397 Stored_Constraint (Rhs_Type)))),
7398 To => Rhs_Discr_Vals);
e502f26d 7399 Next_Discriminant (Discr);
7400 end loop;
00f91aef 7401 end if;
00f91aef 7402
e502f26d 7403 else
7404 Discr := First_Discriminant (Rhs_Type);
7405 while Present (Discr) loop
82b93248 7406 Append_Elmt
7407 (New_Copy (Get_Discriminant_Value
7408 (Discr,
7409 Rhs_Type,
7410 Stored_Constraint (Rhs_Type))),
7411 To => Rhs_Discr_Vals);
e502f26d 7412 Next_Discriminant (Discr);
7413 end loop;
00f91aef 7414 end if;
7415
e502f26d 7416 -- Now merge the list of discriminant values so that values
7417 -- of corresponding discriminants are adjacent.
7418
7419 declare
7420 Params : List_Id;
7421 L_Elmt : Elmt_Id;
7422 R_Elmt : Elmt_Id;
7423
7424 begin
7425 Params := New_List (L_Exp, R_Exp);
7426 L_Elmt := First_Elmt (Lhs_Discr_Vals);
7427 R_Elmt := First_Elmt (Rhs_Discr_Vals);
7428 while Present (L_Elmt) loop
7429 Append_To (Params, Node (L_Elmt));
7430 Append_To (Params, Node (R_Elmt));
7431 Next_Elmt (L_Elmt);
7432 Next_Elmt (R_Elmt);
7433 end loop;
7434
7435 Rewrite (N,
7436 Make_Function_Call (Loc,
83c6c069 7437 Name => New_Occurrence_Of (Eq, Loc),
e502f26d 7438 Parameter_Associations => Params));
7439 end;
00f91aef 7440 end;
7441
7442 -- Normal case, not an unchecked union
7443
7444 else
7445 Rewrite (N,
7446 Make_Function_Call (Loc,
83c6c069 7447 Name => New_Occurrence_Of (Eq, Loc),
00f91aef 7448 Parameter_Associations => New_List (L_Exp, R_Exp)));
7449 end if;
ee6ba406 7450
7451 Analyze_And_Resolve (N, Standard_Boolean, Suppress => All_Checks);
7452 end Build_Equality_Call;
7453
00f91aef 7454 ------------------------------------
7455 -- Has_Unconstrained_UU_Component --
7456 ------------------------------------
7457
7458 function Has_Unconstrained_UU_Component
7459 (Typ : Node_Id) return Boolean
7460 is
7461 Tdef : constant Node_Id :=
811e2566 7462 Type_Definition (Declaration_Node (Base_Type (Typ)));
00f91aef 7463 Clist : Node_Id;
7464 Vpart : Node_Id;
7465
7466 function Component_Is_Unconstrained_UU
7467 (Comp : Node_Id) return Boolean;
7468 -- Determines whether the subtype of the component is an
7469 -- unconstrained Unchecked_Union.
7470
7471 function Variant_Is_Unconstrained_UU
7472 (Variant : Node_Id) return Boolean;
7473 -- Determines whether a component of the variant has an unconstrained
7474 -- Unchecked_Union subtype.
7475
7476 -----------------------------------
7477 -- Component_Is_Unconstrained_UU --
7478 -----------------------------------
7479
7480 function Component_Is_Unconstrained_UU
7481 (Comp : Node_Id) return Boolean
7482 is
7483 begin
7484 if Nkind (Comp) /= N_Component_Declaration then
7485 return False;
7486 end if;
7487
7488 declare
7489 Sindic : constant Node_Id :=
7490 Subtype_Indication (Component_Definition (Comp));
7491
7492 begin
7493 -- Unconstrained nominal type. In the case of a constraint
7494 -- present, the node kind would have been N_Subtype_Indication.
7495
7496 if Nkind (Sindic) = N_Identifier then
7497 return Is_Unchecked_Union (Base_Type (Etype (Sindic)));
7498 end if;
7499
7500 return False;
7501 end;
7502 end Component_Is_Unconstrained_UU;
7503
7504 ---------------------------------
7505 -- Variant_Is_Unconstrained_UU --
7506 ---------------------------------
7507
7508 function Variant_Is_Unconstrained_UU
7509 (Variant : Node_Id) return Boolean
7510 is
7511 Clist : constant Node_Id := Component_List (Variant);
7512
7513 begin
7514 if Is_Empty_List (Component_Items (Clist)) then
7515 return False;
7516 end if;
7517
38f5559f 7518 -- We only need to test one component
7519
00f91aef 7520 declare
7521 Comp : Node_Id := First (Component_Items (Clist));
7522
7523 begin
7524 while Present (Comp) loop
00f91aef 7525 if Component_Is_Unconstrained_UU (Comp) then
7526 return True;
7527 end if;
7528
7529 Next (Comp);
7530 end loop;
7531 end;
7532
7533 -- None of the components withing the variant were of
7534 -- unconstrained Unchecked_Union type.
7535
7536 return False;
7537 end Variant_Is_Unconstrained_UU;
7538
7539 -- Start of processing for Has_Unconstrained_UU_Component
7540
7541 begin
7542 if Null_Present (Tdef) then
7543 return False;
7544 end if;
7545
7546 Clist := Component_List (Tdef);
7547 Vpart := Variant_Part (Clist);
7548
7549 -- Inspect available components
7550
7551 if Present (Component_Items (Clist)) then
7552 declare
7553 Comp : Node_Id := First (Component_Items (Clist));
7554
7555 begin
7556 while Present (Comp) loop
7557
36b938a3 7558 -- One component is sufficient
00f91aef 7559
7560 if Component_Is_Unconstrained_UU (Comp) then
7561 return True;
7562 end if;
7563
7564 Next (Comp);
7565 end loop;
7566 end;
7567 end if;
7568
7569 -- Inspect available components withing variants
7570
7571 if Present (Vpart) then
7572 declare
7573 Variant : Node_Id := First (Variants (Vpart));
7574
7575 begin
7576 while Present (Variant) loop
7577
36b938a3 7578 -- One component within a variant is sufficient
00f91aef 7579
7580 if Variant_Is_Unconstrained_UU (Variant) then
7581 return True;
7582 end if;
7583
7584 Next (Variant);
7585 end loop;
7586 end;
7587 end if;
7588
7589 -- Neither the available components, nor the components inside the
7590 -- variant parts were of an unconstrained Unchecked_Union subtype.
7591
7592 return False;
7593 end Has_Unconstrained_UU_Component;
7594
ee6ba406 7595 -- Start of processing for Expand_N_Op_Eq
7596
7597 begin
7598 Binary_Op_Validity_Checks (N);
7599
d94b5da2 7600 -- Deal with private types
7601
ee6ba406 7602 if Ekind (Typl) = E_Private_Type then
7603 Typl := Underlying_Type (Typl);
ee6ba406 7604 elsif Ekind (Typl) = E_Private_Subtype then
7605 Typl := Underlying_Type (Base_Type (Typl));
38f5559f 7606 else
7607 null;
ee6ba406 7608 end if;
7609
7610 -- It may happen in error situations that the underlying type is not
7611 -- set. The error will be detected later, here we just defend the
7612 -- expander code.
7613
7614 if No (Typl) then
7615 return;
7616 end if;
7617
d234ced5 7618 -- Now get the implementation base type (note that plain Base_Type here
7619 -- might lead us back to the private type, which is not what we want!)
7620
7621 Typl := Implementation_Base_Type (Typl);
ee6ba406 7622
48680a09 7623 -- Equality between variant records results in a call to a routine
7624 -- that has conditional tests of the discriminant value(s), and hence
7625 -- violates the No_Implicit_Conditionals restriction.
7626
7627 if Has_Variant_Part (Typl) then
7628 declare
7629 Msg : Boolean;
7630
7631 begin
7632 Check_Restriction (Msg, No_Implicit_Conditionals, N);
7633
7634 if Msg then
7635 Error_Msg_N
7636 ("\comparison of variant records tests discriminants", N);
7637 return;
7638 end if;
7639 end;
7640 end if;
7641
d94b5da2 7642 -- Deal with overflow checks in MINIMIZED/ELIMINATED mode and if that
412f75eb 7643 -- means we no longer have a comparison operation, we are all done.
d94b5da2 7644
7645 Expand_Compare_Minimize_Eliminate_Overflow (N);
7646
7647 if Nkind (N) /= N_Op_Eq then
7648 return;
7649 end if;
7650
ee6ba406 7651 -- Boolean types (requiring handling of non-standard case)
7652
38f5559f 7653 if Is_Boolean_Type (Typl) then
ee6ba406 7654 Adjust_Condition (Left_Opnd (N));
7655 Adjust_Condition (Right_Opnd (N));
7656 Set_Etype (N, Standard_Boolean);
7657 Adjust_Result_Type (N, Typ);
7658
7659 -- Array types
7660
7661 elsif Is_Array_Type (Typl) then
7662
8f199ad0 7663 -- If we are doing full validity checking, and it is possible for the
7664 -- array elements to be invalid then expand out array comparisons to
7665 -- make sure that we check the array elements.
9dfe12ae 7666
8f199ad0 7667 if Validity_Check_Operands
7668 and then not Is_Known_Valid (Component_Type (Typl))
7669 then
9dfe12ae 7670 declare
7671 Save_Force_Validity_Checks : constant Boolean :=
7672 Force_Validity_Checks;
7673 begin
7674 Force_Validity_Checks := True;
7675 Rewrite (N,
80d4fec4 7676 Expand_Array_Equality
7677 (N,
7678 Relocate_Node (Lhs),
7679 Relocate_Node (Rhs),
7680 Bodies,
7681 Typl));
7682 Insert_Actions (N, Bodies);
9dfe12ae 7683 Analyze_And_Resolve (N, Standard_Boolean);
7684 Force_Validity_Checks := Save_Force_Validity_Checks;
7685 end;
7686
4660e715 7687 -- Packed case where both operands are known aligned
ee6ba406 7688
4660e715 7689 elsif Is_Bit_Packed_Array (Typl)
7690 and then not Is_Possibly_Unaligned_Object (Lhs)
7691 and then not Is_Possibly_Unaligned_Object (Rhs)
7692 then
ee6ba406 7693 Expand_Packed_Eq (N);
7694
f84d3d59 7695 -- Where the component type is elementary we can use a block bit
7696 -- comparison (if supported on the target) exception in the case
7697 -- of floating-point (negative zero issues require element by
2fe893b9 7698 -- element comparison), and atomic/VFA types (where we must be sure
4660e715 7699 -- to load elements independently) and possibly unaligned arrays.
ee6ba406 7700
ee6ba406 7701 elsif Is_Elementary_Type (Component_Type (Typl))
7702 and then not Is_Floating_Point_Type (Component_Type (Typl))
2fe893b9 7703 and then not Is_Atomic_Or_VFA (Component_Type (Typl))
4660e715 7704 and then not Is_Possibly_Unaligned_Object (Lhs)
7705 and then not Is_Possibly_Unaligned_Object (Rhs)
9dfe12ae 7706 and then Support_Composite_Compare_On_Target
ee6ba406 7707 then
7708 null;
7709
f1e2dcc5 7710 -- For composite and floating-point cases, expand equality loop to
7711 -- make sure of using proper comparisons for tagged types, and
7712 -- correctly handling the floating-point case.
ee6ba406 7713
7714 else
7715 Rewrite (N,
80d4fec4 7716 Expand_Array_Equality
7717 (N,
7718 Relocate_Node (Lhs),
7719 Relocate_Node (Rhs),
7720 Bodies,
7721 Typl));
ee6ba406 7722 Insert_Actions (N, Bodies, Suppress => All_Checks);
7723 Analyze_And_Resolve (N, Standard_Boolean, Suppress => All_Checks);
7724 end if;
7725
7726 -- Record Types
7727
7728 elsif Is_Record_Type (Typl) then
7729
7730 -- For tagged types, use the primitive "="
7731
7732 if Is_Tagged_Type (Typl) then
7733
99f2248e 7734 -- No need to do anything else compiling under restriction
7735 -- No_Dispatching_Calls. During the semantic analysis we
7736 -- already notified such violation.
7737
7738 if Restriction_Active (No_Dispatching_Calls) then
7739 return;
7740 end if;
7741
f1e2dcc5 7742 -- If this is derived from an untagged private type completed with
7743 -- a tagged type, it does not have a full view, so we use the
7744 -- primitive operations of the private type. This check should no
7745 -- longer be necessary when these types get their full views???
ee6ba406 7746
7747 if Is_Private_Type (A_Typ)
7748 and then not Is_Tagged_Type (A_Typ)
7749 and then Is_Derived_Type (A_Typ)
7750 and then No (Full_View (A_Typ))
7751 then
f1e2dcc5 7752 -- Search for equality operation, checking that the operands
7753 -- have the same type. Note that we must find a matching entry,
39a0c1d3 7754 -- or something is very wrong.
752e1833 7755
ee6ba406 7756 Prim := First_Elmt (Collect_Primitive_Operations (A_Typ));
7757
752e1833 7758 while Present (Prim) loop
7759 exit when Chars (Node (Prim)) = Name_Op_Eq
7760 and then Etype (First_Formal (Node (Prim))) =
7761 Etype (Next_Formal (First_Formal (Node (Prim))))
7762 and then
7763 Base_Type (Etype (Node (Prim))) = Standard_Boolean;
7764
ee6ba406 7765 Next_Elmt (Prim);
ee6ba406 7766 end loop;
7767
752e1833 7768 pragma Assert (Present (Prim));
ee6ba406 7769 Op_Name := Node (Prim);
9dfe12ae 7770
7771 -- Find the type's predefined equality or an overriding
71959747 7772 -- user-defined equality. The reason for not simply calling
9dfe12ae 7773 -- Find_Prim_Op here is that there may be a user-defined
71959747 7774 -- overloaded equality op that precedes the equality that we
7775 -- want, so we have to explicitly search (e.g., there could be
7776 -- an equality with two different parameter types).
9dfe12ae 7777
ee6ba406 7778 else
9dfe12ae 7779 if Is_Class_Wide_Type (Typl) then
71959747 7780 Typl := Find_Specific_Type (Typl);
9dfe12ae 7781 end if;
7782
7783 Prim := First_Elmt (Primitive_Operations (Typl));
9dfe12ae 7784 while Present (Prim) loop
7785 exit when Chars (Node (Prim)) = Name_Op_Eq
7786 and then Etype (First_Formal (Node (Prim))) =
7787 Etype (Next_Formal (First_Formal (Node (Prim))))
cafd02b3 7788 and then
7789 Base_Type (Etype (Node (Prim))) = Standard_Boolean;
9dfe12ae 7790
7791 Next_Elmt (Prim);
9dfe12ae 7792 end loop;
7793
752e1833 7794 pragma Assert (Present (Prim));
9dfe12ae 7795 Op_Name := Node (Prim);
ee6ba406 7796 end if;
7797
7798 Build_Equality_Call (Op_Name);
7799
00f91aef 7800 -- Ada 2005 (AI-216): Program_Error is raised when evaluating the
7801 -- predefined equality operator for a type which has a subcomponent
7802 -- of an Unchecked_Union type whose nominal subtype is unconstrained.
7803
7804 elsif Has_Unconstrained_UU_Component (Typl) then
7805 Insert_Action (N,
7806 Make_Raise_Program_Error (Loc,
7807 Reason => PE_Unchecked_Union_Restriction));
7808
7809 -- Prevent Gigi from generating incorrect code by rewriting the
de922300 7810 -- equality as a standard False. (is this documented somewhere???)
00f91aef 7811
7812 Rewrite (N,
7813 New_Occurrence_Of (Standard_False, Loc));
7814
7815 elsif Is_Unchecked_Union (Typl) then
7816
7817 -- If we can infer the discriminants of the operands, we make a
7818 -- call to the TSS equality function.
7819
7820 if Has_Inferable_Discriminants (Lhs)
7821 and then
7822 Has_Inferable_Discriminants (Rhs)
7823 then
7824 Build_Equality_Call
7825 (TSS (Root_Type (Typl), TSS_Composite_Equality));
7826
7827 else
7828 -- Ada 2005 (AI-216): Program_Error is raised when evaluating
7829 -- the predefined equality operator for an Unchecked_Union type
7830 -- if either of the operands lack inferable discriminants.
7831
7832 Insert_Action (N,
7833 Make_Raise_Program_Error (Loc,
7834 Reason => PE_Unchecked_Union_Restriction));
7835
82acbdda 7836 -- Emit a warning on source equalities only, otherwise the
7837 -- message may appear out of place due to internal use. The
7838 -- warning is unconditional because it is required by the
7839 -- language.
7840
7841 if Comes_From_Source (N) then
7842 Error_Msg_N
a89c99bc 7843 ("Unchecked_Union discriminants cannot be determined??",
82acbdda 7844 N);
7845 Error_Msg_N
a89c99bc 7846 ("\Program_Error will be raised for equality operation??",
82acbdda 7847 N);
7848 end if;
7849
00f91aef 7850 -- Prevent Gigi from generating incorrect code by rewriting
de922300 7851 -- the equality as a standard False (documented where???).
00f91aef 7852
7853 Rewrite (N,
7854 New_Occurrence_Of (Standard_False, Loc));
00f91aef 7855 end if;
7856
ee6ba406 7857 -- If a type support function is present (for complex cases), use it
7858
9dfe12ae 7859 elsif Present (TSS (Root_Type (Typl), TSS_Composite_Equality)) then
7860 Build_Equality_Call
7861 (TSS (Root_Type (Typl), TSS_Composite_Equality));
ee6ba406 7862
26080eca 7863 -- When comparing two Bounded_Strings, use the primitive equality of
7864 -- the root Super_String type.
7865
7866 elsif Is_Bounded_String (Typl) then
7867 Prim :=
7868 First_Elmt (Collect_Primitive_Operations (Root_Type (Typl)));
7869
7870 while Present (Prim) loop
7871 exit when Chars (Node (Prim)) = Name_Op_Eq
7872 and then Etype (First_Formal (Node (Prim))) =
7873 Etype (Next_Formal (First_Formal (Node (Prim))))
7874 and then Base_Type (Etype (Node (Prim))) = Standard_Boolean;
7875
7876 Next_Elmt (Prim);
7877 end loop;
7878
7879 -- A Super_String type should always have a primitive equality
7880
7881 pragma Assert (Present (Prim));
7882 Build_Equality_Call (Node (Prim));
7883
ee6ba406 7884 -- Otherwise expand the component by component equality. Note that
36b938a3 7885 -- we never use block-bit comparisons for records, because of the
2a801d20 7886 -- problems with gaps. The back end will often be able to recombine
ee6ba406 7887 -- the separate comparisons that we generate here.
7888
7889 else
7890 Remove_Side_Effects (Lhs);
7891 Remove_Side_Effects (Rhs);
7892 Rewrite (N,
7893 Expand_Record_Equality (N, Typl, Lhs, Rhs, Bodies));
7894
7895 Insert_Actions (N, Bodies, Suppress => All_Checks);
7896 Analyze_And_Resolve (N, Standard_Boolean, Suppress => All_Checks);
7897 end if;
7898 end if;
7899
35c57fc7 7900 -- Test if result is known at compile time
ee6ba406 7901
35c57fc7 7902 Rewrite_Comparison (N);
38f5559f 7903
36625869 7904 -- Special optimization of length comparison
7905
4ecb1318 7906 Optimize_Length_Comparison (N);
36625869 7907
5292f25c 7908 -- One more special case: if we have a comparison of X'Result = expr
36625869 7909 -- in floating-point, then if not already there, change expr to be
5292f25c 7910 -- f'Machine (expr) to eliminate surprise from extra precision.
36625869 7911
7912 if Is_Floating_Point_Type (Typl)
7913 and then Nkind (Original_Node (Lhs)) = N_Attribute_Reference
7914 and then Attribute_Name (Original_Node (Lhs)) = Name_Result
7915 then
7916 -- Stick in the Typ'Machine call if not already there
7917
7918 if Nkind (Rhs) /= N_Attribute_Reference
7919 or else Attribute_Name (Rhs) /= Name_Machine
7920 then
7921 Rewrite (Rhs,
7922 Make_Attribute_Reference (Loc,
7923 Prefix => New_Occurrence_Of (Typl, Loc),
7924 Attribute_Name => Name_Machine,
7925 Expressions => New_List (Relocate_Node (Rhs))));
7926 Analyze_And_Resolve (Rhs, Typl);
7927 end if;
7928 end if;
ee6ba406 7929 end Expand_N_Op_Eq;
7930
7931 -----------------------
7932 -- Expand_N_Op_Expon --
7933 -----------------------
7934
7935 procedure Expand_N_Op_Expon (N : Node_Id) is
98b2a090 7936 Loc : constant Source_Ptr := Sloc (N);
7937 Ovflo : constant Boolean := Do_Overflow_Check (N);
7938 Typ : constant Entity_Id := Etype (N);
7939 Rtyp : constant Entity_Id := Root_Type (Typ);
7940
7941 Bastyp : Entity_Id;
ee6ba406 7942
23225afb 7943 function Wrap_MA (Exp : Node_Id) return Node_Id;
7944 -- Given an expression Exp, if the root type is Float or Long_Float,
7945 -- then wrap the expression in a call of Bastyp'Machine, to stop any
7946 -- extra precision. This is done to ensure that X**A = X**B when A is
7947 -- a static constant and B is a variable with the same value. For any
7948 -- other type, the node Exp is returned unchanged.
7949
7950 -------------
7951 -- Wrap_MA --
7952 -------------
7953
7954 function Wrap_MA (Exp : Node_Id) return Node_Id is
7955 Loc : constant Source_Ptr := Sloc (Exp);
98b2a090 7956
23225afb 7957 begin
7958 if Rtyp = Standard_Float or else Rtyp = Standard_Long_Float then
7959 return
7960 Make_Attribute_Reference (Loc,
7961 Attribute_Name => Name_Machine,
7962 Prefix => New_Occurrence_Of (Bastyp, Loc),
7963 Expressions => New_List (Relocate_Node (Exp)));
7964 else
7965 return Exp;
7966 end if;
7967 end Wrap_MA;
7968
98b2a090 7969 -- Local variables
7970
7971 Base : Node_Id;
7972 Ent : Entity_Id;
7973 Etyp : Entity_Id;
7974 Exp : Node_Id;
7975 Exptyp : Entity_Id;
7976 Expv : Uint;
7977 Rent : RE_Id;
7978 Temp : Node_Id;
7979 Xnode : Node_Id;
7980
281cf495 7981 -- Start of processing for Expand_N_Op_Expon
23225afb 7982
ee6ba406 7983 begin
7984 Binary_Op_Validity_Checks (N);
7985
8a075a7e 7986 -- CodePeer wants to see the unexpanded N_Op_Expon node
568b0f6a 7987
8a075a7e 7988 if CodePeer_Mode then
568b0f6a 7989 return;
7990 end if;
7991
281cf495 7992 -- Relocation of left and right operands must be done after performing
7993 -- the validity checks since the generation of validation checks may
7994 -- remove side effects.
7995
7996 Base := Relocate_Node (Left_Opnd (N));
7997 Bastyp := Etype (Base);
7998 Exp := Relocate_Node (Right_Opnd (N));
7999 Exptyp := Etype (Exp);
8000
f1e2dcc5 8001 -- If either operand is of a private type, then we have the use of an
8002 -- intrinsic operator, and we get rid of the privateness, by using root
8003 -- types of underlying types for the actual operation. Otherwise the
8004 -- private types will cause trouble if we expand multiplications or
8005 -- shifts etc. We also do this transformation if the result type is
8006 -- different from the base type.
f15731c4 8007
8008 if Is_Private_Type (Etype (Base))
568b0f6a 8009 or else Is_Private_Type (Typ)
8010 or else Is_Private_Type (Exptyp)
8011 or else Rtyp /= Root_Type (Bastyp)
f15731c4 8012 then
8013 declare
8014 Bt : constant Entity_Id := Root_Type (Underlying_Type (Bastyp));
8015 Et : constant Entity_Id := Root_Type (Underlying_Type (Exptyp));
f15731c4 8016 begin
8017 Rewrite (N,
8018 Unchecked_Convert_To (Typ,
8019 Make_Op_Expon (Loc,
8020 Left_Opnd => Unchecked_Convert_To (Bt, Base),
8021 Right_Opnd => Unchecked_Convert_To (Et, Exp))));
8022 Analyze_And_Resolve (N, Typ);
8023 return;
8024 end;
8025 end if;
8026
f32c377d 8027 -- Check for MINIMIZED/ELIMINATED overflow mode
de922300 8028
f32c377d 8029 if Minimized_Eliminated_Overflow_Check (N) then
de922300 8030 Apply_Arithmetic_Overflow_Check (N);
8031 return;
8032 end if;
8033
595e47de 8034 -- Test for case of known right argument where we can replace the
8035 -- exponentiation by an equivalent expression using multiplication.
ee6ba406 8036
3b509a92 8037 -- Note: use CRT_Safe version of Compile_Time_Known_Value because in
8038 -- configurable run-time mode, we may not have the exponentiation
8039 -- routine available, and we don't want the legality of the program
8040 -- to depend on how clever the compiler is in knowing values.
8041
8042 if CRT_Safe_Compile_Time_Known_Value (Exp) then
ee6ba406 8043 Expv := Expr_Value (Exp);
8044
8045 -- We only fold small non-negative exponents. You might think we
8046 -- could fold small negative exponents for the real case, but we
8047 -- can't because we are required to raise Constraint_Error for
8048 -- the case of 0.0 ** (negative) even if Machine_Overflows = False.
23225afb 8049 -- See ACVC test C4A012B, and it is not worth generating the test.
ee6ba406 8050
c6f2a102 8051 -- For small negative exponents, we return the reciprocal of
8052 -- the folding of the exponentiation for the opposite (positive)
8053 -- exponent, as required by Ada RM 4.5.6(11/3).
8054
8055 if abs Expv <= 4 then
ee6ba406 8056
8057 -- X ** 0 = 1 (or 1.0)
8058
8059 if Expv = 0 then
f6f20e0e 8060
8061 -- Call Remove_Side_Effects to ensure that any side effects
8062 -- in the ignored left operand (in particular function calls
8063 -- to user defined functions) are properly executed.
8064
8065 Remove_Side_Effects (Base);
8066
ee6ba406 8067 if Ekind (Typ) in Integer_Kind then
8068 Xnode := Make_Integer_Literal (Loc, Intval => 1);
8069 else
8070 Xnode := Make_Real_Literal (Loc, Ureal_1);
8071 end if;
8072
8073 -- X ** 1 = X
8074
8075 elsif Expv = 1 then
8076 Xnode := Base;
8077
8078 -- X ** 2 = X * X
8079
8080 elsif Expv = 2 then
8081 Xnode :=
23225afb 8082 Wrap_MA (
8083 Make_Op_Multiply (Loc,
8084 Left_Opnd => Duplicate_Subexpr (Base),
8085 Right_Opnd => Duplicate_Subexpr_No_Checks (Base)));
ee6ba406 8086
8087 -- X ** 3 = X * X * X
8088
8089 elsif Expv = 3 then
8090 Xnode :=
23225afb 8091 Wrap_MA (
8092 Make_Op_Multiply (Loc,
8093 Left_Opnd =>
8094 Make_Op_Multiply (Loc,
8095 Left_Opnd => Duplicate_Subexpr (Base),
8096 Right_Opnd => Duplicate_Subexpr_No_Checks (Base)),
8097 Right_Opnd => Duplicate_Subexpr_No_Checks (Base)));
ee6ba406 8098
8099 -- X ** 4 ->
595e47de 8100
8101 -- do
ee6ba406 8102 -- En : constant base'type := base * base;
595e47de 8103 -- in
ee6ba406 8104 -- En * En
8105
c6f2a102 8106 elsif Expv = 4 then
46eb6933 8107 Temp := Make_Temporary (Loc, 'E', Base);
ee6ba406 8108
595e47de 8109 Xnode :=
8110 Make_Expression_With_Actions (Loc,
8111 Actions => New_List (
8112 Make_Object_Declaration (Loc,
8113 Defining_Identifier => Temp,
8114 Constant_Present => True,
83c6c069 8115 Object_Definition => New_Occurrence_Of (Typ, Loc),
595e47de 8116 Expression =>
23225afb 8117 Wrap_MA (
8118 Make_Op_Multiply (Loc,
8119 Left_Opnd =>
8120 Duplicate_Subexpr (Base),
8121 Right_Opnd =>
8122 Duplicate_Subexpr_No_Checks (Base))))),
595e47de 8123
ee6ba406 8124 Expression =>
23225afb 8125 Wrap_MA (
8126 Make_Op_Multiply (Loc,
8127 Left_Opnd => New_Occurrence_Of (Temp, Loc),
8128 Right_Opnd => New_Occurrence_Of (Temp, Loc))));
c6f2a102 8129
8130 -- X ** N = 1.0 / X ** (-N)
8131 -- N in -4 .. -1
8132
8133 else
8134 pragma Assert
8135 (Expv = -1 or Expv = -2 or Expv = -3 or Expv = -4);
6b44d713 8136
c6f2a102 8137 Xnode :=
8138 Make_Op_Divide (Loc,
8139 Left_Opnd =>
8140 Make_Float_Literal (Loc,
8141 Radix => Uint_1,
8142 Significand => Uint_1,
8143 Exponent => Uint_0),
8144 Right_Opnd =>
8145 Make_Op_Expon (Loc,
8146 Left_Opnd => Duplicate_Subexpr (Base),
8147 Right_Opnd =>
8148 Make_Integer_Literal (Loc,
8149 Intval => -Expv)));
ee6ba406 8150 end if;
8151
8152 Rewrite (N, Xnode);
8153 Analyze_And_Resolve (N, Typ);
8154 return;
8155 end if;
8156 end if;
8157
00e1556e 8158 -- Deal with optimizing 2 ** expression to shift where possible
f1e2dcc5 8159
8f3b5017 8160 -- Note: we used to check that Exptyp was an unsigned type. But that is
8161 -- an unnecessary check, since if Exp is negative, we have a run-time
8162 -- error that is either caught (so we get the right result) or we have
8163 -- suppressed the check, in which case the code is erroneous anyway.
8164
00e1556e 8165 if Is_Integer_Type (Rtyp)
8166
e9793878 8167 -- The base value must be "safe compile-time known", and exactly 2
00e1556e 8168
8169 and then Nkind (Base) = N_Integer_Literal
3b509a92 8170 and then CRT_Safe_Compile_Time_Known_Value (Base)
8171 and then Expr_Value (Base) = Uint_2
00e1556e 8172
8173 -- We only handle cases where the right type is a integer
8174
ee6ba406 8175 and then Is_Integer_Type (Root_Type (Exptyp))
8176 and then Esize (Root_Type (Exptyp)) <= Esize (Standard_Integer)
00e1556e 8177
8178 -- This transformation is not applicable for a modular type with a
09ae61a2 8179 -- nonbinary modulus because we do not handle modular reduction in
00e1556e 8180 -- a correct manner if we attempt this transformation in this case.
8181
8182 and then not Non_Binary_Modulus (Typ)
ee6ba406 8183 then
00e1556e 8184 -- Handle the cases where our parent is a division or multiplication
8185 -- specially. In these cases we can convert to using a shift at the
8186 -- parent level if we are not doing overflow checking, since it is
8187 -- too tricky to combine the overflow check at the parent level.
ee6ba406 8188
00e1556e 8189 if not Ovflo
8190 and then Nkind_In (Parent (N), N_Op_Divide, N_Op_Multiply)
8191 then
006b904a 8192 declare
8193 P : constant Node_Id := Parent (N);
8194 L : constant Node_Id := Left_Opnd (P);
8195 R : constant Node_Id := Right_Opnd (P);
8196
8197 begin
8198 if (Nkind (P) = N_Op_Multiply
2eb0ff42 8199 and then
8200 ((Is_Integer_Type (Etype (L)) and then R = N)
8201 or else
8202 (Is_Integer_Type (Etype (R)) and then L = N))
8203 and then not Do_Overflow_Check (P))
8204
006b904a 8205 or else
8206 (Nkind (P) = N_Op_Divide
6f0d10f7 8207 and then Is_Integer_Type (Etype (L))
8208 and then Is_Unsigned_Type (Etype (L))
8209 and then R = N
8210 and then not Do_Overflow_Check (P))
006b904a 8211 then
8212 Set_Is_Power_Of_2_For_Shift (N);
8213 return;
8214 end if;
8215 end;
8216
00e1556e 8217 -- Here we just have 2 ** N on its own, so we can convert this to a
8218 -- shift node. We are prepared to deal with overflow here, and we
8219 -- also have to handle proper modular reduction for binary modular.
006b904a 8220
00e1556e 8221 else
8222 declare
8223 OK : Boolean;
8224 Lo : Uint;
8225 Hi : Uint;
8226
8227 MaxS : Uint;
8228 -- Maximum shift count with no overflow
8229
8230 TestS : Boolean;
8231 -- Set True if we must test the shift count
8232
7014074b 8233 Test_Gt : Node_Id;
8234 -- Node for test against TestS
8235
00e1556e 8236 begin
8237 -- Compute maximum shift based on the underlying size. For a
8238 -- modular type this is one less than the size.
8239
8240 if Is_Modular_Integer_Type (Typ) then
8241
8242 -- For modular integer types, this is the size of the value
8243 -- being shifted minus one. Any larger values will cause
8244 -- modular reduction to a result of zero. Note that we do
8245 -- want the RM_Size here (e.g. mod 2 ** 7, we want a result
8246 -- of 6, since 2**7 should be reduced to zero).
8247
8248 MaxS := RM_Size (Rtyp) - 1;
8249
8250 -- For signed integer types, we use the size of the value
8251 -- being shifted minus 2. Larger values cause overflow.
8252
8253 else
8254 MaxS := Esize (Rtyp) - 2;
8255 end if;
8256
8257 -- Determine range to see if it can be larger than MaxS
8258
8259 Determine_Range
8260 (Right_Opnd (N), OK, Lo, Hi, Assume_Valid => True);
8261 TestS := (not OK) or else Hi > MaxS;
8262
8263 -- Signed integer case
8264
8265 if Is_Signed_Integer_Type (Typ) then
8266
8267 -- Generate overflow check if overflow is active. Note that
8268 -- we can simply ignore the possibility of overflow if the
8269 -- flag is not set (means that overflow cannot happen or
8270 -- that overflow checks are suppressed).
8271
8272 if Ovflo and TestS then
8273 Insert_Action (N,
8274 Make_Raise_Constraint_Error (Loc,
8275 Condition =>
8276 Make_Op_Gt (Loc,
8277 Left_Opnd => Duplicate_Subexpr (Right_Opnd (N)),
8278 Right_Opnd => Make_Integer_Literal (Loc, MaxS)),
8279 Reason => CE_Overflow_Check_Failed));
8280 end if;
8281
8282 -- Now rewrite node as Shift_Left (1, right-operand)
8283
8284 Rewrite (N,
8285 Make_Op_Shift_Left (Loc,
8286 Left_Opnd => Make_Integer_Literal (Loc, Uint_1),
8287 Right_Opnd => Right_Opnd (N)));
8288
8289 -- Modular integer case
8290
8291 else pragma Assert (Is_Modular_Integer_Type (Typ));
8292
8293 -- If shift count can be greater than MaxS, we need to wrap
8294 -- the shift in a test that will reduce the result value to
8295 -- zero if this shift count is exceeded.
8296
8297 if TestS then
7014074b 8298
8299 -- Note: build node for the comparison first, before we
8300 -- reuse the Right_Opnd, so that we have proper parents
8301 -- in place for the Duplicate_Subexpr call.
8302
8303 Test_Gt :=
8304 Make_Op_Gt (Loc,
8305 Left_Opnd => Duplicate_Subexpr (Right_Opnd (N)),
8306 Right_Opnd => Make_Integer_Literal (Loc, MaxS));
8307
00e1556e 8308 Rewrite (N,
8309 Make_If_Expression (Loc,
8310 Expressions => New_List (
7014074b 8311 Test_Gt,
00e1556e 8312 Make_Integer_Literal (Loc, Uint_0),
00e1556e 8313 Make_Op_Shift_Left (Loc,
8314 Left_Opnd => Make_Integer_Literal (Loc, Uint_1),
8315 Right_Opnd => Right_Opnd (N)))));
8316
8317 -- If we know shift count cannot be greater than MaxS, then
8318 -- it is safe to just rewrite as a shift with no test.
8319
8320 else
8321 Rewrite (N,
8322 Make_Op_Shift_Left (Loc,
8323 Left_Opnd => Make_Integer_Literal (Loc, Uint_1),
8324 Right_Opnd => Right_Opnd (N)));
8325 end if;
8326 end if;
8327
8328 Analyze_And_Resolve (N, Typ);
8329 return;
8330 end;
006b904a 8331 end if;
ee6ba406 8332 end if;
8333
f15731c4 8334 -- Fall through if exponentiation must be done using a runtime routine
8335
f15731c4 8336 -- First deal with modular case
ee6ba406 8337
8338 if Is_Modular_Integer_Type (Rtyp) then
8339
23225afb 8340 -- Nonbinary modular case, we call the special exponentiation
8341 -- routine for the nonbinary case, converting the argument to
8342 -- Long_Long_Integer and passing the modulus value. Then the
8343 -- result is converted back to the base type.
ee6ba406 8344
8345 if Non_Binary_Modulus (Rtyp) then
ee6ba406 8346 Rewrite (N,
8347 Convert_To (Typ,
8348 Make_Function_Call (Loc,
82b93248 8349 Name =>
8350 New_Occurrence_Of (RTE (RE_Exp_Modular), Loc),
ee6ba406 8351 Parameter_Associations => New_List (
c5d641ca 8352 Convert_To (RTE (RE_Unsigned), Base),
ee6ba406 8353 Make_Integer_Literal (Loc, Modulus (Rtyp)),
8354 Exp))));
8355
23225afb 8356 -- Binary modular case, in this case, we call one of two routines,
8357 -- either the unsigned integer case, or the unsigned long long
8358 -- integer case, with a final "and" operation to do the required mod.
ee6ba406 8359
8360 else
8361 if UI_To_Int (Esize (Rtyp)) <= Standard_Integer_Size then
8362 Ent := RTE (RE_Exp_Unsigned);
8363 else
8364 Ent := RTE (RE_Exp_Long_Long_Unsigned);
8365 end if;
8366
8367 Rewrite (N,
8368 Convert_To (Typ,
8369 Make_Op_And (Loc,
82b93248 8370 Left_Opnd =>
ee6ba406 8371 Make_Function_Call (Loc,
82b93248 8372 Name => New_Occurrence_Of (Ent, Loc),
ee6ba406 8373 Parameter_Associations => New_List (
8374 Convert_To (Etype (First_Formal (Ent)), Base),
8375 Exp)),
8376 Right_Opnd =>
8377 Make_Integer_Literal (Loc, Modulus (Rtyp) - 1))));
8378
8379 end if;
8380
8381 -- Common exit point for modular type case
8382
8383 Analyze_And_Resolve (N, Typ);
8384 return;
8385
9dfe12ae 8386 -- Signed integer cases, done using either Integer or Long_Long_Integer.
8387 -- It is not worth having routines for Short_[Short_]Integer, since for
8388 -- most machines it would not help, and it would generate more code that
ea150575 8389 -- might need certification when a certified run time is required.
ee6ba406 8390
9dfe12ae 8391 -- In the integer cases, we have two routines, one for when overflow
ea150575 8392 -- checks are required, and one when they are not required, since there
8393 -- is a real gain in omitting checks on many machines.
ee6ba406 8394
9dfe12ae 8395 elsif Rtyp = Base_Type (Standard_Long_Long_Integer)
8396 or else (Rtyp = Base_Type (Standard_Long_Integer)
cf04d13c 8397 and then
8398 Esize (Standard_Long_Integer) > Esize (Standard_Integer))
8399 or else Rtyp = Universal_Integer
ee6ba406 8400 then
9dfe12ae 8401 Etyp := Standard_Long_Long_Integer;
8402
111399d1 8403 if Ovflo then
ee6ba406 8404 Rent := RE_Exp_Long_Long_Integer;
8405 else
8406 Rent := RE_Exn_Long_Long_Integer;
8407 end if;
8408
9dfe12ae 8409 elsif Is_Signed_Integer_Type (Rtyp) then
8410 Etyp := Standard_Integer;
ee6ba406 8411
111399d1 8412 if Ovflo then
9dfe12ae 8413 Rent := RE_Exp_Integer;
ee6ba406 8414 else
9dfe12ae 8415 Rent := RE_Exn_Integer;
ee6ba406 8416 end if;
9dfe12ae 8417
23225afb 8418 -- Floating-point cases. We do not need separate routines for the
8419 -- overflow case here, since in the case of floating-point, we generate
8420 -- infinities anyway as a rule (either that or we automatically trap
8421 -- overflow), and if there is an infinity generated and a range check
8422 -- is required, the check will fail anyway.
8423
8424 -- Historical note: we used to convert everything to Long_Long_Float
8425 -- and call a single common routine, but this had the undesirable effect
8426 -- of giving different results for small static exponent values and the
8427 -- same dynamic values.
9dfe12ae 8428
8429 else
8430 pragma Assert (Is_Floating_Point_Type (Rtyp));
23225afb 8431
8432 if Rtyp = Standard_Float then
8433 Etyp := Standard_Float;
8434 Rent := RE_Exn_Float;
8435
8436 elsif Rtyp = Standard_Long_Float then
8437 Etyp := Standard_Long_Float;
8438 Rent := RE_Exn_Long_Float;
8439
8440 else
8441 Etyp := Standard_Long_Long_Float;
8442 Rent := RE_Exn_Long_Long_Float;
8443 end if;
ee6ba406 8444 end if;
8445
8446 -- Common processing for integer cases and floating-point cases.
9dfe12ae 8447 -- If we are in the right type, we can call runtime routine directly
ee6ba406 8448
9dfe12ae 8449 if Typ = Etyp
ee6ba406 8450 and then Rtyp /= Universal_Integer
8451 and then Rtyp /= Universal_Real
8452 then
8453 Rewrite (N,
23225afb 8454 Wrap_MA (
8455 Make_Function_Call (Loc,
8456 Name => New_Occurrence_Of (RTE (Rent), Loc),
8457 Parameter_Associations => New_List (Base, Exp))));
ee6ba406 8458
8459 -- Otherwise we have to introduce conversions (conversions are also
9dfe12ae 8460 -- required in the universal cases, since the runtime routine is
afd4ea71 8461 -- typed using one of the standard types).
ee6ba406 8462
8463 else
8464 Rewrite (N,
8465 Convert_To (Typ,
8466 Make_Function_Call (Loc,
83c6c069 8467 Name => New_Occurrence_Of (RTE (Rent), Loc),
ee6ba406 8468 Parameter_Associations => New_List (
9dfe12ae 8469 Convert_To (Etyp, Base),
ee6ba406 8470 Exp))));
8471 end if;
8472
8473 Analyze_And_Resolve (N, Typ);
8474 return;
8475
9dfe12ae 8476 exception
8477 when RE_Not_Available =>
8478 return;
ee6ba406 8479 end Expand_N_Op_Expon;
8480
8481 --------------------
8482 -- Expand_N_Op_Ge --
8483 --------------------
8484
8485 procedure Expand_N_Op_Ge (N : Node_Id) is
8486 Typ : constant Entity_Id := Etype (N);
8487 Op1 : constant Node_Id := Left_Opnd (N);
8488 Op2 : constant Node_Id := Right_Opnd (N);
8489 Typ1 : constant Entity_Id := Base_Type (Etype (Op1));
8490
8491 begin
8492 Binary_Op_Validity_Checks (N);
8493
d94b5da2 8494 -- Deal with overflow checks in MINIMIZED/ELIMINATED mode and if that
412f75eb 8495 -- means we no longer have a comparison operation, we are all done.
d94b5da2 8496
8497 Expand_Compare_Minimize_Eliminate_Overflow (N);
8498
8499 if Nkind (N) /= N_Op_Ge then
8500 return;
8501 end if;
8502
8503 -- Array type case
8504
38f5559f 8505 if Is_Array_Type (Typ1) then
ee6ba406 8506 Expand_Array_Comparison (N);
8507 return;
8508 end if;
8509
d94b5da2 8510 -- Deal with boolean operands
8511
ee6ba406 8512 if Is_Boolean_Type (Typ1) then
8513 Adjust_Condition (Op1);
8514 Adjust_Condition (Op2);
8515 Set_Etype (N, Standard_Boolean);
8516 Adjust_Result_Type (N, Typ);
8517 end if;
8518
8519 Rewrite_Comparison (N);
38f5559f 8520
4ecb1318 8521 Optimize_Length_Comparison (N);
ee6ba406 8522 end Expand_N_Op_Ge;
8523
8524 --------------------
8525 -- Expand_N_Op_Gt --
8526 --------------------
8527
8528 procedure Expand_N_Op_Gt (N : Node_Id) is
8529 Typ : constant Entity_Id := Etype (N);
8530 Op1 : constant Node_Id := Left_Opnd (N);
8531 Op2 : constant Node_Id := Right_Opnd (N);
8532 Typ1 : constant Entity_Id := Base_Type (Etype (Op1));
8533
8534 begin
8535 Binary_Op_Validity_Checks (N);
8536
d94b5da2 8537 -- Deal with overflow checks in MINIMIZED/ELIMINATED mode and if that
412f75eb 8538 -- means we no longer have a comparison operation, we are all done.
d94b5da2 8539
8540 Expand_Compare_Minimize_Eliminate_Overflow (N);
8541
8542 if Nkind (N) /= N_Op_Gt then
8543 return;
8544 end if;
8545
8546 -- Deal with array type operands
8547
38f5559f 8548 if Is_Array_Type (Typ1) then
ee6ba406 8549 Expand_Array_Comparison (N);
8550 return;
8551 end if;
8552
d94b5da2 8553 -- Deal with boolean type operands
8554
ee6ba406 8555 if Is_Boolean_Type (Typ1) then
8556 Adjust_Condition (Op1);
8557 Adjust_Condition (Op2);
8558 Set_Etype (N, Standard_Boolean);
8559 Adjust_Result_Type (N, Typ);
8560 end if;
8561
8562 Rewrite_Comparison (N);
38f5559f 8563
4ecb1318 8564 Optimize_Length_Comparison (N);
ee6ba406 8565 end Expand_N_Op_Gt;
8566
8567 --------------------
8568 -- Expand_N_Op_Le --
8569 --------------------
8570
8571 procedure Expand_N_Op_Le (N : Node_Id) is
8572 Typ : constant Entity_Id := Etype (N);
8573 Op1 : constant Node_Id := Left_Opnd (N);
8574 Op2 : constant Node_Id := Right_Opnd (N);
8575 Typ1 : constant Entity_Id := Base_Type (Etype (Op1));
8576
8577 begin
8578 Binary_Op_Validity_Checks (N);
8579
d94b5da2 8580 -- Deal with overflow checks in MINIMIZED/ELIMINATED mode and if that
412f75eb 8581 -- means we no longer have a comparison operation, we are all done.
d94b5da2 8582
8583 Expand_Compare_Minimize_Eliminate_Overflow (N);
8584
8585 if Nkind (N) /= N_Op_Le then
8586 return;
8587 end if;
8588
8589 -- Deal with array type operands
8590
38f5559f 8591 if Is_Array_Type (Typ1) then
ee6ba406 8592 Expand_Array_Comparison (N);
8593 return;
8594 end if;
8595
d94b5da2 8596 -- Deal with Boolean type operands
8597
ee6ba406 8598 if Is_Boolean_Type (Typ1) then
8599 Adjust_Condition (Op1);
8600 Adjust_Condition (Op2);
8601 Set_Etype (N, Standard_Boolean);
8602 Adjust_Result_Type (N, Typ);
8603 end if;
8604
8605 Rewrite_Comparison (N);
38f5559f 8606
4ecb1318 8607 Optimize_Length_Comparison (N);
ee6ba406 8608 end Expand_N_Op_Le;
8609
8610 --------------------
8611 -- Expand_N_Op_Lt --
8612 --------------------
8613
8614 procedure Expand_N_Op_Lt (N : Node_Id) is
8615 Typ : constant Entity_Id := Etype (N);
8616 Op1 : constant Node_Id := Left_Opnd (N);
8617 Op2 : constant Node_Id := Right_Opnd (N);
8618 Typ1 : constant Entity_Id := Base_Type (Etype (Op1));
8619
8620 begin
8621 Binary_Op_Validity_Checks (N);
8622
d94b5da2 8623 -- Deal with overflow checks in MINIMIZED/ELIMINATED mode and if that
412f75eb 8624 -- means we no longer have a comparison operation, we are all done.
d94b5da2 8625
8626 Expand_Compare_Minimize_Eliminate_Overflow (N);
8627
8628 if Nkind (N) /= N_Op_Lt then
8629 return;
8630 end if;
8631
8632 -- Deal with array type operands
8633
38f5559f 8634 if Is_Array_Type (Typ1) then
ee6ba406 8635 Expand_Array_Comparison (N);
8636 return;
8637 end if;
8638
d94b5da2 8639 -- Deal with Boolean type operands
8640
ee6ba406 8641 if Is_Boolean_Type (Typ1) then
8642 Adjust_Condition (Op1);
8643 Adjust_Condition (Op2);
8644 Set_Etype (N, Standard_Boolean);
8645 Adjust_Result_Type (N, Typ);
8646 end if;
8647
8648 Rewrite_Comparison (N);
38f5559f 8649
4ecb1318 8650 Optimize_Length_Comparison (N);
ee6ba406 8651 end Expand_N_Op_Lt;
8652
8653 -----------------------
8654 -- Expand_N_Op_Minus --
8655 -----------------------
8656
8657 procedure Expand_N_Op_Minus (N : Node_Id) is
8658 Loc : constant Source_Ptr := Sloc (N);
8659 Typ : constant Entity_Id := Etype (N);
8660
8661 begin
8662 Unary_Op_Validity_Checks (N);
8663
f32c377d 8664 -- Check for MINIMIZED/ELIMINATED overflow mode
8665
8666 if Minimized_Eliminated_Overflow_Check (N) then
8667 Apply_Arithmetic_Overflow_Check (N);
8668 return;
8669 end if;
8670
f15731c4 8671 if not Backend_Overflow_Checks_On_Target
ee6ba406 8672 and then Is_Signed_Integer_Type (Etype (N))
8673 and then Do_Overflow_Check (N)
8674 then
8675 -- Software overflow checking expands -expr into (0 - expr)
8676
8677 Rewrite (N,
8678 Make_Op_Subtract (Loc,
8679 Left_Opnd => Make_Integer_Literal (Loc, 0),
8680 Right_Opnd => Right_Opnd (N)));
8681
8682 Analyze_And_Resolve (N, Typ);
ee6ba406 8683 end if;
61b6f3d9 8684
2a801d20 8685 -- When generating C code, convert nonbinary modular minus into code
8686 -- that relies on the front-end expansion of operator Mod.
61b6f3d9 8687
8688 if Modify_Tree_For_C then
2a801d20 8689 Expand_Nonbinary_Modular_Op (N);
61b6f3d9 8690 end if;
ee6ba406 8691 end Expand_N_Op_Minus;
8692
8693 ---------------------
8694 -- Expand_N_Op_Mod --
8695 ---------------------
8696
8697 procedure Expand_N_Op_Mod (N : Node_Id) is
8698 Loc : constant Source_Ptr := Sloc (N);
9dfe12ae 8699 Typ : constant Entity_Id := Etype (N);
ee6ba406 8700 DDC : constant Boolean := Do_Division_Check (N);
8701
f32c377d 8702 Left : Node_Id;
8703 Right : Node_Id;
8704
ee6ba406 8705 LLB : Uint;
8706 Llo : Uint;
8707 Lhi : Uint;
8708 LOK : Boolean;
8709 Rlo : Uint;
8710 Rhi : Uint;
8711 ROK : Boolean;
8712
8f199ad0 8713 pragma Warnings (Off, Lhi);
8714
ee6ba406 8715 begin
8716 Binary_Op_Validity_Checks (N);
8717
f32c377d 8718 -- Check for MINIMIZED/ELIMINATED overflow mode
8719
8720 if Minimized_Eliminated_Overflow_Check (N) then
8721 Apply_Arithmetic_Overflow_Check (N);
8722 return;
8723 end if;
8724
a45d946f 8725 if Is_Integer_Type (Etype (N)) then
8726 Apply_Divide_Checks (N);
f32c377d 8727
8728 -- All done if we don't have a MOD any more, which can happen as a
8729 -- result of overflow expansion in MINIMIZED or ELIMINATED modes.
8730
8731 if Nkind (N) /= N_Op_Mod then
8732 return;
8733 end if;
a45d946f 8734 end if;
8735
f32c377d 8736 -- Proceed with expansion of mod operator
8737
8738 Left := Left_Opnd (N);
8739 Right := Right_Opnd (N);
8740
0549db8a 8741 Determine_Range (Right, ROK, Rlo, Rhi, Assume_Valid => True);
8742 Determine_Range (Left, LOK, Llo, Lhi, Assume_Valid => True);
ee6ba406 8743
34ebc386 8744 -- Convert mod to rem if operands are both known to be non-negative, or
8745 -- both known to be non-positive (these are the cases in which rem and
8746 -- mod are the same, see (RM 4.5.5(28-30)). We do this since it is quite
8747 -- likely that this will improve the quality of code, (the operation now
8748 -- corresponds to the hardware remainder), and it does not seem likely
8749 -- that it could be harmful. It also avoids some cases of the elaborate
8750 -- expansion in Modify_Tree_For_C mode below (since Ada rem = C %).
8751
8752 if (LOK and ROK)
8753 and then ((Llo >= 0 and then Rlo >= 0)
82b93248 8754 or else
34ebc386 8755 (Lhi <= 0 and then Rhi <= 0))
8756 then
ee6ba406 8757 Rewrite (N,
8758 Make_Op_Rem (Sloc (N),
8759 Left_Opnd => Left_Opnd (N),
8760 Right_Opnd => Right_Opnd (N)));
8761
f1e2dcc5 8762 -- Instead of reanalyzing the node we do the analysis manually. This
8763 -- avoids anomalies when the replacement is done in an instance and
8764 -- is epsilon more efficient.
ee6ba406 8765
8766 Set_Entity (N, Standard_Entity (S_Op_Rem));
9dfe12ae 8767 Set_Etype (N, Typ);
ee6ba406 8768 Set_Do_Division_Check (N, DDC);
8769 Expand_N_Op_Rem (N);
8770 Set_Analyzed (N);
34ebc386 8771 return;
ee6ba406 8772
8773 -- Otherwise, normal mod processing
8774
8775 else
9dfe12ae 8776 -- Apply optimization x mod 1 = 0. We don't really need that with
111399d1 8777 -- gcc, but it is useful with other back ends and is certainly
8778 -- harmless.
9dfe12ae 8779
8780 if Is_Integer_Type (Etype (N))
8781 and then Compile_Time_Known_Value (Right)
8782 and then Expr_Value (Right) = Uint_1
8783 then
f6f20e0e 8784 -- Call Remove_Side_Effects to ensure that any side effects in
8785 -- the ignored left operand (in particular function calls to
8786 -- user defined functions) are properly executed.
8787
8788 Remove_Side_Effects (Left);
8789
9dfe12ae 8790 Rewrite (N, Make_Integer_Literal (Loc, 0));
8791 Analyze_And_Resolve (N, Typ);
8792 return;
8793 end if;
8794
34ebc386 8795 -- If we still have a mod operator and we are in Modify_Tree_For_C
8796 -- mode, and we have a signed integer type, then here is where we do
8797 -- the rewrite in terms of Rem. Note this rewrite bypasses the need
8798 -- for the special handling of the annoying case of largest negative
8799 -- number mod minus one.
8800
8801 if Nkind (N) = N_Op_Mod
8802 and then Is_Signed_Integer_Type (Typ)
8803 and then Modify_Tree_For_C
8804 then
8805 -- In the general case, we expand A mod B as
8806
8807 -- Tnn : constant typ := A rem B;
8808 -- ..
8809 -- (if (A >= 0) = (B >= 0) then Tnn
8810 -- elsif Tnn = 0 then 0
8811 -- else Tnn + B)
8812
8813 -- The comparison can be written simply as A >= 0 if we know that
8814 -- B >= 0 which is a very common case.
8815
8816 -- An important optimization is when B is known at compile time
8817 -- to be 2**K for some constant. In this case we can simply AND
8818 -- the left operand with the bit string 2**K-1 (i.e. K 1-bits)
8819 -- and that works for both the positive and negative cases.
8820
8821 declare
8822 P2 : constant Nat := Power_Of_Two (Right);
8823
8824 begin
8825 if P2 /= 0 then
8826 Rewrite (N,
8827 Unchecked_Convert_To (Typ,
8828 Make_Op_And (Loc,
8829 Left_Opnd =>
8830 Unchecked_Convert_To
8831 (Corresponding_Unsigned_Type (Typ), Left),
8832 Right_Opnd =>
8833 Make_Integer_Literal (Loc, 2 ** P2 - 1))));
8834 Analyze_And_Resolve (N, Typ);
8835 return;
8836 end if;
8837 end;
8838
8839 -- Here for the full rewrite
8840
8841 declare
8842 Tnn : constant Entity_Id := Make_Temporary (Sloc (N), 'T', N);
8843 Cmp : Node_Id;
8844
8845 begin
8846 Cmp :=
8847 Make_Op_Ge (Loc,
8848 Left_Opnd => Duplicate_Subexpr_No_Checks (Left),
8849 Right_Opnd => Make_Integer_Literal (Loc, 0));
8850
8851 if not LOK or else Rlo < 0 then
8852 Cmp :=
8853 Make_Op_Eq (Loc,
8854 Left_Opnd => Cmp,
8855 Right_Opnd =>
8856 Make_Op_Ge (Loc,
8857 Left_Opnd => Duplicate_Subexpr_No_Checks (Right),
8858 Right_Opnd => Make_Integer_Literal (Loc, 0)));
8859 end if;
8860
8861 Insert_Action (N,
8862 Make_Object_Declaration (Loc,
8863 Defining_Identifier => Tnn,
8864 Constant_Present => True,
8865 Object_Definition => New_Occurrence_Of (Typ, Loc),
8866 Expression =>
8867 Make_Op_Rem (Loc,
8868 Left_Opnd => Left,
8869 Right_Opnd => Right)));
8870
8871 Rewrite (N,
8872 Make_If_Expression (Loc,
8873 Expressions => New_List (
8874 Cmp,
8875 New_Occurrence_Of (Tnn, Loc),
8876 Make_If_Expression (Loc,
8877 Is_Elsif => True,
8878 Expressions => New_List (
8879 Make_Op_Eq (Loc,
8880 Left_Opnd => New_Occurrence_Of (Tnn, Loc),
8881 Right_Opnd => Make_Integer_Literal (Loc, 0)),
8882 Make_Integer_Literal (Loc, 0),
8883 Make_Op_Add (Loc,
8884 Left_Opnd => New_Occurrence_Of (Tnn, Loc),
8885 Right_Opnd =>
8886 Duplicate_Subexpr_No_Checks (Right)))))));
8887
8888 Analyze_And_Resolve (N, Typ);
8889 return;
8890 end;
8891 end if;
8892
8893 -- Deal with annoying case of largest negative number mod minus one.
8894 -- Gigi may not handle this case correctly, because on some targets,
8895 -- the mod value is computed using a divide instruction which gives
8896 -- an overflow trap for this case.
c6431a40 8897
8898 -- It would be a bit more efficient to figure out which targets
8899 -- this is really needed for, but in practice it is reasonable
8900 -- to do the following special check in all cases, since it means
8901 -- we get a clearer message, and also the overhead is minimal given
8902 -- that division is expensive in any case.
ee6ba406 8903
f1e2dcc5 8904 -- In fact the check is quite easy, if the right operand is -1, then
8905 -- the mod value is always 0, and we can just ignore the left operand
8906 -- completely in this case.
ee6ba406 8907
a45d946f 8908 -- This only applies if we still have a mod operator. Skip if we
8909 -- have already rewritten this (e.g. in the case of eliminated
8910 -- overflow checks which have driven us into bignum mode).
9dfe12ae 8911
a45d946f 8912 if Nkind (N) = N_Op_Mod then
ee6ba406 8913
a45d946f 8914 -- The operand type may be private (e.g. in the expansion of an
8915 -- intrinsic operation) so we must use the underlying type to get
8916 -- the bounds, and convert the literals explicitly.
ee6ba406 8917
a45d946f 8918 LLB :=
8919 Expr_Value
8920 (Type_Low_Bound (Base_Type (Underlying_Type (Etype (Left)))));
8921
8922 if ((not ROK) or else (Rlo <= (-1) and then (-1) <= Rhi))
cf04d13c 8923 and then ((not LOK) or else (Llo = LLB))
a45d946f 8924 then
8925 Rewrite (N,
92f1631f 8926 Make_If_Expression (Loc,
a45d946f 8927 Expressions => New_List (
8928 Make_Op_Eq (Loc,
8929 Left_Opnd => Duplicate_Subexpr (Right),
8930 Right_Opnd =>
8931 Unchecked_Convert_To (Typ,
8932 Make_Integer_Literal (Loc, -1))),
8933 Unchecked_Convert_To (Typ,
8934 Make_Integer_Literal (Loc, Uint_0)),
8935 Relocate_Node (N))));
8936
8937 Set_Analyzed (Next (Next (First (Expressions (N)))));
8938 Analyze_And_Resolve (N, Typ);
8939 end if;
ee6ba406 8940 end if;
8941 end if;
8942 end Expand_N_Op_Mod;
8943
8944 --------------------------
8945 -- Expand_N_Op_Multiply --
8946 --------------------------
8947
8948 procedure Expand_N_Op_Multiply (N : Node_Id) is
f6f20e0e 8949 Loc : constant Source_Ptr := Sloc (N);
8950 Lop : constant Node_Id := Left_Opnd (N);
8951 Rop : constant Node_Id := Right_Opnd (N);
9dfe12ae 8952
f6f20e0e 8953 Lp2 : constant Boolean :=
6f0d10f7 8954 Nkind (Lop) = N_Op_Expon and then Is_Power_Of_2_For_Shift (Lop);
f6f20e0e 8955 Rp2 : constant Boolean :=
6f0d10f7 8956 Nkind (Rop) = N_Op_Expon and then Is_Power_Of_2_For_Shift (Rop);
9dfe12ae 8957
ee6ba406 8958 Ltyp : constant Entity_Id := Etype (Lop);
8959 Rtyp : constant Entity_Id := Etype (Rop);
8960 Typ : Entity_Id := Etype (N);
8961
8962 begin
8963 Binary_Op_Validity_Checks (N);
8964
f32c377d 8965 -- Check for MINIMIZED/ELIMINATED overflow mode
8966
8967 if Minimized_Eliminated_Overflow_Check (N) then
8968 Apply_Arithmetic_Overflow_Check (N);
8969 return;
8970 end if;
8971
ee6ba406 8972 -- Special optimizations for integer types
8973
8974 if Is_Integer_Type (Typ) then
8975
f6f20e0e 8976 -- N * 0 = 0 for integer types
ee6ba406 8977
f6f20e0e 8978 if Compile_Time_Known_Value (Rop)
8979 and then Expr_Value (Rop) = Uint_0
ee6ba406 8980 then
f6f20e0e 8981 -- Call Remove_Side_Effects to ensure that any side effects in
8982 -- the ignored left operand (in particular function calls to
8983 -- user defined functions) are properly executed.
8984
8985 Remove_Side_Effects (Lop);
8986
8987 Rewrite (N, Make_Integer_Literal (Loc, Uint_0));
8988 Analyze_And_Resolve (N, Typ);
8989 return;
8990 end if;
8991
8992 -- Similar handling for 0 * N = 0
8993
8994 if Compile_Time_Known_Value (Lop)
8995 and then Expr_Value (Lop) = Uint_0
8996 then
8997 Remove_Side_Effects (Rop);
ee6ba406 8998 Rewrite (N, Make_Integer_Literal (Loc, Uint_0));
8999 Analyze_And_Resolve (N, Typ);
9000 return;
9001 end if;
9002
9003 -- N * 1 = 1 * N = N for integer types
9004
9dfe12ae 9005 -- This optimisation is not done if we are going to
9006 -- rewrite the product 1 * 2 ** N to a shift.
9007
9008 if Compile_Time_Known_Value (Rop)
9009 and then Expr_Value (Rop) = Uint_1
9010 and then not Lp2
ee6ba406 9011 then
9dfe12ae 9012 Rewrite (N, Lop);
ee6ba406 9013 return;
9014
9dfe12ae 9015 elsif Compile_Time_Known_Value (Lop)
9016 and then Expr_Value (Lop) = Uint_1
9017 and then not Rp2
ee6ba406 9018 then
9dfe12ae 9019 Rewrite (N, Rop);
ee6ba406 9020 return;
9021 end if;
9022 end if;
9023
ee6ba406 9024 -- Convert x * 2 ** y to Shift_Left (x, y). Note that the fact that
9025 -- Is_Power_Of_2_For_Shift is set means that we know that our left
9026 -- operand is an integer, as required for this to work.
9027
9dfe12ae 9028 if Rp2 then
9029 if Lp2 then
ee6ba406 9030
9dfe12ae 9031 -- Convert 2 ** A * 2 ** B into 2 ** (A + B)
ee6ba406 9032
9033 Rewrite (N,
9034 Make_Op_Expon (Loc,
9035 Left_Opnd => Make_Integer_Literal (Loc, 2),
9036 Right_Opnd =>
9037 Make_Op_Add (Loc,
9038 Left_Opnd => Right_Opnd (Lop),
9039 Right_Opnd => Right_Opnd (Rop))));
9040 Analyze_And_Resolve (N, Typ);
9041 return;
9042
9043 else
da94c58f 9044 -- If the result is modular, perform the reduction of the result
9045 -- appropriately.
9046
9047 if Is_Modular_Integer_Type (Typ)
9048 and then not Non_Binary_Modulus (Typ)
9049 then
9050 Rewrite (N,
e5e512c5 9051 Make_Op_And (Loc,
9052 Left_Opnd =>
9053 Make_Op_Shift_Left (Loc,
9054 Left_Opnd => Lop,
9055 Right_Opnd =>
9056 Convert_To (Standard_Natural, Right_Opnd (Rop))),
9057 Right_Opnd =>
da94c58f 9058 Make_Integer_Literal (Loc, Modulus (Typ) - 1)));
e5e512c5 9059
da94c58f 9060 else
9061 Rewrite (N,
9062 Make_Op_Shift_Left (Loc,
9063 Left_Opnd => Lop,
9064 Right_Opnd =>
9065 Convert_To (Standard_Natural, Right_Opnd (Rop))));
9066 end if;
9067
ee6ba406 9068 Analyze_And_Resolve (N, Typ);
9069 return;
9070 end if;
9071
9072 -- Same processing for the operands the other way round
9073
9dfe12ae 9074 elsif Lp2 then
da94c58f 9075 if Is_Modular_Integer_Type (Typ)
9076 and then not Non_Binary_Modulus (Typ)
9077 then
9078 Rewrite (N,
e5e512c5 9079 Make_Op_And (Loc,
9080 Left_Opnd =>
9081 Make_Op_Shift_Left (Loc,
9082 Left_Opnd => Rop,
9083 Right_Opnd =>
9084 Convert_To (Standard_Natural, Right_Opnd (Lop))),
9085 Right_Opnd =>
9086 Make_Integer_Literal (Loc, Modulus (Typ) - 1)));
9087
da94c58f 9088 else
9089 Rewrite (N,
9090 Make_Op_Shift_Left (Loc,
9091 Left_Opnd => Rop,
9092 Right_Opnd =>
9093 Convert_To (Standard_Natural, Right_Opnd (Lop))));
9094 end if;
9095
ee6ba406 9096 Analyze_And_Resolve (N, Typ);
9097 return;
9098 end if;
9099
9100 -- Do required fixup of universal fixed operation
9101
9102 if Typ = Universal_Fixed then
9103 Fixup_Universal_Fixed_Operation (N);
9104 Typ := Etype (N);
9105 end if;
9106
9107 -- Multiplications with fixed-point results
9108
9109 if Is_Fixed_Point_Type (Typ) then
9110
f1e2dcc5 9111 -- No special processing if Treat_Fixed_As_Integer is set, since from
9112 -- a semantic point of view such operations are simply integer
9113 -- operations and will be treated that way.
ee6ba406 9114
9115 if not Treat_Fixed_As_Integer (N) then
9116
9117 -- Case of fixed * integer => fixed
9118
9119 if Is_Integer_Type (Rtyp) then
9120 Expand_Multiply_Fixed_By_Integer_Giving_Fixed (N);
9121
9122 -- Case of integer * fixed => fixed
9123
9124 elsif Is_Integer_Type (Ltyp) then
9125 Expand_Multiply_Integer_By_Fixed_Giving_Fixed (N);
9126
9127 -- Case of fixed * fixed => fixed
9128
9129 else
9130 Expand_Multiply_Fixed_By_Fixed_Giving_Fixed (N);
9131 end if;
9132 end if;
9133
f1e2dcc5 9134 -- Other cases of multiplication of fixed-point operands. Again we
9135 -- exclude the cases where Treat_Fixed_As_Integer flag is set.
ee6ba406 9136
9137 elsif (Is_Fixed_Point_Type (Ltyp) or else Is_Fixed_Point_Type (Rtyp))
9138 and then not Treat_Fixed_As_Integer (N)
9139 then
9140 if Is_Integer_Type (Typ) then
9141 Expand_Multiply_Fixed_By_Fixed_Giving_Integer (N);
9142 else
9143 pragma Assert (Is_Floating_Point_Type (Typ));
9144 Expand_Multiply_Fixed_By_Fixed_Giving_Float (N);
9145 end if;
9146
f1e2dcc5 9147 -- Mixed-mode operations can appear in a non-static universal context,
9148 -- in which case the integer argument must be converted explicitly.
ee6ba406 9149
6f0d10f7 9150 elsif Typ = Universal_Real and then Is_Integer_Type (Rtyp) then
ee6ba406 9151 Rewrite (Rop, Convert_To (Universal_Real, Relocate_Node (Rop)));
ee6ba406 9152 Analyze_And_Resolve (Rop, Universal_Real);
9153
6f0d10f7 9154 elsif Typ = Universal_Real and then Is_Integer_Type (Ltyp) then
ee6ba406 9155 Rewrite (Lop, Convert_To (Universal_Real, Relocate_Node (Lop)));
ee6ba406 9156 Analyze_And_Resolve (Lop, Universal_Real);
9157
9158 -- Non-fixed point cases, check software overflow checking required
9159
9160 elsif Is_Signed_Integer_Type (Etype (N)) then
9161 Apply_Arithmetic_Overflow_Check (N);
9162 end if;
54d549ff 9163
9164 -- Overflow checks for floating-point if -gnateF mode active
9165
9166 Check_Float_Op_Overflow (N);
61b6f3d9 9167
2a801d20 9168 -- When generating C code, convert nonbinary modular multiplications
9169 -- into code that relies on the front-end expansion of operator Mod.
61b6f3d9 9170
9171 if Modify_Tree_For_C then
2a801d20 9172 Expand_Nonbinary_Modular_Op (N);
61b6f3d9 9173 end if;
ee6ba406 9174 end Expand_N_Op_Multiply;
9175
9176 --------------------
9177 -- Expand_N_Op_Ne --
9178 --------------------
9179
ee6ba406 9180 procedure Expand_N_Op_Ne (N : Node_Id) is
38f5559f 9181 Typ : constant Entity_Id := Etype (Left_Opnd (N));
ee6ba406 9182
9183 begin
38f5559f 9184 -- Case of elementary type with standard operator
ee6ba406 9185
38f5559f 9186 if Is_Elementary_Type (Typ)
9187 and then Sloc (Entity (N)) = Standard_Location
9188 then
9189 Binary_Op_Validity_Checks (N);
ee6ba406 9190
d94b5da2 9191 -- Deal with overflow checks in MINIMIZED/ELIMINATED mode and if
412f75eb 9192 -- means we no longer have a /= operation, we are all done.
d94b5da2 9193
9194 Expand_Compare_Minimize_Eliminate_Overflow (N);
9195
9196 if Nkind (N) /= N_Op_Ne then
9197 return;
9198 end if;
9199
38f5559f 9200 -- Boolean types (requiring handling of non-standard case)
ee6ba406 9201
38f5559f 9202 if Is_Boolean_Type (Typ) then
9203 Adjust_Condition (Left_Opnd (N));
9204 Adjust_Condition (Right_Opnd (N));
9205 Set_Etype (N, Standard_Boolean);
9206 Adjust_Result_Type (N, Typ);
9207 end if;
9dfe12ae 9208
38f5559f 9209 Rewrite_Comparison (N);
9210
38f5559f 9211 -- For all cases other than elementary types, we rewrite node as the
9212 -- negation of an equality operation, and reanalyze. The equality to be
9213 -- used is defined in the same scope and has the same signature. This
9214 -- signature must be set explicitly since in an instance it may not have
9215 -- the same visibility as in the generic unit. This avoids duplicating
9216 -- or factoring the complex code for record/array equality tests etc.
9217
a63a0aad 9218 -- This case is also used for the minimal expansion performed in
9219 -- GNATprove mode.
9220
38f5559f 9221 else
9222 declare
9223 Loc : constant Source_Ptr := Sloc (N);
9224 Neg : Node_Id;
9225 Ne : constant Entity_Id := Entity (N);
9226
9227 begin
9228 Binary_Op_Validity_Checks (N);
9229
9230 Neg :=
9231 Make_Op_Not (Loc,
9232 Right_Opnd =>
9233 Make_Op_Eq (Loc,
9234 Left_Opnd => Left_Opnd (N),
9235 Right_Opnd => Right_Opnd (N)));
a63a0aad 9236
9237 -- The level of parentheses is useless in GNATprove mode, and
9238 -- bumping its level here leads to wrong columns being used in
9239 -- check messages, hence skip it in this mode.
9240
9241 if not GNATprove_Mode then
9242 Set_Paren_Count (Right_Opnd (Neg), 1);
9243 end if;
38f5559f 9244
9245 if Scope (Ne) /= Standard_Standard then
9246 Set_Entity (Right_Opnd (Neg), Corresponding_Equality (Ne));
9247 end if;
9248
fe639c68 9249 -- For navigation purposes, we want to treat the inequality as an
38f5559f 9250 -- implicit reference to the corresponding equality. Preserve the
fe639c68 9251 -- Comes_From_ source flag to generate proper Xref entries.
38f5559f 9252
9253 Preserve_Comes_From_Source (Neg, N);
9254 Preserve_Comes_From_Source (Right_Opnd (Neg), N);
9255 Rewrite (N, Neg);
9256 Analyze_And_Resolve (N, Standard_Boolean);
9257 end;
9258 end if;
4ecb1318 9259
a63a0aad 9260 -- No need for optimization in GNATprove mode, where we would rather see
9261 -- the original source expression.
9262
9263 if not GNATprove_Mode then
9264 Optimize_Length_Comparison (N);
9265 end if;
ee6ba406 9266 end Expand_N_Op_Ne;
9267
9268 ---------------------
9269 -- Expand_N_Op_Not --
9270 ---------------------
9271
f1e2dcc5 9272 -- If the argument is other than a Boolean array type, there is no special
e9b26a1d 9273 -- expansion required, except for dealing with validity checks, and non-
9274 -- standard boolean representations.
ee6ba406 9275
e9b26a1d 9276 -- For the packed array case, we call the special routine in Exp_Pakd,
9277 -- except that if the component size is greater than one, we use the
9278 -- standard routine generating a gruesome loop (it is so peculiar to have
9279 -- packed arrays with non-standard Boolean representations anyway, so it
9280 -- does not matter that we do not handle this case efficiently).
ee6ba406 9281
e9b26a1d 9282 -- For the unpacked array case (and for the special packed case where we
9283 -- have non standard Booleans, as discussed above), we generate and insert
9284 -- into the tree the following function definition:
ee6ba406 9285
9286 -- function Nnnn (A : arr) is
9287 -- B : arr;
9288 -- begin
9289 -- for J in a'range loop
9290 -- B (J) := not A (J);
9291 -- end loop;
9292 -- return B;
9293 -- end Nnnn;
9294
9295 -- Here arr is the actual subtype of the parameter (and hence always
9296 -- constrained). Then we replace the not with a call to this function.
9297
9298 procedure Expand_N_Op_Not (N : Node_Id) is
9299 Loc : constant Source_Ptr := Sloc (N);
9300 Typ : constant Entity_Id := Etype (N);
9301 Opnd : Node_Id;
9302 Arr : Entity_Id;
9303 A : Entity_Id;
9304 B : Entity_Id;
9305 J : Entity_Id;
9306 A_J : Node_Id;
9307 B_J : Node_Id;
9308
9309 Func_Name : Entity_Id;
9310 Loop_Statement : Node_Id;
9311
9312 begin
9313 Unary_Op_Validity_Checks (N);
9314
9315 -- For boolean operand, deal with non-standard booleans
9316
9317 if Is_Boolean_Type (Typ) then
9318 Adjust_Condition (Right_Opnd (N));
9319 Set_Etype (N, Standard_Boolean);
9320 Adjust_Result_Type (N, Typ);
9321 return;
9322 end if;
9323
b6242b97 9324 -- Only array types need any other processing
ee6ba406 9325
b6242b97 9326 if not Is_Array_Type (Typ) then
ee6ba406 9327 return;
9328 end if;
9329
4660e715 9330 -- Case of array operand. If bit packed with a component size of 1,
9331 -- handle it in Exp_Pakd if the operand is known to be aligned.
ee6ba406 9332
4660e715 9333 if Is_Bit_Packed_Array (Typ)
9334 and then Component_Size (Typ) = 1
9335 and then not Is_Possibly_Unaligned_Object (Right_Opnd (N))
9336 then
ee6ba406 9337 Expand_Packed_Not (N);
9338 return;
9339 end if;
9340
9dfe12ae 9341 -- Case of array operand which is not bit-packed. If the context is
9342 -- a safe assignment, call in-place operation, If context is a larger
9343 -- boolean expression in the context of a safe assignment, expansion is
9344 -- done by enclosing operation.
ee6ba406 9345
9346 Opnd := Relocate_Node (Right_Opnd (N));
9347 Convert_To_Actual_Subtype (Opnd);
9348 Arr := Etype (Opnd);
9349 Ensure_Defined (Arr, N);
40a5a4cb 9350 Silly_Boolean_Array_Not_Test (N, Arr);
ee6ba406 9351
9dfe12ae 9352 if Nkind (Parent (N)) = N_Assignment_Statement then
9353 if Safe_In_Place_Array_Op (Name (Parent (N)), N, Empty) then
9354 Build_Boolean_Array_Proc_Call (Parent (N), Opnd, Empty);
9355 return;
9356
f84d3d59 9357 -- Special case the negation of a binary operation
9dfe12ae 9358
1627db8a 9359 elsif Nkind_In (Opnd, N_Op_And, N_Op_Or, N_Op_Xor)
9dfe12ae 9360 and then Safe_In_Place_Array_Op
1627db8a 9361 (Name (Parent (N)), Left_Opnd (Opnd), Right_Opnd (Opnd))
9dfe12ae 9362 then
9363 Build_Boolean_Array_Proc_Call (Parent (N), Opnd, Empty);
9364 return;
9365 end if;
9366
9367 elsif Nkind (Parent (N)) in N_Binary_Op
9368 and then Nkind (Parent (Parent (N))) = N_Assignment_Statement
9369 then
9370 declare
9371 Op1 : constant Node_Id := Left_Opnd (Parent (N));
9372 Op2 : constant Node_Id := Right_Opnd (Parent (N));
9373 Lhs : constant Node_Id := Name (Parent (Parent (N)));
9374
9375 begin
9376 if Safe_In_Place_Array_Op (Lhs, Op1, Op2) then
9dfe12ae 9377
f5fbfaa6 9378 -- (not A) op (not B) can be reduced to a single call
9379
9380 if N = Op1 and then Nkind (Op2) = N_Op_Not then
9dfe12ae 9381 return;
9382
f235fede 9383 elsif N = Op2 and then Nkind (Op1) = N_Op_Not then
9384 return;
9385
f5fbfaa6 9386 -- A xor (not B) can also be special-cased
9dfe12ae 9387
f5fbfaa6 9388 elsif N = Op2 and then Nkind (Parent (N)) = N_Op_Xor then
9dfe12ae 9389 return;
9390 end if;
9391 end if;
9392 end;
9393 end if;
9394
ee6ba406 9395 A := Make_Defining_Identifier (Loc, Name_uA);
9396 B := Make_Defining_Identifier (Loc, Name_uB);
9397 J := Make_Defining_Identifier (Loc, Name_uJ);
9398
9399 A_J :=
9400 Make_Indexed_Component (Loc,
83c6c069 9401 Prefix => New_Occurrence_Of (A, Loc),
9402 Expressions => New_List (New_Occurrence_Of (J, Loc)));
ee6ba406 9403
9404 B_J :=
9405 Make_Indexed_Component (Loc,
83c6c069 9406 Prefix => New_Occurrence_Of (B, Loc),
9407 Expressions => New_List (New_Occurrence_Of (J, Loc)));
ee6ba406 9408
9409 Loop_Statement :=
9410 Make_Implicit_Loop_Statement (N,
9411 Identifier => Empty,
9412
9413 Iteration_Scheme =>
9414 Make_Iteration_Scheme (Loc,
9415 Loop_Parameter_Specification =>
9416 Make_Loop_Parameter_Specification (Loc,
64427fe6 9417 Defining_Identifier => J,
ee6ba406 9418 Discrete_Subtype_Definition =>
9419 Make_Attribute_Reference (Loc,
64427fe6 9420 Prefix => Make_Identifier (Loc, Chars (A)),
ee6ba406 9421 Attribute_Name => Name_Range))),
9422
9423 Statements => New_List (
9424 Make_Assignment_Statement (Loc,
9425 Name => B_J,
9426 Expression => Make_Op_Not (Loc, A_J))));
9427
46eb6933 9428 Func_Name := Make_Temporary (Loc, 'N');
ee6ba406 9429 Set_Is_Inlined (Func_Name);
9430
9431 Insert_Action (N,
9432 Make_Subprogram_Body (Loc,
9433 Specification =>
9434 Make_Function_Specification (Loc,
9435 Defining_Unit_Name => Func_Name,
9436 Parameter_Specifications => New_List (
9437 Make_Parameter_Specification (Loc,
9438 Defining_Identifier => A,
83c6c069 9439 Parameter_Type => New_Occurrence_Of (Typ, Loc))),
9440 Result_Definition => New_Occurrence_Of (Typ, Loc)),
ee6ba406 9441
9442 Declarations => New_List (
9443 Make_Object_Declaration (Loc,
9444 Defining_Identifier => B,
83c6c069 9445 Object_Definition => New_Occurrence_Of (Arr, Loc))),
ee6ba406 9446
9447 Handled_Statement_Sequence =>
9448 Make_Handled_Sequence_Of_Statements (Loc,
9449 Statements => New_List (
9450 Loop_Statement,
a3e461ac 9451 Make_Simple_Return_Statement (Loc,
64427fe6 9452 Expression => Make_Identifier (Loc, Chars (B)))))));
ee6ba406 9453
9454 Rewrite (N,
9455 Make_Function_Call (Loc,
83c6c069 9456 Name => New_Occurrence_Of (Func_Name, Loc),
ee6ba406 9457 Parameter_Associations => New_List (Opnd)));
9458
9459 Analyze_And_Resolve (N, Typ);
9460 end Expand_N_Op_Not;
9461
9462 --------------------
9463 -- Expand_N_Op_Or --
9464 --------------------
9465
9466 procedure Expand_N_Op_Or (N : Node_Id) is
9467 Typ : constant Entity_Id := Etype (N);
9468
9469 begin
9470 Binary_Op_Validity_Checks (N);
9471
9472 if Is_Array_Type (Etype (N)) then
9473 Expand_Boolean_Operator (N);
9474
9475 elsif Is_Boolean_Type (Etype (N)) then
0033d60c 9476 Adjust_Condition (Left_Opnd (N));
9477 Adjust_Condition (Right_Opnd (N));
9478 Set_Etype (N, Standard_Boolean);
9479 Adjust_Result_Type (N, Typ);
9f294c82 9480
9481 elsif Is_Intrinsic_Subprogram (Entity (N)) then
9482 Expand_Intrinsic_Call (N, Entity (N));
61b6f3d9 9483 end if;
9484
2a801d20 9485 -- When generating C code, convert nonbinary modular operators into code
9486 -- that relies on the front-end expansion of operator Mod.
9f294c82 9487
61b6f3d9 9488 if Modify_Tree_For_C then
2a801d20 9489 Expand_Nonbinary_Modular_Op (N);
ee6ba406 9490 end if;
9491 end Expand_N_Op_Or;
9492
9493 ----------------------
9494 -- Expand_N_Op_Plus --
9495 ----------------------
9496
9497 procedure Expand_N_Op_Plus (N : Node_Id) is
9498 begin
9499 Unary_Op_Validity_Checks (N);
f32c377d 9500
9501 -- Check for MINIMIZED/ELIMINATED overflow mode
9502
9503 if Minimized_Eliminated_Overflow_Check (N) then
9504 Apply_Arithmetic_Overflow_Check (N);
9505 return;
9506 end if;
ee6ba406 9507 end Expand_N_Op_Plus;
9508
9509 ---------------------
9510 -- Expand_N_Op_Rem --
9511 ---------------------
9512
9513 procedure Expand_N_Op_Rem (N : Node_Id) is
9514 Loc : constant Source_Ptr := Sloc (N);
9dfe12ae 9515 Typ : constant Entity_Id := Etype (N);
ee6ba406 9516
f32c377d 9517 Left : Node_Id;
9518 Right : Node_Id;
ee6ba406 9519
0549db8a 9520 Lo : Uint;
9521 Hi : Uint;
9522 OK : Boolean;
ee6ba406 9523
0549db8a 9524 Lneg : Boolean;
9525 Rneg : Boolean;
9526 -- Set if corresponding operand can be negative
9527
9528 pragma Unreferenced (Hi);
8f199ad0 9529
ee6ba406 9530 begin
9531 Binary_Op_Validity_Checks (N);
9532
f32c377d 9533 -- Check for MINIMIZED/ELIMINATED overflow mode
9534
9535 if Minimized_Eliminated_Overflow_Check (N) then
9536 Apply_Arithmetic_Overflow_Check (N);
9537 return;
9538 end if;
9539
ee6ba406 9540 if Is_Integer_Type (Etype (N)) then
2fe22c69 9541 Apply_Divide_Checks (N);
f32c377d 9542
9543 -- All done if we don't have a REM any more, which can happen as a
9544 -- result of overflow expansion in MINIMIZED or ELIMINATED modes.
9545
9546 if Nkind (N) /= N_Op_Rem then
9547 return;
9548 end if;
ee6ba406 9549 end if;
9550
f32c377d 9551 -- Proceed with expansion of REM
9552
9553 Left := Left_Opnd (N);
9554 Right := Right_Opnd (N);
9555
f1e2dcc5 9556 -- Apply optimization x rem 1 = 0. We don't really need that with gcc,
111399d1 9557 -- but it is useful with other back ends, and is certainly harmless.
9dfe12ae 9558
9559 if Is_Integer_Type (Etype (N))
9560 and then Compile_Time_Known_Value (Right)
9561 and then Expr_Value (Right) = Uint_1
9562 then
f6f20e0e 9563 -- Call Remove_Side_Effects to ensure that any side effects in the
9564 -- ignored left operand (in particular function calls to user defined
9565 -- functions) are properly executed.
9566
9567 Remove_Side_Effects (Left);
9568
9dfe12ae 9569 Rewrite (N, Make_Integer_Literal (Loc, 0));
9570 Analyze_And_Resolve (N, Typ);
9571 return;
9572 end if;
9573
f1e2dcc5 9574 -- Deal with annoying case of largest negative number remainder minus
c6431a40 9575 -- one. Gigi may not handle this case correctly, because on some
9576 -- targets, the mod value is computed using a divide instruction
9577 -- which gives an overflow trap for this case.
9578
9579 -- It would be a bit more efficient to figure out which targets this
9580 -- is really needed for, but in practice it is reasonable to do the
9581 -- following special check in all cases, since it means we get a clearer
9582 -- message, and also the overhead is minimal given that division is
9583 -- expensive in any case.
ee6ba406 9584
f1e2dcc5 9585 -- In fact the check is quite easy, if the right operand is -1, then
9586 -- the remainder is always 0, and we can just ignore the left operand
9587 -- completely in this case.
ee6ba406 9588
0549db8a 9589 Determine_Range (Right, OK, Lo, Hi, Assume_Valid => True);
9590 Lneg := (not OK) or else Lo < 0;
9dfe12ae 9591
0549db8a 9592 Determine_Range (Left, OK, Lo, Hi, Assume_Valid => True);
9593 Rneg := (not OK) or else Lo < 0;
9dfe12ae 9594
0549db8a 9595 -- We won't mess with trying to find out if the left operand can really
9596 -- be the largest negative number (that's a pain in the case of private
9597 -- types and this is really marginal). We will just assume that we need
9598 -- the test if the left operand can be negative at all.
9dfe12ae 9599
0549db8a 9600 if Lneg and Rneg then
ee6ba406 9601 Rewrite (N,
92f1631f 9602 Make_If_Expression (Loc,
ee6ba406 9603 Expressions => New_List (
9604 Make_Op_Eq (Loc,
64427fe6 9605 Left_Opnd => Duplicate_Subexpr (Right),
ee6ba406 9606 Right_Opnd =>
64427fe6 9607 Unchecked_Convert_To (Typ, Make_Integer_Literal (Loc, -1))),
ee6ba406 9608
9dfe12ae 9609 Unchecked_Convert_To (Typ,
9610 Make_Integer_Literal (Loc, Uint_0)),
ee6ba406 9611
9612 Relocate_Node (N))));
9613
9614 Set_Analyzed (Next (Next (First (Expressions (N)))));
9615 Analyze_And_Resolve (N, Typ);
9616 end if;
9617 end Expand_N_Op_Rem;
9618
9619 -----------------------------
9620 -- Expand_N_Op_Rotate_Left --
9621 -----------------------------
9622
9623 procedure Expand_N_Op_Rotate_Left (N : Node_Id) is
9624 begin
9625 Binary_Op_Validity_Checks (N);
5542710d 9626
9627 -- If we are in Modify_Tree_For_C mode, there is no rotate left in C,
9628 -- so we rewrite in terms of logical shifts
9629
9630 -- Shift_Left (Num, Bits) or Shift_Right (num, Esize - Bits)
9631
9632 -- where Bits is the shift count mod Esize (the mod operation here
9633 -- deals with ludicrous large shift counts, which are apparently OK).
9634
09ae61a2 9635 -- What about nonbinary modulus ???
5542710d 9636
9637 declare
9638 Loc : constant Source_Ptr := Sloc (N);
9639 Rtp : constant Entity_Id := Etype (Right_Opnd (N));
9640 Typ : constant Entity_Id := Etype (N);
9641
9642 begin
9643 if Modify_Tree_For_C then
9644 Rewrite (Right_Opnd (N),
9645 Make_Op_Rem (Loc,
9646 Left_Opnd => Relocate_Node (Right_Opnd (N)),
9647 Right_Opnd => Make_Integer_Literal (Loc, Esize (Typ))));
9648
9649 Analyze_And_Resolve (Right_Opnd (N), Rtp);
9650
9651 Rewrite (N,
9652 Make_Op_Or (Loc,
9653 Left_Opnd =>
9654 Make_Op_Shift_Left (Loc,
9655 Left_Opnd => Left_Opnd (N),
9656 Right_Opnd => Right_Opnd (N)),
84004385 9657
5542710d 9658 Right_Opnd =>
9659 Make_Op_Shift_Right (Loc,
9660 Left_Opnd => Duplicate_Subexpr_No_Checks (Left_Opnd (N)),
9661 Right_Opnd =>
9662 Make_Op_Subtract (Loc,
9663 Left_Opnd => Make_Integer_Literal (Loc, Esize (Typ)),
9664 Right_Opnd =>
9665 Duplicate_Subexpr_No_Checks (Right_Opnd (N))))));
9666
9667 Analyze_And_Resolve (N, Typ);
9668 end if;
9669 end;
ee6ba406 9670 end Expand_N_Op_Rotate_Left;
9671
9672 ------------------------------
9673 -- Expand_N_Op_Rotate_Right --
9674 ------------------------------
9675
9676 procedure Expand_N_Op_Rotate_Right (N : Node_Id) is
9677 begin
9678 Binary_Op_Validity_Checks (N);
5542710d 9679
9680 -- If we are in Modify_Tree_For_C mode, there is no rotate right in C,
9681 -- so we rewrite in terms of logical shifts
9682
9683 -- Shift_Right (Num, Bits) or Shift_Left (num, Esize - Bits)
9684
9685 -- where Bits is the shift count mod Esize (the mod operation here
9686 -- deals with ludicrous large shift counts, which are apparently OK).
9687
09ae61a2 9688 -- What about nonbinary modulus ???
5542710d 9689
9690 declare
9691 Loc : constant Source_Ptr := Sloc (N);
9692 Rtp : constant Entity_Id := Etype (Right_Opnd (N));
9693 Typ : constant Entity_Id := Etype (N);
9694
9695 begin
9696 Rewrite (Right_Opnd (N),
9697 Make_Op_Rem (Loc,
9698 Left_Opnd => Relocate_Node (Right_Opnd (N)),
9699 Right_Opnd => Make_Integer_Literal (Loc, Esize (Typ))));
9700
9701 Analyze_And_Resolve (Right_Opnd (N), Rtp);
9702
9703 if Modify_Tree_For_C then
9704 Rewrite (N,
9705 Make_Op_Or (Loc,
9706 Left_Opnd =>
9707 Make_Op_Shift_Right (Loc,
9708 Left_Opnd => Left_Opnd (N),
9709 Right_Opnd => Right_Opnd (N)),
84004385 9710
5542710d 9711 Right_Opnd =>
9712 Make_Op_Shift_Left (Loc,
9713 Left_Opnd => Duplicate_Subexpr_No_Checks (Left_Opnd (N)),
9714 Right_Opnd =>
9715 Make_Op_Subtract (Loc,
9716 Left_Opnd => Make_Integer_Literal (Loc, Esize (Typ)),
9717 Right_Opnd =>
9718 Duplicate_Subexpr_No_Checks (Right_Opnd (N))))));
9719
9720 Analyze_And_Resolve (N, Typ);
9721 end if;
9722 end;
ee6ba406 9723 end Expand_N_Op_Rotate_Right;
9724
9725 ----------------------------
9726 -- Expand_N_Op_Shift_Left --
9727 ----------------------------
9728
84004385 9729 -- Note: nothing in this routine depends on left as opposed to right shifts
9730 -- so we share the routine for expanding shift right operations.
9731
ee6ba406 9732 procedure Expand_N_Op_Shift_Left (N : Node_Id) is
9733 begin
9734 Binary_Op_Validity_Checks (N);
84004385 9735
9736 -- If we are in Modify_Tree_For_C mode, then ensure that the right
9737 -- operand is not greater than the word size (since that would not
9738 -- be defined properly by the corresponding C shift operator).
9739
9740 if Modify_Tree_For_C then
9741 declare
9742 Right : constant Node_Id := Right_Opnd (N);
9743 Loc : constant Source_Ptr := Sloc (Right);
9744 Typ : constant Entity_Id := Etype (N);
9745 Siz : constant Uint := Esize (Typ);
9746 Orig : Node_Id;
9747 OK : Boolean;
9748 Lo : Uint;
9749 Hi : Uint;
9750
9751 begin
9752 if Compile_Time_Known_Value (Right) then
9753 if Expr_Value (Right) >= Siz then
9754 Rewrite (N, Make_Integer_Literal (Loc, 0));
9755 Analyze_And_Resolve (N, Typ);
9756 end if;
9757
9758 -- Not compile time known, find range
9759
9760 else
9761 Determine_Range (Right, OK, Lo, Hi, Assume_Valid => True);
9762
9763 -- Nothing to do if known to be OK range, otherwise expand
9764
9765 if not OK or else Hi >= Siz then
9766
9767 -- Prevent recursion on copy of shift node
9768
9769 Orig := Relocate_Node (N);
9770 Set_Analyzed (Orig);
9771
9772 -- Now do the rewrite
9773
9774 Rewrite (N,
9775 Make_If_Expression (Loc,
9776 Expressions => New_List (
9777 Make_Op_Ge (Loc,
9778 Left_Opnd => Duplicate_Subexpr_Move_Checks (Right),
9779 Right_Opnd => Make_Integer_Literal (Loc, Siz)),
9780 Make_Integer_Literal (Loc, 0),
9781 Orig)));
9782 Analyze_And_Resolve (N, Typ);
9783 end if;
9784 end if;
9785 end;
9786 end if;
ee6ba406 9787 end Expand_N_Op_Shift_Left;
9788
9789 -----------------------------
9790 -- Expand_N_Op_Shift_Right --
9791 -----------------------------
9792
9793 procedure Expand_N_Op_Shift_Right (N : Node_Id) is
9794 begin
84004385 9795 -- Share shift left circuit
9796
9797 Expand_N_Op_Shift_Left (N);
ee6ba406 9798 end Expand_N_Op_Shift_Right;
9799
9800 ----------------------------------------
9801 -- Expand_N_Op_Shift_Right_Arithmetic --
9802 ----------------------------------------
9803
9804 procedure Expand_N_Op_Shift_Right_Arithmetic (N : Node_Id) is
9805 begin
9806 Binary_Op_Validity_Checks (N);
5542710d 9807
9808 -- If we are in Modify_Tree_For_C mode, there is no shift right
9809 -- arithmetic in C, so we rewrite in terms of logical shifts.
9810
9811 -- Shift_Right (Num, Bits) or
9812 -- (if Num >= Sign
9813 -- then not (Shift_Right (Mask, bits))
9814 -- else 0)
9815
9816 -- Here Mask is all 1 bits (2**size - 1), and Sign is 2**(size - 1)
9817
9818 -- Note: in almost all C compilers it would work to just shift a
9819 -- signed integer right, but it's undefined and we cannot rely on it.
9820
84004385 9821 -- Note: the above works fine for shift counts greater than or equal
9822 -- to the word size, since in this case (not (Shift_Right (Mask, bits)))
9823 -- generates all 1'bits.
9824
09ae61a2 9825 -- What about nonbinary modulus ???
5542710d 9826
9827 declare
9828 Loc : constant Source_Ptr := Sloc (N);
9829 Typ : constant Entity_Id := Etype (N);
9830 Sign : constant Uint := 2 ** (Esize (Typ) - 1);
9831 Mask : constant Uint := (2 ** Esize (Typ)) - 1;
9832 Left : constant Node_Id := Left_Opnd (N);
9833 Right : constant Node_Id := Right_Opnd (N);
9834 Maskx : Node_Id;
9835
9836 begin
9837 if Modify_Tree_For_C then
9838
9839 -- Here if not (Shift_Right (Mask, bits)) can be computed at
9840 -- compile time as a single constant.
9841
9842 if Compile_Time_Known_Value (Right) then
9843 declare
9844 Val : constant Uint := Expr_Value (Right);
9845
9846 begin
9847 if Val >= Esize (Typ) then
9848 Maskx := Make_Integer_Literal (Loc, Mask);
9849
9850 else
9851 Maskx :=
9852 Make_Integer_Literal (Loc,
9853 Intval => Mask - (Mask / (2 ** Expr_Value (Right))));
9854 end if;
9855 end;
9856
9857 else
9858 Maskx :=
9859 Make_Op_Not (Loc,
9860 Right_Opnd =>
9861 Make_Op_Shift_Right (Loc,
9862 Left_Opnd => Make_Integer_Literal (Loc, Mask),
9863 Right_Opnd => Duplicate_Subexpr_No_Checks (Right)));
9864 end if;
9865
9866 -- Now do the rewrite
9867
9868 Rewrite (N,
9869 Make_Op_Or (Loc,
9870 Left_Opnd =>
9871 Make_Op_Shift_Right (Loc,
9872 Left_Opnd => Left,
9873 Right_Opnd => Right),
9874 Right_Opnd =>
9875 Make_If_Expression (Loc,
9876 Expressions => New_List (
9877 Make_Op_Ge (Loc,
9878 Left_Opnd => Duplicate_Subexpr_No_Checks (Left),
9879 Right_Opnd => Make_Integer_Literal (Loc, Sign)),
9880 Maskx,
9881 Make_Integer_Literal (Loc, 0)))));
9882 Analyze_And_Resolve (N, Typ);
9883 end if;
9884 end;
ee6ba406 9885 end Expand_N_Op_Shift_Right_Arithmetic;
9886
9887 --------------------------
9888 -- Expand_N_Op_Subtract --
9889 --------------------------
9890
9891 procedure Expand_N_Op_Subtract (N : Node_Id) is
9892 Typ : constant Entity_Id := Etype (N);
9893
9894 begin
9895 Binary_Op_Validity_Checks (N);
9896
f32c377d 9897 -- Check for MINIMIZED/ELIMINATED overflow mode
9898
9899 if Minimized_Eliminated_Overflow_Check (N) then
9900 Apply_Arithmetic_Overflow_Check (N);
9901 return;
9902 end if;
9903
ee6ba406 9904 -- N - 0 = N for integer types
9905
9906 if Is_Integer_Type (Typ)
9907 and then Compile_Time_Known_Value (Right_Opnd (N))
9908 and then Expr_Value (Right_Opnd (N)) = 0
9909 then
9910 Rewrite (N, Left_Opnd (N));
9911 return;
9912 end if;
9913
36b938a3 9914 -- Arithmetic overflow checks for signed integer/fixed point types
ee6ba406 9915
cf04d13c 9916 if Is_Signed_Integer_Type (Typ) or else Is_Fixed_Point_Type (Typ) then
ee6ba406 9917 Apply_Arithmetic_Overflow_Check (N);
ee6ba406 9918 end if;
54d549ff 9919
9920 -- Overflow checks for floating-point if -gnateF mode active
9921
9922 Check_Float_Op_Overflow (N);
61b6f3d9 9923
2a801d20 9924 -- When generating C code, convert nonbinary modular subtractions into
9925 -- code that relies on the front-end expansion of operator Mod.
61b6f3d9 9926
9927 if Modify_Tree_For_C then
2a801d20 9928 Expand_Nonbinary_Modular_Op (N);
61b6f3d9 9929 end if;
ee6ba406 9930 end Expand_N_Op_Subtract;
9931
9932 ---------------------
9933 -- Expand_N_Op_Xor --
9934 ---------------------
9935
9936 procedure Expand_N_Op_Xor (N : Node_Id) is
9937 Typ : constant Entity_Id := Etype (N);
9938
9939 begin
9940 Binary_Op_Validity_Checks (N);
9941
9942 if Is_Array_Type (Etype (N)) then
9943 Expand_Boolean_Operator (N);
9944
9945 elsif Is_Boolean_Type (Etype (N)) then
9946 Adjust_Condition (Left_Opnd (N));
9947 Adjust_Condition (Right_Opnd (N));
9948 Set_Etype (N, Standard_Boolean);
9949 Adjust_Result_Type (N, Typ);
9f294c82 9950
9951 elsif Is_Intrinsic_Subprogram (Entity (N)) then
9952 Expand_Intrinsic_Call (N, Entity (N));
9953
ee6ba406 9954 end if;
9955 end Expand_N_Op_Xor;
9956
9957 ----------------------
9958 -- Expand_N_Or_Else --
9959 ----------------------
9960
3755dbc5 9961 procedure Expand_N_Or_Else (N : Node_Id)
9962 renames Expand_Short_Circuit_Operator;
ee6ba406 9963
9964 -----------------------------------
9965 -- Expand_N_Qualified_Expression --
9966 -----------------------------------
9967
9968 procedure Expand_N_Qualified_Expression (N : Node_Id) is
9969 Operand : constant Node_Id := Expression (N);
9970 Target_Type : constant Entity_Id := Entity (Subtype_Mark (N));
9971
9972 begin
0cba9418 9973 -- Do validity check if validity checking operands
9974
6f0d10f7 9975 if Validity_Checks_On and Validity_Check_Operands then
0cba9418 9976 Ensure_Valid (Operand);
9977 end if;
9978
9979 -- Apply possible constraint check
9980
ee6ba406 9981 Apply_Constraint_Check (Operand, Target_Type, No_Sliding => True);
a9b57347 9982
9983 if Do_Range_Check (Operand) then
9984 Set_Do_Range_Check (Operand, False);
9985 Generate_Range_Check (Operand, Target_Type, CE_Range_Check_Failed);
9986 end if;
ee6ba406 9987 end Expand_N_Qualified_Expression;
9988
39d4bf68 9989 ------------------------------------
9990 -- Expand_N_Quantified_Expression --
9991 ------------------------------------
9992
6a7bc898 9993 -- We expand:
9994
9995 -- for all X in range => Cond
39d4bf68 9996
6a7bc898 9997 -- into:
39d4bf68 9998
6a7bc898 9999 -- T := True;
10000 -- for X in range loop
10001 -- if not Cond then
10002 -- T := False;
10003 -- exit;
10004 -- end if;
10005 -- end loop;
3decff5a 10006
7a19298b 10007 -- Similarly, an existentially quantified expression:
3decff5a 10008
6a7bc898 10009 -- for some X in range => Cond
3decff5a 10010
6a7bc898 10011 -- becomes:
3decff5a 10012
6a7bc898 10013 -- T := False;
10014 -- for X in range loop
10015 -- if Cond then
10016 -- T := True;
10017 -- exit;
10018 -- end if;
10019 -- end loop;
3decff5a 10020
6a7bc898 10021 -- In both cases, the iteration may be over a container in which case it is
10022 -- given by an iterator specification, not a loop parameter specification.
39d4bf68 10023
6a7bc898 10024 procedure Expand_N_Quantified_Expression (N : Node_Id) is
0baac39e 10025 Actions : constant List_Id := New_List;
10026 For_All : constant Boolean := All_Present (N);
10027 Iter_Spec : constant Node_Id := Iterator_Specification (N);
10028 Loc : constant Source_Ptr := Sloc (N);
10029 Loop_Spec : constant Node_Id := Loop_Parameter_Specification (N);
10030 Cond : Node_Id;
10031 Flag : Entity_Id;
10032 Scheme : Node_Id;
10033 Stmts : List_Id;
75ef9625 10034
39d4bf68 10035 begin
0baac39e 10036 -- Create the declaration of the flag which tracks the status of the
10037 -- quantified expression. Generate:
1b24a6cb 10038
0baac39e 10039 -- Flag : Boolean := (True | False);
1b24a6cb 10040
0baac39e 10041 Flag := Make_Temporary (Loc, 'T', N);
1b24a6cb 10042
0baac39e 10043 Append_To (Actions,
3decff5a 10044 Make_Object_Declaration (Loc,
0baac39e 10045 Defining_Identifier => Flag,
6a7bc898 10046 Object_Definition => New_Occurrence_Of (Standard_Boolean, Loc),
10047 Expression =>
0baac39e 10048 New_Occurrence_Of (Boolean_Literals (For_All), Loc)));
10049
10050 -- Construct the circuitry which tracks the status of the quantified
10051 -- expression. Generate:
10052
10053 -- if [not] Cond then
10054 -- Flag := (False | True);
10055 -- exit;
10056 -- end if;
39d4bf68 10057
6a7bc898 10058 Cond := Relocate_Node (Condition (N));
39d4bf68 10059
0baac39e 10060 if For_All then
6a7bc898 10061 Cond := Make_Op_Not (Loc, Cond);
39d4bf68 10062 end if;
10063
0baac39e 10064 Stmts := New_List (
6a7bc898 10065 Make_Implicit_If_Statement (N,
10066 Condition => Cond,
10067 Then_Statements => New_List (
10068 Make_Assignment_Statement (Loc,
0baac39e 10069 Name => New_Occurrence_Of (Flag, Loc),
6a7bc898 10070 Expression =>
0baac39e 10071 New_Occurrence_Of (Boolean_Literals (not For_All), Loc)),
10072 Make_Exit_Statement (Loc))));
10073
10074 -- Build the loop equivalent of the quantified expression
6a7bc898 10075
0baac39e 10076 if Present (Iter_Spec) then
10077 Scheme :=
1b24a6cb 10078 Make_Iteration_Scheme (Loc,
0baac39e 10079 Iterator_Specification => Iter_Spec);
75ef9625 10080 else
0baac39e 10081 Scheme :=
1b24a6cb 10082 Make_Iteration_Scheme (Loc,
0baac39e 10083 Loop_Parameter_Specification => Loop_Spec);
75ef9625 10084 end if;
10085
39d4bf68 10086 Append_To (Actions,
10087 Make_Loop_Statement (Loc,
0baac39e 10088 Iteration_Scheme => Scheme,
10089 Statements => Stmts,
6a7bc898 10090 End_Label => Empty));
39d4bf68 10091
0baac39e 10092 -- Transform the quantified expression
10093
39d4bf68 10094 Rewrite (N,
10095 Make_Expression_With_Actions (Loc,
0baac39e 10096 Expression => New_Occurrence_Of (Flag, Loc),
39d4bf68 10097 Actions => Actions));
39d4bf68 10098 Analyze_And_Resolve (N, Standard_Boolean);
10099 end Expand_N_Quantified_Expression;
10100
ee6ba406 10101 ---------------------------------
10102 -- Expand_N_Selected_Component --
10103 ---------------------------------
10104
ee6ba406 10105 procedure Expand_N_Selected_Component (N : Node_Id) is
10106 Loc : constant Source_Ptr := Sloc (N);
10107 Par : constant Node_Id := Parent (N);
10108 P : constant Node_Id := Prefix (N);
ef0772bc 10109 S : constant Node_Id := Selector_Name (N);
9dfe12ae 10110 Ptyp : Entity_Id := Underlying_Type (Etype (P));
ee6ba406 10111 Disc : Entity_Id;
ee6ba406 10112 New_N : Node_Id;
9dfe12ae 10113 Dcon : Elmt_Id;
39a79c9e 10114 Dval : Node_Id;
ee6ba406 10115
10116 function In_Left_Hand_Side (Comp : Node_Id) return Boolean;
10117 -- Gigi needs a temporary for prefixes that depend on a discriminant,
10118 -- unless the context of an assignment can provide size information.
9dfe12ae 10119 -- Don't we have a general routine that does this???
10120
278c67dc 10121 function Is_Subtype_Declaration return Boolean;
10122 -- The replacement of a discriminant reference by its value is required
bdf265a3 10123 -- if this is part of the initialization of an temporary generated by a
10124 -- change of representation. This shows up as the construction of a
278c67dc 10125 -- discriminant constraint for a subtype declared at the same point as
bdf265a3 10126 -- the entity in the prefix of the selected component. We recognize this
10127 -- case when the context of the reference is:
10128 -- subtype ST is T(Obj.D);
10129 -- where the entity for Obj comes from source, and ST has the same sloc.
278c67dc 10130
9dfe12ae 10131 -----------------------
10132 -- In_Left_Hand_Side --
10133 -----------------------
ee6ba406 10134
10135 function In_Left_Hand_Side (Comp : Node_Id) return Boolean is
10136 begin
9dfe12ae 10137 return (Nkind (Parent (Comp)) = N_Assignment_Statement
3decff5a 10138 and then Comp = Name (Parent (Comp)))
9dfe12ae 10139 or else (Present (Parent (Comp))
3decff5a 10140 and then Nkind (Parent (Comp)) in N_Subexpr
10141 and then In_Left_Hand_Side (Parent (Comp)));
ee6ba406 10142 end In_Left_Hand_Side;
10143
278c67dc 10144 -----------------------------
10145 -- Is_Subtype_Declaration --
10146 -----------------------------
10147
10148 function Is_Subtype_Declaration return Boolean is
10149 Par : constant Node_Id := Parent (N);
278c67dc 10150 begin
10151 return
10152 Nkind (Par) = N_Index_Or_Discriminant_Constraint
10153 and then Nkind (Parent (Parent (Par))) = N_Subtype_Declaration
10154 and then Comes_From_Source (Entity (Prefix (N)))
10155 and then Sloc (Par) = Sloc (Entity (Prefix (N)));
10156 end Is_Subtype_Declaration;
10157
9dfe12ae 10158 -- Start of processing for Expand_N_Selected_Component
10159
ee6ba406 10160 begin
9dfe12ae 10161 -- Insert explicit dereference if required
10162
10163 if Is_Access_Type (Ptyp) then
78efad62 10164
10165 -- First set prefix type to proper access type, in case it currently
10166 -- has a private (non-access) view of this type.
10167
10168 Set_Etype (P, Ptyp);
10169
9dfe12ae 10170 Insert_Explicit_Dereference (P);
28ed91d4 10171 Analyze_And_Resolve (P, Designated_Type (Ptyp));
9dfe12ae 10172
10173 if Ekind (Etype (P)) = E_Private_Subtype
10174 and then Is_For_Access_Subtype (Etype (P))
10175 then
10176 Set_Etype (P, Base_Type (Etype (P)));
10177 end if;
10178
10179 Ptyp := Etype (P);
10180 end if;
10181
10182 -- Deal with discriminant check required
10183
ee6ba406 10184 if Do_Discriminant_Check (N) then
ef0772bc 10185 if Present (Discriminant_Checking_Func
10186 (Original_Record_Component (Entity (S))))
10187 then
10188 -- Present the discriminant checking function to the backend, so
10189 -- that it can inline the call to the function.
10190
10191 Add_Inlined_Body
10192 (Discriminant_Checking_Func
32d2c8a5 10193 (Original_Record_Component (Entity (S))),
10194 N);
ee6ba406 10195
ef0772bc 10196 -- Now reset the flag and generate the call
ee6ba406 10197
ef0772bc 10198 Set_Do_Discriminant_Check (N, False);
10199 Generate_Discriminant_Check (N);
ee6ba406 10200
ef0772bc 10201 -- In the case of Unchecked_Union, no discriminant checking is
10202 -- actually performed.
ee6ba406 10203
ef0772bc 10204 else
10205 Set_Do_Discriminant_Check (N, False);
10206 end if;
ee6ba406 10207 end if;
10208
40a5a4cb 10209 -- Ada 2005 (AI-318-02): If the prefix is a call to a build-in-place
10210 -- function, then additional actuals must be passed.
10211
cd24e497 10212 if Is_Build_In_Place_Function_Call (P) then
40a5a4cb 10213 Make_Build_In_Place_Call_In_Anonymous_Context (P);
8b3a98b2 10214
10215 -- Ada 2005 (AI-318-02): Specialization of the previous case for prefix
10216 -- containing build-in-place function calls whose returned object covers
10217 -- interface types.
10218
cd24e497 10219 elsif Present (Unqual_BIP_Iface_Function_Call (P)) then
8b3a98b2 10220 Make_Build_In_Place_Iface_Call_In_Anonymous_Context (P);
40a5a4cb 10221 end if;
10222
9dfe12ae 10223 -- Gigi cannot handle unchecked conversions that are the prefix of a
10224 -- selected component with discriminants. This must be checked during
10225 -- expansion, because during analysis the type of the selector is not
10226 -- known at the point the prefix is analyzed. If the conversion is the
10227 -- target of an assignment, then we cannot force the evaluation.
ee6ba406 10228
10229 if Nkind (Prefix (N)) = N_Unchecked_Type_Conversion
10230 and then Has_Discriminants (Etype (N))
10231 and then not In_Left_Hand_Side (N)
10232 then
10233 Force_Evaluation (Prefix (N));
10234 end if;
10235
10236 -- Remaining processing applies only if selector is a discriminant
10237
10238 if Ekind (Entity (Selector_Name (N))) = E_Discriminant then
10239
10240 -- If the selector is a discriminant of a constrained record type,
9dfe12ae 10241 -- we may be able to rewrite the expression with the actual value
10242 -- of the discriminant, a useful optimization in some cases.
ee6ba406 10243
10244 if Is_Record_Type (Ptyp)
10245 and then Has_Discriminants (Ptyp)
10246 and then Is_Constrained (Ptyp)
ee6ba406 10247 then
9dfe12ae 10248 -- Do this optimization for discrete types only, and not for
39a0c1d3 10249 -- access types (access discriminants get us into trouble).
ee6ba406 10250
9dfe12ae 10251 if not Is_Discrete_Type (Etype (N)) then
10252 null;
10253
83d2f9bc 10254 -- Don't do this on the left-hand side of an assignment statement.
64427fe6 10255 -- Normally one would think that references like this would not
10256 -- occur, but they do in generated code, and mean that we really
39a0c1d3 10257 -- do want to assign the discriminant.
9dfe12ae 10258
10259 elsif Nkind (Par) = N_Assignment_Statement
10260 and then Name (Par) = N
10261 then
10262 null;
10263
f1e2dcc5 10264 -- Don't do this optimization for the prefix of an attribute or
e8a30fc0 10265 -- the name of an object renaming declaration since these are
f1e2dcc5 10266 -- contexts where we do not want the value anyway.
9dfe12ae 10267
10268 elsif (Nkind (Par) = N_Attribute_Reference
6f0d10f7 10269 and then Prefix (Par) = N)
9dfe12ae 10270 or else Is_Renamed_Object (N)
10271 then
10272 null;
10273
10274 -- Don't do this optimization if we are within the code for a
10275 -- discriminant check, since the whole point of such a check may
39a0c1d3 10276 -- be to verify the condition on which the code below depends.
9dfe12ae 10277
10278 elsif Is_In_Discriminant_Check (N) then
10279 null;
10280
10281 -- Green light to see if we can do the optimization. There is
f1e2dcc5 10282 -- still one condition that inhibits the optimization below but
10283 -- now is the time to check the particular discriminant.
9dfe12ae 10284
10285 else
f1e2dcc5 10286 -- Loop through discriminants to find the matching discriminant
10287 -- constraint to see if we can copy it.
9dfe12ae 10288
10289 Disc := First_Discriminant (Ptyp);
10290 Dcon := First_Elmt (Discriminant_Constraint (Ptyp));
10291 Discr_Loop : while Present (Dcon) loop
39a79c9e 10292 Dval := Node (Dcon);
9dfe12ae 10293
fb7f2fc4 10294 -- Check if this is the matching discriminant and if the
10295 -- discriminant value is simple enough to make sense to
10296 -- copy. We don't want to copy complex expressions, and
10297 -- indeed to do so can cause trouble (before we put in
10298 -- this guard, a discriminant expression containing an
7d6293c6 10299 -- AND THEN was copied, causing problems for coverage
928c11f3 10300 -- analysis tools).
fb7f2fc4 10301
278c67dc 10302 -- However, if the reference is part of the initialization
10303 -- code generated for an object declaration, we must use
10304 -- the discriminant value from the subtype constraint,
10305 -- because the selected component may be a reference to the
10306 -- object being initialized, whose discriminant is not yet
10307 -- set. This only happens in complex cases involving changes
10308 -- or representation.
10309
fb7f2fc4 10310 if Disc = Entity (Selector_Name (N))
10311 and then (Is_Entity_Name (Dval)
b5214f00 10312 or else Compile_Time_Known_Value (Dval)
10313 or else Is_Subtype_Declaration)
fb7f2fc4 10314 then
9dfe12ae 10315 -- Here we have the matching discriminant. Check for
10316 -- the case of a discriminant of a component that is
10317 -- constrained by an outer discriminant, which cannot
10318 -- be optimized away.
10319
39a79c9e 10320 if Denotes_Discriminant
10321 (Dval, Check_Concurrent => True)
10322 then
10323 exit Discr_Loop;
10324
10325 elsif Nkind (Original_Node (Dval)) = N_Selected_Component
10326 and then
10327 Denotes_Discriminant
10328 (Selector_Name (Original_Node (Dval)), True)
10329 then
10330 exit Discr_Loop;
10331
10332 -- Do not retrieve value if constraint is not static. It
10333 -- is generally not useful, and the constraint may be a
10334 -- rewritten outer discriminant in which case it is in
10335 -- fact incorrect.
10336
10337 elsif Is_Entity_Name (Dval)
39a79c9e 10338 and then
6f0d10f7 10339 Nkind (Parent (Entity (Dval))) = N_Object_Declaration
10340 and then Present (Expression (Parent (Entity (Dval))))
10341 and then not
cda40848 10342 Is_OK_Static_Expression
39a79c9e 10343 (Expression (Parent (Entity (Dval))))
9dfe12ae 10344 then
10345 exit Discr_Loop;
ee6ba406 10346
f1e2dcc5 10347 -- In the context of a case statement, the expression may
10348 -- have the base type of the discriminant, and we need to
10349 -- preserve the constraint to avoid spurious errors on
10350 -- missing cases.
ee6ba406 10351
9dfe12ae 10352 elsif Nkind (Parent (N)) = N_Case_Statement
39a79c9e 10353 and then Etype (Dval) /= Etype (Disc)
ee6ba406 10354 then
10355 Rewrite (N,
10356 Make_Qualified_Expression (Loc,
9dfe12ae 10357 Subtype_Mark =>
10358 New_Occurrence_Of (Etype (Disc), Loc),
10359 Expression =>
39a79c9e 10360 New_Copy_Tree (Dval)));
cb226482 10361 Analyze_And_Resolve (N, Etype (Disc));
9dfe12ae 10362
10363 -- In case that comes out as a static expression,
10364 -- reset it (a selected component is never static).
10365
10366 Set_Is_Static_Expression (N, False);
10367 return;
10368
10369 -- Otherwise we can just copy the constraint, but the
39a0c1d3 10370 -- result is certainly not static. In some cases the
cb226482 10371 -- discriminant constraint has been analyzed in the
10372 -- context of the original subtype indication, but for
10373 -- itypes the constraint might not have been analyzed
10374 -- yet, and this must be done now.
9dfe12ae 10375
ee6ba406 10376 else
39a79c9e 10377 Rewrite (N, New_Copy_Tree (Dval));
cb226482 10378 Analyze_And_Resolve (N);
9dfe12ae 10379 Set_Is_Static_Expression (N, False);
10380 return;
ee6ba406 10381 end if;
ee6ba406 10382 end if;
10383
9dfe12ae 10384 Next_Elmt (Dcon);
10385 Next_Discriminant (Disc);
10386 end loop Discr_Loop;
ee6ba406 10387
9dfe12ae 10388 -- Note: the above loop should always find a matching
10389 -- discriminant, but if it does not, we just missed an
928c11f3 10390 -- optimization due to some glitch (perhaps a previous
10391 -- error), so ignore.
9dfe12ae 10392
10393 end if;
ee6ba406 10394 end if;
10395
10396 -- The only remaining processing is in the case of a discriminant of
10397 -- a concurrent object, where we rewrite the prefix to denote the
10398 -- corresponding record type. If the type is derived and has renamed
10399 -- discriminants, use corresponding discriminant, which is the one
10400 -- that appears in the corresponding record.
10401
10402 if not Is_Concurrent_Type (Ptyp) then
10403 return;
10404 end if;
10405
10406 Disc := Entity (Selector_Name (N));
10407
10408 if Is_Derived_Type (Ptyp)
10409 and then Present (Corresponding_Discriminant (Disc))
10410 then
10411 Disc := Corresponding_Discriminant (Disc);
10412 end if;
10413
10414 New_N :=
10415 Make_Selected_Component (Loc,
10416 Prefix =>
10417 Unchecked_Convert_To (Corresponding_Record_Type (Ptyp),
10418 New_Copy_Tree (P)),
10419 Selector_Name => Make_Identifier (Loc, Chars (Disc)));
10420
10421 Rewrite (N, New_N);
10422 Analyze (N);
10423 end if;
d306cbee 10424
11700d57 10425 -- Set Atomic_Sync_Required if necessary for atomic component
d306cbee 10426
11700d57 10427 if Nkind (N) = N_Selected_Component then
10428 declare
10429 E : constant Entity_Id := Entity (Selector_Name (N));
10430 Set : Boolean;
10431
10432 begin
10433 -- If component is atomic, but type is not, setting depends on
10434 -- disable/enable state for the component.
10435
10436 if Is_Atomic (E) and then not Is_Atomic (Etype (E)) then
10437 Set := not Atomic_Synchronization_Disabled (E);
10438
10439 -- If component is not atomic, but its type is atomic, setting
10440 -- depends on disable/enable state for the type.
10441
10442 elsif not Is_Atomic (E) and then Is_Atomic (Etype (E)) then
10443 Set := not Atomic_Synchronization_Disabled (Etype (E));
10444
10445 -- If both component and type are atomic, we disable if either
10446 -- component or its type have sync disabled.
10447
10448 elsif Is_Atomic (E) and then Is_Atomic (Etype (E)) then
10449 Set := (not Atomic_Synchronization_Disabled (E))
10450 and then
10451 (not Atomic_Synchronization_Disabled (Etype (E)));
10452
10453 else
10454 Set := False;
10455 end if;
10456
10457 -- Set flag if required
10458
10459 if Set then
10460 Activate_Atomic_Synchronization (N);
10461 end if;
10462 end;
d306cbee 10463 end if;
ee6ba406 10464 end Expand_N_Selected_Component;
10465
10466 --------------------
10467 -- Expand_N_Slice --
10468 --------------------
10469
10470 procedure Expand_N_Slice (N : Node_Id) is
778ebf56 10471 Loc : constant Source_Ptr := Sloc (N);
10472 Typ : constant Entity_Id := Etype (N);
9dfe12ae 10473
37cb33b0 10474 function Is_Procedure_Actual (N : Node_Id) return Boolean;
f1e2dcc5 10475 -- Check whether the argument is an actual for a procedure call, in
10476 -- which case the expansion of a bit-packed slice is deferred until the
10477 -- call itself is expanded. The reason this is required is that we might
10478 -- have an IN OUT or OUT parameter, and the copy out is essential, and
10479 -- that copy out would be missed if we created a temporary here in
10480 -- Expand_N_Slice. Note that we don't bother to test specifically for an
10481 -- IN OUT or OUT mode parameter, since it is a bit tricky to do, and it
10482 -- is harmless to defer expansion in the IN case, since the call
10483 -- processing will still generate the appropriate copy in operation,
10484 -- which will take care of the slice.
37cb33b0 10485
447e605f 10486 procedure Make_Temporary_For_Slice;
f1e2dcc5 10487 -- Create a named variable for the value of the slice, in cases where
2a801d20 10488 -- the back end cannot handle it properly, e.g. when packed types or
f1e2dcc5 10489 -- unaligned slices are involved.
9dfe12ae 10490
37cb33b0 10491 -------------------------
10492 -- Is_Procedure_Actual --
10493 -------------------------
10494
10495 function Is_Procedure_Actual (N : Node_Id) return Boolean is
10496 Par : Node_Id := Parent (N);
9988dae3 10497
37cb33b0 10498 begin
37cb33b0 10499 loop
eed46cf9 10500 -- If our parent is a procedure call we can return
10501
37cb33b0 10502 if Nkind (Par) = N_Procedure_Call_Statement then
10503 return True;
314a23b6 10504
f1e2dcc5 10505 -- If our parent is a type conversion, keep climbing the tree,
10506 -- since a type conversion can be a procedure actual. Also keep
10507 -- climbing if parameter association or a qualified expression,
10508 -- since these are additional cases that do can appear on
10509 -- procedure actuals.
314a23b6 10510
1627db8a 10511 elsif Nkind_In (Par, N_Type_Conversion,
10512 N_Parameter_Association,
10513 N_Qualified_Expression)
eed46cf9 10514 then
37cb33b0 10515 Par := Parent (Par);
eed46cf9 10516
10517 -- Any other case is not what we are looking for
10518
10519 else
10520 return False;
37cb33b0 10521 end if;
10522 end loop;
37cb33b0 10523 end Is_Procedure_Actual;
10524
447e605f 10525 ------------------------------
10526 -- Make_Temporary_For_Slice --
10527 ------------------------------
9dfe12ae 10528
447e605f 10529 procedure Make_Temporary_For_Slice is
447e605f 10530 Ent : constant Entity_Id := Make_Temporary (Loc, 'T', N);
778ebf56 10531 Decl : Node_Id;
dea95b6d 10532
9dfe12ae 10533 begin
10534 Decl :=
10535 Make_Object_Declaration (Loc,
10536 Defining_Identifier => Ent,
10537 Object_Definition => New_Occurrence_Of (Typ, Loc));
10538
10539 Set_No_Initialization (Decl);
10540
10541 Insert_Actions (N, New_List (
10542 Decl,
10543 Make_Assignment_Statement (Loc,
778ebf56 10544 Name => New_Occurrence_Of (Ent, Loc),
9dfe12ae 10545 Expression => Relocate_Node (N))));
10546
10547 Rewrite (N, New_Occurrence_Of (Ent, Loc));
10548 Analyze_And_Resolve (N, Typ);
447e605f 10549 end Make_Temporary_For_Slice;
9dfe12ae 10550
778ebf56 10551 -- Local variables
10552
cf45b231 10553 Pref : constant Node_Id := Prefix (N);
10554 Pref_Typ : Entity_Id := Etype (Pref);
778ebf56 10555
9dfe12ae 10556 -- Start of processing for Expand_N_Slice
ee6ba406 10557
10558 begin
10559 -- Special handling for access types
10560
778ebf56 10561 if Is_Access_Type (Pref_Typ) then
10562 Pref_Typ := Designated_Type (Pref_Typ);
ee6ba406 10563
778ebf56 10564 Rewrite (Pref,
28ed91d4 10565 Make_Explicit_Dereference (Sloc (N),
778ebf56 10566 Prefix => Relocate_Node (Pref)));
ee6ba406 10567
778ebf56 10568 Analyze_And_Resolve (Pref, Pref_Typ);
ee6ba406 10569 end if;
10570
40a5a4cb 10571 -- Ada 2005 (AI-318-02): If the prefix is a call to a build-in-place
10572 -- function, then additional actuals must be passed.
10573
cd24e497 10574 if Is_Build_In_Place_Function_Call (Pref) then
778ebf56 10575 Make_Build_In_Place_Call_In_Anonymous_Context (Pref);
8b3a98b2 10576
10577 -- Ada 2005 (AI-318-02): Specialization of the previous case for prefix
10578 -- containing build-in-place function calls whose returned object covers
10579 -- interface types.
10580
cd24e497 10581 elsif Present (Unqual_BIP_Iface_Function_Call (Pref)) then
8b3a98b2 10582 Make_Build_In_Place_Iface_Call_In_Anonymous_Context (Pref);
40a5a4cb 10583 end if;
10584
ee6ba406 10585 -- The remaining case to be handled is packed slices. We can leave
10586 -- packed slices as they are in the following situations:
10587
10588 -- 1. Right or left side of an assignment (we can handle this
10589 -- situation correctly in the assignment statement expansion).
10590
f1e2dcc5 10591 -- 2. Prefix of indexed component (the slide is optimized away in this
10592 -- case, see the start of Expand_N_Slice.)
ee6ba406 10593
f1e2dcc5 10594 -- 3. Object renaming declaration, since we want the name of the
10595 -- slice, not the value.
ee6ba406 10596
f1e2dcc5 10597 -- 4. Argument to procedure call, since copy-in/copy-out handling may
10598 -- be required, and this is handled in the expansion of call
10599 -- itself.
ee6ba406 10600
f1e2dcc5 10601 -- 5. Prefix of an address attribute (this is an error which is caught
10602 -- elsewhere, and the expansion would interfere with generating the
10603 -- error message).
ee6ba406 10604
37cb33b0 10605 if not Is_Packed (Typ) then
9988dae3 10606
f1e2dcc5 10607 -- Apply transformation for actuals of a function call, where
10608 -- Expand_Actuals is not used.
37cb33b0 10609
10610 if Nkind (Parent (N)) = N_Function_Call
10611 and then Is_Possibly_Unaligned_Slice (N)
10612 then
447e605f 10613 Make_Temporary_For_Slice;
37cb33b0 10614 end if;
10615
10616 elsif Nkind (Parent (N)) = N_Assignment_Statement
10617 or else (Nkind (Parent (Parent (N))) = N_Assignment_Statement
6f0d10f7 10618 and then Parent (N) = Name (Parent (Parent (N))))
ee6ba406 10619 then
37cb33b0 10620 return;
ee6ba406 10621
37cb33b0 10622 elsif Nkind (Parent (N)) = N_Indexed_Component
10623 or else Is_Renamed_Object (N)
10624 or else Is_Procedure_Actual (N)
10625 then
10626 return;
ee6ba406 10627
5c61a0ff 10628 elsif Nkind (Parent (N)) = N_Attribute_Reference
10629 and then Attribute_Name (Parent (N)) = Name_Address
9dfe12ae 10630 then
37cb33b0 10631 return;
10632
10633 else
447e605f 10634 Make_Temporary_For_Slice;
ee6ba406 10635 end if;
10636 end Expand_N_Slice;
10637
10638 ------------------------------
10639 -- Expand_N_Type_Conversion --
10640 ------------------------------
10641
10642 procedure Expand_N_Type_Conversion (N : Node_Id) is
10643 Loc : constant Source_Ptr := Sloc (N);
10644 Operand : constant Node_Id := Expression (N);
10645 Target_Type : constant Entity_Id := Etype (N);
10646 Operand_Type : Entity_Id := Etype (Operand);
10647
10648 procedure Handle_Changed_Representation;
f1e2dcc5 10649 -- This is called in the case of record and array type conversions to
10650 -- see if there is a change of representation to be handled. Change of
10651 -- representation is actually handled at the assignment statement level,
10652 -- and what this procedure does is rewrite node N conversion as an
10653 -- assignment to temporary. If there is no change of representation,
10654 -- then the conversion node is unchanged.
ee6ba406 10655
515242d8 10656 procedure Raise_Accessibility_Error;
10657 -- Called when we know that an accessibility check will fail. Rewrites
10658 -- node N to an appropriate raise statement and outputs warning msgs.
56e11f12 10659 -- The Etype of the raise node is set to Target_Type. Note that in this
10660 -- case the rest of the processing should be skipped (i.e. the call to
10661 -- this procedure will be followed by "goto Done").
515242d8 10662
ee6ba406 10663 procedure Real_Range_Check;
10664 -- Handles generation of range check for real target value
10665
47d210a3 10666 function Has_Extra_Accessibility (Id : Entity_Id) return Boolean;
10667 -- True iff Present (Effective_Extra_Accessibility (Id)) successfully
10668 -- evaluates to True.
10669
ee6ba406 10670 -----------------------------------
10671 -- Handle_Changed_Representation --
10672 -----------------------------------
10673
10674 procedure Handle_Changed_Representation is
10675 Temp : Entity_Id;
10676 Decl : Node_Id;
10677 Odef : Node_Id;
ee6ba406 10678 N_Ix : Node_Id;
10679 Cons : List_Id;
10680
10681 begin
0cba9418 10682 -- Nothing else to do if no change of representation
ee6ba406 10683
10684 if Same_Representation (Operand_Type, Target_Type) then
10685 return;
10686
10687 -- The real change of representation work is done by the assignment
10688 -- statement processing. So if this type conversion is appearing as
10689 -- the expression of an assignment statement, nothing needs to be
10690 -- done to the conversion.
10691
10692 elsif Nkind (Parent (N)) = N_Assignment_Statement then
10693 return;
10694
10695 -- Otherwise we need to generate a temporary variable, and do the
10696 -- change of representation assignment into that temporary variable.
10697 -- The conversion is then replaced by a reference to this variable.
10698
10699 else
10700 Cons := No_List;
10701
f1e2dcc5 10702 -- If type is unconstrained we have to add a constraint, copied
83d2f9bc 10703 -- from the actual value of the left-hand side.
ee6ba406 10704
10705 if not Is_Constrained (Target_Type) then
10706 if Has_Discriminants (Operand_Type) then
9dfe12ae 10707
9600e689 10708 -- A change of representation can only apply to untagged
10709 -- types. We need to build the constraint that applies to
10710 -- the target type, using the constraints of the operand.
10711 -- The analysis is complicated if there are both inherited
10712 -- discriminants and constrained discriminants.
10713 -- We iterate over the discriminants of the target, and
10714 -- find the discriminant of the same name:
9dfe12ae 10715
9600e689 10716 -- a) If there is a corresponding discriminant in the object
10717 -- then the value is a selected component of the operand.
10718
10719 -- b) Otherwise the value of a constrained discriminant is
10720 -- found in the stored constraint of the operand.
10721
10722 declare
10723 Stored : constant Elist_Id :=
a740d7fa 10724 Stored_Constraint (Operand_Type);
9600e689 10725
10726 Elmt : Elmt_Id;
10727
10728 Disc_O : Entity_Id;
10729 -- Discriminant of the operand type. Its value in the
a740d7fa 10730 -- object is captured in a selected component.
9600e689 10731
10732 Disc_S : Entity_Id;
10733 -- Stored discriminant of the operand. If present, it
10734 -- corresponds to a constrained discriminant of the
10735 -- parent type.
10736
10737 Disc_T : Entity_Id;
10738 -- Discriminant of the target type
10739
10740 begin
10741 Disc_T := First_Discriminant (Target_Type);
10742 Disc_O := First_Discriminant (Operand_Type);
10743 Disc_S := First_Stored_Discriminant (Operand_Type);
10744
10745 if Present (Stored) then
10746 Elmt := First_Elmt (Stored);
10747 end if;
10748
10749 Cons := New_List;
10750 while Present (Disc_T) loop
10751 if Present (Disc_O)
10752 and then Chars (Disc_T) = Chars (Disc_O)
10753 then
10754 Append_To (Cons,
10755 Make_Selected_Component (Loc,
10756 Prefix =>
10757 Duplicate_Subexpr_Move_Checks (Operand),
a740d7fa 10758 Selector_Name =>
9600e689 10759 Make_Identifier (Loc, Chars (Disc_O))));
10760 Next_Discriminant (Disc_O);
10761
10762 elsif Present (Disc_S) then
10763 Append_To (Cons, New_Copy_Tree (Node (Elmt)));
10764 Next_Elmt (Elmt);
10765 end if;
10766
10767 Next_Discriminant (Disc_T);
10768 end loop;
10769 end;
ee6ba406 10770
10771 elsif Is_Array_Type (Operand_Type) then
10772 N_Ix := First_Index (Target_Type);
10773 Cons := New_List;
10774
10775 for J in 1 .. Number_Dimensions (Operand_Type) loop
10776
10777 -- We convert the bounds explicitly. We use an unchecked
10778 -- conversion because bounds checks are done elsewhere.
10779
10780 Append_To (Cons,
10781 Make_Range (Loc,
a740d7fa 10782 Low_Bound =>
ee6ba406 10783 Unchecked_Convert_To (Etype (N_Ix),
10784 Make_Attribute_Reference (Loc,
a740d7fa 10785 Prefix =>
9dfe12ae 10786 Duplicate_Subexpr_No_Checks
ee6ba406 10787 (Operand, Name_Req => True),
10788 Attribute_Name => Name_First,
10789 Expressions => New_List (
10790 Make_Integer_Literal (Loc, J)))),
10791
10792 High_Bound =>
10793 Unchecked_Convert_To (Etype (N_Ix),
10794 Make_Attribute_Reference (Loc,
a740d7fa 10795 Prefix =>
9dfe12ae 10796 Duplicate_Subexpr_No_Checks
ee6ba406 10797 (Operand, Name_Req => True),
10798 Attribute_Name => Name_Last,
10799 Expressions => New_List (
10800 Make_Integer_Literal (Loc, J))))));
10801
10802 Next_Index (N_Ix);
10803 end loop;
10804 end if;
10805 end if;
10806
10807 Odef := New_Occurrence_Of (Target_Type, Loc);
10808
10809 if Present (Cons) then
10810 Odef :=
10811 Make_Subtype_Indication (Loc,
10812 Subtype_Mark => Odef,
a740d7fa 10813 Constraint =>
ee6ba406 10814 Make_Index_Or_Discriminant_Constraint (Loc,
10815 Constraints => Cons));
10816 end if;
10817
46eb6933 10818 Temp := Make_Temporary (Loc, 'C');
ee6ba406 10819 Decl :=
10820 Make_Object_Declaration (Loc,
10821 Defining_Identifier => Temp,
10822 Object_Definition => Odef);
10823
10824 Set_No_Initialization (Decl, True);
10825
10826 -- Insert required actions. It is essential to suppress checks
10827 -- since we have suppressed default initialization, which means
10828 -- that the variable we create may have no discriminants.
10829
10830 Insert_Actions (N,
10831 New_List (
10832 Decl,
10833 Make_Assignment_Statement (Loc,
a740d7fa 10834 Name => New_Occurrence_Of (Temp, Loc),
ee6ba406 10835 Expression => Relocate_Node (N))),
10836 Suppress => All_Checks);
10837
10838 Rewrite (N, New_Occurrence_Of (Temp, Loc));
10839 return;
10840 end if;
10841 end Handle_Changed_Representation;
10842
515242d8 10843 -------------------------------
10844 -- Raise_Accessibility_Error --
10845 -------------------------------
10846
10847 procedure Raise_Accessibility_Error is
10848 begin
c4968aa2 10849 Error_Msg_Warn := SPARK_Mode /= On;
515242d8 10850 Rewrite (N,
10851 Make_Raise_Program_Error (Sloc (N),
10852 Reason => PE_Accessibility_Check_Failed));
10853 Set_Etype (N, Target_Type);
10854
4098232e 10855 Error_Msg_N ("<<accessibility check failure", N);
10856 Error_Msg_NE ("\<<& [", N, Standard_Program_Error);
515242d8 10857 end Raise_Accessibility_Error;
10858
ee6ba406 10859 ----------------------
10860 -- Real_Range_Check --
10861 ----------------------
10862
f1e2dcc5 10863 -- Case of conversions to floating-point or fixed-point. If range checks
10864 -- are enabled and the target type has a range constraint, we convert:
ee6ba406 10865
10866 -- typ (x)
10867
10868 -- to
10869
10870 -- Tnn : typ'Base := typ'Base (x);
10871 -- [constraint_error when Tnn < typ'First or else Tnn > typ'Last]
10872 -- Tnn
10873
f1e2dcc5 10874 -- This is necessary when there is a conversion of integer to float or
10875 -- to fixed-point to ensure that the correct checks are made. It is not
10876 -- necessary for float to float where it is enough to simply set the
10877 -- Do_Range_Check flag.
9dfe12ae 10878
ee6ba406 10879 procedure Real_Range_Check is
10880 Btyp : constant Entity_Id := Base_Type (Target_Type);
10881 Lo : constant Node_Id := Type_Low_Bound (Target_Type);
10882 Hi : constant Node_Id := Type_High_Bound (Target_Type);
9dfe12ae 10883 Xtyp : constant Entity_Id := Etype (Operand);
ee6ba406 10884 Conv : Node_Id;
10885 Tnn : Entity_Id;
10886
10887 begin
10888 -- Nothing to do if conversion was rewritten
10889
10890 if Nkind (N) /= N_Type_Conversion then
10891 return;
10892 end if;
10893
f1e2dcc5 10894 -- Nothing to do if range checks suppressed, or target has the same
10895 -- range as the base type (or is the base type).
ee6ba406 10896
10897 if Range_Checks_Suppressed (Target_Type)
6f0d10f7 10898 or else (Lo = Type_Low_Bound (Btyp)
ee6ba406 10899 and then
10900 Hi = Type_High_Bound (Btyp))
10901 then
10902 return;
10903 end if;
10904
f1e2dcc5 10905 -- Nothing to do if expression is an entity on which checks have been
10906 -- suppressed.
ee6ba406 10907
9dfe12ae 10908 if Is_Entity_Name (Operand)
10909 and then Range_Checks_Suppressed (Entity (Operand))
10910 then
10911 return;
10912 end if;
10913
f1e2dcc5 10914 -- Nothing to do if bounds are all static and we can tell that the
10915 -- expression is within the bounds of the target. Note that if the
10916 -- operand is of an unconstrained floating-point type, then we do
10917 -- not trust it to be in range (might be infinite)
9dfe12ae 10918
10919 declare
38f5559f 10920 S_Lo : constant Node_Id := Type_Low_Bound (Xtyp);
10921 S_Hi : constant Node_Id := Type_High_Bound (Xtyp);
9dfe12ae 10922
10923 begin
10924 if (not Is_Floating_Point_Type (Xtyp)
10925 or else Is_Constrained (Xtyp))
10926 and then Compile_Time_Known_Value (S_Lo)
10927 and then Compile_Time_Known_Value (S_Hi)
10928 and then Compile_Time_Known_Value (Hi)
10929 and then Compile_Time_Known_Value (Lo)
10930 then
10931 declare
10932 D_Lov : constant Ureal := Expr_Value_R (Lo);
10933 D_Hiv : constant Ureal := Expr_Value_R (Hi);
10934 S_Lov : Ureal;
10935 S_Hiv : Ureal;
10936
10937 begin
10938 if Is_Real_Type (Xtyp) then
10939 S_Lov := Expr_Value_R (S_Lo);
10940 S_Hiv := Expr_Value_R (S_Hi);
10941 else
10942 S_Lov := UR_From_Uint (Expr_Value (S_Lo));
10943 S_Hiv := UR_From_Uint (Expr_Value (S_Hi));
10944 end if;
10945
10946 if D_Hiv > D_Lov
10947 and then S_Lov >= D_Lov
10948 and then S_Hiv <= D_Hiv
10949 then
37c6552c 10950 -- Unset the range check flag on the current value of
10951 -- Expression (N), since the captured Operand may have
10952 -- been rewritten (such as for the case of a conversion
10953 -- to a fixed-point type).
10954
10955 Set_Do_Range_Check (Expression (N), False);
10956
9dfe12ae 10957 return;
10958 end if;
10959 end;
10960 end if;
10961 end;
10962
10963 -- For float to float conversions, we are done
10964
10965 if Is_Floating_Point_Type (Xtyp)
10966 and then
10967 Is_Floating_Point_Type (Btyp)
ee6ba406 10968 then
10969 return;
10970 end if;
10971
9dfe12ae 10972 -- Otherwise rewrite the conversion as described above
ee6ba406 10973
10974 Conv := Relocate_Node (N);
8eb4a5eb 10975 Rewrite (Subtype_Mark (Conv), New_Occurrence_Of (Btyp, Loc));
ee6ba406 10976 Set_Etype (Conv, Btyp);
10977
38f5559f 10978 -- Enable overflow except for case of integer to float conversions,
10979 -- where it is never required, since we can never have overflow in
10980 -- this case.
ee6ba406 10981
9dfe12ae 10982 if not Is_Integer_Type (Etype (Operand)) then
10983 Enable_Overflow_Check (Conv);
ee6ba406 10984 end if;
10985
46eb6933 10986 Tnn := Make_Temporary (Loc, 'T', Conv);
ee6ba406 10987
10988 Insert_Actions (N, New_List (
10989 Make_Object_Declaration (Loc,
10990 Defining_Identifier => Tnn,
10991 Object_Definition => New_Occurrence_Of (Btyp, Loc),
cf685aee 10992 Constant_Present => True,
10993 Expression => Conv),
ee6ba406 10994
10995 Make_Raise_Constraint_Error (Loc,
f15731c4 10996 Condition =>
10997 Make_Or_Else (Loc,
10998 Left_Opnd =>
10999 Make_Op_Lt (Loc,
11000 Left_Opnd => New_Occurrence_Of (Tnn, Loc),
11001 Right_Opnd =>
11002 Make_Attribute_Reference (Loc,
11003 Attribute_Name => Name_First,
11004 Prefix =>
11005 New_Occurrence_Of (Target_Type, Loc))),
ee6ba406 11006
f15731c4 11007 Right_Opnd =>
11008 Make_Op_Gt (Loc,
11009 Left_Opnd => New_Occurrence_Of (Tnn, Loc),
11010 Right_Opnd =>
11011 Make_Attribute_Reference (Loc,
11012 Attribute_Name => Name_Last,
11013 Prefix =>
11014 New_Occurrence_Of (Target_Type, Loc)))),
11015 Reason => CE_Range_Check_Failed)));
ee6ba406 11016
11017 Rewrite (N, New_Occurrence_Of (Tnn, Loc));
11018 Analyze_And_Resolve (N, Btyp);
11019 end Real_Range_Check;
11020
47d210a3 11021 -----------------------------
11022 -- Has_Extra_Accessibility --
11023 -----------------------------
11024
11025 -- Returns true for a formal of an anonymous access type or for
11026 -- an Ada 2012-style stand-alone object of an anonymous access type.
11027
11028 function Has_Extra_Accessibility (Id : Entity_Id) return Boolean is
11029 begin
11030 if Is_Formal (Id) or else Ekind_In (Id, E_Constant, E_Variable) then
11031 return Present (Effective_Extra_Accessibility (Id));
11032 else
11033 return False;
11034 end if;
11035 end Has_Extra_Accessibility;
11036
ee6ba406 11037 -- Start of processing for Expand_N_Type_Conversion
11038
11039 begin
8e802312 11040 -- First remove check marks put by the semantic analysis on the type
53fc0f29 11041 -- conversion between array types. We need these checks, and they will
11042 -- be generated by this expansion routine, but we do not depend on these
11043 -- flags being set, and since we do intend to expand the checks in the
11044 -- front end, we don't want them on the tree passed to the back end.
8e802312 11045
11046 if Is_Array_Type (Target_Type) then
11047 if Is_Constrained (Target_Type) then
11048 Set_Do_Length_Check (N, False);
11049 else
11050 Set_Do_Range_Check (Operand, False);
11051 end if;
11052 end if;
11053
f1e2dcc5 11054 -- Nothing at all to do if conversion is to the identical type so remove
9af0ddc7 11055 -- the conversion completely, it is useless, except that it may carry
11056 -- an Assignment_OK attribute, which must be propagated to the operand.
ee6ba406 11057
11058 if Operand_Type = Target_Type then
c23ec5da 11059 if Assignment_OK (N) then
11060 Set_Assignment_OK (Operand);
11061 end if;
11062
9dfe12ae 11063 Rewrite (N, Relocate_Node (Operand));
5b5df4a9 11064 goto Done;
ee6ba406 11065 end if;
11066
f1e2dcc5 11067 -- Nothing to do if this is the second argument of read. This is a
11068 -- "backwards" conversion that will be handled by the specialized code
11069 -- in attribute processing.
ee6ba406 11070
11071 if Nkind (Parent (N)) = N_Attribute_Reference
11072 and then Attribute_Name (Parent (N)) = Name_Read
11073 and then Next (First (Expressions (Parent (N)))) = N
11074 then
5b5df4a9 11075 goto Done;
11076 end if;
11077
11078 -- Check for case of converting to a type that has an invariant
ae8e8392 11079 -- associated with it. This requires an invariant check. We insert
11080 -- a call:
5b5df4a9 11081
ae8e8392 11082 -- invariant_check (typ (expr))
5b5df4a9 11083
ae8e8392 11084 -- in the code, after removing side effects from the expression.
11085 -- This is clearer than replacing the conversion into an expression
11086 -- with actions, because the context may impose additional actions
11087 -- (tag checks, membership tests, etc.) that conflict with this
11088 -- rewriting (used previously).
5b5df4a9 11089
11090 -- Note: the Comes_From_Source check, and then the resetting of this
11091 -- flag prevents what would otherwise be an infinite recursion.
11092
f54f1dff 11093 if Has_Invariants (Target_Type)
11094 and then Present (Invariant_Procedure (Target_Type))
5b5df4a9 11095 and then Comes_From_Source (N)
11096 then
11097 Set_Comes_From_Source (N, False);
ae8e8392 11098 Remove_Side_Effects (N);
11099 Insert_Action (N, Make_Invariant_Call (Duplicate_Subexpr (N)));
5b5df4a9 11100 goto Done;
ee6ba406 11101 end if;
11102
11103 -- Here if we may need to expand conversion
11104
8eb4a5eb 11105 -- If the operand of the type conversion is an arithmetic operation on
11106 -- signed integers, and the based type of the signed integer type in
11107 -- question is smaller than Standard.Integer, we promote both of the
11108 -- operands to type Integer.
11109
11110 -- For example, if we have
11111
11112 -- target-type (opnd1 + opnd2)
11113
11114 -- and opnd1 and opnd2 are of type short integer, then we rewrite
11115 -- this as:
11116
11117 -- target-type (integer(opnd1) + integer(opnd2))
11118
11119 -- We do this because we are always allowed to compute in a larger type
11120 -- if we do the right thing with the result, and in this case we are
11121 -- going to do a conversion which will do an appropriate check to make
11122 -- sure that things are in range of the target type in any case. This
11123 -- avoids some unnecessary intermediate overflows.
11124
bea86011 11125 -- We might consider a similar transformation in the case where the
11126 -- target is a real type or a 64-bit integer type, and the operand
11127 -- is an arithmetic operation using a 32-bit integer type. However,
11128 -- we do not bother with this case, because it could cause significant
6fb3c314 11129 -- inefficiencies on 32-bit machines. On a 64-bit machine it would be
bea86011 11130 -- much cheaper, but we don't want different behavior on 32-bit and
11131 -- 64-bit machines. Note that the exclusion of the 64-bit case also
11132 -- handles the configurable run-time cases where 64-bit arithmetic
11133 -- may simply be unavailable.
8eb4a5eb 11134
11135 -- Note: this circuit is partially redundant with respect to the circuit
11136 -- in Checks.Apply_Arithmetic_Overflow_Check, but we catch more cases in
11137 -- the processing here. Also we still need the Checks circuit, since we
11138 -- have to be sure not to generate junk overflow checks in the first
39a0c1d3 11139 -- place, since it would be trick to remove them here.
8eb4a5eb 11140
df40eeb0 11141 if Integer_Promotion_Possible (N) then
8eb4a5eb 11142
df40eeb0 11143 -- All conditions met, go ahead with transformation
8eb4a5eb 11144
df40eeb0 11145 declare
11146 Opnd : Node_Id;
11147 L, R : Node_Id;
bea86011 11148
df40eeb0 11149 begin
11150 R :=
11151 Make_Type_Conversion (Loc,
83c6c069 11152 Subtype_Mark => New_Occurrence_Of (Standard_Integer, Loc),
df40eeb0 11153 Expression => Relocate_Node (Right_Opnd (Operand)));
8eb4a5eb 11154
36e5d81f 11155 Opnd := New_Op_Node (Nkind (Operand), Loc);
11156 Set_Right_Opnd (Opnd, R);
8eb4a5eb 11157
36e5d81f 11158 if Nkind (Operand) in N_Binary_Op then
df40eeb0 11159 L :=
8eb4a5eb 11160 Make_Type_Conversion (Loc,
83c6c069 11161 Subtype_Mark => New_Occurrence_Of (Standard_Integer, Loc),
df40eeb0 11162 Expression => Relocate_Node (Left_Opnd (Operand)));
11163
36e5d81f 11164 Set_Left_Opnd (Opnd, L);
11165 end if;
8eb4a5eb 11166
36e5d81f 11167 Rewrite (N,
11168 Make_Type_Conversion (Loc,
11169 Subtype_Mark => Relocate_Node (Subtype_Mark (N)),
11170 Expression => Opnd));
bea86011 11171
36e5d81f 11172 Analyze_And_Resolve (N, Target_Type);
5b5df4a9 11173 goto Done;
df40eeb0 11174 end;
11175 end if;
8eb4a5eb 11176
0cba9418 11177 -- Do validity check if validity checking operands
11178
6f0d10f7 11179 if Validity_Checks_On and Validity_Check_Operands then
0cba9418 11180 Ensure_Valid (Operand);
11181 end if;
11182
ee6ba406 11183 -- Special case of converting from non-standard boolean type
11184
11185 if Is_Boolean_Type (Operand_Type)
11186 and then (Nonzero_Is_True (Operand_Type))
11187 then
11188 Adjust_Condition (Operand);
11189 Set_Etype (Operand, Standard_Boolean);
11190 Operand_Type := Standard_Boolean;
11191 end if;
11192
11193 -- Case of converting to an access type
11194
11195 if Is_Access_Type (Target_Type) then
11196
ad675b56 11197 -- If this type conversion was internally generated by the front end
281cf495 11198 -- to displace the pointer to the object to reference an interface
ad675b56 11199 -- type and the original node was an Unrestricted_Access attribute,
281cf495 11200 -- then skip applying accessibility checks (because, according to the
11201 -- GNAT Reference Manual, this attribute is similar to 'Access except
11202 -- that all accessibility and aliased view checks are omitted).
11203
11204 if not Comes_From_Source (N)
11205 and then Is_Interface (Designated_Type (Target_Type))
11206 and then Nkind (Original_Node (N)) = N_Attribute_Reference
98b2a090 11207 and then Attribute_Name (Original_Node (N)) =
11208 Name_Unrestricted_Access
281cf495 11209 then
11210 null;
11211
a3e461ac 11212 -- Apply an accessibility check when the conversion operand is an
11213 -- access parameter (or a renaming thereof), unless conversion was
ad75f6a5 11214 -- expanded from an Unchecked_ or Unrestricted_Access attribute,
4cb8adff 11215 -- or for the actual of a class-wide interface parameter. Note that
11216 -- other checks may still need to be applied below (such as tagged
11217 -- type checks).
ee6ba406 11218
281cf495 11219 elsif Is_Entity_Name (Operand)
47d210a3 11220 and then Has_Extra_Accessibility (Entity (Operand))
ee6ba406 11221 and then Ekind (Etype (Operand)) = E_Anonymous_Access_Type
a3e461ac 11222 and then (Nkind (Original_Node (N)) /= N_Attribute_Reference
11223 or else Attribute_Name (Original_Node (N)) = Name_Access)
ee6ba406 11224 then
ad75f6a5 11225 if not Comes_From_Source (N)
4cb8adff 11226 and then Nkind_In (Parent (N), N_Function_Call,
11227 N_Procedure_Call_Statement)
ad75f6a5 11228 and then Is_Interface (Designated_Type (Target_Type))
11229 and then Is_Class_Wide_Type (Designated_Type (Target_Type))
11230 then
11231 null;
11232
11233 else
11234 Apply_Accessibility_Check
11235 (Operand, Target_Type, Insert_Node => Operand);
11236 end if;
ee6ba406 11237
55dc6dc2 11238 -- If the level of the operand type is statically deeper than the
f1e2dcc5 11239 -- level of the target type, then force Program_Error. Note that this
11240 -- can only occur for cases where the attribute is within the body of
55387e86 11241 -- an instantiation, otherwise the conversion will already have been
11242 -- rejected as illegal.
11243
11244 -- Note: warnings are issued by the analyzer for the instance cases
ee6ba406 11245
11246 elsif In_Instance_Body
55387e86 11247
11248 -- The case where the target type is an anonymous access type of
11249 -- a discriminant is excluded, because the level of such a type
11250 -- depends on the context and currently the level returned for such
11251 -- types is zero, resulting in warnings about about check failures
11252 -- in certain legal cases involving class-wide interfaces as the
11253 -- designated type (some cases, such as return statements, are
11254 -- checked at run time, but not clear if these are handled right
11255 -- in general, see 3.10.2(12/2-12.5/3) ???).
11256
fd71e467 11257 and then
11258 not (Ekind (Target_Type) = E_Anonymous_Access_Type
11259 and then Present (Associated_Node_For_Itype (Target_Type))
11260 and then Nkind (Associated_Node_For_Itype (Target_Type)) =
11261 N_Discriminant_Specification)
11262 and then
11263 Type_Access_Level (Operand_Type) > Type_Access_Level (Target_Type)
ee6ba406 11264 then
515242d8 11265 Raise_Accessibility_Error;
56e11f12 11266 goto Done;
ee6ba406 11267
f1e2dcc5 11268 -- When the operand is a selected access discriminant the check needs
11269 -- to be made against the level of the object denoted by the prefix
11270 -- of the selected name. Force Program_Error for this case as well
11271 -- (this accessibility violation can only happen if within the body
11272 -- of an instantiation).
ee6ba406 11273
11274 elsif In_Instance_Body
11275 and then Ekind (Operand_Type) = E_Anonymous_Access_Type
11276 and then Nkind (Operand) = N_Selected_Component
11277 and then Object_Access_Level (Operand) >
11278 Type_Access_Level (Target_Type)
11279 then
515242d8 11280 Raise_Accessibility_Error;
5b5df4a9 11281 goto Done;
ee6ba406 11282 end if;
11283 end if;
11284
11285 -- Case of conversions of tagged types and access to tagged types
11286
f1e2dcc5 11287 -- When needed, that is to say when the expression is class-wide, Add
11288 -- runtime a tag check for (strict) downward conversion by using the
11289 -- membership test, generating:
ee6ba406 11290
11291 -- [constraint_error when Operand not in Target_Type'Class]
11292
11293 -- or in the access type case
11294
11295 -- [constraint_error
11296 -- when Operand /= null
11297 -- and then Operand.all not in
11298 -- Designated_Type (Target_Type)'Class]
11299
11300 if (Is_Access_Type (Target_Type)
11301 and then Is_Tagged_Type (Designated_Type (Target_Type)))
11302 or else Is_Tagged_Type (Target_Type)
11303 then
f1e2dcc5 11304 -- Do not do any expansion in the access type case if the parent is a
11305 -- renaming, since this is an error situation which will be caught by
11306 -- Sem_Ch8, and the expansion can interfere with this error check.
ee6ba406 11307
fd1be697 11308 if Is_Access_Type (Target_Type) and then Is_Renamed_Object (N) then
5b5df4a9 11309 goto Done;
ee6ba406 11310 end if;
11311
99f2248e 11312 -- Otherwise, proceed with processing tagged conversion
ee6ba406 11313
fd1be697 11314 Tagged_Conversion : declare
1dd89e29 11315 Actual_Op_Typ : Entity_Id;
11316 Actual_Targ_Typ : Entity_Id;
11317 Make_Conversion : Boolean := False;
11318 Root_Op_Typ : Entity_Id;
ee6ba406 11319
1dd89e29 11320 procedure Make_Tag_Check (Targ_Typ : Entity_Id);
11321 -- Create a membership check to test whether Operand is a member
11322 -- of Targ_Typ. If the original Target_Type is an access, include
11323 -- a test for null value. The check is inserted at N.
11324
11325 --------------------
11326 -- Make_Tag_Check --
11327 --------------------
11328
11329 procedure Make_Tag_Check (Targ_Typ : Entity_Id) is
11330 Cond : Node_Id;
11331
11332 begin
11333 -- Generate:
11334 -- [Constraint_Error
11335 -- when Operand /= null
11336 -- and then Operand.all not in Targ_Typ]
11337
11338 if Is_Access_Type (Target_Type) then
11339 Cond :=
11340 Make_And_Then (Loc,
11341 Left_Opnd =>
11342 Make_Op_Ne (Loc,
11343 Left_Opnd => Duplicate_Subexpr_No_Checks (Operand),
11344 Right_Opnd => Make_Null (Loc)),
11345
11346 Right_Opnd =>
11347 Make_Not_In (Loc,
11348 Left_Opnd =>
11349 Make_Explicit_Dereference (Loc,
11350 Prefix => Duplicate_Subexpr_No_Checks (Operand)),
83c6c069 11351 Right_Opnd => New_Occurrence_Of (Targ_Typ, Loc)));
1dd89e29 11352
11353 -- Generate:
11354 -- [Constraint_Error when Operand not in Targ_Typ]
11355
11356 else
11357 Cond :=
11358 Make_Not_In (Loc,
11359 Left_Opnd => Duplicate_Subexpr_No_Checks (Operand),
83c6c069 11360 Right_Opnd => New_Occurrence_Of (Targ_Typ, Loc));
1dd89e29 11361 end if;
11362
11363 Insert_Action (N,
11364 Make_Raise_Constraint_Error (Loc,
11365 Condition => Cond,
87b5bd92 11366 Reason => CE_Tag_Check_Failed),
11367 Suppress => All_Checks);
1dd89e29 11368 end Make_Tag_Check;
11369
fd1be697 11370 -- Start of processing for Tagged_Conversion
ee6ba406 11371
11372 begin
87d6f1a4 11373 -- Handle entities from the limited view
dc95506e 11374
87d6f1a4 11375 if Is_Access_Type (Operand_Type) then
dc95506e 11376 Actual_Op_Typ :=
11377 Available_View (Designated_Type (Operand_Type));
87d6f1a4 11378 else
11379 Actual_Op_Typ := Operand_Type;
11380 end if;
11381
11382 if Is_Access_Type (Target_Type) then
dc95506e 11383 Actual_Targ_Typ :=
11384 Available_View (Designated_Type (Target_Type));
ee6ba406 11385 else
1dd89e29 11386 Actual_Targ_Typ := Target_Type;
ee6ba406 11387 end if;
11388
1dd89e29 11389 Root_Op_Typ := Root_Type (Actual_Op_Typ);
11390
e8ccec48 11391 -- Ada 2005 (AI-251): Handle interface type conversion
11392
250b2c22 11393 if Is_Interface (Actual_Op_Typ)
c86b9754 11394 or else
11395 Is_Interface (Actual_Targ_Typ)
250b2c22 11396 then
61ce7f9f 11397 Expand_Interface_Conversion (N);
5b5df4a9 11398 goto Done;
e8ccec48 11399 end if;
11400
1dd89e29 11401 if not Tag_Checks_Suppressed (Actual_Targ_Typ) then
ee6ba406 11402
1dd89e29 11403 -- Create a runtime tag check for a downward class-wide type
11404 -- conversion.
ee6ba406 11405
1dd89e29 11406 if Is_Class_Wide_Type (Actual_Op_Typ)
dc95506e 11407 and then Actual_Op_Typ /= Actual_Targ_Typ
1dd89e29 11408 and then Root_Op_Typ /= Actual_Targ_Typ
cb4af01d 11409 and then Is_Ancestor (Root_Op_Typ, Actual_Targ_Typ,
11410 Use_Full_View => True)
1dd89e29 11411 then
11412 Make_Tag_Check (Class_Wide_Type (Actual_Targ_Typ));
11413 Make_Conversion := True;
11414 end if;
ee6ba406 11415
1dd89e29 11416 -- AI05-0073: If the result subtype of the function is defined
11417 -- by an access_definition designating a specific tagged type
11418 -- T, a check is made that the result value is null or the tag
11419 -- of the object designated by the result value identifies T.
11420 -- Constraint_Error is raised if this check fails.
ee6ba406 11421
ae70cd27 11422 if Nkind (Parent (N)) = N_Simple_Return_Statement then
1dd89e29 11423 declare
68bac88c 11424 Func : Entity_Id;
1dd89e29 11425 Func_Typ : Entity_Id;
11426
11427 begin
68bac88c 11428 -- Climb scope stack looking for the enclosing function
1dd89e29 11429
68bac88c 11430 Func := Current_Scope;
1dd89e29 11431 while Present (Func)
11432 and then Ekind (Func) /= E_Function
11433 loop
11434 Func := Scope (Func);
11435 end loop;
11436
11437 -- The function's return subtype must be defined using
11438 -- an access definition.
11439
11440 if Nkind (Result_Definition (Parent (Func))) =
11441 N_Access_Definition
11442 then
11443 Func_Typ := Directly_Designated_Type (Etype (Func));
11444
11445 -- The return subtype denotes a specific tagged type,
11446 -- in other words, a non class-wide type.
11447
11448 if Is_Tagged_Type (Func_Typ)
11449 and then not Is_Class_Wide_Type (Func_Typ)
11450 then
11451 Make_Tag_Check (Actual_Targ_Typ);
11452 Make_Conversion := True;
11453 end if;
11454 end if;
11455 end;
ee6ba406 11456 end if;
11457
1dd89e29 11458 -- We have generated a tag check for either a class-wide type
11459 -- conversion or for AI05-0073.
ee6ba406 11460
1dd89e29 11461 if Make_Conversion then
11462 declare
11463 Conv : Node_Id;
11464 begin
11465 Conv :=
11466 Make_Unchecked_Type_Conversion (Loc,
11467 Subtype_Mark => New_Occurrence_Of (Target_Type, Loc),
11468 Expression => Relocate_Node (Expression (N)));
11469 Rewrite (N, Conv);
11470 Analyze_And_Resolve (N, Target_Type);
11471 end;
11472 end if;
ee6ba406 11473 end if;
fd1be697 11474 end Tagged_Conversion;
ee6ba406 11475
11476 -- Case of other access type conversions
11477
11478 elsif Is_Access_Type (Target_Type) then
11479 Apply_Constraint_Check (Operand, Target_Type);
11480
11481 -- Case of conversions from a fixed-point type
11482
f1e2dcc5 11483 -- These conversions require special expansion and processing, found in
11484 -- the Exp_Fixd package. We ignore cases where Conversion_OK is set,
11485 -- since from a semantic point of view, these are simple integer
ee6ba406 11486 -- conversions, which do not need further processing.
11487
11488 elsif Is_Fixed_Point_Type (Operand_Type)
11489 and then not Conversion_OK (N)
11490 then
11491 -- We should never see universal fixed at this case, since the
11492 -- expansion of the constituent divide or multiply should have
11493 -- eliminated the explicit mention of universal fixed.
11494
11495 pragma Assert (Operand_Type /= Universal_Fixed);
11496
f1e2dcc5 11497 -- Check for special case of the conversion to universal real that
11498 -- occurs as a result of the use of a round attribute. In this case,
11499 -- the real type for the conversion is taken from the target type of
11500 -- the Round attribute and the result must be marked as rounded.
ee6ba406 11501
11502 if Target_Type = Universal_Real
11503 and then Nkind (Parent (N)) = N_Attribute_Reference
11504 and then Attribute_Name (Parent (N)) = Name_Round
11505 then
11506 Set_Rounded_Result (N);
11507 Set_Etype (N, Etype (Parent (N)));
11508 end if;
11509
11510 -- Otherwise do correct fixed-conversion, but skip these if the
fd1be697 11511 -- Conversion_OK flag is set, because from a semantic point of view
11512 -- these are simple integer conversions needing no further processing
11513 -- (the backend will simply treat them as integers).
ee6ba406 11514
11515 if not Conversion_OK (N) then
11516 if Is_Fixed_Point_Type (Etype (N)) then
11517 Expand_Convert_Fixed_To_Fixed (N);
11518 Real_Range_Check;
11519
11520 elsif Is_Integer_Type (Etype (N)) then
11521 Expand_Convert_Fixed_To_Integer (N);
11522
11523 else
11524 pragma Assert (Is_Floating_Point_Type (Etype (N)));
11525 Expand_Convert_Fixed_To_Float (N);
11526 Real_Range_Check;
11527 end if;
11528 end if;
11529
11530 -- Case of conversions to a fixed-point type
11531
f1e2dcc5 11532 -- These conversions require special expansion and processing, found in
11533 -- the Exp_Fixd package. Again, ignore cases where Conversion_OK is set,
11534 -- since from a semantic point of view, these are simple integer
11535 -- conversions, which do not need further processing.
ee6ba406 11536
11537 elsif Is_Fixed_Point_Type (Target_Type)
11538 and then not Conversion_OK (N)
11539 then
11540 if Is_Integer_Type (Operand_Type) then
11541 Expand_Convert_Integer_To_Fixed (N);
11542 Real_Range_Check;
11543 else
11544 pragma Assert (Is_Floating_Point_Type (Operand_Type));
11545 Expand_Convert_Float_To_Fixed (N);
11546 Real_Range_Check;
11547 end if;
11548
11549 -- Case of float-to-integer conversions
11550
11551 -- We also handle float-to-fixed conversions with Conversion_OK set
11552 -- since semantically the fixed-point target is treated as though it
11553 -- were an integer in such cases.
11554
11555 elsif Is_Floating_Point_Type (Operand_Type)
11556 and then
11557 (Is_Integer_Type (Target_Type)
11558 or else
11559 (Is_Fixed_Point_Type (Target_Type) and then Conversion_OK (N)))
11560 then
ee6ba406 11561 -- One more check here, gcc is still not able to do conversions of
11562 -- this type with proper overflow checking, and so gigi is doing an
11563 -- approximation of what is required by doing floating-point compares
11564 -- with the end-point. But that can lose precision in some cases, and
38f5559f 11565 -- give a wrong result. Converting the operand to Universal_Real is
ee6ba406 11566 -- helpful, but still does not catch all cases with 64-bit integers
fd1be697 11567 -- on targets with only 64-bit floats.
99f2248e 11568
11569 -- The above comment seems obsoleted by Apply_Float_Conversion_Check
11570 -- Can this code be removed ???
ee6ba406 11571
9dfe12ae 11572 if Do_Range_Check (Operand) then
11573 Rewrite (Operand,
ee6ba406 11574 Make_Type_Conversion (Loc,
11575 Subtype_Mark =>
38f5559f 11576 New_Occurrence_Of (Universal_Real, Loc),
ee6ba406 11577 Expression =>
9dfe12ae 11578 Relocate_Node (Operand)));
ee6ba406 11579
38f5559f 11580 Set_Etype (Operand, Universal_Real);
9dfe12ae 11581 Enable_Range_Check (Operand);
11582 Set_Do_Range_Check (Expression (Operand), False);
ee6ba406 11583 end if;
11584
11585 -- Case of array conversions
11586
f1e2dcc5 11587 -- Expansion of array conversions, add required length/range checks but
11588 -- only do this if there is no change of representation. For handling of
11589 -- this case, see Handle_Changed_Representation.
ee6ba406 11590
11591 elsif Is_Array_Type (Target_Type) then
ee6ba406 11592 if Is_Constrained (Target_Type) then
11593 Apply_Length_Check (Operand, Target_Type);
11594 else
11595 Apply_Range_Check (Operand, Target_Type);
11596 end if;
11597
11598 Handle_Changed_Representation;
11599
11600 -- Case of conversions of discriminated types
11601
f1e2dcc5 11602 -- Add required discriminant checks if target is constrained. Again this
11603 -- change is skipped if we have a change of representation.
ee6ba406 11604
11605 elsif Has_Discriminants (Target_Type)
11606 and then Is_Constrained (Target_Type)
11607 then
11608 Apply_Discriminant_Check (Operand, Target_Type);
11609 Handle_Changed_Representation;
11610
11611 -- Case of all other record conversions. The only processing required
11612 -- is to check for a change of representation requiring the special
11613 -- assignment processing.
11614
11615 elsif Is_Record_Type (Target_Type) then
00f91aef 11616
11617 -- Ada 2005 (AI-216): Program_Error is raised when converting from
f1e2dcc5 11618 -- a derived Unchecked_Union type to an unconstrained type that is
11619 -- not Unchecked_Union if the operand lacks inferable discriminants.
00f91aef 11620
11621 if Is_Derived_Type (Operand_Type)
11622 and then Is_Unchecked_Union (Base_Type (Operand_Type))
11623 and then not Is_Constrained (Target_Type)
11624 and then not Is_Unchecked_Union (Base_Type (Target_Type))
11625 and then not Has_Inferable_Discriminants (Operand)
11626 then
f1e2dcc5 11627 -- To prevent Gigi from generating illegal code, we generate a
00f91aef 11628 -- Program_Error node, but we give it the target type of the
de922300 11629 -- conversion (is this requirement documented somewhere ???)
00f91aef 11630
11631 declare
11632 PE : constant Node_Id := Make_Raise_Program_Error (Loc,
11633 Reason => PE_Unchecked_Union_Restriction);
11634
11635 begin
11636 Set_Etype (PE, Target_Type);
11637 Rewrite (N, PE);
11638
11639 end;
11640 else
11641 Handle_Changed_Representation;
11642 end if;
ee6ba406 11643
11644 -- Case of conversions of enumeration types
11645
11646 elsif Is_Enumeration_Type (Target_Type) then
11647
11648 -- Special processing is required if there is a change of
fd1be697 11649 -- representation (from enumeration representation clauses).
ee6ba406 11650
11651 if not Same_Representation (Target_Type, Operand_Type) then
11652
11653 -- Convert: x(y) to x'val (ytyp'val (y))
11654
11655 Rewrite (N,
c8af2df9 11656 Make_Attribute_Reference (Loc,
11657 Prefix => New_Occurrence_Of (Target_Type, Loc),
11658 Attribute_Name => Name_Val,
11659 Expressions => New_List (
11660 Make_Attribute_Reference (Loc,
11661 Prefix => New_Occurrence_Of (Operand_Type, Loc),
11662 Attribute_Name => Name_Pos,
11663 Expressions => New_List (Operand)))));
ee6ba406 11664
11665 Analyze_And_Resolve (N, Target_Type);
11666 end if;
11667
11668 -- Case of conversions to floating-point
11669
11670 elsif Is_Floating_Point_Type (Target_Type) then
11671 Real_Range_Check;
ee6ba406 11672 end if;
11673
f1e2dcc5 11674 -- At this stage, either the conversion node has been transformed into
fd1be697 11675 -- some other equivalent expression, or left as a conversion that can be
11676 -- handled by Gigi, in the following cases:
ee6ba406 11677
11678 -- Conversions with no change of representation or type
11679
f1e2dcc5 11680 -- Numeric conversions involving integer, floating- and fixed-point
11681 -- values. Fixed-point values are allowed only if Conversion_OK is
11682 -- set, i.e. if the fixed-point values are to be treated as integers.
ee6ba406 11683
f84d3d59 11684 -- No other conversions should be passed to Gigi
11685
11686 -- Check: are these rules stated in sinfo??? if so, why restate here???
ee6ba406 11687
f1e2dcc5 11688 -- The only remaining step is to generate a range check if we still have
11689 -- a type conversion at this stage and Do_Range_Check is set. For now we
1f5d83cf 11690 -- do this only for conversions of discrete types and for float-to-float
11691 -- conversions.
9dfe12ae 11692
c8a2d809 11693 if Nkind (N) = N_Type_Conversion then
9dfe12ae 11694
1f5d83cf 11695 -- For now we only support floating-point cases where both source
11696 -- and target are floating-point types. Conversions where the source
11697 -- and target involve integer or fixed-point types are still TBD,
11698 -- though not clear whether those can even happen at this point, due
11699 -- to transformations above. ???
9dfe12ae 11700
c8a2d809 11701 if Is_Floating_Point_Type (Etype (N))
1f5d83cf 11702 and then Is_Floating_Point_Type (Etype (Expression (N)))
c8a2d809 11703 then
11704 if Do_Range_Check (Expression (N))
11705 and then Is_Floating_Point_Type (Target_Type)
11706 then
11707 Generate_Range_Check
11708 (Expression (N), Target_Type, CE_Range_Check_Failed);
11709 end if;
9dfe12ae 11710
1f5d83cf 11711 -- Discrete-to-discrete conversions
11712
c8a2d809 11713 elsif Is_Discrete_Type (Etype (N)) then
11714 declare
11715 Expr : constant Node_Id := Expression (N);
11716 Ftyp : Entity_Id;
11717 Ityp : Entity_Id;
9dfe12ae 11718
c8a2d809 11719 begin
11720 if Do_Range_Check (Expr)
11721 and then Is_Discrete_Type (Etype (Expr))
9dfe12ae 11722 then
c8a2d809 11723 Set_Do_Range_Check (Expr, False);
9dfe12ae 11724
c8a2d809 11725 -- Before we do a range check, we have to deal with treating
11726 -- a fixed-point operand as an integer. The way we do this
11727 -- is simply to do an unchecked conversion to an appropriate
11728 -- integer type large enough to hold the result.
9dfe12ae 11729
c8a2d809 11730 -- This code is not active yet, because we are only dealing
11731 -- with discrete types so far ???
9dfe12ae 11732
c8a2d809 11733 if Nkind (Expr) in N_Has_Treat_Fixed_As_Integer
11734 and then Treat_Fixed_As_Integer (Expr)
11735 then
11736 Ftyp := Base_Type (Etype (Expr));
9dfe12ae 11737
c8a2d809 11738 if Esize (Ftyp) >= Esize (Standard_Integer) then
11739 Ityp := Standard_Long_Long_Integer;
11740 else
11741 Ityp := Standard_Integer;
11742 end if;
cda40848 11743
c8a2d809 11744 Rewrite (Expr, Unchecked_Convert_To (Ityp, Expr));
11745 end if;
11746
11747 -- Reset overflow flag, since the range check will include
11748 -- dealing with possible overflow, and generate the check.
11749 -- If Address is either a source type or target type,
11750 -- suppress range check to avoid typing anomalies when
11751 -- it is a visible integer type.
11752
11753 Set_Do_Overflow_Check (N, False);
11754
2301b984 11755 if not Is_Descendant_Of_Address (Etype (Expr))
11756 and then not Is_Descendant_Of_Address (Target_Type)
c8a2d809 11757 then
11758 Generate_Range_Check
11759 (Expr, Target_Type, CE_Range_Check_Failed);
11760 end if;
9756a605 11761 end if;
c8a2d809 11762 end;
11763 end if;
9dfe12ae 11764 end if;
38f5559f 11765
5b5df4a9 11766 -- Here at end of processing
11767
7aafae1c 11768 <<Done>>
11769 -- Apply predicate check if required. Note that we can't just call
11770 -- Apply_Predicate_Check here, because the type looks right after
11771 -- the conversion and it would omit the check. The Comes_From_Source
11772 -- guard is necessary to prevent infinite recursions when we generate
11773 -- internal conversions for the purpose of checking predicates.
11774
11775 if Present (Predicate_Function (Target_Type))
2c011bc5 11776 and then not Predicates_Ignored (Target_Type)
7aafae1c 11777 and then Target_Type /= Operand_Type
11778 and then Comes_From_Source (N)
11779 then
0319323f 11780 declare
11781 New_Expr : constant Node_Id := Duplicate_Subexpr (N);
11782
11783 begin
11784 -- Avoid infinite recursion on the subsequent expansion of
11785 -- of the copy of the original type conversion.
11786
11787 Set_Comes_From_Source (New_Expr, False);
11788 Insert_Action (N, Make_Predicate_Check (Target_Type, New_Expr));
11789 end;
7aafae1c 11790 end if;
ee6ba406 11791 end Expand_N_Type_Conversion;
11792
11793 -----------------------------------
11794 -- Expand_N_Unchecked_Expression --
11795 -----------------------------------
11796
fd1be697 11797 -- Remove the unchecked expression node from the tree. Its job was simply
ee6ba406 11798 -- to make sure that its constituent expression was handled with checks
11799 -- off, and now that that is done, we can remove it from the tree, and
fd1be697 11800 -- indeed must, since Gigi does not expect to see these nodes.
ee6ba406 11801
11802 procedure Expand_N_Unchecked_Expression (N : Node_Id) is
11803 Exp : constant Node_Id := Expression (N);
ee6ba406 11804 begin
fd1be697 11805 Set_Assignment_OK (Exp, Assignment_OK (N) or else Assignment_OK (Exp));
ee6ba406 11806 Rewrite (N, Exp);
11807 end Expand_N_Unchecked_Expression;
11808
11809 ----------------------------------------
11810 -- Expand_N_Unchecked_Type_Conversion --
11811 ----------------------------------------
11812
f1e2dcc5 11813 -- If this cannot be handled by Gigi and we haven't already made a
11814 -- temporary for it, do it now.
ee6ba406 11815
11816 procedure Expand_N_Unchecked_Type_Conversion (N : Node_Id) is
11817 Target_Type : constant Entity_Id := Etype (N);
11818 Operand : constant Node_Id := Expression (N);
11819 Operand_Type : constant Entity_Id := Etype (Operand);
11820
11821 begin
c23ec5da 11822 -- Nothing at all to do if conversion is to the identical type so remove
9af0ddc7 11823 -- the conversion completely, it is useless, except that it may carry
fd1be697 11824 -- an Assignment_OK indication which must be propagated to the operand.
c23ec5da 11825
11826 if Operand_Type = Target_Type then
dea95b6d 11827
fd1be697 11828 -- Code duplicates Expand_N_Unchecked_Expression above, factor???
11829
c23ec5da 11830 if Assignment_OK (N) then
11831 Set_Assignment_OK (Operand);
11832 end if;
11833
11834 Rewrite (N, Relocate_Node (Operand));
11835 return;
11836 end if;
11837
ee6ba406 11838 -- If we have a conversion of a compile time known value to a target
11839 -- type and the value is in range of the target type, then we can simply
11840 -- replace the construct by an integer literal of the correct type. We
11841 -- only apply this to integer types being converted. Possibly it may
11842 -- apply in other cases, but it is too much trouble to worry about.
11843
11844 -- Note that we do not do this transformation if the Kill_Range_Check
11845 -- flag is set, since then the value may be outside the expected range.
11846 -- This happens in the Normalize_Scalars case.
11847
e8ccec48 11848 -- We also skip this if either the target or operand type is biased
11849 -- because in this case, the unchecked conversion is supposed to
11850 -- preserve the bit pattern, not the integer value.
11851
ee6ba406 11852 if Is_Integer_Type (Target_Type)
e8ccec48 11853 and then not Has_Biased_Representation (Target_Type)
ee6ba406 11854 and then Is_Integer_Type (Operand_Type)
e8ccec48 11855 and then not Has_Biased_Representation (Operand_Type)
ee6ba406 11856 and then Compile_Time_Known_Value (Operand)
11857 and then not Kill_Range_Check (N)
11858 then
11859 declare
11860 Val : constant Uint := Expr_Value (Operand);
11861
11862 begin
11863 if Compile_Time_Known_Value (Type_Low_Bound (Target_Type))
11864 and then
11865 Compile_Time_Known_Value (Type_High_Bound (Target_Type))
11866 and then
11867 Val >= Expr_Value (Type_Low_Bound (Target_Type))
11868 and then
11869 Val <= Expr_Value (Type_High_Bound (Target_Type))
11870 then
11871 Rewrite (N, Make_Integer_Literal (Sloc (N), Val));
9756a605 11872
f1e2dcc5 11873 -- If Address is the target type, just set the type to avoid a
11874 -- spurious type error on the literal when Address is a visible
11875 -- integer type.
9756a605 11876
2301b984 11877 if Is_Descendant_Of_Address (Target_Type) then
9756a605 11878 Set_Etype (N, Target_Type);
11879 else
11880 Analyze_And_Resolve (N, Target_Type);
11881 end if;
11882
ee6ba406 11883 return;
11884 end if;
11885 end;
11886 end if;
11887
11888 -- Nothing to do if conversion is safe
11889
11890 if Safe_Unchecked_Type_Conversion (N) then
11891 return;
11892 end if;
11893
11894 -- Otherwise force evaluation unless Assignment_OK flag is set (this
6e9f198b 11895 -- flag indicates ??? More comments needed here)
ee6ba406 11896
11897 if Assignment_OK (N) then
11898 null;
11899 else
11900 Force_Evaluation (N);
11901 end if;
11902 end Expand_N_Unchecked_Type_Conversion;
11903
11904 ----------------------------
11905 -- Expand_Record_Equality --
11906 ----------------------------
11907
11908 -- For non-variant records, Equality is expanded when needed into:
11909
11910 -- and then Lhs.Discr1 = Rhs.Discr1
11911 -- and then ...
11912 -- and then Lhs.Discrn = Rhs.Discrn
11913 -- and then Lhs.Cmp1 = Rhs.Cmp1
11914 -- and then ...
11915 -- and then Lhs.Cmpn = Rhs.Cmpn
11916
2a801d20 11917 -- The expression is folded by the back end for adjacent fields. This
ee6ba406 11918 -- function is called for tagged record in only one occasion: for imple-
11919 -- menting predefined primitive equality (see Predefined_Primitives_Bodies)
11920 -- otherwise the primitive "=" is used directly.
11921
11922 function Expand_Record_Equality
11923 (Nod : Node_Id;
11924 Typ : Entity_Id;
11925 Lhs : Node_Id;
11926 Rhs : Node_Id;
752e1833 11927 Bodies : List_Id) return Node_Id
ee6ba406 11928 is
11929 Loc : constant Source_Ptr := Sloc (Nod);
11930
e2aa7314 11931 Result : Node_Id;
11932 C : Entity_Id;
11933
11934 First_Time : Boolean := True;
11935
0145066d 11936 function Element_To_Compare (C : Entity_Id) return Entity_Id;
11937 -- Return the next discriminant or component to compare, starting with
11938 -- C, skipping inherited components.
e2aa7314 11939
0145066d 11940 ------------------------
11941 -- Element_To_Compare --
11942 ------------------------
ee6ba406 11943
0145066d 11944 function Element_To_Compare (C : Entity_Id) return Entity_Id is
11945 Comp : Entity_Id;
6b65ff8e 11946
ee6ba406 11947 begin
0145066d 11948 Comp := C;
0145066d 11949 loop
11950 -- Exit loop when the next element to be compared is found, or
11951 -- there is no more such element.
ee6ba406 11952
0145066d 11953 exit when No (Comp);
6a06584c 11954
0145066d 11955 exit when Ekind_In (Comp, E_Discriminant, E_Component)
11956 and then not (
ee6ba406 11957
0145066d 11958 -- Skip inherited components
ee6ba406 11959
0145066d 11960 -- Note: for a tagged type, we always generate the "=" primitive
11961 -- for the base type (not on the first subtype), so the test for
11962 -- Comp /= Original_Record_Component (Comp) is True for
11963 -- inherited components only.
e423341f 11964
0145066d 11965 (Is_Tagged_Type (Typ)
6b65ff8e 11966 and then Comp /= Original_Record_Component (Comp))
e423341f 11967
0145066d 11968 -- Skip _Tag
914796b1 11969
0145066d 11970 or else Chars (Comp) = Name_uTag
11971
0145066d 11972 -- Skip interface elements (secondary tags???)
11973
11974 or else Is_Interface (Etype (Comp)));
11975
11976 Next_Entity (Comp);
11977 end loop;
11978
11979 return Comp;
11980 end Element_To_Compare;
ee6ba406 11981
ee6ba406 11982 -- Start of processing for Expand_Record_Equality
11983
11984 begin
ee6ba406 11985 -- Generates the following code: (assuming that Typ has one Discr and
11986 -- component C2 is also a record)
11987
11988 -- True
11989 -- and then Lhs.Discr1 = Rhs.Discr1
11990 -- and then Lhs.C1 = Rhs.C1
11991 -- and then Lhs.C2.C1=Rhs.C2.C1 and then ... Lhs.C2.Cn=Rhs.C2.Cn
11992 -- and then ...
11993 -- and then Lhs.Cmpn = Rhs.Cmpn
11994
83c6c069 11995 Result := New_Occurrence_Of (Standard_True, Loc);
0145066d 11996 C := Element_To_Compare (First_Entity (Typ));
ee6ba406 11997 while Present (C) loop
ee6ba406 11998 declare
11999 New_Lhs : Node_Id;
12000 New_Rhs : Node_Id;
b374288a 12001 Check : Node_Id;
ee6ba406 12002
12003 begin
12004 if First_Time then
12005 First_Time := False;
12006 New_Lhs := Lhs;
12007 New_Rhs := Rhs;
ee6ba406 12008 else
12009 New_Lhs := New_Copy_Tree (Lhs);
12010 New_Rhs := New_Copy_Tree (Rhs);
12011 end if;
12012
b374288a 12013 Check :=
12014 Expand_Composite_Equality (Nod, Etype (C),
12015 Lhs =>
12016 Make_Selected_Component (Loc,
26080eca 12017 Prefix => New_Lhs,
83c6c069 12018 Selector_Name => New_Occurrence_Of (C, Loc)),
b374288a 12019 Rhs =>
12020 Make_Selected_Component (Loc,
26080eca 12021 Prefix => New_Rhs,
83c6c069 12022 Selector_Name => New_Occurrence_Of (C, Loc)),
b374288a 12023 Bodies => Bodies);
12024
12025 -- If some (sub)component is an unchecked_union, the whole
12026 -- operation will raise program error.
12027
12028 if Nkind (Check) = N_Raise_Program_Error then
12029 Result := Check;
12030 Set_Etype (Result, Standard_Boolean);
12031 exit;
12032 else
12033 Result :=
12034 Make_And_Then (Loc,
12035 Left_Opnd => Result,
12036 Right_Opnd => Check);
12037 end if;
ee6ba406 12038 end;
12039
0145066d 12040 C := Element_To_Compare (Next_Entity (C));
ee6ba406 12041 end loop;
12042
12043 return Result;
12044 end Expand_Record_Equality;
12045
9765de15 12046 ---------------------------
12047 -- Expand_Set_Membership --
12048 ---------------------------
12049
12050 procedure Expand_Set_Membership (N : Node_Id) is
12051 Lop : constant Node_Id := Left_Opnd (N);
12052 Alt : Node_Id;
12053 Res : Node_Id;
12054
12055 function Make_Cond (Alt : Node_Id) return Node_Id;
12056 -- If the alternative is a subtype mark, create a simple membership
12057 -- test. Otherwise create an equality test for it.
12058
12059 ---------------
12060 -- Make_Cond --
12061 ---------------
12062
12063 function Make_Cond (Alt : Node_Id) return Node_Id is
12064 Cond : Node_Id;
12065 L : constant Node_Id := New_Copy (Lop);
12066 R : constant Node_Id := Relocate_Node (Alt);
12067
12068 begin
12069 if (Is_Entity_Name (Alt) and then Is_Type (Entity (Alt)))
12070 or else Nkind (Alt) = N_Range
12071 then
12072 Cond :=
12073 Make_In (Sloc (Alt),
12074 Left_Opnd => L,
12075 Right_Opnd => R);
12076 else
12077 Cond :=
12078 Make_Op_Eq (Sloc (Alt),
12079 Left_Opnd => L,
12080 Right_Opnd => R);
12081 end if;
12082
12083 return Cond;
12084 end Make_Cond;
12085
12086 -- Start of processing for Expand_Set_Membership
12087
12088 begin
12089 Remove_Side_Effects (Lop);
12090
12091 Alt := Last (Alternatives (N));
12092 Res := Make_Cond (Alt);
12093
12094 Prev (Alt);
12095 while Present (Alt) loop
12096 Res :=
12097 Make_Or_Else (Sloc (Alt),
12098 Left_Opnd => Make_Cond (Alt),
12099 Right_Opnd => Res);
12100 Prev (Alt);
12101 end loop;
12102
12103 Rewrite (N, Res);
12104 Analyze_And_Resolve (N, Standard_Boolean);
12105 end Expand_Set_Membership;
12106
3755dbc5 12107 -----------------------------------
12108 -- Expand_Short_Circuit_Operator --
12109 -----------------------------------
12110
6b73a73b 12111 -- Deal with special expansion if actions are present for the right operand
12112 -- and deal with optimizing case of arguments being True or False. We also
12113 -- deal with the special case of non-standard boolean values.
3755dbc5 12114
12115 procedure Expand_Short_Circuit_Operator (N : Node_Id) is
12116 Loc : constant Source_Ptr := Sloc (N);
12117 Typ : constant Entity_Id := Etype (N);
3755dbc5 12118 Left : constant Node_Id := Left_Opnd (N);
12119 Right : constant Node_Id := Right_Opnd (N);
6b73a73b 12120 LocR : constant Source_Ptr := Sloc (Right);
3755dbc5 12121 Actlist : List_Id;
12122
12123 Shortcut_Value : constant Boolean := Nkind (N) = N_Or_Else;
12124 Shortcut_Ent : constant Entity_Id := Boolean_Literals (Shortcut_Value);
12125 -- If Left = Shortcut_Value then Right need not be evaluated
12126
9c890dc4 12127 function Make_Test_Expr (Opnd : Node_Id) return Node_Id;
12128 -- For Opnd a boolean expression, return a Boolean expression equivalent
12129 -- to Opnd /= Shortcut_Value.
12130
12131 --------------------
12132 -- Make_Test_Expr --
12133 --------------------
12134
12135 function Make_Test_Expr (Opnd : Node_Id) return Node_Id is
12136 begin
12137 if Shortcut_Value then
12138 return Make_Op_Not (Sloc (Opnd), Opnd);
12139 else
12140 return Opnd;
12141 end if;
12142 end Make_Test_Expr;
12143
12144 -- Local variables
12145
12146 Op_Var : Entity_Id;
12147 -- Entity for a temporary variable holding the value of the operator,
12148 -- used for expansion in the case where actions are present.
12149
12150 -- Start of processing for Expand_Short_Circuit_Operator
12151
3755dbc5 12152 begin
12153 -- Deal with non-standard booleans
12154
12155 if Is_Boolean_Type (Typ) then
12156 Adjust_Condition (Left);
12157 Adjust_Condition (Right);
12158 Set_Etype (N, Standard_Boolean);
12159 end if;
12160
12161 -- Check for cases where left argument is known to be True or False
12162
12163 if Compile_Time_Known_Value (Left) then
9a4f36a4 12164
12165 -- Mark SCO for left condition as compile time known
12166
12167 if Generate_SCO and then Comes_From_Source (Left) then
12168 Set_SCO_Condition (Left, Expr_Value_E (Left) = Standard_True);
12169 end if;
12170
3755dbc5 12171 -- Rewrite True AND THEN Right / False OR ELSE Right to Right.
12172 -- Any actions associated with Right will be executed unconditionally
12173 -- and can thus be inserted into the tree unconditionally.
12174
12175 if Expr_Value_E (Left) /= Shortcut_Ent then
12176 if Present (Actions (N)) then
12177 Insert_Actions (N, Actions (N));
12178 end if;
12179
12180 Rewrite (N, Right);
12181
12182 -- Rewrite False AND THEN Right / True OR ELSE Right to Left.
12183 -- In this case we can forget the actions associated with Right,
12184 -- since they will never be executed.
12185
12186 else
12187 Kill_Dead_Code (Right);
12188 Kill_Dead_Code (Actions (N));
12189 Rewrite (N, New_Occurrence_Of (Shortcut_Ent, Loc));
12190 end if;
12191
12192 Adjust_Result_Type (N, Typ);
12193 return;
12194 end if;
12195
6b73a73b 12196 -- If Actions are present for the right operand, we have to do some
12197 -- special processing. We can't just let these actions filter back into
12198 -- code preceding the short circuit (which is what would have happened
12199 -- if we had not trapped them in the short-circuit form), since they
12200 -- must only be executed if the right operand of the short circuit is
12201 -- executed and not otherwise.
3755dbc5 12202
6b73a73b 12203 if Present (Actions (N)) then
12204 Actlist := Actions (N);
3755dbc5 12205
9c890dc4 12206 -- The old approach is to expand:
12207
12208 -- left AND THEN right
12209
12210 -- into
12211
12212 -- C : Boolean := False;
12213 -- IF left THEN
12214 -- Actions;
12215 -- IF right THEN
12216 -- C := True;
12217 -- END IF;
12218 -- END IF;
12219
12220 -- and finally rewrite the operator into a reference to C. Similarly
12221 -- for left OR ELSE right, with negated values. Note that this
12222 -- rewrite causes some difficulties for coverage analysis because
12223 -- of the introduction of the new variable C, which obscures the
12224 -- structure of the test.
12225
12226 -- We use this "old approach" if Minimize_Expression_With_Actions
12227 -- is True.
12228
12229 if Minimize_Expression_With_Actions then
12230 Op_Var := Make_Temporary (Loc, 'C', Related_Node => N);
12231
12232 Insert_Action (N,
12233 Make_Object_Declaration (Loc,
12234 Defining_Identifier => Op_Var,
12235 Object_Definition =>
12236 New_Occurrence_Of (Standard_Boolean, Loc),
12237 Expression =>
12238 New_Occurrence_Of (Shortcut_Ent, Loc)));
12239
12240 Append_To (Actlist,
12241 Make_Implicit_If_Statement (Right,
12242 Condition => Make_Test_Expr (Right),
12243 Then_Statements => New_List (
12244 Make_Assignment_Statement (LocR,
12245 Name => New_Occurrence_Of (Op_Var, LocR),
12246 Expression =>
12247 New_Occurrence_Of
12248 (Boolean_Literals (not Shortcut_Value), LocR)))));
12249
12250 Insert_Action (N,
12251 Make_Implicit_If_Statement (Left,
12252 Condition => Make_Test_Expr (Left),
12253 Then_Statements => Actlist));
12254
12255 Rewrite (N, New_Occurrence_Of (Op_Var, Loc));
12256 Analyze_And_Resolve (N, Standard_Boolean);
12257
12258 -- The new approach (the default) is to use an
12259 -- Expression_With_Actions node for the right operand of the
12260 -- short-circuit form. Note that this solves the traceability
f6f7b3f4 12261 -- problems for coverage analysis.
3755dbc5 12262
9c890dc4 12263 else
12264 Rewrite (Right,
12265 Make_Expression_With_Actions (LocR,
12266 Expression => Relocate_Node (Right),
12267 Actions => Actlist));
cf8fe84b 12268
9c890dc4 12269 Set_Actions (N, No_List);
12270 Analyze_And_Resolve (Right, Standard_Boolean);
12271 end if;
6b73a73b 12272
3755dbc5 12273 Adjust_Result_Type (N, Typ);
12274 return;
12275 end if;
12276
12277 -- No actions present, check for cases of right argument True/False
12278
12279 if Compile_Time_Known_Value (Right) then
9a4f36a4 12280
12281 -- Mark SCO for left condition as compile time known
12282
12283 if Generate_SCO and then Comes_From_Source (Right) then
12284 Set_SCO_Condition (Right, Expr_Value_E (Right) = Standard_True);
12285 end if;
12286
9c890dc4 12287 -- Change (Left and then True), (Left or else False) to Left. Note
12288 -- that we know there are no actions associated with the right
3755dbc5 12289 -- operand, since we just checked for this case above.
12290
12291 if Expr_Value_E (Right) /= Shortcut_Ent then
12292 Rewrite (N, Left);
12293
12294 -- Change (Left and then False), (Left or else True) to Right,
12295 -- making sure to preserve any side effects associated with the Left
12296 -- operand.
12297
12298 else
12299 Remove_Side_Effects (Left);
12300 Rewrite (N, New_Occurrence_Of (Shortcut_Ent, Loc));
12301 end if;
12302 end if;
12303
12304 Adjust_Result_Type (N, Typ);
12305 end Expand_Short_Circuit_Operator;
12306
ee6ba406 12307 -------------------------------------
12308 -- Fixup_Universal_Fixed_Operation --
12309 -------------------------------------
12310
12311 procedure Fixup_Universal_Fixed_Operation (N : Node_Id) is
12312 Conv : constant Node_Id := Parent (N);
12313
12314 begin
12315 -- We must have a type conversion immediately above us
12316
12317 pragma Assert (Nkind (Conv) = N_Type_Conversion);
12318
12319 -- Normally the type conversion gives our target type. The exception
12320 -- occurs in the case of the Round attribute, where the conversion
12321 -- will be to universal real, and our real type comes from the Round
12322 -- attribute (as well as an indication that we must round the result)
12323
12324 if Nkind (Parent (Conv)) = N_Attribute_Reference
12325 and then Attribute_Name (Parent (Conv)) = Name_Round
12326 then
12327 Set_Etype (N, Etype (Parent (Conv)));
12328 Set_Rounded_Result (N);
12329
12330 -- Normal case where type comes from conversion above us
12331
12332 else
12333 Set_Etype (N, Etype (Conv));
12334 end if;
12335 end Fixup_Universal_Fixed_Operation;
12336
00f91aef 12337 ---------------------------------
12338 -- Has_Inferable_Discriminants --
12339 ---------------------------------
12340
12341 function Has_Inferable_Discriminants (N : Node_Id) return Boolean is
12342
12343 function Prefix_Is_Formal_Parameter (N : Node_Id) return Boolean;
12344 -- Determines whether the left-most prefix of a selected component is a
12345 -- formal parameter in a subprogram. Assumes N is a selected component.
12346
12347 --------------------------------
12348 -- Prefix_Is_Formal_Parameter --
12349 --------------------------------
12350
12351 function Prefix_Is_Formal_Parameter (N : Node_Id) return Boolean is
608b54ce 12352 Sel_Comp : Node_Id;
00f91aef 12353
12354 begin
12355 -- Move to the left-most prefix by climbing up the tree
12356
608b54ce 12357 Sel_Comp := N;
00f91aef 12358 while Present (Parent (Sel_Comp))
12359 and then Nkind (Parent (Sel_Comp)) = N_Selected_Component
12360 loop
12361 Sel_Comp := Parent (Sel_Comp);
12362 end loop;
12363
12364 return Ekind (Entity (Prefix (Sel_Comp))) in Formal_Kind;
12365 end Prefix_Is_Formal_Parameter;
12366
12367 -- Start of processing for Has_Inferable_Discriminants
12368
12369 begin
00f91aef 12370 -- For selected components, the subtype of the selector must be a
12371 -- constrained Unchecked_Union. If the component is subject to a
12372 -- per-object constraint, then the enclosing object must have inferable
12373 -- discriminants.
12374
608b54ce 12375 if Nkind (N) = N_Selected_Component then
00f91aef 12376 if Has_Per_Object_Constraint (Entity (Selector_Name (N))) then
12377
12378 -- A small hack. If we have a per-object constrained selected
12379 -- component of a formal parameter, return True since we do not
12380 -- know the actual parameter association yet.
12381
12382 if Prefix_Is_Formal_Parameter (N) then
12383 return True;
00f91aef 12384
12385 -- Otherwise, check the enclosing object and the selector
12386
608b54ce 12387 else
12388 return Has_Inferable_Discriminants (Prefix (N))
12389 and then Has_Inferable_Discriminants (Selector_Name (N));
12390 end if;
00f91aef 12391
12392 -- The call to Has_Inferable_Discriminants will determine whether
12393 -- the selector has a constrained Unchecked_Union nominal type.
12394
608b54ce 12395 else
12396 return Has_Inferable_Discriminants (Selector_Name (N));
12397 end if;
00f91aef 12398
12399 -- A qualified expression has inferable discriminants if its subtype
12400 -- mark is a constrained Unchecked_Union subtype.
12401
12402 elsif Nkind (N) = N_Qualified_Expression then
7dc534ca 12403 return Is_Unchecked_Union (Etype (Subtype_Mark (N)))
b98fca2b 12404 and then Is_Constrained (Etype (Subtype_Mark (N)));
00f91aef 12405
608b54ce 12406 -- For all other names, it is sufficient to have a constrained
12407 -- Unchecked_Union nominal subtype.
12408
12409 else
12410 return Is_Unchecked_Union (Base_Type (Etype (N)))
12411 and then Is_Constrained (Etype (N));
12412 end if;
00f91aef 12413 end Has_Inferable_Discriminants;
12414
ee6ba406 12415 -------------------------------
12416 -- Insert_Dereference_Action --
12417 -------------------------------
12418
12419 procedure Insert_Dereference_Action (N : Node_Id) is
ee6ba406 12420 function Is_Checked_Storage_Pool (P : Entity_Id) return Boolean;
752e1833 12421 -- Return true if type of P is derived from Checked_Pool;
12422
12423 -----------------------------
12424 -- Is_Checked_Storage_Pool --
12425 -----------------------------
ee6ba406 12426
12427 function Is_Checked_Storage_Pool (P : Entity_Id) return Boolean is
12428 T : Entity_Id;
cf04d13c 12429
ee6ba406 12430 begin
12431 if No (P) then
12432 return False;
12433 end if;
12434
12435 T := Etype (P);
12436 while T /= Etype (T) loop
12437 if Is_RTE (T, RE_Checked_Pool) then
12438 return True;
12439 else
12440 T := Etype (T);
12441 end if;
12442 end loop;
12443
12444 return False;
12445 end Is_Checked_Storage_Pool;
12446
30d0732d 12447 -- Local variables
12448
5841ad12 12449 Context : constant Node_Id := Parent (N);
12450 Ptr_Typ : constant Entity_Id := Etype (N);
12451 Desig_Typ : constant Entity_Id :=
12452 Available_View (Designated_Type (Ptr_Typ));
12453 Loc : constant Source_Ptr := Sloc (N);
12454 Pool : constant Entity_Id := Associated_Storage_Pool (Ptr_Typ);
30d0732d 12455
a52fe7b1 12456 Addr : Entity_Id;
12457 Alig : Entity_Id;
12458 Deref : Node_Id;
12459 Size : Entity_Id;
12460 Size_Bits : Node_Id;
12461 Stmt : Node_Id;
30d0732d 12462
ee6ba406 12463 -- Start of processing for Insert_Dereference_Action
12464
12465 begin
5841ad12 12466 pragma Assert (Nkind (Context) = N_Explicit_Dereference);
28ed91d4 12467
30d0732d 12468 -- Do not re-expand a dereference which has already been processed by
12469 -- this routine.
12470
5841ad12 12471 if Has_Dereference_Action (Context) then
ee6ba406 12472 return;
ee6ba406 12473
30d0732d 12474 -- Do not perform this type of expansion for internally-generated
12475 -- dereferences.
ee6ba406 12476
5841ad12 12477 elsif not Comes_From_Source (Original_Node (Context)) then
30d0732d 12478 return;
ee6ba406 12479
30d0732d 12480 -- A dereference action is only applicable to objects which have been
12481 -- allocated on a checked pool.
ee6ba406 12482
30d0732d 12483 elsif not Is_Checked_Storage_Pool (Pool) then
12484 return;
12485 end if;
ee6ba406 12486
30d0732d 12487 -- Extract the address of the dereferenced object. Generate:
7eb0e22f 12488
30d0732d 12489 -- Addr : System.Address := <N>'Pool_Address;
ee6ba406 12490
30d0732d 12491 Addr := Make_Temporary (Loc, 'P');
ee6ba406 12492
30d0732d 12493 Insert_Action (N,
12494 Make_Object_Declaration (Loc,
12495 Defining_Identifier => Addr,
12496 Object_Definition =>
83c6c069 12497 New_Occurrence_Of (RTE (RE_Address), Loc),
30d0732d 12498 Expression =>
12499 Make_Attribute_Reference (Loc,
12500 Prefix => Duplicate_Subexpr_Move_Checks (N),
12501 Attribute_Name => Name_Pool_Address)));
12502
12503 -- Calculate the size of the dereferenced object. Generate:
7eb0e22f 12504
30d0732d 12505 -- Size : Storage_Count := <N>.all'Size / Storage_Unit;
12506
12507 Deref :=
12508 Make_Explicit_Dereference (Loc,
12509 Prefix => Duplicate_Subexpr_Move_Checks (N));
12510 Set_Has_Dereference_Action (Deref);
ee6ba406 12511
a52fe7b1 12512 Size_Bits :=
12513 Make_Attribute_Reference (Loc,
12514 Prefix => Deref,
12515 Attribute_Name => Name_Size);
12516
12517 -- Special case of an unconstrained array: need to add descriptor size
12518
5841ad12 12519 if Is_Array_Type (Desig_Typ)
12520 and then not Is_Constrained (First_Subtype (Desig_Typ))
a52fe7b1 12521 then
12522 Size_Bits :=
12523 Make_Op_Add (Loc,
12524 Left_Opnd =>
12525 Make_Attribute_Reference (Loc,
12526 Prefix =>
5841ad12 12527 New_Occurrence_Of (First_Subtype (Desig_Typ), Loc),
a52fe7b1 12528 Attribute_Name => Name_Descriptor_Size),
12529 Right_Opnd => Size_Bits);
12530 end if;
30d0732d 12531
a52fe7b1 12532 Size := Make_Temporary (Loc, 'S');
30d0732d 12533 Insert_Action (N,
12534 Make_Object_Declaration (Loc,
12535 Defining_Identifier => Size,
12536 Object_Definition =>
83c6c069 12537 New_Occurrence_Of (RTE (RE_Storage_Count), Loc),
30d0732d 12538 Expression =>
12539 Make_Op_Divide (Loc,
a52fe7b1 12540 Left_Opnd => Size_Bits,
12541 Right_Opnd => Make_Integer_Literal (Loc, System_Storage_Unit))));
ee6ba406 12542
30d0732d 12543 -- Calculate the alignment of the dereferenced object. Generate:
12544 -- Alig : constant Storage_Count := <N>.all'Alignment;
ee6ba406 12545
30d0732d 12546 Deref :=
12547 Make_Explicit_Dereference (Loc,
12548 Prefix => Duplicate_Subexpr_Move_Checks (N));
12549 Set_Has_Dereference_Action (Deref);
12550
12551 Alig := Make_Temporary (Loc, 'A');
30d0732d 12552 Insert_Action (N,
12553 Make_Object_Declaration (Loc,
12554 Defining_Identifier => Alig,
12555 Object_Definition =>
83c6c069 12556 New_Occurrence_Of (RTE (RE_Storage_Count), Loc),
30d0732d 12557 Expression =>
12558 Make_Attribute_Reference (Loc,
12559 Prefix => Deref,
12560 Attribute_Name => Name_Alignment)));
12561
12562 -- A dereference of a controlled object requires special processing. The
12563 -- finalization machinery requests additional space from the underlying
12564 -- pool to allocate and hide two pointers. As a result, a checked pool
12565 -- may mark the wrong memory as valid. Since checked pools do not have
12566 -- knowledge of hidden pointers, we have to bring the two pointers back
12567 -- in view in order to restore the original state of the object.
12568
5841ad12 12569 -- The address manipulation is not performed for access types that are
12570 -- subject to pragma No_Heap_Finalization because the two pointers do
12571 -- not exist in the first place.
12572
12573 if No_Heap_Finalization (Ptr_Typ) then
12574 null;
12575
12576 elsif Needs_Finalization (Desig_Typ) then
30d0732d 12577
12578 -- Adjust the address and size of the dereferenced object. Generate:
12579 -- Adjust_Controlled_Dereference (Addr, Size, Alig);
12580
12581 Stmt :=
12582 Make_Procedure_Call_Statement (Loc,
12583 Name =>
83c6c069 12584 New_Occurrence_Of (RTE (RE_Adjust_Controlled_Dereference), Loc),
30d0732d 12585 Parameter_Associations => New_List (
83c6c069 12586 New_Occurrence_Of (Addr, Loc),
12587 New_Occurrence_Of (Size, Loc),
12588 New_Occurrence_Of (Alig, Loc)));
30d0732d 12589
12590 -- Class-wide types complicate things because we cannot determine
12591 -- statically whether the actual object is truly controlled. We must
12592 -- generate a runtime check to detect this property. Generate:
12593 --
12594 -- if Needs_Finalization (<N>.all'Tag) then
12595 -- <Stmt>;
12596 -- end if;
12597
5841ad12 12598 if Is_Class_Wide_Type (Desig_Typ) then
30d0732d 12599 Deref :=
12600 Make_Explicit_Dereference (Loc,
12601 Prefix => Duplicate_Subexpr_Move_Checks (N));
12602 Set_Has_Dereference_Action (Deref);
12603
12604 Stmt :=
5c72df40 12605 Make_Implicit_If_Statement (N,
30d0732d 12606 Condition =>
12607 Make_Function_Call (Loc,
12608 Name =>
83c6c069 12609 New_Occurrence_Of (RTE (RE_Needs_Finalization), Loc),
30d0732d 12610 Parameter_Associations => New_List (
12611 Make_Attribute_Reference (Loc,
12612 Prefix => Deref,
12613 Attribute_Name => Name_Tag))),
12614 Then_Statements => New_List (Stmt));
12615 end if;
12616
12617 Insert_Action (N, Stmt);
12618 end if;
12619
12620 -- Generate:
12621 -- Dereference (Pool, Addr, Size, Alig);
12622
12623 Insert_Action (N,
12624 Make_Procedure_Call_Statement (Loc,
12625 Name =>
83c6c069 12626 New_Occurrence_Of
30d0732d 12627 (Find_Prim_Op (Etype (Pool), Name_Dereference), Loc),
12628 Parameter_Associations => New_List (
83c6c069 12629 New_Occurrence_Of (Pool, Loc),
12630 New_Occurrence_Of (Addr, Loc),
12631 New_Occurrence_Of (Size, Loc),
12632 New_Occurrence_Of (Alig, Loc))));
30d0732d 12633
12634 -- Mark the explicit dereference as processed to avoid potential
12635 -- infinite expansion.
12636
5841ad12 12637 Set_Has_Dereference_Action (Context);
ee6ba406 12638
9dfe12ae 12639 exception
12640 when RE_Not_Available =>
12641 return;
ee6ba406 12642 end Insert_Dereference_Action;
12643
df40eeb0 12644 --------------------------------
12645 -- Integer_Promotion_Possible --
12646 --------------------------------
12647
12648 function Integer_Promotion_Possible (N : Node_Id) return Boolean is
12649 Operand : constant Node_Id := Expression (N);
12650 Operand_Type : constant Entity_Id := Etype (Operand);
12651 Root_Operand_Type : constant Entity_Id := Root_Type (Operand_Type);
12652
12653 begin
12654 pragma Assert (Nkind (N) = N_Type_Conversion);
12655
12656 return
12657
12658 -- We only do the transformation for source constructs. We assume
12659 -- that the expander knows what it is doing when it generates code.
12660
12661 Comes_From_Source (N)
12662
12663 -- If the operand type is Short_Integer or Short_Short_Integer,
12664 -- then we will promote to Integer, which is available on all
12665 -- targets, and is sufficient to ensure no intermediate overflow.
12666 -- Furthermore it is likely to be as efficient or more efficient
12667 -- than using the smaller type for the computation so we do this
12668 -- unconditionally.
12669
12670 and then
12671 (Root_Operand_Type = Base_Type (Standard_Short_Integer)
cf04d13c 12672 or else
df40eeb0 12673 Root_Operand_Type = Base_Type (Standard_Short_Short_Integer))
12674
12675 -- Test for interesting operation, which includes addition,
36e5d81f 12676 -- division, exponentiation, multiplication, subtraction, absolute
12677 -- value and unary negation. Unary "+" is omitted since it is a
12678 -- no-op and thus can't overflow.
df40eeb0 12679
36e5d81f 12680 and then Nkind_In (Operand, N_Op_Abs,
12681 N_Op_Add,
df40eeb0 12682 N_Op_Divide,
12683 N_Op_Expon,
12684 N_Op_Minus,
12685 N_Op_Multiply,
12686 N_Op_Subtract);
12687 end Integer_Promotion_Possible;
12688
ee6ba406 12689 ------------------------------
12690 -- Make_Array_Comparison_Op --
12691 ------------------------------
12692
12693 -- This is a hand-coded expansion of the following generic function:
12694
12695 -- generic
12696 -- type elem is (<>);
12697 -- type index is (<>);
12698 -- type a is array (index range <>) of elem;
e8ccec48 12699
ee6ba406 12700 -- function Gnnn (X : a; Y: a) return boolean is
12701 -- J : index := Y'first;
e8ccec48 12702
ee6ba406 12703 -- begin
12704 -- if X'length = 0 then
12705 -- return false;
e8ccec48 12706
ee6ba406 12707 -- elsif Y'length = 0 then
12708 -- return true;
e8ccec48 12709
ee6ba406 12710 -- else
12711 -- for I in X'range loop
12712 -- if X (I) = Y (J) then
12713 -- if J = Y'last then
12714 -- exit;
12715 -- else
12716 -- J := index'succ (J);
12717 -- end if;
e8ccec48 12718
ee6ba406 12719 -- else
12720 -- return X (I) > Y (J);
12721 -- end if;
12722 -- end loop;
e8ccec48 12723
ee6ba406 12724 -- return X'length > Y'length;
12725 -- end if;
12726 -- end Gnnn;
12727
12728 -- Note that since we are essentially doing this expansion by hand, we
12729 -- do not need to generate an actual or formal generic part, just the
12730 -- instantiated function itself.
12731
316f8a9b 12732 -- Perhaps we could have the actual generic available in the run-time,
12733 -- obtained by rtsfind, and actually expand a real instantiation ???
12734
ee6ba406 12735 function Make_Array_Comparison_Op
752e1833 12736 (Typ : Entity_Id;
12737 Nod : Node_Id) return Node_Id
ee6ba406 12738 is
12739 Loc : constant Source_Ptr := Sloc (Nod);
12740
12741 X : constant Entity_Id := Make_Defining_Identifier (Loc, Name_uX);
12742 Y : constant Entity_Id := Make_Defining_Identifier (Loc, Name_uY);
12743 I : constant Entity_Id := Make_Defining_Identifier (Loc, Name_uI);
12744 J : constant Entity_Id := Make_Defining_Identifier (Loc, Name_uJ);
12745
12746 Index : constant Entity_Id := Base_Type (Etype (First_Index (Typ)));
12747
12748 Loop_Statement : Node_Id;
12749 Loop_Body : Node_Id;
12750 If_Stat : Node_Id;
12751 Inner_If : Node_Id;
12752 Final_Expr : Node_Id;
12753 Func_Body : Node_Id;
12754 Func_Name : Entity_Id;
12755 Formals : List_Id;
12756 Length1 : Node_Id;
12757 Length2 : Node_Id;
12758
12759 begin
12760 -- if J = Y'last then
12761 -- exit;
12762 -- else
12763 -- J := index'succ (J);
12764 -- end if;
12765
12766 Inner_If :=
12767 Make_Implicit_If_Statement (Nod,
12768 Condition =>
12769 Make_Op_Eq (Loc,
83c6c069 12770 Left_Opnd => New_Occurrence_Of (J, Loc),
ee6ba406 12771 Right_Opnd =>
12772 Make_Attribute_Reference (Loc,
83c6c069 12773 Prefix => New_Occurrence_Of (Y, Loc),
ee6ba406 12774 Attribute_Name => Name_Last)),
12775
12776 Then_Statements => New_List (
12777 Make_Exit_Statement (Loc)),
12778
12779 Else_Statements =>
12780 New_List (
12781 Make_Assignment_Statement (Loc,
83c6c069 12782 Name => New_Occurrence_Of (J, Loc),
ee6ba406 12783 Expression =>
12784 Make_Attribute_Reference (Loc,
83c6c069 12785 Prefix => New_Occurrence_Of (Index, Loc),
ee6ba406 12786 Attribute_Name => Name_Succ,
83c6c069 12787 Expressions => New_List (New_Occurrence_Of (J, Loc))))));
ee6ba406 12788
12789 -- if X (I) = Y (J) then
12790 -- if ... end if;
12791 -- else
12792 -- return X (I) > Y (J);
12793 -- end if;
12794
12795 Loop_Body :=
12796 Make_Implicit_If_Statement (Nod,
12797 Condition =>
12798 Make_Op_Eq (Loc,
12799 Left_Opnd =>
12800 Make_Indexed_Component (Loc,
83c6c069 12801 Prefix => New_Occurrence_Of (X, Loc),
12802 Expressions => New_List (New_Occurrence_Of (I, Loc))),
ee6ba406 12803
12804 Right_Opnd =>
12805 Make_Indexed_Component (Loc,
83c6c069 12806 Prefix => New_Occurrence_Of (Y, Loc),
12807 Expressions => New_List (New_Occurrence_Of (J, Loc)))),
ee6ba406 12808
12809 Then_Statements => New_List (Inner_If),
12810
12811 Else_Statements => New_List (
a3e461ac 12812 Make_Simple_Return_Statement (Loc,
ee6ba406 12813 Expression =>
12814 Make_Op_Gt (Loc,
12815 Left_Opnd =>
12816 Make_Indexed_Component (Loc,
83c6c069 12817 Prefix => New_Occurrence_Of (X, Loc),
12818 Expressions => New_List (New_Occurrence_Of (I, Loc))),
ee6ba406 12819
12820 Right_Opnd =>
12821 Make_Indexed_Component (Loc,
83c6c069 12822 Prefix => New_Occurrence_Of (Y, Loc),
ee6ba406 12823 Expressions => New_List (
83c6c069 12824 New_Occurrence_Of (J, Loc)))))));
ee6ba406 12825
12826 -- for I in X'range loop
12827 -- if ... end if;
12828 -- end loop;
12829
12830 Loop_Statement :=
12831 Make_Implicit_Loop_Statement (Nod,
12832 Identifier => Empty,
12833
12834 Iteration_Scheme =>
12835 Make_Iteration_Scheme (Loc,
12836 Loop_Parameter_Specification =>
12837 Make_Loop_Parameter_Specification (Loc,
12838 Defining_Identifier => I,
12839 Discrete_Subtype_Definition =>
12840 Make_Attribute_Reference (Loc,
83c6c069 12841 Prefix => New_Occurrence_Of (X, Loc),
ee6ba406 12842 Attribute_Name => Name_Range))),
12843
12844 Statements => New_List (Loop_Body));
12845
12846 -- if X'length = 0 then
12847 -- return false;
12848 -- elsif Y'length = 0 then
12849 -- return true;
12850 -- else
12851 -- for ... loop ... end loop;
12852 -- return X'length > Y'length;
12853 -- end if;
12854
12855 Length1 :=
12856 Make_Attribute_Reference (Loc,
83c6c069 12857 Prefix => New_Occurrence_Of (X, Loc),
ee6ba406 12858 Attribute_Name => Name_Length);
12859
12860 Length2 :=
12861 Make_Attribute_Reference (Loc,
83c6c069 12862 Prefix => New_Occurrence_Of (Y, Loc),
ee6ba406 12863 Attribute_Name => Name_Length);
12864
12865 Final_Expr :=
12866 Make_Op_Gt (Loc,
12867 Left_Opnd => Length1,
12868 Right_Opnd => Length2);
12869
12870 If_Stat :=
12871 Make_Implicit_If_Statement (Nod,
12872 Condition =>
12873 Make_Op_Eq (Loc,
12874 Left_Opnd =>
12875 Make_Attribute_Reference (Loc,
83c6c069 12876 Prefix => New_Occurrence_Of (X, Loc),
ee6ba406 12877 Attribute_Name => Name_Length),
12878 Right_Opnd =>
12879 Make_Integer_Literal (Loc, 0)),
12880
12881 Then_Statements =>
12882 New_List (
a3e461ac 12883 Make_Simple_Return_Statement (Loc,
83c6c069 12884 Expression => New_Occurrence_Of (Standard_False, Loc))),
ee6ba406 12885
12886 Elsif_Parts => New_List (
12887 Make_Elsif_Part (Loc,
12888 Condition =>
12889 Make_Op_Eq (Loc,
12890 Left_Opnd =>
12891 Make_Attribute_Reference (Loc,
83c6c069 12892 Prefix => New_Occurrence_Of (Y, Loc),
ee6ba406 12893 Attribute_Name => Name_Length),
12894 Right_Opnd =>
12895 Make_Integer_Literal (Loc, 0)),
12896
12897 Then_Statements =>
12898 New_List (
a3e461ac 12899 Make_Simple_Return_Statement (Loc,
83c6c069 12900 Expression => New_Occurrence_Of (Standard_True, Loc))))),
ee6ba406 12901
12902 Else_Statements => New_List (
12903 Loop_Statement,
a3e461ac 12904 Make_Simple_Return_Statement (Loc,
ee6ba406 12905 Expression => Final_Expr)));
12906
12907 -- (X : a; Y: a)
12908
12909 Formals := New_List (
12910 Make_Parameter_Specification (Loc,
12911 Defining_Identifier => X,
83c6c069 12912 Parameter_Type => New_Occurrence_Of (Typ, Loc)),
ee6ba406 12913
12914 Make_Parameter_Specification (Loc,
12915 Defining_Identifier => Y,
83c6c069 12916 Parameter_Type => New_Occurrence_Of (Typ, Loc)));
ee6ba406 12917
12918 -- function Gnnn (...) return boolean is
12919 -- J : index := Y'first;
12920 -- begin
12921 -- if ... end if;
12922 -- end Gnnn;
12923
46eb6933 12924 Func_Name := Make_Temporary (Loc, 'G');
ee6ba406 12925
12926 Func_Body :=
12927 Make_Subprogram_Body (Loc,
12928 Specification =>
12929 Make_Function_Specification (Loc,
12930 Defining_Unit_Name => Func_Name,
12931 Parameter_Specifications => Formals,
83c6c069 12932 Result_Definition => New_Occurrence_Of (Standard_Boolean, Loc)),
ee6ba406 12933
12934 Declarations => New_List (
12935 Make_Object_Declaration (Loc,
12936 Defining_Identifier => J,
83c6c069 12937 Object_Definition => New_Occurrence_Of (Index, Loc),
ee6ba406 12938 Expression =>
12939 Make_Attribute_Reference (Loc,
83c6c069 12940 Prefix => New_Occurrence_Of (Y, Loc),
ee6ba406 12941 Attribute_Name => Name_First))),
12942
12943 Handled_Statement_Sequence =>
12944 Make_Handled_Sequence_Of_Statements (Loc,
12945 Statements => New_List (If_Stat)));
12946
12947 return Func_Body;
ee6ba406 12948 end Make_Array_Comparison_Op;
12949
12950 ---------------------------
12951 -- Make_Boolean_Array_Op --
12952 ---------------------------
12953
f1e2dcc5 12954 -- For logical operations on boolean arrays, expand in line the following,
12955 -- replacing 'and' with 'or' or 'xor' where needed:
ee6ba406 12956
12957 -- function Annn (A : typ; B: typ) return typ is
12958 -- C : typ;
12959 -- begin
12960 -- for J in A'range loop
12961 -- C (J) := A (J) op B (J);
12962 -- end loop;
12963 -- return C;
12964 -- end Annn;
12965
12966 -- Here typ is the boolean array type
12967
12968 function Make_Boolean_Array_Op
752e1833 12969 (Typ : Entity_Id;
12970 N : Node_Id) return Node_Id
ee6ba406 12971 is
12972 Loc : constant Source_Ptr := Sloc (N);
12973
12974 A : constant Entity_Id := Make_Defining_Identifier (Loc, Name_uA);
12975 B : constant Entity_Id := Make_Defining_Identifier (Loc, Name_uB);
12976 C : constant Entity_Id := Make_Defining_Identifier (Loc, Name_uC);
12977 J : constant Entity_Id := Make_Defining_Identifier (Loc, Name_uJ);
12978
12979 A_J : Node_Id;
12980 B_J : Node_Id;
12981 C_J : Node_Id;
12982 Op : Node_Id;
12983
12984 Formals : List_Id;
12985 Func_Name : Entity_Id;
12986 Func_Body : Node_Id;
12987 Loop_Statement : Node_Id;
12988
12989 begin
12990 A_J :=
12991 Make_Indexed_Component (Loc,
83c6c069 12992 Prefix => New_Occurrence_Of (A, Loc),
12993 Expressions => New_List (New_Occurrence_Of (J, Loc)));
ee6ba406 12994
12995 B_J :=
12996 Make_Indexed_Component (Loc,
83c6c069 12997 Prefix => New_Occurrence_Of (B, Loc),
12998 Expressions => New_List (New_Occurrence_Of (J, Loc)));
ee6ba406 12999
13000 C_J :=
13001 Make_Indexed_Component (Loc,
83c6c069 13002 Prefix => New_Occurrence_Of (C, Loc),
13003 Expressions => New_List (New_Occurrence_Of (J, Loc)));
ee6ba406 13004
13005 if Nkind (N) = N_Op_And then
13006 Op :=
13007 Make_Op_And (Loc,
13008 Left_Opnd => A_J,
13009 Right_Opnd => B_J);
13010
13011 elsif Nkind (N) = N_Op_Or then
13012 Op :=
13013 Make_Op_Or (Loc,
13014 Left_Opnd => A_J,
13015 Right_Opnd => B_J);
13016
13017 else
13018 Op :=
13019 Make_Op_Xor (Loc,
13020 Left_Opnd => A_J,
13021 Right_Opnd => B_J);
13022 end if;
13023
13024 Loop_Statement :=
13025 Make_Implicit_Loop_Statement (N,
13026 Identifier => Empty,
13027
13028 Iteration_Scheme =>
13029 Make_Iteration_Scheme (Loc,
13030 Loop_Parameter_Specification =>
13031 Make_Loop_Parameter_Specification (Loc,
13032 Defining_Identifier => J,
13033 Discrete_Subtype_Definition =>
13034 Make_Attribute_Reference (Loc,
83c6c069 13035 Prefix => New_Occurrence_Of (A, Loc),
ee6ba406 13036 Attribute_Name => Name_Range))),
13037
13038 Statements => New_List (
13039 Make_Assignment_Statement (Loc,
13040 Name => C_J,
13041 Expression => Op)));
13042
13043 Formals := New_List (
13044 Make_Parameter_Specification (Loc,
13045 Defining_Identifier => A,
83c6c069 13046 Parameter_Type => New_Occurrence_Of (Typ, Loc)),
ee6ba406 13047
13048 Make_Parameter_Specification (Loc,
13049 Defining_Identifier => B,
83c6c069 13050 Parameter_Type => New_Occurrence_Of (Typ, Loc)));
ee6ba406 13051
46eb6933 13052 Func_Name := Make_Temporary (Loc, 'A');
ee6ba406 13053 Set_Is_Inlined (Func_Name);
13054
13055 Func_Body :=
13056 Make_Subprogram_Body (Loc,
13057 Specification =>
13058 Make_Function_Specification (Loc,
13059 Defining_Unit_Name => Func_Name,
13060 Parameter_Specifications => Formals,
83c6c069 13061 Result_Definition => New_Occurrence_Of (Typ, Loc)),
ee6ba406 13062
13063 Declarations => New_List (
13064 Make_Object_Declaration (Loc,
13065 Defining_Identifier => C,
83c6c069 13066 Object_Definition => New_Occurrence_Of (Typ, Loc))),
ee6ba406 13067
13068 Handled_Statement_Sequence =>
13069 Make_Handled_Sequence_Of_Statements (Loc,
13070 Statements => New_List (
13071 Loop_Statement,
a3e461ac 13072 Make_Simple_Return_Statement (Loc,
83c6c069 13073 Expression => New_Occurrence_Of (C, Loc)))));
ee6ba406 13074
13075 return Func_Body;
13076 end Make_Boolean_Array_Op;
13077
f32c377d 13078 -----------------------------------------
13079 -- Minimized_Eliminated_Overflow_Check --
13080 -----------------------------------------
13081
13082 function Minimized_Eliminated_Overflow_Check (N : Node_Id) return Boolean is
13083 begin
13084 return
13085 Is_Signed_Integer_Type (Etype (N))
0df9d43f 13086 and then Overflow_Check_Mode in Minimized_Or_Eliminated;
f32c377d 13087 end Minimized_Eliminated_Overflow_Check;
13088
4ecb1318 13089 --------------------------------
13090 -- Optimize_Length_Comparison --
13091 --------------------------------
13092
13093 procedure Optimize_Length_Comparison (N : Node_Id) is
13094 Loc : constant Source_Ptr := Sloc (N);
13095 Typ : constant Entity_Id := Etype (N);
13096 Result : Node_Id;
13097
13098 Left : Node_Id;
13099 Right : Node_Id;
13100 -- First and Last attribute reference nodes, which end up as left and
13101 -- right operands of the optimized result.
13102
13103 Is_Zero : Boolean;
13104 -- True for comparison operand of zero
13105
13106 Comp : Node_Id;
13107 -- Comparison operand, set only if Is_Zero is false
13108
13109 Ent : Entity_Id;
13110 -- Entity whose length is being compared
13111
13112 Index : Node_Id;
13113 -- Integer_Literal node for length attribute expression, or Empty
13114 -- if there is no such expression present.
13115
13116 Ityp : Entity_Id;
13117 -- Type of array index to which 'Length is applied
13118
13119 Op : Node_Kind := Nkind (N);
13120 -- Kind of comparison operator, gets flipped if operands backwards
13121
13122 function Is_Optimizable (N : Node_Id) return Boolean;
6d3cdc7f 13123 -- Tests N to see if it is an optimizable comparison value (defined as
13124 -- constant zero or one, or something else where the value is known to
13125 -- be positive and in the range of 32-bits, and where the corresponding
13126 -- Length value is also known to be 32-bits. If result is true, sets
13127 -- Is_Zero, Ityp, and Comp accordingly.
4ecb1318 13128
13129 function Is_Entity_Length (N : Node_Id) return Boolean;
13130 -- Tests if N is a length attribute applied to a simple entity. If so,
13131 -- returns True, and sets Ent to the entity, and Index to the integer
13132 -- literal provided as an attribute expression, or to Empty if none.
13133 -- Also returns True if the expression is a generated type conversion
13134 -- whose expression is of the desired form. This latter case arises
13135 -- when Apply_Universal_Integer_Attribute_Check installs a conversion
13136 -- to check for being in range, which is not needed in this context.
13137 -- Returns False if neither condition holds.
13138
13139 function Prepare_64 (N : Node_Id) return Node_Id;
13140 -- Given a discrete expression, returns a Long_Long_Integer typed
13141 -- expression representing the underlying value of the expression.
13142 -- This is done with an unchecked conversion to the result type. We
13143 -- use unchecked conversion to handle the enumeration type case.
13144
13145 ----------------------
13146 -- Is_Entity_Length --
13147 ----------------------
13148
13149 function Is_Entity_Length (N : Node_Id) return Boolean is
13150 begin
13151 if Nkind (N) = N_Attribute_Reference
13152 and then Attribute_Name (N) = Name_Length
13153 and then Is_Entity_Name (Prefix (N))
13154 then
13155 Ent := Entity (Prefix (N));
13156
13157 if Present (Expressions (N)) then
13158 Index := First (Expressions (N));
13159 else
13160 Index := Empty;
13161 end if;
13162
13163 return True;
13164
13165 elsif Nkind (N) = N_Type_Conversion
13166 and then not Comes_From_Source (N)
13167 then
13168 return Is_Entity_Length (Expression (N));
13169
13170 else
13171 return False;
13172 end if;
13173 end Is_Entity_Length;
13174
13175 --------------------
13176 -- Is_Optimizable --
13177 --------------------
13178
13179 function Is_Optimizable (N : Node_Id) return Boolean is
13180 Val : Uint;
13181 OK : Boolean;
13182 Lo : Uint;
13183 Hi : Uint;
13184 Indx : Node_Id;
13185
13186 begin
13187 if Compile_Time_Known_Value (N) then
13188 Val := Expr_Value (N);
13189
13190 if Val = Uint_0 then
13191 Is_Zero := True;
13192 Comp := Empty;
13193 return True;
13194
13195 elsif Val = Uint_1 then
13196 Is_Zero := False;
13197 Comp := Empty;
13198 return True;
13199 end if;
13200 end if;
13201
13202 -- Here we have to make sure of being within 32-bits
13203
13204 Determine_Range (N, OK, Lo, Hi, Assume_Valid => True);
13205
13206 if not OK
6d3cdc7f 13207 or else Lo < Uint_1
4ecb1318 13208 or else Hi > UI_From_Int (Int'Last)
13209 then
13210 return False;
13211 end if;
13212
6d3cdc7f 13213 -- Comparison value was within range, so now we must check the index
13214 -- value to make sure it is also within 32-bits.
4ecb1318 13215
13216 Indx := First_Index (Etype (Ent));
13217
13218 if Present (Index) then
13219 for J in 2 .. UI_To_Int (Intval (Index)) loop
13220 Next_Index (Indx);
13221 end loop;
13222 end if;
13223
13224 Ityp := Etype (Indx);
13225
13226 if Esize (Ityp) > 32 then
13227 return False;
13228 end if;
13229
13230 Is_Zero := False;
13231 Comp := N;
13232 return True;
13233 end Is_Optimizable;
13234
13235 ----------------
13236 -- Prepare_64 --
13237 ----------------
13238
13239 function Prepare_64 (N : Node_Id) return Node_Id is
13240 begin
13241 return Unchecked_Convert_To (Standard_Long_Long_Integer, N);
13242 end Prepare_64;
13243
13244 -- Start of processing for Optimize_Length_Comparison
13245
13246 begin
13247 -- Nothing to do if not a comparison
13248
13249 if Op not in N_Op_Compare then
13250 return;
13251 end if;
13252
111399d1 13253 -- Nothing to do if special -gnatd.P debug flag set.
4ecb1318 13254
111399d1 13255 if Debug_Flag_Dot_PP then
4ecb1318 13256 return;
13257 end if;
13258
13259 -- Ent'Length op 0/1
13260
13261 if Is_Entity_Length (Left_Opnd (N))
13262 and then Is_Optimizable (Right_Opnd (N))
13263 then
13264 null;
13265
13266 -- 0/1 op Ent'Length
13267
13268 elsif Is_Entity_Length (Right_Opnd (N))
13269 and then Is_Optimizable (Left_Opnd (N))
13270 then
13271 -- Flip comparison to opposite sense
13272
13273 case Op is
13274 when N_Op_Lt => Op := N_Op_Gt;
13275 when N_Op_Le => Op := N_Op_Ge;
13276 when N_Op_Gt => Op := N_Op_Lt;
13277 when N_Op_Ge => Op := N_Op_Le;
13278 when others => null;
13279 end case;
13280
13281 -- Else optimization not possible
13282
13283 else
13284 return;
13285 end if;
13286
13287 -- Fall through if we will do the optimization
13288
13289 -- Cases to handle:
13290
13291 -- X'Length = 0 => X'First > X'Last
13292 -- X'Length = 1 => X'First = X'Last
13293 -- X'Length = n => X'First + (n - 1) = X'Last
13294
13295 -- X'Length /= 0 => X'First <= X'Last
13296 -- X'Length /= 1 => X'First /= X'Last
13297 -- X'Length /= n => X'First + (n - 1) /= X'Last
13298
13299 -- X'Length >= 0 => always true, warn
13300 -- X'Length >= 1 => X'First <= X'Last
13301 -- X'Length >= n => X'First + (n - 1) <= X'Last
13302
13303 -- X'Length > 0 => X'First <= X'Last
13304 -- X'Length > 1 => X'First < X'Last
13305 -- X'Length > n => X'First + (n - 1) < X'Last
13306
13307 -- X'Length <= 0 => X'First > X'Last (warn, could be =)
13308 -- X'Length <= 1 => X'First >= X'Last
13309 -- X'Length <= n => X'First + (n - 1) >= X'Last
13310
13311 -- X'Length < 0 => always false (warn)
13312 -- X'Length < 1 => X'First > X'Last
13313 -- X'Length < n => X'First + (n - 1) > X'Last
13314
13315 -- Note: for the cases of n (not constant 0,1), we require that the
13316 -- corresponding index type be integer or shorter (i.e. not 64-bit),
13317 -- and the same for the comparison value. Then we do the comparison
13318 -- using 64-bit arithmetic (actually long long integer), so that we
13319 -- cannot have overflow intefering with the result.
13320
13321 -- First deal with warning cases
13322
13323 if Is_Zero then
13324 case Op is
13325
13326 -- X'Length >= 0
13327
13328 when N_Op_Ge =>
13329 Rewrite (N,
13330 Convert_To (Typ, New_Occurrence_Of (Standard_True, Loc)));
13331 Analyze_And_Resolve (N, Typ);
13332 Warn_On_Known_Condition (N);
13333 return;
13334
13335 -- X'Length < 0
13336
13337 when N_Op_Lt =>
13338 Rewrite (N,
13339 Convert_To (Typ, New_Occurrence_Of (Standard_False, Loc)));
13340 Analyze_And_Resolve (N, Typ);
13341 Warn_On_Known_Condition (N);
13342 return;
13343
13344 when N_Op_Le =>
13345 if Constant_Condition_Warnings
13346 and then Comes_From_Source (Original_Node (N))
13347 then
6e9f198b 13348 Error_Msg_N ("could replace by ""'=""?c?", N);
4ecb1318 13349 end if;
13350
13351 Op := N_Op_Eq;
13352
13353 when others =>
13354 null;
13355 end case;
13356 end if;
13357
13358 -- Build the First reference we will use
13359
13360 Left :=
13361 Make_Attribute_Reference (Loc,
13362 Prefix => New_Occurrence_Of (Ent, Loc),
13363 Attribute_Name => Name_First);
13364
13365 if Present (Index) then
13366 Set_Expressions (Left, New_List (New_Copy (Index)));
13367 end if;
13368
13369 -- If general value case, then do the addition of (n - 1), and
13370 -- also add the needed conversions to type Long_Long_Integer.
13371
13372 if Present (Comp) then
13373 Left :=
13374 Make_Op_Add (Loc,
13375 Left_Opnd => Prepare_64 (Left),
13376 Right_Opnd =>
13377 Make_Op_Subtract (Loc,
13378 Left_Opnd => Prepare_64 (Comp),
13379 Right_Opnd => Make_Integer_Literal (Loc, 1)));
13380 end if;
13381
13382 -- Build the Last reference we will use
13383
13384 Right :=
13385 Make_Attribute_Reference (Loc,
13386 Prefix => New_Occurrence_Of (Ent, Loc),
13387 Attribute_Name => Name_Last);
13388
13389 if Present (Index) then
13390 Set_Expressions (Right, New_List (New_Copy (Index)));
13391 end if;
13392
13393 -- If general operand, convert Last reference to Long_Long_Integer
13394
13395 if Present (Comp) then
13396 Right := Prepare_64 (Right);
13397 end if;
13398
13399 -- Check for cases to optimize
13400
13401 -- X'Length = 0 => X'First > X'Last
13402 -- X'Length < 1 => X'First > X'Last
13403 -- X'Length < n => X'First + (n - 1) > X'Last
13404
13405 if (Is_Zero and then Op = N_Op_Eq)
13406 or else (not Is_Zero and then Op = N_Op_Lt)
13407 then
13408 Result :=
13409 Make_Op_Gt (Loc,
13410 Left_Opnd => Left,
13411 Right_Opnd => Right);
13412
13413 -- X'Length = 1 => X'First = X'Last
13414 -- X'Length = n => X'First + (n - 1) = X'Last
13415
13416 elsif not Is_Zero and then Op = N_Op_Eq then
13417 Result :=
13418 Make_Op_Eq (Loc,
13419 Left_Opnd => Left,
13420 Right_Opnd => Right);
13421
13422 -- X'Length /= 0 => X'First <= X'Last
13423 -- X'Length > 0 => X'First <= X'Last
13424
13425 elsif Is_Zero and (Op = N_Op_Ne or else Op = N_Op_Gt) then
13426 Result :=
13427 Make_Op_Le (Loc,
13428 Left_Opnd => Left,
13429 Right_Opnd => Right);
13430
13431 -- X'Length /= 1 => X'First /= X'Last
13432 -- X'Length /= n => X'First + (n - 1) /= X'Last
13433
13434 elsif not Is_Zero and then Op = N_Op_Ne then
13435 Result :=
13436 Make_Op_Ne (Loc,
13437 Left_Opnd => Left,
13438 Right_Opnd => Right);
13439
13440 -- X'Length >= 1 => X'First <= X'Last
13441 -- X'Length >= n => X'First + (n - 1) <= X'Last
13442
13443 elsif not Is_Zero and then Op = N_Op_Ge then
13444 Result :=
13445 Make_Op_Le (Loc,
13446 Left_Opnd => Left,
739b155e 13447 Right_Opnd => Right);
4ecb1318 13448
13449 -- X'Length > 1 => X'First < X'Last
13450 -- X'Length > n => X'First + (n = 1) < X'Last
13451
13452 elsif not Is_Zero and then Op = N_Op_Gt then
13453 Result :=
13454 Make_Op_Lt (Loc,
13455 Left_Opnd => Left,
13456 Right_Opnd => Right);
13457
13458 -- X'Length <= 1 => X'First >= X'Last
13459 -- X'Length <= n => X'First + (n - 1) >= X'Last
13460
13461 elsif not Is_Zero and then Op = N_Op_Le then
13462 Result :=
13463 Make_Op_Ge (Loc,
13464 Left_Opnd => Left,
13465 Right_Opnd => Right);
13466
13467 -- Should not happen at this stage
13468
13469 else
13470 raise Program_Error;
13471 end if;
13472
13473 -- Rewrite and finish up
13474
13475 Rewrite (N, Result);
13476 Analyze_And_Resolve (N, Typ);
13477 return;
13478 end Optimize_Length_Comparison;
13479
29d958a7 13480 --------------------------------
13481 -- Process_If_Case_Statements --
13482 --------------------------------
13483
13484 procedure Process_If_Case_Statements (N : Node_Id; Stmts : List_Id) is
13485 Decl : Node_Id;
13486
13487 begin
13488 Decl := First (Stmts);
13489 while Present (Decl) loop
13490 if Nkind (Decl) = N_Object_Declaration
13491 and then Is_Finalizable_Transient (Decl, N)
13492 then
545d732b 13493 Process_Transient_In_Expression (Decl, N, Stmts);
29d958a7 13494 end if;
13495
13496 Next (Decl);
13497 end loop;
13498 end Process_If_Case_Statements;
13499
545d732b 13500 -------------------------------------
13501 -- Process_Transient_In_Expression --
13502 -------------------------------------
1f35ddbe 13503
545d732b 13504 procedure Process_Transient_In_Expression
13505 (Obj_Decl : Node_Id;
13506 Expr : Node_Id;
13507 Stmts : List_Id)
fdbdf68c 13508 is
545d732b 13509 Loc : constant Source_Ptr := Sloc (Obj_Decl);
13510 Obj_Id : constant Entity_Id := Defining_Identifier (Obj_Decl);
29d958a7 13511
545d732b 13512 Hook_Context : constant Node_Id := Find_Hook_Context (Expr);
cf8fe84b 13513 -- The node on which to insert the hook as an action. This is usually
13514 -- the innermost enclosing non-transient construct.
737e8460 13515
545d732b 13516 Fin_Call : Node_Id;
13517 Hook_Assign : Node_Id;
13518 Hook_Clear : Node_Id;
13519 Hook_Decl : Node_Id;
13520 Hook_Insert : Node_Id;
13521 Ptr_Decl : Node_Id;
13522
cf8fe84b 13523 Fin_Context : Node_Id;
13524 -- The node after which to insert the finalization actions of the
545d732b 13525 -- transient object.
1f35ddbe 13526
7c4fb271 13527 begin
545d732b 13528 pragma Assert (Nkind_In (Expr, N_Case_Expression,
13529 N_Expression_With_Actions,
13530 N_If_Expression));
fdbdf68c 13531
13532 -- When the context is a Boolean evaluation, all three nodes capture the
13533 -- result of their computation in a local temporary:
13534
13535 -- do
13536 -- Trans_Id : Ctrl_Typ := ...;
13537 -- Result : constant Boolean := ... Trans_Id ...;
13538 -- <finalize Trans_Id>
13539 -- in Result end;
13540
545d732b 13541 -- As a result, the finalization of any transient objects can safely
13542 -- take place after the result capture.
fdbdf68c 13543
13544 -- ??? could this be extended to elementary types?
13545
545d732b 13546 if Is_Boolean_Type (Etype (Expr)) then
fdbdf68c 13547 Fin_Context := Last (Stmts);
13548
545d732b 13549 -- Otherwise the immediate context may not be safe enough to carry
13550 -- out transient object finalization due to aliasing and nesting of
13551 -- constructs. Insert calls to [Deep_]Finalize after the innermost
fdbdf68c 13552 -- enclosing non-transient construct.
13553
7c4fb271 13554 else
cf8fe84b 13555 Fin_Context := Hook_Context;
7c4fb271 13556 end if;
737e8460 13557
545d732b 13558 -- Mark the transient object as successfully processed to avoid double
13559 -- finalization.
1f35ddbe 13560
545d732b 13561 Set_Is_Finalized_Transient (Obj_Id);
1f35ddbe 13562
545d732b 13563 -- Construct all the pieces necessary to hook and finalize a transient
13564 -- object.
1f35ddbe 13565
545d732b 13566 Build_Transient_Object_Statements
13567 (Obj_Decl => Obj_Decl,
13568 Fin_Call => Fin_Call,
13569 Hook_Assign => Hook_Assign,
13570 Hook_Clear => Hook_Clear,
13571 Hook_Decl => Hook_Decl,
13572 Ptr_Decl => Ptr_Decl,
13573 Finalize_Obj => False);
1f35ddbe 13574
545d732b 13575 -- Add the access type which provides a reference to the transient
13576 -- object. Generate:
1f35ddbe 13577
545d732b 13578 -- type Ptr_Typ is access all Desig_Typ;
1f35ddbe 13579
545d732b 13580 Insert_Action (Hook_Context, Ptr_Decl);
13581
13582 -- Add the temporary which acts as a hook to the transient object.
13583 -- Generate:
1f35ddbe 13584
cf8fe84b 13585 -- Hook : Ptr_Id := null;
1f35ddbe 13586
545d732b 13587 Insert_Action (Hook_Context, Hook_Decl);
1f35ddbe 13588
545d732b 13589 -- When the transient object is initialized by an aggregate, the hook
13590 -- must capture the object after the last aggregate assignment takes
13591 -- place. Only then is the object considered initialized. Generate:
1f35ddbe 13592
545d732b 13593 -- Hook := Ptr_Typ (Obj_Id);
1f35ddbe 13594 -- <or>
cf8fe84b 13595 -- Hook := Obj_Id'Unrestricted_Access;
1f35ddbe 13596
545d732b 13597 if Ekind_In (Obj_Id, E_Constant, E_Variable)
4d40fc09 13598 and then Present (Last_Aggregate_Assignment (Obj_Id))
13599 then
cf8fe84b 13600 Hook_Insert := Last_Aggregate_Assignment (Obj_Id);
4d40fc09 13601
13602 -- Otherwise the hook seizes the related object immediately
13603
13604 else
545d732b 13605 Hook_Insert := Obj_Decl;
4d40fc09 13606 end if;
13607
545d732b 13608 Insert_After_And_Analyze (Hook_Insert, Hook_Assign);
1f35ddbe 13609
13610 -- When the node is part of a return statement, there is no need to
13611 -- insert a finalization call, as the general finalization mechanism
545d732b 13612 -- (see Build_Finalizer) would take care of the transient object on
13613 -- subprogram exit. Note that it would also be impossible to insert the
13614 -- finalization code after the return statement as this will render it
13615 -- unreachable.
1f35ddbe 13616
cf8fe84b 13617 if Nkind (Fin_Context) = N_Simple_Return_Statement then
13618 null;
1f35ddbe 13619
545d732b 13620 -- Finalize the hook after the context has been evaluated. Generate:
13621
13622 -- if Hook /= null then
13623 -- [Deep_]Finalize (Hook.all);
13624 -- Hook := null;
13625 -- end if;
1f35ddbe 13626
cf8fe84b 13627 else
13628 Insert_Action_After (Fin_Context,
545d732b 13629 Make_Implicit_If_Statement (Obj_Decl,
cf8fe84b 13630 Condition =>
13631 Make_Op_Ne (Loc,
545d732b 13632 Left_Opnd =>
13633 New_Occurrence_Of (Defining_Entity (Hook_Decl), Loc),
cf8fe84b 13634 Right_Opnd => Make_Null (Loc)),
13635
13636 Then_Statements => New_List (
545d732b 13637 Fin_Call,
13638 Hook_Clear)));
1f35ddbe 13639 end if;
545d732b 13640 end Process_Transient_In_Expression;
1f35ddbe 13641
ee6ba406 13642 ------------------------
13643 -- Rewrite_Comparison --
13644 ------------------------
13645
13646 procedure Rewrite_Comparison (N : Node_Id) is
fa65ad5e 13647 Typ : constant Entity_Id := Etype (N);
9c486805 13648
fa65ad5e 13649 False_Result : Boolean;
13650 True_Result : Boolean;
9c486805 13651
35c57fc7 13652 begin
13653 if Nkind (N) = N_Type_Conversion then
13654 Rewrite_Comparison (Expression (N));
e8ccec48 13655 return;
ee6ba406 13656
35c57fc7 13657 elsif Nkind (N) not in N_Op_Compare then
e8ccec48 13658 return;
13659 end if;
ee6ba406 13660
fa65ad5e 13661 -- Determine the potential outcome of the comparison assuming that the
13662 -- operands are valid and emit a warning when the comparison evaluates
13663 -- to True or False only in the presence of invalid values.
9c486805 13664
fa65ad5e 13665 Warn_On_Constant_Valid_Condition (N);
ee6ba406 13666
fa65ad5e 13667 -- Determine the potential outcome of the comparison assuming that the
13668 -- operands are not valid.
38f5559f 13669
fa65ad5e 13670 Test_Comparison
13671 (Op => N,
13672 Assume_Valid => False,
13673 True_Result => True_Result,
13674 False_Result => False_Result);
9c486805 13675
fa65ad5e 13676 -- The outcome is a decisive False or True, rewrite the operator
9c486805 13677
fa65ad5e 13678 if False_Result or True_Result then
13679 Rewrite (N,
13680 Convert_To (Typ,
13681 New_Occurrence_Of (Boolean_Literals (True_Result), Sloc (N))));
9c486805 13682
fa65ad5e 13683 Analyze_And_Resolve (N, Typ);
13684 Warn_On_Known_Condition (N);
13685 end if;
ee6ba406 13686 end Rewrite_Comparison;
13687
9dfe12ae 13688 ----------------------------
13689 -- Safe_In_Place_Array_Op --
13690 ----------------------------
13691
13692 function Safe_In_Place_Array_Op
752e1833 13693 (Lhs : Node_Id;
13694 Op1 : Node_Id;
13695 Op2 : Node_Id) return Boolean
9dfe12ae 13696 is
13697 Target : Entity_Id;
13698
13699 function Is_Safe_Operand (Op : Node_Id) return Boolean;
13700 -- Operand is safe if it cannot overlap part of the target of the
13701 -- operation. If the operand and the target are identical, the operand
13702 -- is safe. The operand can be empty in the case of negation.
13703
13704 function Is_Unaliased (N : Node_Id) return Boolean;
f84d3d59 13705 -- Check that N is a stand-alone entity
9dfe12ae 13706
13707 ------------------
13708 -- Is_Unaliased --
13709 ------------------
13710
13711 function Is_Unaliased (N : Node_Id) return Boolean is
13712 begin
13713 return
13714 Is_Entity_Name (N)
13715 and then No (Address_Clause (Entity (N)))
13716 and then No (Renamed_Object (Entity (N)));
13717 end Is_Unaliased;
13718
13719 ---------------------
13720 -- Is_Safe_Operand --
13721 ---------------------
13722
13723 function Is_Safe_Operand (Op : Node_Id) return Boolean is
13724 begin
13725 if No (Op) then
13726 return True;
13727
13728 elsif Is_Entity_Name (Op) then
13729 return Is_Unaliased (Op);
13730
1627db8a 13731 elsif Nkind_In (Op, N_Indexed_Component, N_Selected_Component) then
9dfe12ae 13732 return Is_Unaliased (Prefix (Op));
13733
13734 elsif Nkind (Op) = N_Slice then
13735 return
13736 Is_Unaliased (Prefix (Op))
13737 and then Entity (Prefix (Op)) /= Target;
13738
13739 elsif Nkind (Op) = N_Op_Not then
13740 return Is_Safe_Operand (Right_Opnd (Op));
13741
13742 else
13743 return False;
13744 end if;
13745 end Is_Safe_Operand;
13746
f32c377d 13747 -- Start of processing for Safe_In_Place_Array_Op
9dfe12ae 13748
13749 begin
f1e2dcc5 13750 -- Skip this processing if the component size is different from system
13751 -- storage unit (since at least for NOT this would cause problems).
9dfe12ae 13752
8eb4a5eb 13753 if Component_Size (Etype (Lhs)) /= System_Storage_Unit then
9dfe12ae 13754 return False;
13755
9dfe12ae 13756 -- Cannot do in place stuff if non-standard Boolean representation
13757
8eb4a5eb 13758 elsif Has_Non_Standard_Rep (Component_Type (Etype (Lhs))) then
9dfe12ae 13759 return False;
13760
13761 elsif not Is_Unaliased (Lhs) then
13762 return False;
fd1be697 13763
9dfe12ae 13764 else
13765 Target := Entity (Lhs);
fd1be697 13766 return Is_Safe_Operand (Op1) and then Is_Safe_Operand (Op2);
9dfe12ae 13767 end if;
13768 end Safe_In_Place_Array_Op;
13769
ee6ba406 13770 -----------------------
13771 -- Tagged_Membership --
13772 -----------------------
13773
f1e2dcc5 13774 -- There are two different cases to consider depending on whether the right
13775 -- operand is a class-wide type or not. If not we just compare the actual
13776 -- tag of the left expr to the target type tag:
ee6ba406 13777 --
13778 -- Left_Expr.Tag = Right_Type'Tag;
13779 --
f1e2dcc5 13780 -- If it is a class-wide type we use the RT function CW_Membership which is
13781 -- usually implemented by looking in the ancestor tables contained in the
13782 -- dispatch table pointed by Left_Expr.Tag for Typ'Tag
ee6ba406 13783
99f2248e 13784 -- Ada 2005 (AI-251): If it is a class-wide interface type we use the RT
13785 -- function IW_Membership which is usually implemented by looking in the
13786 -- table of abstract interface types plus the ancestor table contained in
13787 -- the dispatch table pointed by Left_Expr.Tag for Typ'Tag
13788
3feedf2a 13789 procedure Tagged_Membership
13790 (N : Node_Id;
13791 SCIL_Node : out Node_Id;
13792 Result : out Node_Id)
13793 is
ee6ba406 13794 Left : constant Node_Id := Left_Opnd (N);
13795 Right : constant Node_Id := Right_Opnd (N);
13796 Loc : constant Source_Ptr := Sloc (N);
13797
23197014 13798 Full_R_Typ : Entity_Id;
ee6ba406 13799 Left_Type : Entity_Id;
3feedf2a 13800 New_Node : Node_Id;
ee6ba406 13801 Right_Type : Entity_Id;
13802 Obj_Tag : Node_Id;
13803
13804 begin
3feedf2a 13805 SCIL_Node := Empty;
13806
dc95506e 13807 -- Handle entities from the limited view
13808
13809 Left_Type := Available_View (Etype (Left));
13810 Right_Type := Available_View (Etype (Right));
ee6ba406 13811
d071cd96 13812 -- In the case where the type is an access type, the test is applied
13813 -- using the designated types (needed in Ada 2012 for implicit anonymous
13814 -- access conversions, for AI05-0149).
13815
13816 if Is_Access_Type (Right_Type) then
13817 Left_Type := Designated_Type (Left_Type);
13818 Right_Type := Designated_Type (Right_Type);
13819 end if;
13820
ee6ba406 13821 if Is_Class_Wide_Type (Left_Type) then
13822 Left_Type := Root_Type (Left_Type);
13823 end if;
13824
23197014 13825 if Is_Class_Wide_Type (Right_Type) then
13826 Full_R_Typ := Underlying_Type (Root_Type (Right_Type));
13827 else
13828 Full_R_Typ := Underlying_Type (Right_Type);
13829 end if;
13830
ee6ba406 13831 Obj_Tag :=
13832 Make_Selected_Component (Loc,
13833 Prefix => Relocate_Node (Left),
4660e715 13834 Selector_Name =>
83c6c069 13835 New_Occurrence_Of (First_Tag_Component (Left_Type), Loc));
ee6ba406 13836
13837 if Is_Class_Wide_Type (Right_Type) then
aad6babd 13838
99f2248e 13839 -- No need to issue a run-time check if we statically know that the
13840 -- result of this membership test is always true. For example,
13841 -- considering the following declarations:
13842
13843 -- type Iface is interface;
13844 -- type T is tagged null record;
13845 -- type DT is new T and Iface with null record;
13846
13847 -- Obj1 : T;
13848 -- Obj2 : DT;
13849
13850 -- These membership tests are always true:
13851
13852 -- Obj1 in T'Class
13853 -- Obj2 in T'Class;
13854 -- Obj2 in Iface'Class;
13855
13856 -- We do not need to handle cases where the membership is illegal.
13857 -- For example:
13858
13859 -- Obj1 in DT'Class; -- Compile time error
13860 -- Obj1 in Iface'Class; -- Compile time error
13861
13862 if not Is_Class_Wide_Type (Left_Type)
cb4af01d 13863 and then (Is_Ancestor (Etype (Right_Type), Left_Type,
13864 Use_Full_View => True)
6f0d10f7 13865 or else (Is_Interface (Etype (Right_Type))
13866 and then Interface_Present_In_Ancestor
cf04d13c 13867 (Typ => Left_Type,
13868 Iface => Etype (Right_Type))))
99f2248e 13869 then
83c6c069 13870 Result := New_Occurrence_Of (Standard_True, Loc);
3feedf2a 13871 return;
99f2248e 13872 end if;
13873
aad6babd 13874 -- Ada 2005 (AI-251): Class-wide applied to interfaces
13875
4dcc60e5 13876 if Is_Interface (Etype (Class_Wide_Type (Right_Type)))
13877
99f2248e 13878 -- Support to: "Iface_CW_Typ in Typ'Class"
4dcc60e5 13879
13880 or else Is_Interface (Left_Type)
13881 then
ea150575 13882 -- Issue error if IW_Membership operation not available in a
13883 -- configurable run time setting.
13884
13885 if not RTE_Available (RE_IW_Membership) then
40a5a4cb 13886 Error_Msg_CRT
13887 ("dynamic membership test on interface types", N);
3feedf2a 13888 Result := Empty;
13889 return;
ea150575 13890 end if;
13891
3feedf2a 13892 Result :=
aad6babd 13893 Make_Function_Call (Loc,
13894 Name => New_Occurrence_Of (RTE (RE_IW_Membership), Loc),
13895 Parameter_Associations => New_List (
13896 Make_Attribute_Reference (Loc,
13897 Prefix => Obj_Tag,
13898 Attribute_Name => Name_Address),
83c6c069 13899 New_Occurrence_Of (
23197014 13900 Node (First_Elmt (Access_Disp_Table (Full_R_Typ))),
aad6babd 13901 Loc)));
13902
13903 -- Ada 95: Normal case
13904
13905 else
3feedf2a 13906 Build_CW_Membership (Loc,
13907 Obj_Tag_Node => Obj_Tag,
13908 Typ_Tag_Node =>
83c6c069 13909 New_Occurrence_Of (
23197014 13910 Node (First_Elmt (Access_Disp_Table (Full_R_Typ))), Loc),
3feedf2a 13911 Related_Nod => N,
13912 New_Node => New_Node);
13913
13914 -- Generate the SCIL node for this class-wide membership test.
13915 -- Done here because the previous call to Build_CW_Membership
13916 -- relocates Obj_Tag.
13917
13918 if Generate_SCIL then
13919 SCIL_Node := Make_SCIL_Membership_Test (Sloc (N));
13920 Set_SCIL_Entity (SCIL_Node, Etype (Right_Type));
13921 Set_SCIL_Tag_Value (SCIL_Node, Obj_Tag);
13922 end if;
13923
13924 Result := New_Node;
aad6babd 13925 end if;
13926
99f2248e 13927 -- Right_Type is not a class-wide type
13928
ee6ba406 13929 else
99f2248e 13930 -- No need to check the tag of the object if Right_Typ is abstract
13931
13932 if Is_Abstract_Type (Right_Type) then
83c6c069 13933 Result := New_Occurrence_Of (Standard_False, Loc);
99f2248e 13934
13935 else
3feedf2a 13936 Result :=
99f2248e 13937 Make_Op_Eq (Loc,
13938 Left_Opnd => Obj_Tag,
13939 Right_Opnd =>
83c6c069 13940 New_Occurrence_Of
23197014 13941 (Node (First_Elmt (Access_Disp_Table (Full_R_Typ))), Loc));
99f2248e 13942 end if;
ee6ba406 13943 end if;
ee6ba406 13944 end Tagged_Membership;
13945
13946 ------------------------------
13947 -- Unary_Op_Validity_Checks --
13948 ------------------------------
13949
13950 procedure Unary_Op_Validity_Checks (N : Node_Id) is
13951 begin
13952 if Validity_Checks_On and Validity_Check_Operands then
13953 Ensure_Valid (Right_Opnd (N));
13954 end if;
13955 end Unary_Op_Validity_Checks;
13956
13957end Exp_Ch4;