]> git.ipfire.org Git - thirdparty/gcc.git/blob - gcc/ada/exp_attr.adb
939183c56359e02a4999c06261104f6f9da5a213
[thirdparty/gcc.git] / gcc / ada / exp_attr.adb
1 ------------------------------------------------------------------------------
2 -- --
3 -- GNAT COMPILER COMPONENTS --
4 -- --
5 -- E X P _ A T T R --
6 -- --
7 -- B o d y --
8 -- --
9 -- Copyright (C) 1992-2020, Free Software Foundation, Inc. --
10 -- --
11 -- GNAT is free software; you can redistribute it and/or modify it under --
12 -- terms of the GNU General Public License as published by the Free Soft- --
13 -- ware Foundation; either version 3, or (at your option) any later ver- --
14 -- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
15 -- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
16 -- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License --
17 -- for more details. You should have received a copy of the GNU General --
18 -- Public License distributed with GNAT; see file COPYING3. If not, go to --
19 -- http://www.gnu.org/licenses for a complete copy of the license. --
20 -- --
21 -- GNAT was originally developed by the GNAT team at New York University. --
22 -- Extensive contributions were provided by Ada Core Technologies Inc. --
23 -- --
24 ------------------------------------------------------------------------------
25
26 with Aspects; use Aspects;
27 with Atree; use Atree;
28 with Checks; use Checks;
29 with Einfo; use Einfo;
30 with Elists; use Elists;
31 with Exp_Atag; use Exp_Atag;
32 with Exp_Ch2; use Exp_Ch2;
33 with Exp_Ch3; use Exp_Ch3;
34 with Exp_Ch6; use Exp_Ch6;
35 with Exp_Ch9; use Exp_Ch9;
36 with Exp_Dist; use Exp_Dist;
37 with Exp_Imgv; use Exp_Imgv;
38 with Exp_Pakd; use Exp_Pakd;
39 with Exp_Strm; use Exp_Strm;
40 with Exp_Tss; use Exp_Tss;
41 with Exp_Util; use Exp_Util;
42 with Expander; use Expander;
43 with Freeze; use Freeze;
44 with Gnatvsn; use Gnatvsn;
45 with Itypes; use Itypes;
46 with Lib; use Lib;
47 with Namet; use Namet;
48 with Nmake; use Nmake;
49 with Nlists; use Nlists;
50 with Opt; use Opt;
51 with Restrict; use Restrict;
52 with Rident; use Rident;
53 with Rtsfind; use Rtsfind;
54 with Sem; use Sem;
55 with Sem_Aux; use Sem_Aux;
56 with Sem_Ch6; use Sem_Ch6;
57 with Sem_Ch7; use Sem_Ch7;
58 with Sem_Ch8; use Sem_Ch8;
59 with Sem_Eval; use Sem_Eval;
60 with Sem_Res; use Sem_Res;
61 with Sem_Util; use Sem_Util;
62 with Sinfo; use Sinfo;
63 with Snames; use Snames;
64 with Stand; use Stand;
65 with Stringt; use Stringt;
66 with Tbuild; use Tbuild;
67 with Ttypes; use Ttypes;
68 with Uintp; use Uintp;
69 with Uname; use Uname;
70 with Validsw; use Validsw;
71
72 package body Exp_Attr is
73
74 -----------------------
75 -- Local Subprograms --
76 -----------------------
77
78 function Build_Array_VS_Func
79 (Attr : Node_Id;
80 Formal_Typ : Entity_Id;
81 Array_Typ : Entity_Id;
82 Comp_Typ : Entity_Id) return Entity_Id;
83 -- Validate the components of an array type by means of a function. Return
84 -- the entity of the validation function. The parameters are as follows:
85 --
86 -- * Attr - the 'Valid_Scalars attribute for which the function is
87 -- generated.
88 --
89 -- * Formal_Typ - the type of the generated function's only formal
90 -- parameter.
91 --
92 -- * Array_Typ - the array type whose components are to be validated
93 --
94 -- * Comp_Typ - the component type of the array
95
96 function Build_Disp_Get_Task_Id_Call (Actual : Node_Id) return Node_Id;
97 -- Build a call to Disp_Get_Task_Id, passing Actual as actual parameter
98
99 function Build_Record_VS_Func
100 (Attr : Node_Id;
101 Formal_Typ : Entity_Id;
102 Rec_Typ : Entity_Id) return Entity_Id;
103 -- Validate the components, discriminants, and variants of a record type by
104 -- means of a function. Return the entity of the validation function. The
105 -- parameters are as follows:
106 --
107 -- * Attr - the 'Valid_Scalars attribute for which the function is
108 -- generated.
109 --
110 -- * Formal_Typ - the type of the generated function's only formal
111 -- parameter.
112 --
113 -- * Rec_Typ - the record type whose internals are to be validated
114
115 procedure Compile_Stream_Body_In_Scope
116 (N : Node_Id;
117 Decl : Node_Id;
118 Arr : Entity_Id;
119 Check : Boolean);
120 -- The body for a stream subprogram may be generated outside of the scope
121 -- of the type. If the type is fully private, it may depend on the full
122 -- view of other types (e.g. indexes) that are currently private as well.
123 -- We install the declarations of the package in which the type is declared
124 -- before compiling the body in what is its proper environment. The Check
125 -- parameter indicates if checks are to be suppressed for the stream body.
126 -- We suppress checks for array/record reads, since the rule is that these
127 -- are like assignments, out of range values due to uninitialized storage,
128 -- or other invalid values do NOT cause a Constraint_Error to be raised.
129 -- If we are within an instance body all visibility has been established
130 -- already and there is no need to install the package.
131
132 -- This mechanism is now extended to the component types of the array type,
133 -- when the component type is not in scope and is private, to handle
134 -- properly the case when the full view has defaulted discriminants.
135
136 -- This special processing is ultimately caused by the fact that the
137 -- compiler lacks a well-defined phase when full views are visible
138 -- everywhere. Having such a separate pass would remove much of the
139 -- special-case code that shuffles partial and full views in the middle
140 -- of semantic analysis and expansion.
141
142 procedure Expand_Access_To_Protected_Op
143 (N : Node_Id;
144 Pref : Node_Id;
145 Typ : Entity_Id);
146 -- An attribute reference to a protected subprogram is transformed into
147 -- a pair of pointers: one to the object, and one to the operations.
148 -- This expansion is performed for 'Access and for 'Unrestricted_Access.
149
150 procedure Expand_Fpt_Attribute
151 (N : Node_Id;
152 Pkg : RE_Id;
153 Nam : Name_Id;
154 Args : List_Id);
155 -- This procedure expands a call to a floating-point attribute function.
156 -- N is the attribute reference node, and Args is a list of arguments to
157 -- be passed to the function call. Pkg identifies the package containing
158 -- the appropriate instantiation of System.Fat_Gen. Float arguments in Args
159 -- have already been converted to the floating-point type for which Pkg was
160 -- instantiated. The Nam argument is the relevant attribute processing
161 -- routine to be called. This is the same as the attribute name, except in
162 -- the Unaligned_Valid case.
163
164 procedure Expand_Fpt_Attribute_R (N : Node_Id);
165 -- This procedure expands a call to a floating-point attribute function
166 -- that takes a single floating-point argument. The function to be called
167 -- is always the same as the attribute name.
168
169 procedure Expand_Fpt_Attribute_RI (N : Node_Id);
170 -- This procedure expands a call to a floating-point attribute function
171 -- that takes one floating-point argument and one integer argument. The
172 -- function to be called is always the same as the attribute name.
173
174 procedure Expand_Fpt_Attribute_RR (N : Node_Id);
175 -- This procedure expands a call to a floating-point attribute function
176 -- that takes two floating-point arguments. The function to be called
177 -- is always the same as the attribute name.
178
179 procedure Expand_Loop_Entry_Attribute (N : Node_Id);
180 -- Handle the expansion of attribute 'Loop_Entry. As a result, the related
181 -- loop may be converted into a conditional block. See body for details.
182
183 procedure Expand_Min_Max_Attribute (N : Node_Id);
184 -- Handle the expansion of attributes 'Max and 'Min, including expanding
185 -- then out if we are in Modify_Tree_For_C mode.
186
187 procedure Expand_Pred_Succ_Attribute (N : Node_Id);
188 -- Handles expansion of Pred or Succ attributes for case of non-real
189 -- operand with overflow checking required.
190
191 procedure Expand_Update_Attribute (N : Node_Id);
192 -- Handle the expansion of attribute Update
193
194 function Get_Index_Subtype (N : Node_Id) return Entity_Id;
195 -- Used for Last, Last, and Length, when the prefix is an array type.
196 -- Obtains the corresponding index subtype.
197
198 procedure Find_Fat_Info
199 (T : Entity_Id;
200 Fat_Type : out Entity_Id;
201 Fat_Pkg : out RE_Id);
202 -- Given a floating-point type T, identifies the package containing the
203 -- attributes for this type (returned in Fat_Pkg), and the corresponding
204 -- type for which this package was instantiated from Fat_Gen. Error if T
205 -- is not a floating-point type.
206
207 function Find_Stream_Subprogram
208 (Typ : Entity_Id;
209 Nam : TSS_Name_Type) return Entity_Id;
210 -- Returns the stream-oriented subprogram attribute for Typ. For tagged
211 -- types, the corresponding primitive operation is looked up, else the
212 -- appropriate TSS from the type itself, or from its closest ancestor
213 -- defining it, is returned. In both cases, inheritance of representation
214 -- aspects is thus taken into account.
215
216 function Full_Base (T : Entity_Id) return Entity_Id;
217 -- The stream functions need to examine the underlying representation of
218 -- composite types. In some cases T may be non-private but its base type
219 -- is, in which case the function returns the corresponding full view.
220
221 function Get_Stream_Convert_Pragma (T : Entity_Id) return Node_Id;
222 -- Given a type, find a corresponding stream convert pragma that applies to
223 -- the implementation base type of this type (Typ). If found, return the
224 -- pragma node, otherwise return Empty if no pragma is found.
225
226 function Is_Constrained_Packed_Array (Typ : Entity_Id) return Boolean;
227 -- Utility for array attributes, returns true on packed constrained
228 -- arrays, and on access to same.
229
230 function Is_Inline_Floating_Point_Attribute (N : Node_Id) return Boolean;
231 -- Returns true iff the given node refers to an attribute call that
232 -- can be expanded directly by the back end and does not need front end
233 -- expansion. Typically used for rounding and truncation attributes that
234 -- appear directly inside a conversion to integer.
235
236 -------------------------
237 -- Build_Array_VS_Func --
238 -------------------------
239
240 function Build_Array_VS_Func
241 (Attr : Node_Id;
242 Formal_Typ : Entity_Id;
243 Array_Typ : Entity_Id;
244 Comp_Typ : Entity_Id) return Entity_Id
245 is
246 Loc : constant Source_Ptr := Sloc (Attr);
247
248 function Validate_Component
249 (Obj_Id : Entity_Id;
250 Indexes : List_Id) return Node_Id;
251 -- Process a single component denoted by indexes Indexes. Obj_Id denotes
252 -- the entity of the validation parameter. Return the check associated
253 -- with the component.
254
255 function Validate_Dimension
256 (Obj_Id : Entity_Id;
257 Dim : Int;
258 Indexes : List_Id) return Node_Id;
259 -- Process dimension Dim of the array type. Obj_Id denotes the entity
260 -- of the validation parameter. Indexes is a list where each dimension
261 -- deposits its loop variable, which will later identify a component.
262 -- Return the loop associated with the current dimension.
263
264 ------------------------
265 -- Validate_Component --
266 ------------------------
267
268 function Validate_Component
269 (Obj_Id : Entity_Id;
270 Indexes : List_Id) return Node_Id
271 is
272 Attr_Nam : Name_Id;
273
274 begin
275 if Is_Scalar_Type (Comp_Typ) then
276 Attr_Nam := Name_Valid;
277 else
278 Attr_Nam := Name_Valid_Scalars;
279 end if;
280
281 -- Generate:
282 -- if not Array_Typ (Obj_Id) (Indexes)'Valid[_Scalars] then
283 -- return False;
284 -- end if;
285
286 return
287 Make_If_Statement (Loc,
288 Condition =>
289 Make_Op_Not (Loc,
290 Right_Opnd =>
291 Make_Attribute_Reference (Loc,
292 Prefix =>
293 Make_Indexed_Component (Loc,
294 Prefix =>
295 Unchecked_Convert_To (Array_Typ,
296 New_Occurrence_Of (Obj_Id, Loc)),
297 Expressions => Indexes),
298 Attribute_Name => Attr_Nam)),
299
300 Then_Statements => New_List (
301 Make_Simple_Return_Statement (Loc,
302 Expression => New_Occurrence_Of (Standard_False, Loc))));
303 end Validate_Component;
304
305 ------------------------
306 -- Validate_Dimension --
307 ------------------------
308
309 function Validate_Dimension
310 (Obj_Id : Entity_Id;
311 Dim : Int;
312 Indexes : List_Id) return Node_Id
313 is
314 Index : Entity_Id;
315
316 begin
317 -- Validate the component once all dimensions have produced their
318 -- individual loops.
319
320 if Dim > Number_Dimensions (Array_Typ) then
321 return Validate_Component (Obj_Id, Indexes);
322
323 -- Process the current dimension
324
325 else
326 Index :=
327 Make_Defining_Identifier (Loc, New_External_Name ('J', Dim));
328
329 Append_To (Indexes, New_Occurrence_Of (Index, Loc));
330
331 -- Generate:
332 -- for J1 in Array_Typ (Obj_Id)'Range (1) loop
333 -- for JN in Array_Typ (Obj_Id)'Range (N) loop
334 -- if not Array_Typ (Obj_Id) (Indexes)'Valid[_Scalars]
335 -- then
336 -- return False;
337 -- end if;
338 -- end loop;
339 -- end loop;
340
341 return
342 Make_Implicit_Loop_Statement (Attr,
343 Identifier => Empty,
344 Iteration_Scheme =>
345 Make_Iteration_Scheme (Loc,
346 Loop_Parameter_Specification =>
347 Make_Loop_Parameter_Specification (Loc,
348 Defining_Identifier => Index,
349 Discrete_Subtype_Definition =>
350 Make_Attribute_Reference (Loc,
351 Prefix =>
352 Unchecked_Convert_To (Array_Typ,
353 New_Occurrence_Of (Obj_Id, Loc)),
354 Attribute_Name => Name_Range,
355 Expressions => New_List (
356 Make_Integer_Literal (Loc, Dim))))),
357 Statements => New_List (
358 Validate_Dimension (Obj_Id, Dim + 1, Indexes)));
359 end if;
360 end Validate_Dimension;
361
362 -- Local variables
363
364 Func_Id : constant Entity_Id := Make_Temporary (Loc, 'V');
365 Indexes : constant List_Id := New_List;
366 Obj_Id : constant Entity_Id := Make_Temporary (Loc, 'A');
367 Stmts : List_Id;
368
369 -- Start of processing for Build_Array_VS_Func
370
371 begin
372 Stmts := New_List (Validate_Dimension (Obj_Id, 1, Indexes));
373
374 -- Generate:
375 -- return True;
376
377 Append_To (Stmts,
378 Make_Simple_Return_Statement (Loc,
379 Expression => New_Occurrence_Of (Standard_True, Loc)));
380
381 -- Generate:
382 -- function Func_Id (Obj_Id : Formal_Typ) return Boolean is
383 -- begin
384 -- Stmts
385 -- end Func_Id;
386
387 Set_Ekind (Func_Id, E_Function);
388 Set_Is_Internal (Func_Id);
389 Set_Is_Pure (Func_Id);
390
391 if not Debug_Generated_Code then
392 Set_Debug_Info_Off (Func_Id);
393 end if;
394
395 Insert_Action (Attr,
396 Make_Subprogram_Body (Loc,
397 Specification =>
398 Make_Function_Specification (Loc,
399 Defining_Unit_Name => Func_Id,
400 Parameter_Specifications => New_List (
401 Make_Parameter_Specification (Loc,
402 Defining_Identifier => Obj_Id,
403 In_Present => True,
404 Out_Present => False,
405 Parameter_Type => New_Occurrence_Of (Formal_Typ, Loc))),
406 Result_Definition =>
407 New_Occurrence_Of (Standard_Boolean, Loc)),
408 Declarations => New_List,
409 Handled_Statement_Sequence =>
410 Make_Handled_Sequence_Of_Statements (Loc,
411 Statements => Stmts)));
412
413 return Func_Id;
414 end Build_Array_VS_Func;
415
416 ---------------------------------
417 -- Build_Disp_Get_Task_Id_Call --
418 ---------------------------------
419
420 function Build_Disp_Get_Task_Id_Call (Actual : Node_Id) return Node_Id is
421 Loc : constant Source_Ptr := Sloc (Actual);
422 Typ : constant Entity_Id := Etype (Actual);
423 Subp : constant Entity_Id := Find_Prim_Op (Typ, Name_uDisp_Get_Task_Id);
424
425 begin
426 -- Generate:
427 -- _Disp_Get_Task_Id (Actual)
428
429 return
430 Make_Function_Call (Loc,
431 Name => New_Occurrence_Of (Subp, Loc),
432 Parameter_Associations => New_List (Actual));
433 end Build_Disp_Get_Task_Id_Call;
434
435 --------------------------
436 -- Build_Record_VS_Func --
437 --------------------------
438
439 function Build_Record_VS_Func
440 (Attr : Node_Id;
441 Formal_Typ : Entity_Id;
442 Rec_Typ : Entity_Id) return Entity_Id
443 is
444 -- NOTE: The logic of Build_Record_VS_Func is intentionally passive.
445 -- It generates code only when there are components, discriminants,
446 -- or variant parts to validate.
447
448 -- NOTE: The routines within Build_Record_VS_Func are intentionally
449 -- unnested to avoid deep indentation of code.
450
451 Loc : constant Source_Ptr := Sloc (Attr);
452
453 procedure Validate_Component_List
454 (Obj_Id : Entity_Id;
455 Comp_List : Node_Id;
456 Stmts : in out List_Id);
457 -- Process all components and variant parts of component list Comp_List.
458 -- Obj_Id denotes the entity of the validation parameter. All new code
459 -- is added to list Stmts.
460
461 procedure Validate_Field
462 (Obj_Id : Entity_Id;
463 Field : Node_Id;
464 Cond : in out Node_Id);
465 -- Process component declaration or discriminant specification Field.
466 -- Obj_Id denotes the entity of the validation parameter. Cond denotes
467 -- an "or else" conditional expression which contains the new code (if
468 -- any).
469
470 procedure Validate_Fields
471 (Obj_Id : Entity_Id;
472 Fields : List_Id;
473 Stmts : in out List_Id);
474 -- Process component declarations or discriminant specifications in list
475 -- Fields. Obj_Id denotes the entity of the validation parameter. All
476 -- new code is added to list Stmts.
477
478 procedure Validate_Variant
479 (Obj_Id : Entity_Id;
480 Var : Node_Id;
481 Alts : in out List_Id);
482 -- Process variant Var. Obj_Id denotes the entity of the validation
483 -- parameter. Alts denotes a list of case statement alternatives which
484 -- contains the new code (if any).
485
486 procedure Validate_Variant_Part
487 (Obj_Id : Entity_Id;
488 Var_Part : Node_Id;
489 Stmts : in out List_Id);
490 -- Process variant part Var_Part. Obj_Id denotes the entity of the
491 -- validation parameter. All new code is added to list Stmts.
492
493 -----------------------------
494 -- Validate_Component_List --
495 -----------------------------
496
497 procedure Validate_Component_List
498 (Obj_Id : Entity_Id;
499 Comp_List : Node_Id;
500 Stmts : in out List_Id)
501 is
502 Var_Part : constant Node_Id := Variant_Part (Comp_List);
503
504 begin
505 -- Validate all components
506
507 Validate_Fields
508 (Obj_Id => Obj_Id,
509 Fields => Component_Items (Comp_List),
510 Stmts => Stmts);
511
512 -- Validate the variant part
513
514 if Present (Var_Part) then
515 Validate_Variant_Part
516 (Obj_Id => Obj_Id,
517 Var_Part => Var_Part,
518 Stmts => Stmts);
519 end if;
520 end Validate_Component_List;
521
522 --------------------
523 -- Validate_Field --
524 --------------------
525
526 procedure Validate_Field
527 (Obj_Id : Entity_Id;
528 Field : Node_Id;
529 Cond : in out Node_Id)
530 is
531 Field_Id : constant Entity_Id := Defining_Entity (Field);
532 Field_Nam : constant Name_Id := Chars (Field_Id);
533 Field_Typ : constant Entity_Id := Validated_View (Etype (Field_Id));
534 Attr_Nam : Name_Id;
535
536 begin
537 -- Do not process internally-generated fields. Note that checking for
538 -- Comes_From_Source is not correct because this will eliminate the
539 -- components within the corresponding record of a protected type.
540
541 if Nam_In (Field_Nam, Name_uObject,
542 Name_uParent,
543 Name_uTag)
544 then
545 null;
546
547 -- Do not process fields without any scalar components
548
549 elsif not Scalar_Part_Present (Field_Typ) then
550 null;
551
552 -- Otherwise the field needs to be validated. Use Make_Identifier
553 -- rather than New_Occurrence_Of to identify the field because the
554 -- wrong entity may be picked up when private types are involved.
555
556 -- Generate:
557 -- [or else] not Rec_Typ (Obj_Id).Item_Nam'Valid[_Scalars]
558
559 else
560 if Is_Scalar_Type (Field_Typ) then
561 Attr_Nam := Name_Valid;
562 else
563 Attr_Nam := Name_Valid_Scalars;
564 end if;
565
566 Evolve_Or_Else (Cond,
567 Make_Op_Not (Loc,
568 Right_Opnd =>
569 Make_Attribute_Reference (Loc,
570 Prefix =>
571 Make_Selected_Component (Loc,
572 Prefix =>
573 Unchecked_Convert_To (Rec_Typ,
574 New_Occurrence_Of (Obj_Id, Loc)),
575 Selector_Name => Make_Identifier (Loc, Field_Nam)),
576 Attribute_Name => Attr_Nam)));
577 end if;
578 end Validate_Field;
579
580 ---------------------
581 -- Validate_Fields --
582 ---------------------
583
584 procedure Validate_Fields
585 (Obj_Id : Entity_Id;
586 Fields : List_Id;
587 Stmts : in out List_Id)
588 is
589 Cond : Node_Id;
590 Field : Node_Id;
591
592 begin
593 -- Assume that none of the fields are eligible for verification
594
595 Cond := Empty;
596
597 -- Validate all fields
598
599 Field := First_Non_Pragma (Fields);
600 while Present (Field) loop
601 Validate_Field
602 (Obj_Id => Obj_Id,
603 Field => Field,
604 Cond => Cond);
605
606 Next_Non_Pragma (Field);
607 end loop;
608
609 -- Generate:
610 -- if not Rec_Typ (Obj_Id).Item_Nam_1'Valid[_Scalars]
611 -- or else not Rec_Typ (Obj_Id).Item_Nam_N'Valid[_Scalars]
612 -- then
613 -- return False;
614 -- end if;
615
616 if Present (Cond) then
617 Append_New_To (Stmts,
618 Make_Implicit_If_Statement (Attr,
619 Condition => Cond,
620 Then_Statements => New_List (
621 Make_Simple_Return_Statement (Loc,
622 Expression => New_Occurrence_Of (Standard_False, Loc)))));
623 end if;
624 end Validate_Fields;
625
626 ----------------------
627 -- Validate_Variant --
628 ----------------------
629
630 procedure Validate_Variant
631 (Obj_Id : Entity_Id;
632 Var : Node_Id;
633 Alts : in out List_Id)
634 is
635 Stmts : List_Id;
636
637 begin
638 -- Assume that none of the components and variants are eligible for
639 -- verification.
640
641 Stmts := No_List;
642
643 -- Validate components
644
645 Validate_Component_List
646 (Obj_Id => Obj_Id,
647 Comp_List => Component_List (Var),
648 Stmts => Stmts);
649
650 -- Generate a null statement in case none of the components were
651 -- verified because this will otherwise eliminate an alternative
652 -- from the variant case statement and render the generated code
653 -- illegal.
654
655 if No (Stmts) then
656 Append_New_To (Stmts, Make_Null_Statement (Loc));
657 end if;
658
659 -- Generate:
660 -- when Discrete_Choices =>
661 -- Stmts
662
663 Append_New_To (Alts,
664 Make_Case_Statement_Alternative (Loc,
665 Discrete_Choices =>
666 New_Copy_List_Tree (Discrete_Choices (Var)),
667 Statements => Stmts));
668 end Validate_Variant;
669
670 ---------------------------
671 -- Validate_Variant_Part --
672 ---------------------------
673
674 procedure Validate_Variant_Part
675 (Obj_Id : Entity_Id;
676 Var_Part : Node_Id;
677 Stmts : in out List_Id)
678 is
679 Vars : constant List_Id := Variants (Var_Part);
680 Alts : List_Id;
681 Var : Node_Id;
682
683 begin
684 -- Assume that none of the variants are eligible for verification
685
686 Alts := No_List;
687
688 -- Validate variants
689
690 Var := First_Non_Pragma (Vars);
691 while Present (Var) loop
692 Validate_Variant
693 (Obj_Id => Obj_Id,
694 Var => Var,
695 Alts => Alts);
696
697 Next_Non_Pragma (Var);
698 end loop;
699
700 -- Even though individual variants may lack eligible components, the
701 -- alternatives must still be generated.
702
703 pragma Assert (Present (Alts));
704
705 -- Generate:
706 -- case Rec_Typ (Obj_Id).Discriminant is
707 -- when Discrete_Choices_1 =>
708 -- Stmts_1
709 -- when Discrete_Choices_N =>
710 -- Stmts_N
711 -- end case;
712
713 Append_New_To (Stmts,
714 Make_Case_Statement (Loc,
715 Expression =>
716 Make_Selected_Component (Loc,
717 Prefix =>
718 Unchecked_Convert_To (Rec_Typ,
719 New_Occurrence_Of (Obj_Id, Loc)),
720 Selector_Name => New_Copy_Tree (Name (Var_Part))),
721 Alternatives => Alts));
722 end Validate_Variant_Part;
723
724 -- Local variables
725
726 Func_Id : constant Entity_Id := Make_Temporary (Loc, 'V');
727 Obj_Id : constant Entity_Id := Make_Temporary (Loc, 'R');
728 Comps : Node_Id;
729 Stmts : List_Id;
730 Typ : Entity_Id;
731 Typ_Decl : Node_Id;
732 Typ_Def : Node_Id;
733 Typ_Ext : Node_Id;
734
735 -- Start of processing for Build_Record_VS_Func
736
737 begin
738 Typ := Rec_Typ;
739
740 -- Use the root type when dealing with a class-wide type
741
742 if Is_Class_Wide_Type (Typ) then
743 Typ := Root_Type (Typ);
744 end if;
745
746 Typ_Decl := Declaration_Node (Typ);
747 Typ_Def := Type_Definition (Typ_Decl);
748
749 -- The components of a derived type are located in the extension part
750
751 if Nkind (Typ_Def) = N_Derived_Type_Definition then
752 Typ_Ext := Record_Extension_Part (Typ_Def);
753
754 if Present (Typ_Ext) then
755 Comps := Component_List (Typ_Ext);
756 else
757 Comps := Empty;
758 end if;
759
760 -- Otherwise the components are available in the definition
761
762 else
763 Comps := Component_List (Typ_Def);
764 end if;
765
766 -- The code generated by this routine is as follows:
767 --
768 -- function Func_Id (Obj_Id : Formal_Typ) return Boolean is
769 -- begin
770 -- if not Rec_Typ (Obj_Id).Discriminant_1'Valid[_Scalars]
771 -- or else not Rec_Typ (Obj_Id).Discriminant_N'Valid[_Scalars]
772 -- then
773 -- return False;
774 -- end if;
775 --
776 -- if not Rec_Typ (Obj_Id).Component_1'Valid[_Scalars]
777 -- or else not Rec_Typ (Obj_Id).Component_N'Valid[_Scalars]
778 -- then
779 -- return False;
780 -- end if;
781 --
782 -- case Discriminant_1 is
783 -- when Choice_1 =>
784 -- if not Rec_Typ (Obj_Id).Component_1'Valid[_Scalars]
785 -- or else not Rec_Typ (Obj_Id).Component_N'Valid[_Scalars]
786 -- then
787 -- return False;
788 -- end if;
789 --
790 -- case Discriminant_N is
791 -- ...
792 -- when Choice_N =>
793 -- ...
794 -- end case;
795 --
796 -- return True;
797 -- end Func_Id;
798
799 -- Assume that the record type lacks eligible components, discriminants,
800 -- and variant parts.
801
802 Stmts := No_List;
803
804 -- Validate the discriminants
805
806 if not Is_Unchecked_Union (Rec_Typ) then
807 Validate_Fields
808 (Obj_Id => Obj_Id,
809 Fields => Discriminant_Specifications (Typ_Decl),
810 Stmts => Stmts);
811 end if;
812
813 -- Validate the components and variant parts
814
815 Validate_Component_List
816 (Obj_Id => Obj_Id,
817 Comp_List => Comps,
818 Stmts => Stmts);
819
820 -- Generate:
821 -- return True;
822
823 Append_New_To (Stmts,
824 Make_Simple_Return_Statement (Loc,
825 Expression => New_Occurrence_Of (Standard_True, Loc)));
826
827 -- Generate:
828 -- function Func_Id (Obj_Id : Formal_Typ) return Boolean is
829 -- begin
830 -- Stmts
831 -- end Func_Id;
832
833 Set_Ekind (Func_Id, E_Function);
834 Set_Is_Internal (Func_Id);
835 Set_Is_Pure (Func_Id);
836
837 if not Debug_Generated_Code then
838 Set_Debug_Info_Off (Func_Id);
839 end if;
840
841 Insert_Action (Attr,
842 Make_Subprogram_Body (Loc,
843 Specification =>
844 Make_Function_Specification (Loc,
845 Defining_Unit_Name => Func_Id,
846 Parameter_Specifications => New_List (
847 Make_Parameter_Specification (Loc,
848 Defining_Identifier => Obj_Id,
849 Parameter_Type => New_Occurrence_Of (Formal_Typ, Loc))),
850 Result_Definition =>
851 New_Occurrence_Of (Standard_Boolean, Loc)),
852 Declarations => New_List,
853 Handled_Statement_Sequence =>
854 Make_Handled_Sequence_Of_Statements (Loc,
855 Statements => Stmts)),
856 Suppress => Discriminant_Check);
857
858 return Func_Id;
859 end Build_Record_VS_Func;
860
861 ----------------------------------
862 -- Compile_Stream_Body_In_Scope --
863 ----------------------------------
864
865 procedure Compile_Stream_Body_In_Scope
866 (N : Node_Id;
867 Decl : Node_Id;
868 Arr : Entity_Id;
869 Check : Boolean)
870 is
871 C_Type : constant Entity_Id := Base_Type (Component_Type (Arr));
872 Curr : constant Entity_Id := Current_Scope;
873 Install : Boolean := False;
874 Scop : Entity_Id := Scope (Arr);
875
876 begin
877 if Is_Hidden (Arr)
878 and then not In_Open_Scopes (Scop)
879 and then Ekind (Scop) = E_Package
880 then
881 Install := True;
882
883 else
884 -- The component type may be private, in which case we install its
885 -- full view to compile the subprogram.
886
887 -- The component type may be private, in which case we install its
888 -- full view to compile the subprogram. We do not do this if the
889 -- type has a Stream_Convert pragma, which indicates that there are
890 -- special stream-processing operations for that type (for example
891 -- Unbounded_String and its wide varieties).
892
893 Scop := Scope (C_Type);
894
895 if Is_Private_Type (C_Type)
896 and then Present (Full_View (C_Type))
897 and then not In_Open_Scopes (Scop)
898 and then Ekind (Scop) = E_Package
899 and then No (Get_Stream_Convert_Pragma (C_Type))
900 then
901 Install := True;
902 end if;
903 end if;
904
905 -- If we are within an instance body, then all visibility has been
906 -- established already and there is no need to install the package.
907
908 if Install and then not In_Instance_Body then
909 Push_Scope (Scop);
910 Install_Visible_Declarations (Scop);
911 Install_Private_Declarations (Scop);
912
913 -- The entities in the package are now visible, but the generated
914 -- stream entity must appear in the current scope (usually an
915 -- enclosing stream function) so that itypes all have their proper
916 -- scopes.
917
918 Push_Scope (Curr);
919 else
920 Install := False;
921 end if;
922
923 if Check then
924 Insert_Action (N, Decl);
925 else
926 Insert_Action (N, Decl, Suppress => All_Checks);
927 end if;
928
929 if Install then
930
931 -- Remove extra copy of current scope, and package itself
932
933 Pop_Scope;
934 End_Package_Scope (Scop);
935 end if;
936 end Compile_Stream_Body_In_Scope;
937
938 -----------------------------------
939 -- Expand_Access_To_Protected_Op --
940 -----------------------------------
941
942 procedure Expand_Access_To_Protected_Op
943 (N : Node_Id;
944 Pref : Node_Id;
945 Typ : Entity_Id)
946 is
947 -- The value of the attribute_reference is a record containing two
948 -- fields: an access to the protected object, and an access to the
949 -- subprogram itself. The prefix is a selected component.
950
951 Loc : constant Source_Ptr := Sloc (N);
952 Agg : Node_Id;
953 Btyp : constant Entity_Id := Base_Type (Typ);
954 Sub : Entity_Id;
955 Sub_Ref : Node_Id;
956 E_T : constant Entity_Id := Equivalent_Type (Btyp);
957 Acc : constant Entity_Id :=
958 Etype (Next_Component (First_Component (E_T)));
959 Obj_Ref : Node_Id;
960 Curr : Entity_Id;
961
962 -- Start of processing for Expand_Access_To_Protected_Op
963
964 begin
965 -- Within the body of the protected type, the prefix designates a local
966 -- operation, and the object is the first parameter of the corresponding
967 -- protected body of the current enclosing operation.
968
969 if Is_Entity_Name (Pref) then
970 -- All indirect calls are external calls, so must do locking and
971 -- barrier reevaluation, even if the 'Access occurs within the
972 -- protected body. Hence the call to External_Subprogram, as opposed
973 -- to Protected_Body_Subprogram, below. See RM-9.5(5). This means
974 -- that indirect calls from within the same protected body will
975 -- deadlock, as allowed by RM-9.5.1(8,15,17).
976
977 Sub := New_Occurrence_Of (External_Subprogram (Entity (Pref)), Loc);
978
979 -- Don't traverse the scopes when the attribute occurs within an init
980 -- proc, because we directly use the _init formal of the init proc in
981 -- that case.
982
983 Curr := Current_Scope;
984 if not Is_Init_Proc (Curr) then
985 pragma Assert (In_Open_Scopes (Scope (Entity (Pref))));
986
987 while Scope (Curr) /= Scope (Entity (Pref)) loop
988 Curr := Scope (Curr);
989 end loop;
990 end if;
991
992 -- In case of protected entries the first formal of its Protected_
993 -- Body_Subprogram is the address of the object.
994
995 if Ekind (Curr) = E_Entry then
996 Obj_Ref :=
997 New_Occurrence_Of
998 (First_Formal
999 (Protected_Body_Subprogram (Curr)), Loc);
1000
1001 -- If the current scope is an init proc, then use the address of the
1002 -- _init formal as the object reference.
1003
1004 elsif Is_Init_Proc (Curr) then
1005 Obj_Ref :=
1006 Make_Attribute_Reference (Loc,
1007 Prefix => New_Occurrence_Of (First_Formal (Curr), Loc),
1008 Attribute_Name => Name_Address);
1009
1010 -- In case of protected subprograms the first formal of its
1011 -- Protected_Body_Subprogram is the object and we get its address.
1012
1013 else
1014 Obj_Ref :=
1015 Make_Attribute_Reference (Loc,
1016 Prefix =>
1017 New_Occurrence_Of
1018 (First_Formal
1019 (Protected_Body_Subprogram (Curr)), Loc),
1020 Attribute_Name => Name_Address);
1021 end if;
1022
1023 -- Case where the prefix is not an entity name. Find the
1024 -- version of the protected operation to be called from
1025 -- outside the protected object.
1026
1027 else
1028 Sub :=
1029 New_Occurrence_Of
1030 (External_Subprogram
1031 (Entity (Selector_Name (Pref))), Loc);
1032
1033 Obj_Ref :=
1034 Make_Attribute_Reference (Loc,
1035 Prefix => Relocate_Node (Prefix (Pref)),
1036 Attribute_Name => Name_Address);
1037 end if;
1038
1039 Sub_Ref :=
1040 Make_Attribute_Reference (Loc,
1041 Prefix => Sub,
1042 Attribute_Name => Name_Access);
1043
1044 -- We set the type of the access reference to the already generated
1045 -- access_to_subprogram type, and declare the reference analyzed, to
1046 -- prevent further expansion when the enclosing aggregate is analyzed.
1047
1048 Set_Etype (Sub_Ref, Acc);
1049 Set_Analyzed (Sub_Ref);
1050
1051 Agg :=
1052 Make_Aggregate (Loc,
1053 Expressions => New_List (Obj_Ref, Sub_Ref));
1054
1055 -- Sub_Ref has been marked as analyzed, but we still need to make sure
1056 -- Sub is correctly frozen.
1057
1058 Freeze_Before (N, Entity (Sub));
1059
1060 Rewrite (N, Agg);
1061 Analyze_And_Resolve (N, E_T);
1062
1063 -- For subsequent analysis, the node must retain its type. The backend
1064 -- will replace it with the equivalent type where needed.
1065
1066 Set_Etype (N, Typ);
1067 end Expand_Access_To_Protected_Op;
1068
1069 --------------------------
1070 -- Expand_Fpt_Attribute --
1071 --------------------------
1072
1073 procedure Expand_Fpt_Attribute
1074 (N : Node_Id;
1075 Pkg : RE_Id;
1076 Nam : Name_Id;
1077 Args : List_Id)
1078 is
1079 Loc : constant Source_Ptr := Sloc (N);
1080 Typ : constant Entity_Id := Etype (N);
1081 Fnm : Node_Id;
1082
1083 begin
1084 -- The function name is the selected component Attr_xxx.yyy where
1085 -- Attr_xxx is the package name, and yyy is the argument Nam.
1086
1087 -- Note: it would be more usual to have separate RE entries for each
1088 -- of the entities in the Fat packages, but first they have identical
1089 -- names (so we would have to have lots of renaming declarations to
1090 -- meet the normal RE rule of separate names for all runtime entities),
1091 -- and second there would be an awful lot of them.
1092
1093 Fnm :=
1094 Make_Selected_Component (Loc,
1095 Prefix => New_Occurrence_Of (RTE (Pkg), Loc),
1096 Selector_Name => Make_Identifier (Loc, Nam));
1097
1098 -- The generated call is given the provided set of parameters, and then
1099 -- wrapped in a conversion which converts the result to the target type.
1100
1101 Rewrite (N,
1102 Convert_To (Typ,
1103 Make_Function_Call (Loc,
1104 Name => Fnm,
1105 Parameter_Associations => Args)));
1106
1107 Analyze_And_Resolve (N, Typ);
1108 end Expand_Fpt_Attribute;
1109
1110 ----------------------------
1111 -- Expand_Fpt_Attribute_R --
1112 ----------------------------
1113
1114 -- The single argument is converted to its root type to call the
1115 -- appropriate runtime function, with the actual call being built
1116 -- by Expand_Fpt_Attribute
1117
1118 procedure Expand_Fpt_Attribute_R (N : Node_Id) is
1119 E1 : constant Node_Id := First (Expressions (N));
1120 Ftp : Entity_Id;
1121 Pkg : RE_Id;
1122 begin
1123 Find_Fat_Info (Etype (E1), Ftp, Pkg);
1124 Expand_Fpt_Attribute
1125 (N, Pkg, Attribute_Name (N),
1126 New_List (Unchecked_Convert_To (Ftp, Relocate_Node (E1))));
1127 end Expand_Fpt_Attribute_R;
1128
1129 -----------------------------
1130 -- Expand_Fpt_Attribute_RI --
1131 -----------------------------
1132
1133 -- The first argument is converted to its root type and the second
1134 -- argument is converted to standard long long integer to call the
1135 -- appropriate runtime function, with the actual call being built
1136 -- by Expand_Fpt_Attribute
1137
1138 procedure Expand_Fpt_Attribute_RI (N : Node_Id) is
1139 E1 : constant Node_Id := First (Expressions (N));
1140 Ftp : Entity_Id;
1141 Pkg : RE_Id;
1142 E2 : constant Node_Id := Next (E1);
1143 begin
1144 Find_Fat_Info (Etype (E1), Ftp, Pkg);
1145 Expand_Fpt_Attribute
1146 (N, Pkg, Attribute_Name (N),
1147 New_List (
1148 Unchecked_Convert_To (Ftp, Relocate_Node (E1)),
1149 Unchecked_Convert_To (Standard_Integer, Relocate_Node (E2))));
1150 end Expand_Fpt_Attribute_RI;
1151
1152 -----------------------------
1153 -- Expand_Fpt_Attribute_RR --
1154 -----------------------------
1155
1156 -- The two arguments are converted to their root types to call the
1157 -- appropriate runtime function, with the actual call being built
1158 -- by Expand_Fpt_Attribute
1159
1160 procedure Expand_Fpt_Attribute_RR (N : Node_Id) is
1161 E1 : constant Node_Id := First (Expressions (N));
1162 E2 : constant Node_Id := Next (E1);
1163 Ftp : Entity_Id;
1164 Pkg : RE_Id;
1165
1166 begin
1167 Find_Fat_Info (Etype (E1), Ftp, Pkg);
1168 Expand_Fpt_Attribute
1169 (N, Pkg, Attribute_Name (N),
1170 New_List (
1171 Unchecked_Convert_To (Ftp, Relocate_Node (E1)),
1172 Unchecked_Convert_To (Ftp, Relocate_Node (E2))));
1173 end Expand_Fpt_Attribute_RR;
1174
1175 ---------------------------------
1176 -- Expand_Loop_Entry_Attribute --
1177 ---------------------------------
1178
1179 procedure Expand_Loop_Entry_Attribute (N : Node_Id) is
1180 procedure Build_Conditional_Block
1181 (Loc : Source_Ptr;
1182 Cond : Node_Id;
1183 Loop_Stmt : Node_Id;
1184 If_Stmt : out Node_Id;
1185 Blk_Stmt : out Node_Id);
1186 -- Create a block Blk_Stmt with an empty declarative list and a single
1187 -- loop Loop_Stmt. The block is encased in an if statement If_Stmt with
1188 -- condition Cond. If_Stmt is Empty when there is no condition provided.
1189
1190 function Is_Array_Iteration (N : Node_Id) return Boolean;
1191 -- Determine whether loop statement N denotes an Ada 2012 iteration over
1192 -- an array object.
1193
1194 -----------------------------
1195 -- Build_Conditional_Block --
1196 -----------------------------
1197
1198 procedure Build_Conditional_Block
1199 (Loc : Source_Ptr;
1200 Cond : Node_Id;
1201 Loop_Stmt : Node_Id;
1202 If_Stmt : out Node_Id;
1203 Blk_Stmt : out Node_Id)
1204 is
1205 begin
1206 -- Do not reanalyze the original loop statement because it is simply
1207 -- being relocated.
1208
1209 Set_Analyzed (Loop_Stmt);
1210
1211 Blk_Stmt :=
1212 Make_Block_Statement (Loc,
1213 Declarations => New_List,
1214 Handled_Statement_Sequence =>
1215 Make_Handled_Sequence_Of_Statements (Loc,
1216 Statements => New_List (Loop_Stmt)));
1217
1218 if Present (Cond) then
1219 If_Stmt :=
1220 Make_If_Statement (Loc,
1221 Condition => Cond,
1222 Then_Statements => New_List (Blk_Stmt));
1223 else
1224 If_Stmt := Empty;
1225 end if;
1226 end Build_Conditional_Block;
1227
1228 ------------------------
1229 -- Is_Array_Iteration --
1230 ------------------------
1231
1232 function Is_Array_Iteration (N : Node_Id) return Boolean is
1233 Stmt : constant Node_Id := Original_Node (N);
1234 Iter : Node_Id;
1235
1236 begin
1237 if Nkind (Stmt) = N_Loop_Statement
1238 and then Present (Iteration_Scheme (Stmt))
1239 and then Present (Iterator_Specification (Iteration_Scheme (Stmt)))
1240 then
1241 Iter := Iterator_Specification (Iteration_Scheme (Stmt));
1242
1243 return
1244 Of_Present (Iter) and then Is_Array_Type (Etype (Name (Iter)));
1245 end if;
1246
1247 return False;
1248 end Is_Array_Iteration;
1249
1250 -- Local variables
1251
1252 Pref : constant Node_Id := Prefix (N);
1253 Base_Typ : constant Entity_Id := Base_Type (Etype (Pref));
1254 Exprs : constant List_Id := Expressions (N);
1255 Aux_Decl : Node_Id;
1256 Blk : Node_Id := Empty;
1257 Decls : List_Id;
1258 Installed : Boolean;
1259 Loc : Source_Ptr;
1260 Loop_Id : Entity_Id;
1261 Loop_Stmt : Node_Id;
1262 Result : Node_Id := Empty;
1263 Scheme : Node_Id;
1264 Temp_Decl : Node_Id;
1265 Temp_Id : Entity_Id;
1266
1267 -- Start of processing for Expand_Loop_Entry_Attribute
1268
1269 begin
1270 -- Step 1: Find the related loop
1271
1272 -- The loop label variant of attribute 'Loop_Entry already has all the
1273 -- information in its expression.
1274
1275 if Present (Exprs) then
1276 Loop_Id := Entity (First (Exprs));
1277 Loop_Stmt := Label_Construct (Parent (Loop_Id));
1278
1279 -- Climb the parent chain to find the nearest enclosing loop. Skip
1280 -- all internally generated loops for quantified expressions and for
1281 -- element iterators over multidimensional arrays because the pragma
1282 -- applies to source loop.
1283
1284 else
1285 Loop_Stmt := N;
1286 while Present (Loop_Stmt) loop
1287 if Nkind (Loop_Stmt) = N_Loop_Statement
1288 and then Nkind (Original_Node (Loop_Stmt)) = N_Loop_Statement
1289 and then Comes_From_Source (Original_Node (Loop_Stmt))
1290 then
1291 exit;
1292 end if;
1293
1294 Loop_Stmt := Parent (Loop_Stmt);
1295 end loop;
1296
1297 Loop_Id := Entity (Identifier (Loop_Stmt));
1298 end if;
1299
1300 Loc := Sloc (Loop_Stmt);
1301
1302 -- Step 2: Transform the loop
1303
1304 -- The loop has already been transformed during the expansion of a prior
1305 -- 'Loop_Entry attribute. Retrieve the declarative list of the block.
1306
1307 if Has_Loop_Entry_Attributes (Loop_Id) then
1308
1309 -- When the related loop name appears as the argument of attribute
1310 -- Loop_Entry, the corresponding label construct is the generated
1311 -- block statement. This is because the expander reuses the label.
1312
1313 if Nkind (Loop_Stmt) = N_Block_Statement then
1314 Decls := Declarations (Loop_Stmt);
1315
1316 -- In all other cases, the loop must appear in the handled sequence
1317 -- of statements of the generated block.
1318
1319 else
1320 pragma Assert
1321 (Nkind (Parent (Loop_Stmt)) = N_Handled_Sequence_Of_Statements
1322 and then
1323 Nkind (Parent (Parent (Loop_Stmt))) = N_Block_Statement);
1324
1325 Decls := Declarations (Parent (Parent (Loop_Stmt)));
1326 end if;
1327
1328 -- Transform the loop into a conditional block
1329
1330 else
1331 Set_Has_Loop_Entry_Attributes (Loop_Id);
1332 Scheme := Iteration_Scheme (Loop_Stmt);
1333
1334 -- Infinite loops are transformed into:
1335
1336 -- declare
1337 -- Temp1 : constant <type of Pref1> := <Pref1>;
1338 -- . . .
1339 -- TempN : constant <type of PrefN> := <PrefN>;
1340 -- begin
1341 -- loop
1342 -- <original source statements with attribute rewrites>
1343 -- end loop;
1344 -- end;
1345
1346 if No (Scheme) then
1347 Build_Conditional_Block (Loc,
1348 Cond => Empty,
1349 Loop_Stmt => Relocate_Node (Loop_Stmt),
1350 If_Stmt => Result,
1351 Blk_Stmt => Blk);
1352
1353 Result := Blk;
1354
1355 -- While loops are transformed into:
1356
1357 -- function Fnn return Boolean is
1358 -- begin
1359 -- <condition actions>
1360 -- return <condition>;
1361 -- end Fnn;
1362
1363 -- if Fnn then
1364 -- declare
1365 -- Temp1 : constant <type of Pref1> := <Pref1>;
1366 -- . . .
1367 -- TempN : constant <type of PrefN> := <PrefN>;
1368 -- begin
1369 -- loop
1370 -- <original source statements with attribute rewrites>
1371 -- exit when not Fnn;
1372 -- end loop;
1373 -- end;
1374 -- end if;
1375
1376 -- Note that loops over iterators and containers are already
1377 -- converted into while loops.
1378
1379 elsif Present (Condition (Scheme)) then
1380 declare
1381 Func_Decl : Node_Id;
1382 Func_Id : Entity_Id;
1383 Stmts : List_Id;
1384
1385 begin
1386 Func_Id := Make_Temporary (Loc, 'F');
1387
1388 -- Wrap the condition of the while loop in a Boolean function.
1389 -- This avoids the duplication of the same code which may lead
1390 -- to gigi issues with respect to multiple declaration of the
1391 -- same entity in the presence of side effects or checks. Note
1392 -- that the condition actions must also be relocated into the
1393 -- wrapping function because they may contain itypes, e.g. in
1394 -- the case of a comparison involving slices.
1395
1396 -- Generate:
1397 -- <condition actions>
1398 -- return <condition>;
1399
1400 if Present (Condition_Actions (Scheme)) then
1401 Stmts := Condition_Actions (Scheme);
1402 else
1403 Stmts := New_List;
1404 end if;
1405
1406 Append_To (Stmts,
1407 Make_Simple_Return_Statement (Loc,
1408 Expression =>
1409 New_Copy_Tree (Condition (Scheme),
1410 New_Scope => Func_Id)));
1411
1412 -- Generate:
1413 -- function Fnn return Boolean is
1414 -- begin
1415 -- <Stmts>
1416 -- end Fnn;
1417
1418 Func_Decl :=
1419 Make_Subprogram_Body (Loc,
1420 Specification =>
1421 Make_Function_Specification (Loc,
1422 Defining_Unit_Name => Func_Id,
1423 Result_Definition =>
1424 New_Occurrence_Of (Standard_Boolean, Loc)),
1425 Declarations => Empty_List,
1426 Handled_Statement_Sequence =>
1427 Make_Handled_Sequence_Of_Statements (Loc,
1428 Statements => Stmts));
1429
1430 -- The function is inserted before the related loop. Make sure
1431 -- to analyze it in the context of the loop's enclosing scope.
1432
1433 Push_Scope (Scope (Loop_Id));
1434 Insert_Action (Loop_Stmt, Func_Decl);
1435 Pop_Scope;
1436
1437 -- The analysis of the condition may have generated entities
1438 -- (such as itypes) that are now used within the function.
1439 -- Adjust their scopes accordingly so that their use appears
1440 -- in their scope of definition.
1441
1442 declare
1443 Ent : Entity_Id;
1444
1445 begin
1446 Ent := First_Entity (Loop_Id);
1447
1448 while Present (Ent) loop
1449 -- Various entities that now occur within the function
1450 -- need to have their scope reset, but not all entities
1451 -- associated with Loop_Id are now inside the function.
1452 -- The function entity itself and loop parameters can
1453 -- be outside the function, and there may be others.
1454 -- It's not clear how the determination of what entity
1455 -- scopes need to be adjusted can be made accurately.
1456 -- Perhaps it will be necessary to traverse the function
1457 -- body to find the exact entities whose scopes need to
1458 -- be reset to the function's Entity_Id. ???
1459
1460 if Ekind (Ent) /= E_Loop_Parameter
1461 and then Ent /= Func_Id
1462 then
1463 Set_Scope (Ent, Func_Id);
1464 end if;
1465
1466 Next_Entity (Ent);
1467 end loop;
1468 end;
1469
1470 -- Transform the original while loop into an infinite loop
1471 -- where the last statement checks the negated condition. This
1472 -- placement ensures that the condition will not be evaluated
1473 -- twice on the first iteration.
1474
1475 Set_Iteration_Scheme (Loop_Stmt, Empty);
1476 Scheme := Empty;
1477
1478 -- Generate:
1479 -- exit when not Fnn;
1480
1481 Append_To (Statements (Loop_Stmt),
1482 Make_Exit_Statement (Loc,
1483 Condition =>
1484 Make_Op_Not (Loc,
1485 Right_Opnd =>
1486 Make_Function_Call (Loc,
1487 Name => New_Occurrence_Of (Func_Id, Loc)))));
1488
1489 Build_Conditional_Block (Loc,
1490 Cond =>
1491 Make_Function_Call (Loc,
1492 Name => New_Occurrence_Of (Func_Id, Loc)),
1493 Loop_Stmt => Relocate_Node (Loop_Stmt),
1494 If_Stmt => Result,
1495 Blk_Stmt => Blk);
1496 end;
1497
1498 -- Ada 2012 iteration over an array is transformed into:
1499
1500 -- if <Array_Nam>'Length (1) > 0
1501 -- and then <Array_Nam>'Length (N) > 0
1502 -- then
1503 -- declare
1504 -- Temp1 : constant <type of Pref1> := <Pref1>;
1505 -- . . .
1506 -- TempN : constant <type of PrefN> := <PrefN>;
1507 -- begin
1508 -- for X in ... loop -- multiple loops depending on dims
1509 -- <original source statements with attribute rewrites>
1510 -- end loop;
1511 -- end;
1512 -- end if;
1513
1514 elsif Is_Array_Iteration (Loop_Stmt) then
1515 declare
1516 Array_Nam : constant Entity_Id :=
1517 Entity (Name (Iterator_Specification
1518 (Iteration_Scheme (Original_Node (Loop_Stmt)))));
1519 Num_Dims : constant Pos :=
1520 Number_Dimensions (Etype (Array_Nam));
1521 Cond : Node_Id := Empty;
1522 Check : Node_Id;
1523
1524 begin
1525 -- Generate a check which determines whether all dimensions of
1526 -- the array are non-null.
1527
1528 for Dim in 1 .. Num_Dims loop
1529 Check :=
1530 Make_Op_Gt (Loc,
1531 Left_Opnd =>
1532 Make_Attribute_Reference (Loc,
1533 Prefix => New_Occurrence_Of (Array_Nam, Loc),
1534 Attribute_Name => Name_Length,
1535 Expressions => New_List (
1536 Make_Integer_Literal (Loc, Dim))),
1537 Right_Opnd =>
1538 Make_Integer_Literal (Loc, 0));
1539
1540 if No (Cond) then
1541 Cond := Check;
1542 else
1543 Cond :=
1544 Make_And_Then (Loc,
1545 Left_Opnd => Cond,
1546 Right_Opnd => Check);
1547 end if;
1548 end loop;
1549
1550 Build_Conditional_Block (Loc,
1551 Cond => Cond,
1552 Loop_Stmt => Relocate_Node (Loop_Stmt),
1553 If_Stmt => Result,
1554 Blk_Stmt => Blk);
1555 end;
1556
1557 -- For loops are transformed into:
1558
1559 -- if <Low> <= <High> then
1560 -- declare
1561 -- Temp1 : constant <type of Pref1> := <Pref1>;
1562 -- . . .
1563 -- TempN : constant <type of PrefN> := <PrefN>;
1564 -- begin
1565 -- for <Def_Id> in <Low> .. <High> loop
1566 -- <original source statements with attribute rewrites>
1567 -- end loop;
1568 -- end;
1569 -- end if;
1570
1571 elsif Present (Loop_Parameter_Specification (Scheme)) then
1572 declare
1573 Loop_Spec : constant Node_Id :=
1574 Loop_Parameter_Specification (Scheme);
1575 Cond : Node_Id;
1576 Subt_Def : Node_Id;
1577
1578 begin
1579 Subt_Def := Discrete_Subtype_Definition (Loop_Spec);
1580
1581 -- When the loop iterates over a subtype indication with a
1582 -- range, use the low and high bounds of the subtype itself.
1583
1584 if Nkind (Subt_Def) = N_Subtype_Indication then
1585 Subt_Def := Scalar_Range (Etype (Subt_Def));
1586 end if;
1587
1588 pragma Assert (Nkind (Subt_Def) = N_Range);
1589
1590 -- Generate
1591 -- Low <= High
1592
1593 Cond :=
1594 Make_Op_Le (Loc,
1595 Left_Opnd => New_Copy_Tree (Low_Bound (Subt_Def)),
1596 Right_Opnd => New_Copy_Tree (High_Bound (Subt_Def)));
1597
1598 Build_Conditional_Block (Loc,
1599 Cond => Cond,
1600 Loop_Stmt => Relocate_Node (Loop_Stmt),
1601 If_Stmt => Result,
1602 Blk_Stmt => Blk);
1603 end;
1604 end if;
1605
1606 Decls := Declarations (Blk);
1607 end if;
1608
1609 -- Step 3: Create a constant to capture the value of the prefix at the
1610 -- entry point into the loop.
1611
1612 Temp_Id := Make_Temporary (Loc, 'P');
1613
1614 -- Preserve the tag of the prefix by offering a specific view of the
1615 -- class-wide version of the prefix.
1616
1617 if Is_Tagged_Type (Base_Typ) then
1618 Tagged_Case : declare
1619 CW_Temp : Entity_Id;
1620 CW_Typ : Entity_Id;
1621
1622 begin
1623 -- Generate:
1624 -- CW_Temp : constant Base_Typ'Class := Base_Typ'Class (Pref);
1625
1626 CW_Temp := Make_Temporary (Loc, 'T');
1627 CW_Typ := Class_Wide_Type (Base_Typ);
1628
1629 Aux_Decl :=
1630 Make_Object_Declaration (Loc,
1631 Defining_Identifier => CW_Temp,
1632 Constant_Present => True,
1633 Object_Definition => New_Occurrence_Of (CW_Typ, Loc),
1634 Expression =>
1635 Convert_To (CW_Typ, Relocate_Node (Pref)));
1636 Append_To (Decls, Aux_Decl);
1637
1638 -- Generate:
1639 -- Temp : Base_Typ renames Base_Typ (CW_Temp);
1640
1641 Temp_Decl :=
1642 Make_Object_Renaming_Declaration (Loc,
1643 Defining_Identifier => Temp_Id,
1644 Subtype_Mark => New_Occurrence_Of (Base_Typ, Loc),
1645 Name =>
1646 Convert_To (Base_Typ, New_Occurrence_Of (CW_Temp, Loc)));
1647 Append_To (Decls, Temp_Decl);
1648 end Tagged_Case;
1649
1650 -- Untagged case
1651
1652 else
1653 Untagged_Case : declare
1654 Temp_Expr : Node_Id;
1655
1656 begin
1657 Aux_Decl := Empty;
1658
1659 -- Generate a nominal type for the constant when the prefix is of
1660 -- a constrained type. This is achieved by setting the Etype of
1661 -- the relocated prefix to its base type. Since the prefix is now
1662 -- the initialization expression of the constant, its freezing
1663 -- will produce a proper nominal type.
1664
1665 Temp_Expr := Relocate_Node (Pref);
1666 Set_Etype (Temp_Expr, Base_Typ);
1667
1668 -- Generate:
1669 -- Temp : constant Base_Typ := Pref;
1670
1671 Temp_Decl :=
1672 Make_Object_Declaration (Loc,
1673 Defining_Identifier => Temp_Id,
1674 Constant_Present => True,
1675 Object_Definition => New_Occurrence_Of (Base_Typ, Loc),
1676 Expression => Temp_Expr);
1677 Append_To (Decls, Temp_Decl);
1678 end Untagged_Case;
1679 end if;
1680
1681 -- Step 4: Analyze all bits
1682
1683 Installed := Current_Scope = Scope (Loop_Id);
1684
1685 -- Depending on the pracement of attribute 'Loop_Entry relative to the
1686 -- associated loop, ensure the proper visibility for analysis.
1687
1688 if not Installed then
1689 Push_Scope (Scope (Loop_Id));
1690 end if;
1691
1692 -- The analysis of the conditional block takes care of the constant
1693 -- declaration.
1694
1695 if Present (Result) then
1696 Rewrite (Loop_Stmt, Result);
1697 Analyze (Loop_Stmt);
1698
1699 -- The conditional block was analyzed when a previous 'Loop_Entry was
1700 -- expanded. There is no point in reanalyzing the block, simply analyze
1701 -- the declaration of the constant.
1702
1703 else
1704 if Present (Aux_Decl) then
1705 Analyze (Aux_Decl);
1706 end if;
1707
1708 Analyze (Temp_Decl);
1709 end if;
1710
1711 Rewrite (N, New_Occurrence_Of (Temp_Id, Loc));
1712 Analyze (N);
1713
1714 if not Installed then
1715 Pop_Scope;
1716 end if;
1717 end Expand_Loop_Entry_Attribute;
1718
1719 ------------------------------
1720 -- Expand_Min_Max_Attribute --
1721 ------------------------------
1722
1723 procedure Expand_Min_Max_Attribute (N : Node_Id) is
1724 begin
1725 -- Min and Max are handled by the back end (except that static cases
1726 -- have already been evaluated during semantic processing, although the
1727 -- back end should not count on this). The one bit of special processing
1728 -- required in the normal case is that these two attributes typically
1729 -- generate conditionals in the code, so check the relevant restriction.
1730
1731 Check_Restriction (No_Implicit_Conditionals, N);
1732 end Expand_Min_Max_Attribute;
1733
1734 ----------------------------------
1735 -- Expand_N_Attribute_Reference --
1736 ----------------------------------
1737
1738 procedure Expand_N_Attribute_Reference (N : Node_Id) is
1739 Loc : constant Source_Ptr := Sloc (N);
1740 Typ : constant Entity_Id := Etype (N);
1741 Btyp : constant Entity_Id := Base_Type (Typ);
1742 Pref : constant Node_Id := Prefix (N);
1743 Ptyp : constant Entity_Id := Etype (Pref);
1744 Exprs : constant List_Id := Expressions (N);
1745 Id : constant Attribute_Id := Get_Attribute_Id (Attribute_Name (N));
1746
1747 procedure Rewrite_Stream_Proc_Call (Pname : Entity_Id);
1748 -- Rewrites a stream attribute for Read, Write or Output with the
1749 -- procedure call. Pname is the entity for the procedure to call.
1750
1751 ------------------------------
1752 -- Rewrite_Stream_Proc_Call --
1753 ------------------------------
1754
1755 procedure Rewrite_Stream_Proc_Call (Pname : Entity_Id) is
1756 Item : constant Node_Id := Next (First (Exprs));
1757 Item_Typ : constant Entity_Id := Etype (Item);
1758 Formal : constant Entity_Id := Next_Formal (First_Formal (Pname));
1759 Formal_Typ : constant Entity_Id := Etype (Formal);
1760 Is_Written : constant Boolean := Ekind (Formal) /= E_In_Parameter;
1761
1762 begin
1763 -- The expansion depends on Item, the second actual, which is
1764 -- the object being streamed in or out.
1765
1766 -- If the item is a component of a packed array type, and
1767 -- a conversion is needed on exit, we introduce a temporary to
1768 -- hold the value, because otherwise the packed reference will
1769 -- not be properly expanded.
1770
1771 if Nkind (Item) = N_Indexed_Component
1772 and then Is_Packed (Base_Type (Etype (Prefix (Item))))
1773 and then Base_Type (Item_Typ) /= Base_Type (Formal_Typ)
1774 and then Is_Written
1775 then
1776 declare
1777 Temp : constant Entity_Id := Make_Temporary (Loc, 'V');
1778 Decl : Node_Id;
1779 Assn : Node_Id;
1780
1781 begin
1782 Decl :=
1783 Make_Object_Declaration (Loc,
1784 Defining_Identifier => Temp,
1785 Object_Definition => New_Occurrence_Of (Formal_Typ, Loc));
1786 Set_Etype (Temp, Formal_Typ);
1787
1788 Assn :=
1789 Make_Assignment_Statement (Loc,
1790 Name => New_Copy_Tree (Item),
1791 Expression =>
1792 Unchecked_Convert_To
1793 (Item_Typ, New_Occurrence_Of (Temp, Loc)));
1794
1795 Rewrite (Item, New_Occurrence_Of (Temp, Loc));
1796 Insert_Actions (N,
1797 New_List (
1798 Decl,
1799 Make_Procedure_Call_Statement (Loc,
1800 Name => New_Occurrence_Of (Pname, Loc),
1801 Parameter_Associations => Exprs),
1802 Assn));
1803
1804 Rewrite (N, Make_Null_Statement (Loc));
1805 return;
1806 end;
1807 end if;
1808
1809 -- For the class-wide dispatching cases, and for cases in which
1810 -- the base type of the second argument matches the base type of
1811 -- the corresponding formal parameter (that is to say the stream
1812 -- operation is not inherited), we are all set, and can use the
1813 -- argument unchanged.
1814
1815 if not Is_Class_Wide_Type (Entity (Pref))
1816 and then not Is_Class_Wide_Type (Etype (Item))
1817 and then Base_Type (Item_Typ) /= Base_Type (Formal_Typ)
1818 then
1819 -- Perform a view conversion when either the argument or the
1820 -- formal parameter are of a private type.
1821
1822 if Is_Private_Type (Base_Type (Formal_Typ))
1823 or else Is_Private_Type (Base_Type (Item_Typ))
1824 then
1825 Rewrite (Item,
1826 Unchecked_Convert_To (Formal_Typ, Relocate_Node (Item)));
1827
1828 -- Otherwise perform a regular type conversion to ensure that all
1829 -- relevant checks are installed.
1830
1831 else
1832 Rewrite (Item, Convert_To (Formal_Typ, Relocate_Node (Item)));
1833 end if;
1834
1835 -- For untagged derived types set Assignment_OK, to prevent
1836 -- copies from being created when the unchecked conversion
1837 -- is expanded (which would happen in Remove_Side_Effects
1838 -- if Expand_N_Unchecked_Conversion were allowed to call
1839 -- Force_Evaluation). The copy could violate Ada semantics in
1840 -- cases such as an actual that is an out parameter. Note that
1841 -- this approach is also used in exp_ch7 for calls to controlled
1842 -- type operations to prevent problems with actuals wrapped in
1843 -- unchecked conversions.
1844
1845 if Is_Untagged_Derivation (Etype (Expression (Item))) then
1846 Set_Assignment_OK (Item);
1847 end if;
1848 end if;
1849
1850 -- The stream operation to call may be a renaming created by an
1851 -- attribute definition clause, and may not be frozen yet. Ensure
1852 -- that it has the necessary extra formals.
1853
1854 if not Is_Frozen (Pname) then
1855 Create_Extra_Formals (Pname);
1856 end if;
1857
1858 -- And now rewrite the call
1859
1860 Rewrite (N,
1861 Make_Procedure_Call_Statement (Loc,
1862 Name => New_Occurrence_Of (Pname, Loc),
1863 Parameter_Associations => Exprs));
1864
1865 Analyze (N);
1866 end Rewrite_Stream_Proc_Call;
1867
1868 -- Start of processing for Expand_N_Attribute_Reference
1869
1870 begin
1871 -- Do required validity checking, if enabled. Do not apply check to
1872 -- output parameters of an Asm instruction, since the value of this
1873 -- is not set till after the attribute has been elaborated, and do
1874 -- not apply the check to the arguments of a 'Read or 'Input attribute
1875 -- reference since the scalar argument is an OUT scalar.
1876
1877 if Validity_Checks_On and then Validity_Check_Operands
1878 and then Id /= Attribute_Asm_Output
1879 and then Id /= Attribute_Read
1880 and then Id /= Attribute_Input
1881 then
1882 declare
1883 Expr : Node_Id;
1884 begin
1885 Expr := First (Expressions (N));
1886 while Present (Expr) loop
1887 Ensure_Valid (Expr);
1888 Next (Expr);
1889 end loop;
1890 end;
1891 end if;
1892
1893 -- Ada 2005 (AI-318-02): If attribute prefix is a call to a build-in-
1894 -- place function, then a temporary return object needs to be created
1895 -- and access to it must be passed to the function.
1896
1897 if Is_Build_In_Place_Function_Call (Pref) then
1898
1899 -- If attribute is 'Old, the context is a postcondition, and
1900 -- the temporary must go in the corresponding subprogram, not
1901 -- the postcondition function or any created blocks, as when
1902 -- the attribute appears in a quantified expression. This is
1903 -- handled below in the expansion of the attribute.
1904
1905 if Attribute_Name (Parent (Pref)) = Name_Old then
1906 null;
1907 else
1908 Make_Build_In_Place_Call_In_Anonymous_Context (Pref);
1909 end if;
1910
1911 -- Ada 2005 (AI-318-02): Specialization of the previous case for prefix
1912 -- containing build-in-place function calls whose returned object covers
1913 -- interface types.
1914
1915 elsif Present (Unqual_BIP_Iface_Function_Call (Pref)) then
1916 Make_Build_In_Place_Iface_Call_In_Anonymous_Context (Pref);
1917 end if;
1918
1919 -- If prefix is a protected type name, this is a reference to the
1920 -- current instance of the type. For a component definition, nothing
1921 -- to do (expansion will occur in the init proc). In other contexts,
1922 -- rewrite into reference to current instance.
1923
1924 if Is_Protected_Self_Reference (Pref)
1925 and then not
1926 (Nkind_In (Parent (N), N_Index_Or_Discriminant_Constraint,
1927 N_Discriminant_Association)
1928 and then Nkind (Parent (Parent (Parent (Parent (N))))) =
1929 N_Component_Definition)
1930
1931 -- No action needed for these attributes since the current instance
1932 -- will be rewritten to be the name of the _object parameter
1933 -- associated with the enclosing protected subprogram (see below).
1934
1935 and then Id /= Attribute_Access
1936 and then Id /= Attribute_Unchecked_Access
1937 and then Id /= Attribute_Unrestricted_Access
1938 then
1939 Rewrite (Pref, Concurrent_Ref (Pref));
1940 Analyze (Pref);
1941 end if;
1942
1943 -- Remaining processing depends on specific attribute
1944
1945 -- Note: individual sections of the following case statement are
1946 -- allowed to assume there is no code after the case statement, and
1947 -- are legitimately allowed to execute return statements if they have
1948 -- nothing more to do.
1949
1950 case Id is
1951
1952 -- Attributes related to Ada 2012 iterators
1953
1954 when Attribute_Constant_Indexing
1955 | Attribute_Default_Iterator
1956 | Attribute_Implicit_Dereference
1957 | Attribute_Iterable
1958 | Attribute_Iterator_Element
1959 | Attribute_Variable_Indexing
1960 =>
1961 null;
1962
1963 -- Internal attributes used to deal with Ada 2012 delayed aspects. These
1964 -- were already rejected by the parser. Thus they shouldn't appear here.
1965
1966 when Internal_Attribute_Id =>
1967 raise Program_Error;
1968
1969 ------------
1970 -- Access --
1971 ------------
1972
1973 when Attribute_Access
1974 | Attribute_Unchecked_Access
1975 | Attribute_Unrestricted_Access
1976 =>
1977 Access_Cases : declare
1978 Ref_Object : constant Node_Id := Get_Referenced_Object (Pref);
1979 Btyp_DDT : Entity_Id;
1980
1981 function Enclosing_Object (N : Node_Id) return Node_Id;
1982 -- If N denotes a compound name (selected component, indexed
1983 -- component, or slice), returns the name of the outermost such
1984 -- enclosing object. Otherwise returns N. If the object is a
1985 -- renaming, then the renamed object is returned.
1986
1987 ----------------------
1988 -- Enclosing_Object --
1989 ----------------------
1990
1991 function Enclosing_Object (N : Node_Id) return Node_Id is
1992 Obj_Name : Node_Id;
1993
1994 begin
1995 Obj_Name := N;
1996 while Nkind_In (Obj_Name, N_Selected_Component,
1997 N_Indexed_Component,
1998 N_Slice)
1999 loop
2000 Obj_Name := Prefix (Obj_Name);
2001 end loop;
2002
2003 return Get_Referenced_Object (Obj_Name);
2004 end Enclosing_Object;
2005
2006 -- Local declarations
2007
2008 Enc_Object : constant Node_Id := Enclosing_Object (Ref_Object);
2009
2010 -- Start of processing for Access_Cases
2011
2012 begin
2013 Btyp_DDT := Designated_Type (Btyp);
2014
2015 -- Handle designated types that come from the limited view
2016
2017 if From_Limited_With (Btyp_DDT)
2018 and then Has_Non_Limited_View (Btyp_DDT)
2019 then
2020 Btyp_DDT := Non_Limited_View (Btyp_DDT);
2021 end if;
2022
2023 -- In order to improve the text of error messages, the designated
2024 -- type of access-to-subprogram itypes is set by the semantics as
2025 -- the associated subprogram entity (see sem_attr). Now we replace
2026 -- such node with the proper E_Subprogram_Type itype.
2027
2028 if Id = Attribute_Unrestricted_Access
2029 and then Is_Subprogram (Directly_Designated_Type (Typ))
2030 then
2031 -- The following conditions ensure that this special management
2032 -- is done only for "Address!(Prim'Unrestricted_Access)" nodes.
2033 -- At this stage other cases in which the designated type is
2034 -- still a subprogram (instead of an E_Subprogram_Type) are
2035 -- wrong because the semantics must have overridden the type of
2036 -- the node with the type imposed by the context.
2037
2038 if Nkind (Parent (N)) = N_Unchecked_Type_Conversion
2039 and then Etype (Parent (N)) = RTE (RE_Prim_Ptr)
2040 then
2041 Set_Etype (N, RTE (RE_Prim_Ptr));
2042
2043 else
2044 declare
2045 Subp : constant Entity_Id :=
2046 Directly_Designated_Type (Typ);
2047 Etyp : Entity_Id;
2048 Extra : Entity_Id := Empty;
2049 New_Formal : Entity_Id;
2050 Old_Formal : Entity_Id := First_Formal (Subp);
2051 Subp_Typ : Entity_Id;
2052
2053 begin
2054 Subp_Typ := Create_Itype (E_Subprogram_Type, N);
2055 Set_Etype (Subp_Typ, Etype (Subp));
2056 Set_Returns_By_Ref (Subp_Typ, Returns_By_Ref (Subp));
2057
2058 if Present (Old_Formal) then
2059 New_Formal := New_Copy (Old_Formal);
2060 Set_First_Entity (Subp_Typ, New_Formal);
2061
2062 loop
2063 Set_Scope (New_Formal, Subp_Typ);
2064 Etyp := Etype (New_Formal);
2065
2066 -- Handle itypes. There is no need to duplicate
2067 -- here the itypes associated with record types
2068 -- (i.e the implicit full view of private types).
2069
2070 if Is_Itype (Etyp)
2071 and then Ekind (Base_Type (Etyp)) /= E_Record_Type
2072 then
2073 Extra := New_Copy (Etyp);
2074 Set_Parent (Extra, New_Formal);
2075 Set_Etype (New_Formal, Extra);
2076 Set_Scope (Extra, Subp_Typ);
2077 end if;
2078
2079 Extra := New_Formal;
2080 Next_Formal (Old_Formal);
2081 exit when No (Old_Formal);
2082
2083 Link_Entities (New_Formal, New_Copy (Old_Formal));
2084 Next_Entity (New_Formal);
2085 end loop;
2086
2087 Unlink_Next_Entity (New_Formal);
2088 Set_Last_Entity (Subp_Typ, Extra);
2089 end if;
2090
2091 -- Now that the explicit formals have been duplicated,
2092 -- any extra formals needed by the subprogram must be
2093 -- created.
2094
2095 if Present (Extra) then
2096 Set_Extra_Formal (Extra, Empty);
2097 end if;
2098
2099 Create_Extra_Formals (Subp_Typ);
2100 Set_Directly_Designated_Type (Typ, Subp_Typ);
2101 end;
2102 end if;
2103 end if;
2104
2105 if Is_Access_Protected_Subprogram_Type (Btyp) then
2106 Expand_Access_To_Protected_Op (N, Pref, Typ);
2107
2108 -- If prefix is a type name, this is a reference to the current
2109 -- instance of the type, within its initialization procedure.
2110
2111 elsif Is_Entity_Name (Pref)
2112 and then Is_Type (Entity (Pref))
2113 then
2114 declare
2115 Par : Node_Id;
2116 Formal : Entity_Id;
2117
2118 begin
2119 -- If the current instance name denotes a task type, then
2120 -- the access attribute is rewritten to be the name of the
2121 -- "_task" parameter associated with the task type's task
2122 -- procedure. An unchecked conversion is applied to ensure
2123 -- a type match in cases of expander-generated calls (e.g.
2124 -- init procs).
2125
2126 if Is_Task_Type (Entity (Pref)) then
2127 Formal :=
2128 First_Entity (Get_Task_Body_Procedure (Entity (Pref)));
2129 while Present (Formal) loop
2130 exit when Chars (Formal) = Name_uTask;
2131 Next_Entity (Formal);
2132 end loop;
2133
2134 pragma Assert (Present (Formal));
2135
2136 Rewrite (N,
2137 Unchecked_Convert_To (Typ,
2138 New_Occurrence_Of (Formal, Loc)));
2139 Set_Etype (N, Typ);
2140
2141 elsif Is_Protected_Type (Entity (Pref)) then
2142
2143 -- No action needed for current instance located in a
2144 -- component definition (expansion will occur in the
2145 -- init proc)
2146
2147 if Is_Protected_Type (Current_Scope) then
2148 null;
2149
2150 -- If the current instance reference is located in a
2151 -- protected subprogram or entry then rewrite the access
2152 -- attribute to be the name of the "_object" parameter.
2153 -- An unchecked conversion is applied to ensure a type
2154 -- match in cases of expander-generated calls (e.g. init
2155 -- procs).
2156
2157 -- The code may be nested in a block, so find enclosing
2158 -- scope that is a protected operation.
2159
2160 else
2161 declare
2162 Subp : Entity_Id;
2163
2164 begin
2165 Subp := Current_Scope;
2166 while Ekind_In (Subp, E_Loop, E_Block) loop
2167 Subp := Scope (Subp);
2168 end loop;
2169
2170 Formal :=
2171 First_Entity
2172 (Protected_Body_Subprogram (Subp));
2173
2174 -- For a protected subprogram the _Object parameter
2175 -- is the protected record, so we create an access
2176 -- to it. The _Object parameter of an entry is an
2177 -- address.
2178
2179 if Ekind (Subp) = E_Entry then
2180 Rewrite (N,
2181 Unchecked_Convert_To (Typ,
2182 New_Occurrence_Of (Formal, Loc)));
2183 Set_Etype (N, Typ);
2184
2185 else
2186 Rewrite (N,
2187 Unchecked_Convert_To (Typ,
2188 Make_Attribute_Reference (Loc,
2189 Attribute_Name => Name_Unrestricted_Access,
2190 Prefix =>
2191 New_Occurrence_Of (Formal, Loc))));
2192 Analyze_And_Resolve (N);
2193 end if;
2194 end;
2195 end if;
2196
2197 -- The expression must appear in a default expression,
2198 -- (which in the initialization procedure is the right-hand
2199 -- side of an assignment), and not in a discriminant
2200 -- constraint.
2201
2202 else
2203 Par := Parent (N);
2204 while Present (Par) loop
2205 exit when Nkind (Par) = N_Assignment_Statement;
2206
2207 if Nkind (Par) = N_Component_Declaration then
2208 return;
2209 end if;
2210
2211 Par := Parent (Par);
2212 end loop;
2213
2214 if Present (Par) then
2215 Rewrite (N,
2216 Make_Attribute_Reference (Loc,
2217 Prefix => Make_Identifier (Loc, Name_uInit),
2218 Attribute_Name => Attribute_Name (N)));
2219
2220 Analyze_And_Resolve (N, Typ);
2221 end if;
2222 end if;
2223 end;
2224
2225 -- If the prefix of an Access attribute is a dereference of an
2226 -- access parameter (or a renaming of such a dereference, or a
2227 -- subcomponent of such a dereference) and the context is a
2228 -- general access type (including the type of an object or
2229 -- component with an access_definition, but not the anonymous
2230 -- type of an access parameter or access discriminant), then
2231 -- apply an accessibility check to the access parameter. We used
2232 -- to rewrite the access parameter as a type conversion, but that
2233 -- could only be done if the immediate prefix of the Access
2234 -- attribute was the dereference, and didn't handle cases where
2235 -- the attribute is applied to a subcomponent of the dereference,
2236 -- since there's generally no available, appropriate access type
2237 -- to convert to in that case. The attribute is passed as the
2238 -- point to insert the check, because the access parameter may
2239 -- come from a renaming, possibly in a different scope, and the
2240 -- check must be associated with the attribute itself.
2241
2242 elsif Id = Attribute_Access
2243 and then Nkind (Enc_Object) = N_Explicit_Dereference
2244 and then Is_Entity_Name (Prefix (Enc_Object))
2245 and then (Ekind (Btyp) = E_General_Access_Type
2246 or else Is_Local_Anonymous_Access (Btyp))
2247 and then Ekind (Entity (Prefix (Enc_Object))) in Formal_Kind
2248 and then Ekind (Etype (Entity (Prefix (Enc_Object))))
2249 = E_Anonymous_Access_Type
2250 and then Present (Extra_Accessibility
2251 (Entity (Prefix (Enc_Object))))
2252 then
2253 Apply_Accessibility_Check (Prefix (Enc_Object), Typ, N);
2254
2255 -- Ada 2005 (AI-251): If the designated type is an interface we
2256 -- add an implicit conversion to force the displacement of the
2257 -- pointer to reference the secondary dispatch table.
2258
2259 elsif Is_Interface (Btyp_DDT)
2260 and then (Comes_From_Source (N)
2261 or else Comes_From_Source (Ref_Object)
2262 or else (Nkind (Ref_Object) in N_Has_Chars
2263 and then Chars (Ref_Object) = Name_uInit))
2264 then
2265 if Nkind (Ref_Object) /= N_Explicit_Dereference then
2266
2267 -- No implicit conversion required if types match, or if
2268 -- the prefix is the class_wide_type of the interface. In
2269 -- either case passing an object of the interface type has
2270 -- already set the pointer correctly.
2271
2272 if Btyp_DDT = Etype (Ref_Object)
2273 or else (Is_Class_Wide_Type (Etype (Ref_Object))
2274 and then
2275 Class_Wide_Type (Btyp_DDT) = Etype (Ref_Object))
2276 then
2277 null;
2278
2279 else
2280 Rewrite (Prefix (N),
2281 Convert_To (Btyp_DDT,
2282 New_Copy_Tree (Prefix (N))));
2283
2284 Analyze_And_Resolve (Prefix (N), Btyp_DDT);
2285 end if;
2286
2287 -- When the object is an explicit dereference, convert the
2288 -- dereference's prefix.
2289
2290 else
2291 declare
2292 Obj_DDT : constant Entity_Id :=
2293 Base_Type
2294 (Directly_Designated_Type
2295 (Etype (Prefix (Ref_Object))));
2296 begin
2297 -- No implicit conversion required if designated types
2298 -- match.
2299
2300 if Obj_DDT /= Btyp_DDT
2301 and then not (Is_Class_Wide_Type (Obj_DDT)
2302 and then Etype (Obj_DDT) = Btyp_DDT)
2303 then
2304 Rewrite (N,
2305 Convert_To (Typ,
2306 New_Copy_Tree (Prefix (Ref_Object))));
2307 Analyze_And_Resolve (N, Typ);
2308 end if;
2309 end;
2310 end if;
2311 end if;
2312 end Access_Cases;
2313
2314 --------------
2315 -- Adjacent --
2316 --------------
2317
2318 -- Transforms 'Adjacent into a call to the floating-point attribute
2319 -- function Adjacent in Fat_xxx (where xxx is the root type)
2320
2321 when Attribute_Adjacent =>
2322 Expand_Fpt_Attribute_RR (N);
2323
2324 -------------
2325 -- Address --
2326 -------------
2327
2328 when Attribute_Address => Address : declare
2329 Task_Proc : Entity_Id;
2330
2331 function Is_Unnested_Component_Init (N : Node_Id) return Boolean;
2332 -- Returns True if N is being used to initialize a component of
2333 -- an activation record object where the component corresponds to
2334 -- the object denoted by the prefix of the attribute N.
2335
2336 function Is_Unnested_Component_Init (N : Node_Id) return Boolean is
2337 begin
2338 return Present (Parent (N))
2339 and then Nkind (Parent (N)) = N_Assignment_Statement
2340 and then Is_Entity_Name (Pref)
2341 and then Present (Activation_Record_Component (Entity (Pref)))
2342 and then Nkind (Name (Parent (N))) = N_Selected_Component
2343 and then Entity (Selector_Name (Name (Parent (N)))) =
2344 Activation_Record_Component (Entity (Pref));
2345 end Is_Unnested_Component_Init;
2346
2347 -- Start of processing for Address
2348
2349 begin
2350 -- If the prefix is a task or a task type, the useful address is that
2351 -- of the procedure for the task body, i.e. the actual program unit.
2352 -- We replace the original entity with that of the procedure.
2353
2354 if Is_Entity_Name (Pref)
2355 and then Is_Task_Type (Entity (Pref))
2356 then
2357 Task_Proc := Next_Entity (Root_Type (Ptyp));
2358
2359 while Present (Task_Proc) loop
2360 exit when Ekind (Task_Proc) = E_Procedure
2361 and then Etype (First_Formal (Task_Proc)) =
2362 Corresponding_Record_Type (Ptyp);
2363 Next_Entity (Task_Proc);
2364 end loop;
2365
2366 if Present (Task_Proc) then
2367 Set_Entity (Pref, Task_Proc);
2368 Set_Etype (Pref, Etype (Task_Proc));
2369 end if;
2370
2371 -- Similarly, the address of a protected operation is the address
2372 -- of the corresponding protected body, regardless of the protected
2373 -- object from which it is selected.
2374
2375 elsif Nkind (Pref) = N_Selected_Component
2376 and then Is_Subprogram (Entity (Selector_Name (Pref)))
2377 and then Is_Protected_Type (Scope (Entity (Selector_Name (Pref))))
2378 then
2379 Rewrite (Pref,
2380 New_Occurrence_Of (
2381 External_Subprogram (Entity (Selector_Name (Pref))), Loc));
2382
2383 elsif Nkind (Pref) = N_Explicit_Dereference
2384 and then Ekind (Ptyp) = E_Subprogram_Type
2385 and then Convention (Ptyp) = Convention_Protected
2386 then
2387 -- The prefix is be a dereference of an access_to_protected_
2388 -- subprogram. The desired address is the second component of
2389 -- the record that represents the access.
2390
2391 declare
2392 Addr : constant Entity_Id := Etype (N);
2393 Ptr : constant Node_Id := Prefix (Pref);
2394 T : constant Entity_Id :=
2395 Equivalent_Type (Base_Type (Etype (Ptr)));
2396
2397 begin
2398 Rewrite (N,
2399 Unchecked_Convert_To (Addr,
2400 Make_Selected_Component (Loc,
2401 Prefix => Unchecked_Convert_To (T, Ptr),
2402 Selector_Name => New_Occurrence_Of (
2403 Next_Entity (First_Entity (T)), Loc))));
2404
2405 Analyze_And_Resolve (N, Addr);
2406 end;
2407
2408 -- Ada 2005 (AI-251): Class-wide interface objects are always
2409 -- "displaced" to reference the tag associated with the interface
2410 -- type. In order to obtain the real address of such objects we
2411 -- generate a call to a run-time subprogram that returns the base
2412 -- address of the object. This call is not generated in cases where
2413 -- the attribute is being used to initialize a component of an
2414 -- activation record object where the component corresponds to
2415 -- prefix of the attribute (for back ends that require "unnesting"
2416 -- of nested subprograms), since the address needs to be assigned
2417 -- as-is to such components.
2418
2419 elsif Is_Class_Wide_Type (Ptyp)
2420 and then Is_Interface (Underlying_Type (Ptyp))
2421 and then Tagged_Type_Expansion
2422 and then not (Nkind (Pref) in N_Has_Entity
2423 and then Is_Subprogram (Entity (Pref)))
2424 and then not Is_Unnested_Component_Init (N)
2425 then
2426 Rewrite (N,
2427 Make_Function_Call (Loc,
2428 Name => New_Occurrence_Of (RTE (RE_Base_Address), Loc),
2429 Parameter_Associations => New_List (
2430 Relocate_Node (N))));
2431 Analyze (N);
2432 return;
2433 end if;
2434
2435 -- Deal with packed array reference, other cases are handled by
2436 -- the back end.
2437
2438 if Involves_Packed_Array_Reference (Pref) then
2439 Expand_Packed_Address_Reference (N);
2440 end if;
2441 end Address;
2442
2443 ---------------
2444 -- Alignment --
2445 ---------------
2446
2447 when Attribute_Alignment => Alignment : declare
2448 New_Node : Node_Id;
2449
2450 begin
2451 -- For class-wide types, X'Class'Alignment is transformed into a
2452 -- direct reference to the Alignment of the class type, so that the
2453 -- back end does not have to deal with the X'Class'Alignment
2454 -- reference.
2455
2456 if Is_Entity_Name (Pref)
2457 and then Is_Class_Wide_Type (Entity (Pref))
2458 then
2459 Rewrite (Prefix (N), New_Occurrence_Of (Entity (Pref), Loc));
2460 return;
2461
2462 -- For x'Alignment applied to an object of a class wide type,
2463 -- transform X'Alignment into a call to the predefined primitive
2464 -- operation _Alignment applied to X.
2465
2466 elsif Is_Class_Wide_Type (Ptyp) then
2467 New_Node :=
2468 Make_Attribute_Reference (Loc,
2469 Prefix => Pref,
2470 Attribute_Name => Name_Tag);
2471
2472 New_Node := Build_Get_Alignment (Loc, New_Node);
2473
2474 -- Case where the context is an unchecked conversion to a specific
2475 -- integer type. We directly convert from the alignment's type.
2476
2477 if Nkind (Parent (N)) = N_Unchecked_Type_Conversion then
2478 Rewrite (N, New_Node);
2479 Analyze_And_Resolve (N);
2480 return;
2481
2482 -- Case where the context is a specific integer type with which
2483 -- the original attribute was compatible. But the alignment has a
2484 -- specific type in a-tags.ads (Standard.Natural) so, in order to
2485 -- preserve type compatibility, we must convert explicitly.
2486
2487 elsif Typ /= Standard_Natural then
2488 New_Node := Convert_To (Typ, New_Node);
2489 end if;
2490
2491 Rewrite (N, New_Node);
2492 Analyze_And_Resolve (N, Typ);
2493 return;
2494
2495 -- For all other cases, we just have to deal with the case of
2496 -- the fact that the result can be universal.
2497
2498 else
2499 Apply_Universal_Integer_Attribute_Checks (N);
2500 end if;
2501 end Alignment;
2502
2503 ---------
2504 -- Bit --
2505 ---------
2506
2507 -- We compute this if a packed array reference was present, otherwise we
2508 -- leave the computation up to the back end.
2509
2510 when Attribute_Bit =>
2511 if Involves_Packed_Array_Reference (Pref) then
2512 Expand_Packed_Bit_Reference (N);
2513 else
2514 Apply_Universal_Integer_Attribute_Checks (N);
2515 end if;
2516
2517 ------------------
2518 -- Bit_Position --
2519 ------------------
2520
2521 -- We compute this if a component clause was present, otherwise we leave
2522 -- the computation up to the back end, since we don't know what layout
2523 -- will be chosen.
2524
2525 -- Note that the attribute can apply to a naked record component
2526 -- in generated code (i.e. the prefix is an identifier that
2527 -- references the component or discriminant entity).
2528
2529 when Attribute_Bit_Position => Bit_Position : declare
2530 CE : Entity_Id;
2531
2532 begin
2533 if Nkind (Pref) = N_Identifier then
2534 CE := Entity (Pref);
2535 else
2536 CE := Entity (Selector_Name (Pref));
2537 end if;
2538
2539 if Known_Static_Component_Bit_Offset (CE) then
2540 Rewrite (N,
2541 Make_Integer_Literal (Loc,
2542 Intval => Component_Bit_Offset (CE)));
2543 Analyze_And_Resolve (N, Typ);
2544
2545 else
2546 Apply_Universal_Integer_Attribute_Checks (N);
2547 end if;
2548 end Bit_Position;
2549
2550 ------------------
2551 -- Body_Version --
2552 ------------------
2553
2554 -- A reference to P'Body_Version or P'Version is expanded to
2555
2556 -- Vnn : Unsigned;
2557 -- pragma Import (C, Vnn, "uuuuT");
2558 -- ...
2559 -- Get_Version_String (Vnn)
2560
2561 -- where uuuu is the unit name (dots replaced by double underscore)
2562 -- and T is B for the cases of Body_Version, or Version applied to a
2563 -- subprogram acting as its own spec, and S for Version applied to a
2564 -- subprogram spec or package. This sequence of code references the
2565 -- unsigned constant created in the main program by the binder.
2566
2567 -- A special exception occurs for Standard, where the string returned
2568 -- is a copy of the library string in gnatvsn.ads.
2569
2570 when Attribute_Body_Version
2571 | Attribute_Version
2572 =>
2573 Version : declare
2574 E : constant Entity_Id := Make_Temporary (Loc, 'V');
2575 Pent : Entity_Id;
2576 S : String_Id;
2577
2578 begin
2579 -- If not library unit, get to containing library unit
2580
2581 Pent := Entity (Pref);
2582 while Pent /= Standard_Standard
2583 and then Scope (Pent) /= Standard_Standard
2584 and then not Is_Child_Unit (Pent)
2585 loop
2586 Pent := Scope (Pent);
2587 end loop;
2588
2589 -- Special case Standard and Standard.ASCII
2590
2591 if Pent = Standard_Standard or else Pent = Standard_ASCII then
2592 Rewrite (N,
2593 Make_String_Literal (Loc,
2594 Strval => Verbose_Library_Version));
2595
2596 -- All other cases
2597
2598 else
2599 -- Build required string constant
2600
2601 Get_Name_String (Get_Unit_Name (Pent));
2602
2603 Start_String;
2604 for J in 1 .. Name_Len - 2 loop
2605 if Name_Buffer (J) = '.' then
2606 Store_String_Chars ("__");
2607 else
2608 Store_String_Char (Get_Char_Code (Name_Buffer (J)));
2609 end if;
2610 end loop;
2611
2612 -- Case of subprogram acting as its own spec, always use body
2613
2614 if Nkind (Declaration_Node (Pent)) in N_Subprogram_Specification
2615 and then Nkind (Parent (Declaration_Node (Pent))) =
2616 N_Subprogram_Body
2617 and then Acts_As_Spec (Parent (Declaration_Node (Pent)))
2618 then
2619 Store_String_Chars ("B");
2620
2621 -- Case of no body present, always use spec
2622
2623 elsif not Unit_Requires_Body (Pent) then
2624 Store_String_Chars ("S");
2625
2626 -- Otherwise use B for Body_Version, S for spec
2627
2628 elsif Id = Attribute_Body_Version then
2629 Store_String_Chars ("B");
2630 else
2631 Store_String_Chars ("S");
2632 end if;
2633
2634 S := End_String;
2635 Lib.Version_Referenced (S);
2636
2637 -- Insert the object declaration
2638
2639 Insert_Actions (N, New_List (
2640 Make_Object_Declaration (Loc,
2641 Defining_Identifier => E,
2642 Object_Definition =>
2643 New_Occurrence_Of (RTE (RE_Unsigned), Loc))));
2644
2645 -- Set entity as imported with correct external name
2646
2647 Set_Is_Imported (E);
2648 Set_Interface_Name (E, Make_String_Literal (Loc, S));
2649
2650 -- Set entity as internal to ensure proper Sprint output of its
2651 -- implicit importation.
2652
2653 Set_Is_Internal (E);
2654
2655 -- And now rewrite original reference
2656
2657 Rewrite (N,
2658 Make_Function_Call (Loc,
2659 Name =>
2660 New_Occurrence_Of (RTE (RE_Get_Version_String), Loc),
2661 Parameter_Associations => New_List (
2662 New_Occurrence_Of (E, Loc))));
2663 end if;
2664
2665 Analyze_And_Resolve (N, RTE (RE_Version_String));
2666 end Version;
2667
2668 -------------
2669 -- Ceiling --
2670 -------------
2671
2672 -- Transforms 'Ceiling into a call to the floating-point attribute
2673 -- function Ceiling in Fat_xxx (where xxx is the root type)
2674
2675 when Attribute_Ceiling =>
2676 Expand_Fpt_Attribute_R (N);
2677
2678 --------------
2679 -- Callable --
2680 --------------
2681
2682 -- Transforms 'Callable attribute into a call to the Callable function
2683
2684 when Attribute_Callable =>
2685
2686 -- We have an object of a task interface class-wide type as a prefix
2687 -- to Callable. Generate:
2688 -- callable (Task_Id (Pref._disp_get_task_id));
2689
2690 if Ada_Version >= Ada_2005
2691 and then Ekind (Ptyp) = E_Class_Wide_Type
2692 and then Is_Interface (Ptyp)
2693 and then Is_Task_Interface (Ptyp)
2694 then
2695 Rewrite (N,
2696 Make_Function_Call (Loc,
2697 Name =>
2698 New_Occurrence_Of (RTE (RE_Callable), Loc),
2699 Parameter_Associations => New_List (
2700 Make_Unchecked_Type_Conversion (Loc,
2701 Subtype_Mark =>
2702 New_Occurrence_Of (RTE (RO_ST_Task_Id), Loc),
2703 Expression => Build_Disp_Get_Task_Id_Call (Pref)))));
2704
2705 else
2706 Rewrite (N, Build_Call_With_Task (Pref, RTE (RE_Callable)));
2707 end if;
2708
2709 Analyze_And_Resolve (N, Standard_Boolean);
2710
2711 ------------
2712 -- Caller --
2713 ------------
2714
2715 -- Transforms 'Caller attribute into a call to either the
2716 -- Task_Entry_Caller or the Protected_Entry_Caller function.
2717
2718 when Attribute_Caller => Caller : declare
2719 Id_Kind : constant Entity_Id := RTE (RO_AT_Task_Id);
2720 Ent : constant Entity_Id := Entity (Pref);
2721 Conctype : constant Entity_Id := Scope (Ent);
2722 Nest_Depth : Integer := 0;
2723 Name : Node_Id;
2724 S : Entity_Id;
2725
2726 begin
2727 -- Protected case
2728
2729 if Is_Protected_Type (Conctype) then
2730 case Corresponding_Runtime_Package (Conctype) is
2731 when System_Tasking_Protected_Objects_Entries =>
2732 Name :=
2733 New_Occurrence_Of
2734 (RTE (RE_Protected_Entry_Caller), Loc);
2735
2736 when System_Tasking_Protected_Objects_Single_Entry =>
2737 Name :=
2738 New_Occurrence_Of
2739 (RTE (RE_Protected_Single_Entry_Caller), Loc);
2740
2741 when others =>
2742 raise Program_Error;
2743 end case;
2744
2745 Rewrite (N,
2746 Unchecked_Convert_To (Id_Kind,
2747 Make_Function_Call (Loc,
2748 Name => Name,
2749 Parameter_Associations => New_List (
2750 New_Occurrence_Of
2751 (Find_Protection_Object (Current_Scope), Loc)))));
2752
2753 -- Task case
2754
2755 else
2756 -- Determine the nesting depth of the E'Caller attribute, that
2757 -- is, how many accept statements are nested within the accept
2758 -- statement for E at the point of E'Caller. The runtime uses
2759 -- this depth to find the specified entry call.
2760
2761 for J in reverse 0 .. Scope_Stack.Last loop
2762 S := Scope_Stack.Table (J).Entity;
2763
2764 -- We should not reach the scope of the entry, as it should
2765 -- already have been checked in Sem_Attr that this attribute
2766 -- reference is within a matching accept statement.
2767
2768 pragma Assert (S /= Conctype);
2769
2770 if S = Ent then
2771 exit;
2772
2773 elsif Is_Entry (S) then
2774 Nest_Depth := Nest_Depth + 1;
2775 end if;
2776 end loop;
2777
2778 Rewrite (N,
2779 Unchecked_Convert_To (Id_Kind,
2780 Make_Function_Call (Loc,
2781 Name =>
2782 New_Occurrence_Of (RTE (RE_Task_Entry_Caller), Loc),
2783 Parameter_Associations => New_List (
2784 Make_Integer_Literal (Loc,
2785 Intval => Int (Nest_Depth))))));
2786 end if;
2787
2788 Analyze_And_Resolve (N, Id_Kind);
2789 end Caller;
2790
2791 -------------
2792 -- Compose --
2793 -------------
2794
2795 -- Transforms 'Compose into a call to the floating-point attribute
2796 -- function Compose in Fat_xxx (where xxx is the root type)
2797
2798 -- Note: we strictly should have special code here to deal with the
2799 -- case of absurdly negative arguments (less than Integer'First)
2800 -- which will return a (signed) zero value, but it hardly seems
2801 -- worth the effort. Absurdly large positive arguments will raise
2802 -- constraint error which is fine.
2803
2804 when Attribute_Compose =>
2805 Expand_Fpt_Attribute_RI (N);
2806
2807 -----------------
2808 -- Constrained --
2809 -----------------
2810
2811 when Attribute_Constrained => Constrained : declare
2812 Formal_Ent : constant Entity_Id := Param_Entity (Pref);
2813
2814 -- Start of processing for Constrained
2815
2816 begin
2817 -- Reference to a parameter where the value is passed as an extra
2818 -- actual, corresponding to the extra formal referenced by the
2819 -- Extra_Constrained field of the corresponding formal. If this
2820 -- is an entry in-parameter, it is replaced by a constant renaming
2821 -- for which Extra_Constrained is never created.
2822
2823 if Present (Formal_Ent)
2824 and then Ekind (Formal_Ent) /= E_Constant
2825 and then Present (Extra_Constrained (Formal_Ent))
2826 then
2827 Rewrite (N,
2828 New_Occurrence_Of
2829 (Extra_Constrained (Formal_Ent), Sloc (N)));
2830
2831 -- If the prefix is an access to object, the attribute applies to
2832 -- the designated object, so rewrite with an explicit dereference.
2833
2834 elsif Is_Access_Type (Ptyp)
2835 and then
2836 (not Is_Entity_Name (Pref) or else Is_Object (Entity (Pref)))
2837 then
2838 Rewrite (Pref,
2839 Make_Explicit_Dereference (Loc, Relocate_Node (Pref)));
2840 Analyze_And_Resolve (N, Standard_Boolean);
2841 return;
2842
2843 -- For variables with a Extra_Constrained field, we use the
2844 -- corresponding entity.
2845
2846 elsif Nkind (Pref) = N_Identifier
2847 and then Ekind (Entity (Pref)) = E_Variable
2848 and then Present (Extra_Constrained (Entity (Pref)))
2849 then
2850 Rewrite (N,
2851 New_Occurrence_Of
2852 (Extra_Constrained (Entity (Pref)), Sloc (N)));
2853
2854 -- For all other cases, we can tell at compile time
2855
2856 else
2857 -- For access type, apply access check as needed
2858
2859 if Is_Entity_Name (Pref)
2860 and then not Is_Type (Entity (Pref))
2861 and then Is_Access_Type (Ptyp)
2862 then
2863 Apply_Access_Check (N);
2864 end if;
2865
2866 Rewrite (N,
2867 New_Occurrence_Of
2868 (Boolean_Literals
2869 (Exp_Util.Attribute_Constrained_Static_Value
2870 (Pref)), Sloc (N)));
2871 end if;
2872
2873 Analyze_And_Resolve (N, Standard_Boolean);
2874 end Constrained;
2875
2876 ---------------
2877 -- Copy_Sign --
2878 ---------------
2879
2880 -- Transforms 'Copy_Sign into a call to the floating-point attribute
2881 -- function Copy_Sign in Fat_xxx (where xxx is the root type)
2882
2883 when Attribute_Copy_Sign =>
2884 Expand_Fpt_Attribute_RR (N);
2885
2886 -----------
2887 -- Count --
2888 -----------
2889
2890 -- Transforms 'Count attribute into a call to the Count function
2891
2892 when Attribute_Count => Count : declare
2893 Call : Node_Id;
2894 Conctyp : Entity_Id;
2895 Entnam : Node_Id;
2896 Entry_Id : Entity_Id;
2897 Index : Node_Id;
2898 Name : Node_Id;
2899
2900 begin
2901 -- If the prefix is a member of an entry family, retrieve both
2902 -- entry name and index. For a simple entry there is no index.
2903
2904 if Nkind (Pref) = N_Indexed_Component then
2905 Entnam := Prefix (Pref);
2906 Index := First (Expressions (Pref));
2907 else
2908 Entnam := Pref;
2909 Index := Empty;
2910 end if;
2911
2912 Entry_Id := Entity (Entnam);
2913
2914 -- Find the concurrent type in which this attribute is referenced
2915 -- (there had better be one).
2916
2917 Conctyp := Current_Scope;
2918 while not Is_Concurrent_Type (Conctyp) loop
2919 Conctyp := Scope (Conctyp);
2920 end loop;
2921
2922 -- Protected case
2923
2924 if Is_Protected_Type (Conctyp) then
2925
2926 -- No need to transform 'Count into a function call if the current
2927 -- scope has been eliminated. In this case such transformation is
2928 -- also not viable because the enclosing protected object is not
2929 -- available.
2930
2931 if Is_Eliminated (Current_Scope) then
2932 return;
2933 end if;
2934
2935 case Corresponding_Runtime_Package (Conctyp) is
2936 when System_Tasking_Protected_Objects_Entries =>
2937 Name := New_Occurrence_Of (RTE (RE_Protected_Count), Loc);
2938
2939 Call :=
2940 Make_Function_Call (Loc,
2941 Name => Name,
2942 Parameter_Associations => New_List (
2943 New_Occurrence_Of
2944 (Find_Protection_Object (Current_Scope), Loc),
2945 Entry_Index_Expression
2946 (Loc, Entry_Id, Index, Scope (Entry_Id))));
2947
2948 when System_Tasking_Protected_Objects_Single_Entry =>
2949 Name :=
2950 New_Occurrence_Of (RTE (RE_Protected_Count_Entry), Loc);
2951
2952 Call :=
2953 Make_Function_Call (Loc,
2954 Name => Name,
2955 Parameter_Associations => New_List (
2956 New_Occurrence_Of
2957 (Find_Protection_Object (Current_Scope), Loc)));
2958
2959 when others =>
2960 raise Program_Error;
2961 end case;
2962
2963 -- Task case
2964
2965 else
2966 Call :=
2967 Make_Function_Call (Loc,
2968 Name => New_Occurrence_Of (RTE (RE_Task_Count), Loc),
2969 Parameter_Associations => New_List (
2970 Entry_Index_Expression (Loc,
2971 Entry_Id, Index, Scope (Entry_Id))));
2972 end if;
2973
2974 -- The call returns type Natural but the context is universal integer
2975 -- so any integer type is allowed. The attribute was already resolved
2976 -- so its Etype is the required result type. If the base type of the
2977 -- context type is other than Standard.Integer we put in a conversion
2978 -- to the required type. This can be a normal typed conversion since
2979 -- both input and output types of the conversion are integer types
2980
2981 if Base_Type (Typ) /= Base_Type (Standard_Integer) then
2982 Rewrite (N, Convert_To (Typ, Call));
2983 else
2984 Rewrite (N, Call);
2985 end if;
2986
2987 Analyze_And_Resolve (N, Typ);
2988 end Count;
2989
2990 ---------------------
2991 -- Descriptor_Size --
2992 ---------------------
2993
2994 when Attribute_Descriptor_Size =>
2995
2996 -- Attribute Descriptor_Size is handled by the back end when applied
2997 -- to an unconstrained array type.
2998
2999 if Is_Array_Type (Ptyp)
3000 and then not Is_Constrained (Ptyp)
3001 then
3002 Apply_Universal_Integer_Attribute_Checks (N);
3003
3004 -- For any other type, the descriptor size is 0 because there is no
3005 -- actual descriptor, but the result is not formally static.
3006
3007 else
3008 Rewrite (N, Make_Integer_Literal (Loc, 0));
3009 Analyze (N);
3010 Set_Is_Static_Expression (N, False);
3011 end if;
3012
3013 ---------------
3014 -- Elab_Body --
3015 ---------------
3016
3017 -- This processing is shared by Elab_Spec
3018
3019 -- What we do is to insert the following declarations
3020
3021 -- procedure tnn;
3022 -- pragma Import (C, enn, "name___elabb/s");
3023
3024 -- and then the Elab_Body/Spec attribute is replaced by a reference
3025 -- to this defining identifier.
3026
3027 when Attribute_Elab_Body
3028 | Attribute_Elab_Spec
3029 =>
3030 -- Leave attribute unexpanded in CodePeer mode: the gnat2scil
3031 -- back-end knows how to handle these attributes directly.
3032
3033 if CodePeer_Mode then
3034 return;
3035 end if;
3036
3037 Elab_Body : declare
3038 Ent : constant Entity_Id := Make_Temporary (Loc, 'E');
3039 Str : String_Id;
3040 Lang : Node_Id;
3041
3042 procedure Make_Elab_String (Nod : Node_Id);
3043 -- Given Nod, an identifier, or a selected component, put the
3044 -- image into the current string literal, with double underline
3045 -- between components.
3046
3047 ----------------------
3048 -- Make_Elab_String --
3049 ----------------------
3050
3051 procedure Make_Elab_String (Nod : Node_Id) is
3052 begin
3053 if Nkind (Nod) = N_Selected_Component then
3054 Make_Elab_String (Prefix (Nod));
3055 Store_String_Char ('_');
3056 Store_String_Char ('_');
3057 Get_Name_String (Chars (Selector_Name (Nod)));
3058
3059 else
3060 pragma Assert (Nkind (Nod) = N_Identifier);
3061 Get_Name_String (Chars (Nod));
3062 end if;
3063
3064 Store_String_Chars (Name_Buffer (1 .. Name_Len));
3065 end Make_Elab_String;
3066
3067 -- Start of processing for Elab_Body/Elab_Spec
3068
3069 begin
3070 -- First we need to prepare the string literal for the name of
3071 -- the elaboration routine to be referenced.
3072
3073 Start_String;
3074 Make_Elab_String (Pref);
3075 Store_String_Chars ("___elab");
3076 Lang := Make_Identifier (Loc, Name_C);
3077
3078 if Id = Attribute_Elab_Body then
3079 Store_String_Char ('b');
3080 else
3081 Store_String_Char ('s');
3082 end if;
3083
3084 Str := End_String;
3085
3086 Insert_Actions (N, New_List (
3087 Make_Subprogram_Declaration (Loc,
3088 Specification =>
3089 Make_Procedure_Specification (Loc,
3090 Defining_Unit_Name => Ent)),
3091
3092 Make_Pragma (Loc,
3093 Chars => Name_Import,
3094 Pragma_Argument_Associations => New_List (
3095 Make_Pragma_Argument_Association (Loc, Expression => Lang),
3096
3097 Make_Pragma_Argument_Association (Loc,
3098 Expression => Make_Identifier (Loc, Chars (Ent))),
3099
3100 Make_Pragma_Argument_Association (Loc,
3101 Expression => Make_String_Literal (Loc, Str))))));
3102
3103 Set_Entity (N, Ent);
3104 Rewrite (N, New_Occurrence_Of (Ent, Loc));
3105 end Elab_Body;
3106
3107 --------------------
3108 -- Elab_Subp_Body --
3109 --------------------
3110
3111 -- Always ignored. In CodePeer mode, gnat2scil knows how to handle
3112 -- this attribute directly, and if we are not in CodePeer mode it is
3113 -- entirely ignored ???
3114
3115 when Attribute_Elab_Subp_Body =>
3116 return;
3117
3118 ----------------
3119 -- Elaborated --
3120 ----------------
3121
3122 -- Elaborated is always True for preelaborated units, predefined units,
3123 -- pure units and units which have Elaborate_Body pragmas. These units
3124 -- have no elaboration entity.
3125
3126 -- Note: The Elaborated attribute is never passed to the back end
3127
3128 when Attribute_Elaborated => Elaborated : declare
3129 Elab_Id : constant Entity_Id := Elaboration_Entity (Entity (Pref));
3130
3131 begin
3132 if Present (Elab_Id) then
3133 Rewrite (N,
3134 Make_Op_Ne (Loc,
3135 Left_Opnd => New_Occurrence_Of (Elab_Id, Loc),
3136 Right_Opnd => Make_Integer_Literal (Loc, Uint_0)));
3137
3138 Analyze_And_Resolve (N, Typ);
3139 else
3140 Rewrite (N, New_Occurrence_Of (Standard_True, Loc));
3141 end if;
3142 end Elaborated;
3143
3144 --------------
3145 -- Enum_Rep --
3146 --------------
3147
3148 when Attribute_Enum_Rep => Enum_Rep : declare
3149 Expr : Node_Id;
3150 Ityp : Entity_Id;
3151 Psiz : Uint;
3152
3153 begin
3154 -- Get the expression, which is X for Enum_Type'Enum_Rep (X) or
3155 -- X'Enum_Rep.
3156
3157 if Is_Non_Empty_List (Exprs) then
3158 Expr := First (Exprs);
3159 else
3160 Expr := Pref;
3161 end if;
3162
3163 -- If the expression is an enumeration literal, it is replaced by the
3164 -- literal value.
3165
3166 if Nkind (Expr) in N_Has_Entity
3167 and then Ekind (Entity (Expr)) = E_Enumeration_Literal
3168 then
3169 Rewrite (N,
3170 Make_Integer_Literal (Loc, Enumeration_Rep (Entity (Expr))));
3171
3172 -- If this is a renaming of a literal, recover the representation
3173 -- of the original. If it renames an expression there is nothing to
3174 -- fold.
3175
3176 elsif Nkind (Expr) in N_Has_Entity
3177 and then Ekind (Entity (Expr)) = E_Constant
3178 and then Present (Renamed_Object (Entity (Expr)))
3179 and then Is_Entity_Name (Renamed_Object (Entity (Expr)))
3180 and then Ekind (Entity (Renamed_Object (Entity (Expr)))) =
3181 E_Enumeration_Literal
3182 then
3183 Rewrite (N,
3184 Make_Integer_Literal (Loc,
3185 Enumeration_Rep (Entity (Renamed_Object (Entity (Expr))))));
3186
3187 -- If not constant-folded above, Enum_Type'Enum_Rep (X) or
3188 -- X'Enum_Rep expands to
3189
3190 -- target-type (X)
3191
3192 -- This is simply a direct conversion from the enumeration type to
3193 -- the target integer type, which is treated by the back end as a
3194 -- normal integer conversion, treating the enumeration type as an
3195 -- integer, which is exactly what we want. We set Conversion_OK to
3196 -- make sure that the analyzer does not complain about what otherwise
3197 -- might be an illegal conversion.
3198
3199 -- However the target type is universal integer in most cases, which
3200 -- is a very large type, so in the case of an enumeration type, we
3201 -- first convert to a small signed integer type in order not to lose
3202 -- the size information.
3203
3204 elsif Is_Enumeration_Type (Ptyp) then
3205 Psiz := RM_Size (Base_Type (Ptyp));
3206
3207 if Psiz < 8 then
3208 Ityp := Standard_Integer_8;
3209
3210 elsif Psiz < 16 then
3211 Ityp := Standard_Integer_16;
3212
3213 elsif Psiz < 32 then
3214 Ityp := Standard_Integer_32;
3215
3216 else
3217 Ityp := Standard_Integer_64;
3218 end if;
3219
3220 Rewrite (N, OK_Convert_To (Ityp, Expr));
3221 Convert_To_And_Rewrite (Typ, N);
3222
3223 else
3224 Rewrite (N, OK_Convert_To (Typ, Expr));
3225 end if;
3226
3227 Analyze_And_Resolve (N, Typ);
3228 end Enum_Rep;
3229
3230 --------------
3231 -- Enum_Val --
3232 --------------
3233
3234 when Attribute_Enum_Val => Enum_Val : declare
3235 Expr : Node_Id;
3236 Btyp : constant Entity_Id := Base_Type (Ptyp);
3237
3238 begin
3239 -- X'Enum_Val (Y) expands to
3240
3241 -- [constraint_error when _rep_to_pos (Y, False) = -1, msg]
3242 -- X!(Y);
3243
3244 Expr := Unchecked_Convert_To (Ptyp, First (Exprs));
3245
3246 -- Ensure that the expression is not truncated since the "bad" bits
3247 -- are desired.
3248
3249 if Nkind (Expr) = N_Unchecked_Type_Conversion then
3250 Set_No_Truncation (Expr);
3251 end if;
3252
3253 Insert_Action (N,
3254 Make_Raise_Constraint_Error (Loc,
3255 Condition =>
3256 Make_Op_Eq (Loc,
3257 Left_Opnd =>
3258 Make_Function_Call (Loc,
3259 Name =>
3260 New_Occurrence_Of (TSS (Btyp, TSS_Rep_To_Pos), Loc),
3261 Parameter_Associations => New_List (
3262 Relocate_Node (Duplicate_Subexpr (Expr)),
3263 New_Occurrence_Of (Standard_False, Loc))),
3264
3265 Right_Opnd => Make_Integer_Literal (Loc, -1)),
3266 Reason => CE_Range_Check_Failed));
3267
3268 Rewrite (N, Expr);
3269 Analyze_And_Resolve (N, Ptyp);
3270 end Enum_Val;
3271
3272 --------------
3273 -- Exponent --
3274 --------------
3275
3276 -- Transforms 'Exponent into a call to the floating-point attribute
3277 -- function Exponent in Fat_xxx (where xxx is the root type)
3278
3279 when Attribute_Exponent =>
3280 Expand_Fpt_Attribute_R (N);
3281
3282 ------------------
3283 -- External_Tag --
3284 ------------------
3285
3286 -- transforme X'External_Tag into Ada.Tags.External_Tag (X'tag)
3287
3288 when Attribute_External_Tag =>
3289 Rewrite (N,
3290 Make_Function_Call (Loc,
3291 Name =>
3292 New_Occurrence_Of (RTE (RE_External_Tag), Loc),
3293 Parameter_Associations => New_List (
3294 Make_Attribute_Reference (Loc,
3295 Attribute_Name => Name_Tag,
3296 Prefix => Prefix (N)))));
3297
3298 Analyze_And_Resolve (N, Standard_String);
3299
3300 -----------------------
3301 -- Finalization_Size --
3302 -----------------------
3303
3304 when Attribute_Finalization_Size => Finalization_Size : declare
3305 function Calculate_Header_Size return Node_Id;
3306 -- Generate a runtime call to calculate the size of the hidden header
3307 -- along with any added padding which would precede a heap-allocated
3308 -- object of the prefix type.
3309
3310 ---------------------------
3311 -- Calculate_Header_Size --
3312 ---------------------------
3313
3314 function Calculate_Header_Size return Node_Id is
3315 begin
3316 -- Generate:
3317 -- Typ (Header_Size_With_Padding (Pref'Alignment))
3318
3319 return
3320 Convert_To (Typ,
3321 Make_Function_Call (Loc,
3322 Name =>
3323 New_Occurrence_Of (RTE (RE_Header_Size_With_Padding), Loc),
3324
3325 Parameter_Associations => New_List (
3326 Make_Attribute_Reference (Loc,
3327 Prefix => New_Copy_Tree (Pref),
3328 Attribute_Name => Name_Alignment))));
3329 end Calculate_Header_Size;
3330
3331 -- Local variables
3332
3333 Size : Entity_Id;
3334
3335 -- Start of Finalization_Size
3336
3337 begin
3338 -- An object of a class-wide type first requires a runtime check to
3339 -- determine whether it is actually controlled or not. Depending on
3340 -- the outcome of this check, the Finalization_Size of the object
3341 -- may be zero or some positive value.
3342 --
3343 -- In this scenario, Pref'Finalization_Size is expanded into
3344 --
3345 -- Size : Integer := 0;
3346 --
3347 -- if Needs_Finalization (Pref'Tag) then
3348 -- Size := Integer (Header_Size_With_Padding (Pref'Alignment));
3349 -- end if;
3350 --
3351 -- and the attribute reference is replaced with a reference to Size.
3352
3353 if Is_Class_Wide_Type (Ptyp) then
3354 Size := Make_Temporary (Loc, 'S');
3355
3356 Insert_Actions (N, New_List (
3357
3358 -- Generate:
3359 -- Size : Integer := 0;
3360
3361 Make_Object_Declaration (Loc,
3362 Defining_Identifier => Size,
3363 Object_Definition =>
3364 New_Occurrence_Of (Standard_Integer, Loc),
3365 Expression => Make_Integer_Literal (Loc, 0)),
3366
3367 -- Generate:
3368 -- if Needs_Finalization (Pref'Tag) then
3369 -- Size :=
3370 -- Integer (Header_Size_With_Padding (Pref'Alignment));
3371 -- end if;
3372
3373 Make_If_Statement (Loc,
3374 Condition =>
3375 Make_Function_Call (Loc,
3376 Name =>
3377 New_Occurrence_Of (RTE (RE_Needs_Finalization), Loc),
3378
3379 Parameter_Associations => New_List (
3380 Make_Attribute_Reference (Loc,
3381 Prefix => New_Copy_Tree (Pref),
3382 Attribute_Name => Name_Tag))),
3383
3384 Then_Statements => New_List (
3385 Make_Assignment_Statement (Loc,
3386 Name => New_Occurrence_Of (Size, Loc),
3387 Expression =>
3388 Convert_To
3389 (Standard_Integer, Calculate_Header_Size))))));
3390
3391 Rewrite (N, New_Occurrence_Of (Size, Loc));
3392
3393 -- The prefix is known to be controlled at compile time. Calculate
3394 -- Finalization_Size by calling function Header_Size_With_Padding.
3395
3396 elsif Needs_Finalization (Ptyp) then
3397 Rewrite (N, Calculate_Header_Size);
3398
3399 -- The prefix is not an object with controlled parts, so its
3400 -- Finalization_Size is zero.
3401
3402 else
3403 Rewrite (N, Make_Integer_Literal (Loc, 0));
3404 end if;
3405
3406 -- Due to cases where the entity type of the attribute is already
3407 -- resolved the rewritten N must get re-resolved to its appropriate
3408 -- type.
3409
3410 Analyze_And_Resolve (N, Typ);
3411 end Finalization_Size;
3412
3413 -----------
3414 -- First --
3415 -----------
3416
3417 when Attribute_First =>
3418
3419 -- If the prefix type is a constrained packed array type which
3420 -- already has a Packed_Array_Impl_Type representation defined, then
3421 -- replace this attribute with a direct reference to 'First of the
3422 -- appropriate index subtype (since otherwise the back end will try
3423 -- to give us the value of 'First for this implementation type).
3424
3425 if Is_Constrained_Packed_Array (Ptyp) then
3426 Rewrite (N,
3427 Make_Attribute_Reference (Loc,
3428 Attribute_Name => Name_First,
3429 Prefix =>
3430 New_Occurrence_Of (Get_Index_Subtype (N), Loc)));
3431 Analyze_And_Resolve (N, Typ);
3432
3433 -- For access type, apply access check as needed
3434
3435 elsif Is_Access_Type (Ptyp) then
3436 Apply_Access_Check (N);
3437
3438 -- For scalar type, if low bound is a reference to an entity, just
3439 -- replace with a direct reference. Note that we can only have a
3440 -- reference to a constant entity at this stage, anything else would
3441 -- have already been rewritten.
3442
3443 elsif Is_Scalar_Type (Ptyp) then
3444 declare
3445 Lo : constant Node_Id := Type_Low_Bound (Ptyp);
3446 begin
3447 if Is_Entity_Name (Lo) then
3448 Rewrite (N, New_Occurrence_Of (Entity (Lo), Loc));
3449 end if;
3450 end;
3451 end if;
3452
3453 ---------------
3454 -- First_Bit --
3455 ---------------
3456
3457 -- Compute this if component clause was present, otherwise we leave the
3458 -- computation to be completed in the back-end, since we don't know what
3459 -- layout will be chosen.
3460
3461 when Attribute_First_Bit => First_Bit_Attr : declare
3462 CE : constant Entity_Id := Entity (Selector_Name (Pref));
3463
3464 begin
3465 -- In Ada 2005 (or later) if we have the non-default bit order, then
3466 -- we return the original value as given in the component clause
3467 -- (RM 2005 13.5.2(3/2)).
3468
3469 if Present (Component_Clause (CE))
3470 and then Ada_Version >= Ada_2005
3471 and then Reverse_Bit_Order (Scope (CE))
3472 then
3473 Rewrite (N,
3474 Make_Integer_Literal (Loc,
3475 Intval => Expr_Value (First_Bit (Component_Clause (CE)))));
3476 Analyze_And_Resolve (N, Typ);
3477
3478 -- Otherwise (Ada 83/95 or Ada 2005 or later with default bit order),
3479 -- rewrite with normalized value if we know it statically.
3480
3481 elsif Known_Static_Component_Bit_Offset (CE) then
3482 Rewrite (N,
3483 Make_Integer_Literal (Loc,
3484 Component_Bit_Offset (CE) mod System_Storage_Unit));
3485 Analyze_And_Resolve (N, Typ);
3486
3487 -- Otherwise left to back end, just do universal integer checks
3488
3489 else
3490 Apply_Universal_Integer_Attribute_Checks (N);
3491 end if;
3492 end First_Bit_Attr;
3493
3494 --------------------------------
3495 -- Fixed_Value, Integer_Value --
3496 --------------------------------
3497
3498 -- We transform
3499
3500 -- fixtype'Fixed_Value (integer-value)
3501 -- inttype'Integer_Value (fixed-value)
3502
3503 -- into
3504
3505 -- fixtype (integer-value)
3506 -- inttype (fixed-value)
3507
3508 -- respectively.
3509
3510 -- We set Conversion_OK on the conversion because we do not want it
3511 -- to go through the fixed-point conversion circuits.
3512
3513 when Attribute_Fixed_Value
3514 | Attribute_Integer_Value
3515 =>
3516 Rewrite (N, OK_Convert_To (Entity (Pref), First (Exprs)));
3517
3518 -- Note that it might appear that a properly analyzed unchecked
3519 -- conversion would be just fine here, but that's not the case,
3520 -- since the full range checks performed by the following calls
3521 -- are critical.
3522
3523 Apply_Type_Conversion_Checks (N);
3524
3525 -- Note that Apply_Type_Conversion_Checks only deals with the
3526 -- overflow checks on conversions involving fixed-point types
3527 -- so we must apply range checks manually on them and expand.
3528
3529 Apply_Scalar_Range_Check
3530 (Expression (N), Etype (N), Fixed_Int => True);
3531
3532 Set_Analyzed (N);
3533 Expand (N);
3534
3535 -----------
3536 -- Floor --
3537 -----------
3538
3539 -- Transforms 'Floor into a call to the floating-point attribute
3540 -- function Floor in Fat_xxx (where xxx is the root type)
3541
3542 when Attribute_Floor =>
3543 Expand_Fpt_Attribute_R (N);
3544
3545 ----------
3546 -- Fore --
3547 ----------
3548
3549 -- For the fixed-point type Typ:
3550
3551 -- Typ'Fore
3552
3553 -- expands into
3554
3555 -- Result_Type (System.Fore (Universal_Real (Type'First)),
3556 -- Universal_Real (Type'Last))
3557
3558 -- Note that we know that the type is a nonstatic subtype, or Fore would
3559 -- have itself been computed dynamically in Eval_Attribute.
3560
3561 when Attribute_Fore =>
3562 Rewrite (N,
3563 Convert_To (Typ,
3564 Make_Function_Call (Loc,
3565 Name =>
3566 New_Occurrence_Of (RTE (RE_Fore), Loc),
3567
3568 Parameter_Associations => New_List (
3569 Convert_To (Universal_Real,
3570 Make_Attribute_Reference (Loc,
3571 Prefix => New_Occurrence_Of (Ptyp, Loc),
3572 Attribute_Name => Name_First)),
3573
3574 Convert_To (Universal_Real,
3575 Make_Attribute_Reference (Loc,
3576 Prefix => New_Occurrence_Of (Ptyp, Loc),
3577 Attribute_Name => Name_Last))))));
3578
3579 Analyze_And_Resolve (N, Typ);
3580
3581 --------------
3582 -- Fraction --
3583 --------------
3584
3585 -- Transforms 'Fraction into a call to the floating-point attribute
3586 -- function Fraction in Fat_xxx (where xxx is the root type)
3587
3588 when Attribute_Fraction =>
3589 Expand_Fpt_Attribute_R (N);
3590
3591 --------------
3592 -- From_Any --
3593 --------------
3594
3595 when Attribute_From_Any => From_Any : declare
3596 Decls : constant List_Id := New_List;
3597
3598 begin
3599 Rewrite (N,
3600 Build_From_Any_Call (Ptyp,
3601 Relocate_Node (First (Exprs)),
3602 Decls));
3603 Insert_Actions (N, Decls);
3604 Analyze_And_Resolve (N, Ptyp);
3605 end From_Any;
3606
3607 ----------------------
3608 -- Has_Same_Storage --
3609 ----------------------
3610
3611 when Attribute_Has_Same_Storage => Has_Same_Storage : declare
3612 Loc : constant Source_Ptr := Sloc (N);
3613
3614 X : constant Node_Id := Prefix (N);
3615 Y : constant Node_Id := First (Expressions (N));
3616 -- The arguments
3617
3618 X_Addr : Node_Id;
3619 Y_Addr : Node_Id;
3620 -- Rhe expressions for their addresses
3621
3622 X_Size : Node_Id;
3623 Y_Size : Node_Id;
3624 -- Rhe expressions for their sizes
3625
3626 begin
3627 -- The attribute is expanded as:
3628
3629 -- (X'address = Y'address)
3630 -- and then (X'Size = Y'Size)
3631
3632 -- If both arguments have the same Etype the second conjunct can be
3633 -- omitted.
3634
3635 X_Addr :=
3636 Make_Attribute_Reference (Loc,
3637 Attribute_Name => Name_Address,
3638 Prefix => New_Copy_Tree (X));
3639
3640 Y_Addr :=
3641 Make_Attribute_Reference (Loc,
3642 Attribute_Name => Name_Address,
3643 Prefix => New_Copy_Tree (Y));
3644
3645 X_Size :=
3646 Make_Attribute_Reference (Loc,
3647 Attribute_Name => Name_Size,
3648 Prefix => New_Copy_Tree (X));
3649
3650 Y_Size :=
3651 Make_Attribute_Reference (Loc,
3652 Attribute_Name => Name_Size,
3653 Prefix => New_Copy_Tree (Y));
3654
3655 if Etype (X) = Etype (Y) then
3656 Rewrite (N,
3657 Make_Op_Eq (Loc,
3658 Left_Opnd => X_Addr,
3659 Right_Opnd => Y_Addr));
3660 else
3661 Rewrite (N,
3662 Make_Op_And (Loc,
3663 Left_Opnd =>
3664 Make_Op_Eq (Loc,
3665 Left_Opnd => X_Addr,
3666 Right_Opnd => Y_Addr),
3667 Right_Opnd =>
3668 Make_Op_Eq (Loc,
3669 Left_Opnd => X_Size,
3670 Right_Opnd => Y_Size)));
3671 end if;
3672
3673 Analyze_And_Resolve (N, Standard_Boolean);
3674 end Has_Same_Storage;
3675
3676 --------------
3677 -- Identity --
3678 --------------
3679
3680 -- For an exception returns a reference to the exception data:
3681 -- Exception_Id!(Prefix'Reference)
3682
3683 -- For a task it returns a reference to the _task_id component of
3684 -- corresponding record:
3685
3686 -- taskV!(Prefix)._Task_Id, converted to the type Task_Id defined
3687
3688 -- in Ada.Task_Identification
3689
3690 when Attribute_Identity => Identity : declare
3691 Id_Kind : Entity_Id;
3692
3693 begin
3694 if Ptyp = Standard_Exception_Type then
3695 Id_Kind := RTE (RE_Exception_Id);
3696
3697 if Present (Renamed_Object (Entity (Pref))) then
3698 Set_Entity (Pref, Renamed_Object (Entity (Pref)));
3699 end if;
3700
3701 Rewrite (N,
3702 Unchecked_Convert_To (Id_Kind, Make_Reference (Loc, Pref)));
3703 else
3704 Id_Kind := RTE (RO_AT_Task_Id);
3705
3706 -- If the prefix is a task interface, the Task_Id is obtained
3707 -- dynamically through a dispatching call, as for other task
3708 -- attributes applied to interfaces.
3709
3710 if Ada_Version >= Ada_2005
3711 and then Ekind (Ptyp) = E_Class_Wide_Type
3712 and then Is_Interface (Ptyp)
3713 and then Is_Task_Interface (Ptyp)
3714 then
3715 Rewrite (N,
3716 Unchecked_Convert_To
3717 (Id_Kind, Build_Disp_Get_Task_Id_Call (Pref)));
3718
3719 else
3720 Rewrite (N,
3721 Unchecked_Convert_To (Id_Kind, Concurrent_Ref (Pref)));
3722 end if;
3723 end if;
3724
3725 Analyze_And_Resolve (N, Id_Kind);
3726 end Identity;
3727
3728 -----------
3729 -- Image --
3730 -----------
3731
3732 -- Image attribute is handled in separate unit Exp_Imgv
3733
3734 when Attribute_Image =>
3735
3736 -- Leave attribute unexpanded in CodePeer mode: the gnat2scil
3737 -- back-end knows how to handle this attribute directly.
3738
3739 if CodePeer_Mode then
3740 return;
3741 end if;
3742
3743 Expand_Image_Attribute (N);
3744
3745 ---------
3746 -- Img --
3747 ---------
3748
3749 -- X'Img is expanded to typ'Image (X), where typ is the type of X
3750
3751 when Attribute_Img =>
3752 Expand_Image_Attribute (N);
3753
3754 -----------
3755 -- Input --
3756 -----------
3757
3758 when Attribute_Input => Input : declare
3759 P_Type : constant Entity_Id := Entity (Pref);
3760 B_Type : constant Entity_Id := Base_Type (P_Type);
3761 U_Type : constant Entity_Id := Underlying_Type (P_Type);
3762 Strm : constant Node_Id := First (Exprs);
3763 Fname : Entity_Id;
3764 Decl : Node_Id;
3765 Call : Node_Id;
3766 Prag : Node_Id;
3767 Arg2 : Node_Id;
3768 Rfunc : Node_Id;
3769
3770 Cntrl : Node_Id := Empty;
3771 -- Value for controlling argument in call. Always Empty except in
3772 -- the dispatching (class-wide type) case, where it is a reference
3773 -- to the dummy object initialized to the right internal tag.
3774
3775 procedure Freeze_Stream_Subprogram (F : Entity_Id);
3776 -- The expansion of the attribute reference may generate a call to
3777 -- a user-defined stream subprogram that is frozen by the call. This
3778 -- can lead to access-before-elaboration problem if the reference
3779 -- appears in an object declaration and the subprogram body has not
3780 -- been seen. The freezing of the subprogram requires special code
3781 -- because it appears in an expanded context where expressions do
3782 -- not freeze their constituents.
3783
3784 ------------------------------
3785 -- Freeze_Stream_Subprogram --
3786 ------------------------------
3787
3788 procedure Freeze_Stream_Subprogram (F : Entity_Id) is
3789 Decl : constant Node_Id := Unit_Declaration_Node (F);
3790 Bod : Node_Id;
3791
3792 begin
3793 -- If this is user-defined subprogram, the corresponding
3794 -- stream function appears as a renaming-as-body, and the
3795 -- user subprogram must be retrieved by tree traversal.
3796
3797 if Present (Decl)
3798 and then Nkind (Decl) = N_Subprogram_Declaration
3799 and then Present (Corresponding_Body (Decl))
3800 then
3801 Bod := Corresponding_Body (Decl);
3802
3803 if Nkind (Unit_Declaration_Node (Bod)) =
3804 N_Subprogram_Renaming_Declaration
3805 then
3806 Set_Is_Frozen (Entity (Name (Unit_Declaration_Node (Bod))));
3807 end if;
3808 end if;
3809 end Freeze_Stream_Subprogram;
3810
3811 -- Start of processing for Input
3812
3813 begin
3814 -- If no underlying type, we have an error that will be diagnosed
3815 -- elsewhere, so here we just completely ignore the expansion.
3816
3817 if No (U_Type) then
3818 return;
3819 end if;
3820
3821 -- Stream operations can appear in user code even if the restriction
3822 -- No_Streams is active (for example, when instantiating a predefined
3823 -- container). In that case rewrite the attribute as a Raise to
3824 -- prevent any run-time use.
3825
3826 if Restriction_Active (No_Streams) then
3827 Rewrite (N,
3828 Make_Raise_Program_Error (Sloc (N),
3829 Reason => PE_Stream_Operation_Not_Allowed));
3830 Set_Etype (N, B_Type);
3831 return;
3832 end if;
3833
3834 -- If there is a TSS for Input, just call it
3835
3836 Fname := Find_Stream_Subprogram (P_Type, TSS_Stream_Input);
3837
3838 if Present (Fname) then
3839 null;
3840
3841 else
3842 -- If there is a Stream_Convert pragma, use it, we rewrite
3843
3844 -- sourcetyp'Input (stream)
3845
3846 -- as
3847
3848 -- sourcetyp (streamread (strmtyp'Input (stream)));
3849
3850 -- where streamread is the given Read function that converts an
3851 -- argument of type strmtyp to type sourcetyp or a type from which
3852 -- it is derived (extra conversion required for the derived case).
3853
3854 Prag := Get_Stream_Convert_Pragma (P_Type);
3855
3856 if Present (Prag) then
3857 Arg2 := Next (First (Pragma_Argument_Associations (Prag)));
3858 Rfunc := Entity (Expression (Arg2));
3859
3860 Rewrite (N,
3861 Convert_To (B_Type,
3862 Make_Function_Call (Loc,
3863 Name => New_Occurrence_Of (Rfunc, Loc),
3864 Parameter_Associations => New_List (
3865 Make_Attribute_Reference (Loc,
3866 Prefix =>
3867 New_Occurrence_Of
3868 (Etype (First_Formal (Rfunc)), Loc),
3869 Attribute_Name => Name_Input,
3870 Expressions => Exprs)))));
3871
3872 Analyze_And_Resolve (N, B_Type);
3873 return;
3874
3875 -- Elementary types
3876
3877 elsif Is_Elementary_Type (U_Type) then
3878
3879 -- A special case arises if we have a defined _Read routine,
3880 -- since in this case we are required to call this routine.
3881
3882 declare
3883 Typ : Entity_Id := P_Type;
3884 begin
3885 if Present (Full_View (Typ)) then
3886 Typ := Full_View (Typ);
3887 end if;
3888
3889 if Present (TSS (Base_Type (Typ), TSS_Stream_Read)) then
3890 Build_Record_Or_Elementary_Input_Function
3891 (Loc, Typ, Decl, Fname, Use_Underlying => False);
3892 Insert_Action (N, Decl);
3893
3894 -- For normal cases, we call the I_xxx routine directly
3895
3896 else
3897 Rewrite (N, Build_Elementary_Input_Call (N));
3898 Analyze_And_Resolve (N, P_Type);
3899 return;
3900 end if;
3901 end;
3902
3903 -- Array type case
3904
3905 elsif Is_Array_Type (U_Type) then
3906 Build_Array_Input_Function (Loc, U_Type, Decl, Fname);
3907 Compile_Stream_Body_In_Scope (N, Decl, U_Type, Check => False);
3908
3909 -- Dispatching case with class-wide type
3910
3911 elsif Is_Class_Wide_Type (P_Type) then
3912
3913 -- No need to do anything else compiling under restriction
3914 -- No_Dispatching_Calls. During the semantic analysis we
3915 -- already notified such violation.
3916
3917 if Restriction_Active (No_Dispatching_Calls) then
3918 return;
3919 end if;
3920
3921 declare
3922 Rtyp : constant Entity_Id := Root_Type (P_Type);
3923
3924 Expr : Node_Id; -- call to Descendant_Tag
3925 Get_Tag : Node_Id; -- expression to read the 'Tag
3926
3927 begin
3928 -- Read the internal tag (RM 13.13.2(34)) and use it to
3929 -- initialize a dummy tag value. We used to unconditionally
3930 -- generate:
3931 --
3932 -- Descendant_Tag (String'Input (Strm), P_Type);
3933 --
3934 -- which turns into a call to String_Input_Blk_IO. However,
3935 -- if the input is malformed, that could try to read an
3936 -- enormous String, causing chaos. So instead we call
3937 -- String_Input_Tag, which does the same thing as
3938 -- String_Input_Blk_IO, except that if the String is
3939 -- absurdly long, it raises an exception.
3940 --
3941 -- However, if the No_Stream_Optimizations restriction
3942 -- is active, we disable this unnecessary attempt at
3943 -- robustness; we really need to read the string
3944 -- character-by-character.
3945 --
3946 -- This value is used only to provide a controlling
3947 -- argument for the eventual _Input call. Descendant_Tag is
3948 -- called rather than Internal_Tag to ensure that we have a
3949 -- tag for a type that is descended from the prefix type and
3950 -- declared at the same accessibility level (the exception
3951 -- Tag_Error will be raised otherwise). The level check is
3952 -- required for Ada 2005 because tagged types can be
3953 -- extended in nested scopes (AI-344).
3954
3955 -- Note: we used to generate an explicit declaration of a
3956 -- constant Ada.Tags.Tag object, and use an occurrence of
3957 -- this constant in Cntrl, but this caused a secondary stack
3958 -- leak.
3959
3960 if Restriction_Active (No_Stream_Optimizations) then
3961 Get_Tag :=
3962 Make_Attribute_Reference (Loc,
3963 Prefix =>
3964 New_Occurrence_Of (Standard_String, Loc),
3965 Attribute_Name => Name_Input,
3966 Expressions => New_List (
3967 Relocate_Node (Duplicate_Subexpr (Strm))));
3968 else
3969 Get_Tag :=
3970 Make_Function_Call (Loc,
3971 Name =>
3972 New_Occurrence_Of
3973 (RTE (RE_String_Input_Tag), Loc),
3974 Parameter_Associations => New_List (
3975 Relocate_Node (Duplicate_Subexpr (Strm))));
3976 end if;
3977
3978 Expr :=
3979 Make_Function_Call (Loc,
3980 Name =>
3981 New_Occurrence_Of (RTE (RE_Descendant_Tag), Loc),
3982 Parameter_Associations => New_List (
3983 Get_Tag,
3984 Make_Attribute_Reference (Loc,
3985 Prefix => New_Occurrence_Of (P_Type, Loc),
3986 Attribute_Name => Name_Tag)));
3987
3988 Set_Etype (Expr, RTE (RE_Tag));
3989
3990 -- Now we need to get the entity for the call, and construct
3991 -- a function call node, where we preset a reference to Dnn
3992 -- as the controlling argument (doing an unchecked convert
3993 -- to the class-wide tagged type to make it look like a real
3994 -- tagged object).
3995
3996 Fname := Find_Prim_Op (Rtyp, TSS_Stream_Input);
3997 Cntrl := Unchecked_Convert_To (P_Type, Expr);
3998 Set_Etype (Cntrl, P_Type);
3999 Set_Parent (Cntrl, N);
4000 end;
4001
4002 -- For tagged types, use the primitive Input function
4003
4004 elsif Is_Tagged_Type (U_Type) then
4005 Fname := Find_Prim_Op (U_Type, TSS_Stream_Input);
4006
4007 -- All other record type cases, including protected records. The
4008 -- latter only arise for expander generated code for handling
4009 -- shared passive partition access.
4010
4011 else
4012 pragma Assert
4013 (Is_Record_Type (U_Type) or else Is_Protected_Type (U_Type));
4014
4015 -- Ada 2005 (AI-216): Program_Error is raised executing default
4016 -- implementation of the Input attribute of an unchecked union
4017 -- type if the type lacks default discriminant values.
4018
4019 if Is_Unchecked_Union (Base_Type (U_Type))
4020 and then No (Discriminant_Constraint (U_Type))
4021 then
4022 Insert_Action (N,
4023 Make_Raise_Program_Error (Loc,
4024 Reason => PE_Unchecked_Union_Restriction));
4025
4026 return;
4027 end if;
4028
4029 -- Build the type's Input function, passing the subtype rather
4030 -- than its base type, because checks are needed in the case of
4031 -- constrained discriminants (see Ada 2012 AI05-0192).
4032
4033 Build_Record_Or_Elementary_Input_Function
4034 (Loc, U_Type, Decl, Fname);
4035 Insert_Action (N, Decl);
4036
4037 if Nkind (Parent (N)) = N_Object_Declaration
4038 and then Is_Record_Type (U_Type)
4039 then
4040 -- The stream function may contain calls to user-defined
4041 -- Read procedures for individual components.
4042
4043 declare
4044 Comp : Entity_Id;
4045 Func : Entity_Id;
4046
4047 begin
4048 Comp := First_Component (U_Type);
4049 while Present (Comp) loop
4050 Func :=
4051 Find_Stream_Subprogram
4052 (Etype (Comp), TSS_Stream_Read);
4053
4054 if Present (Func) then
4055 Freeze_Stream_Subprogram (Func);
4056 end if;
4057
4058 Next_Component (Comp);
4059 end loop;
4060 end;
4061 end if;
4062 end if;
4063 end if;
4064
4065 -- If we fall through, Fname is the function to be called. The result
4066 -- is obtained by calling the appropriate function, then converting
4067 -- the result. The conversion does a subtype check.
4068
4069 Call :=
4070 Make_Function_Call (Loc,
4071 Name => New_Occurrence_Of (Fname, Loc),
4072 Parameter_Associations => New_List (
4073 Relocate_Node (Strm)));
4074
4075 Set_Controlling_Argument (Call, Cntrl);
4076 Rewrite (N, Unchecked_Convert_To (P_Type, Call));
4077 Analyze_And_Resolve (N, P_Type);
4078
4079 if Nkind (Parent (N)) = N_Object_Declaration then
4080 Freeze_Stream_Subprogram (Fname);
4081 end if;
4082 end Input;
4083
4084 -------------------
4085 -- Invalid_Value --
4086 -------------------
4087
4088 when Attribute_Invalid_Value =>
4089 Rewrite (N, Get_Simple_Init_Val (Ptyp, N));
4090
4091 -- The value produced may be a conversion of a literal, which must be
4092 -- resolved to establish its proper type.
4093
4094 Analyze_And_Resolve (N);
4095
4096 ----------
4097 -- Last --
4098 ----------
4099
4100 when Attribute_Last =>
4101
4102 -- If the prefix type is a constrained packed array type which
4103 -- already has a Packed_Array_Impl_Type representation defined, then
4104 -- replace this attribute with a direct reference to 'Last of the
4105 -- appropriate index subtype (since otherwise the back end will try
4106 -- to give us the value of 'Last for this implementation type).
4107
4108 if Is_Constrained_Packed_Array (Ptyp) then
4109 Rewrite (N,
4110 Make_Attribute_Reference (Loc,
4111 Attribute_Name => Name_Last,
4112 Prefix => New_Occurrence_Of (Get_Index_Subtype (N), Loc)));
4113 Analyze_And_Resolve (N, Typ);
4114
4115 -- For access type, apply access check as needed
4116
4117 elsif Is_Access_Type (Ptyp) then
4118 Apply_Access_Check (N);
4119
4120 -- For scalar type, if low bound is a reference to an entity, just
4121 -- replace with a direct reference. Note that we can only have a
4122 -- reference to a constant entity at this stage, anything else would
4123 -- have already been rewritten.
4124
4125 elsif Is_Scalar_Type (Ptyp) then
4126 declare
4127 Hi : constant Node_Id := Type_High_Bound (Ptyp);
4128 begin
4129 if Is_Entity_Name (Hi) then
4130 Rewrite (N, New_Occurrence_Of (Entity (Hi), Loc));
4131 end if;
4132 end;
4133 end if;
4134
4135 --------------
4136 -- Last_Bit --
4137 --------------
4138
4139 -- We compute this if a component clause was present, otherwise we leave
4140 -- the computation up to the back end, since we don't know what layout
4141 -- will be chosen.
4142
4143 when Attribute_Last_Bit => Last_Bit_Attr : declare
4144 CE : constant Entity_Id := Entity (Selector_Name (Pref));
4145
4146 begin
4147 -- In Ada 2005 (or later) if we have the non-default bit order, then
4148 -- we return the original value as given in the component clause
4149 -- (RM 2005 13.5.2(3/2)).
4150
4151 if Present (Component_Clause (CE))
4152 and then Ada_Version >= Ada_2005
4153 and then Reverse_Bit_Order (Scope (CE))
4154 then
4155 Rewrite (N,
4156 Make_Integer_Literal (Loc,
4157 Intval => Expr_Value (Last_Bit (Component_Clause (CE)))));
4158 Analyze_And_Resolve (N, Typ);
4159
4160 -- Otherwise (Ada 83/95 or Ada 2005 or later with default bit order),
4161 -- rewrite with normalized value if we know it statically.
4162
4163 elsif Known_Static_Component_Bit_Offset (CE)
4164 and then Known_Static_Esize (CE)
4165 then
4166 Rewrite (N,
4167 Make_Integer_Literal (Loc,
4168 Intval => (Component_Bit_Offset (CE) mod System_Storage_Unit)
4169 + Esize (CE) - 1));
4170 Analyze_And_Resolve (N, Typ);
4171
4172 -- Otherwise leave to back end, just apply universal integer checks
4173
4174 else
4175 Apply_Universal_Integer_Attribute_Checks (N);
4176 end if;
4177 end Last_Bit_Attr;
4178
4179 ------------------
4180 -- Leading_Part --
4181 ------------------
4182
4183 -- Transforms 'Leading_Part into a call to the floating-point attribute
4184 -- function Leading_Part in Fat_xxx (where xxx is the root type)
4185
4186 -- Note: strictly, we should generate special case code to deal with
4187 -- absurdly large positive arguments (greater than Integer'Last), which
4188 -- result in returning the first argument unchanged, but it hardly seems
4189 -- worth the effort. We raise constraint error for absurdly negative
4190 -- arguments which is fine.
4191
4192 when Attribute_Leading_Part =>
4193 Expand_Fpt_Attribute_RI (N);
4194
4195 ------------
4196 -- Length --
4197 ------------
4198
4199 when Attribute_Length => Length : declare
4200 Ityp : Entity_Id;
4201 Xnum : Uint;
4202
4203 begin
4204 -- Processing for packed array types
4205
4206 if Is_Array_Type (Ptyp) and then Is_Packed (Ptyp) then
4207 Ityp := Get_Index_Subtype (N);
4208
4209 -- If the index type, Ityp, is an enumeration type with holes,
4210 -- then we calculate X'Length explicitly using
4211
4212 -- Typ'Max
4213 -- (0, Ityp'Pos (X'Last (N)) -
4214 -- Ityp'Pos (X'First (N)) + 1);
4215
4216 -- Since the bounds in the template are the representation values
4217 -- and the back end would get the wrong value.
4218
4219 if Is_Enumeration_Type (Ityp)
4220 and then Present (Enum_Pos_To_Rep (Base_Type (Ityp)))
4221 then
4222 if No (Exprs) then
4223 Xnum := Uint_1;
4224 else
4225 Xnum := Expr_Value (First (Expressions (N)));
4226 end if;
4227
4228 Rewrite (N,
4229 Make_Attribute_Reference (Loc,
4230 Prefix => New_Occurrence_Of (Typ, Loc),
4231 Attribute_Name => Name_Max,
4232 Expressions => New_List
4233 (Make_Integer_Literal (Loc, 0),
4234
4235 Make_Op_Add (Loc,
4236 Left_Opnd =>
4237 Make_Op_Subtract (Loc,
4238 Left_Opnd =>
4239 Make_Attribute_Reference (Loc,
4240 Prefix => New_Occurrence_Of (Ityp, Loc),
4241 Attribute_Name => Name_Pos,
4242
4243 Expressions => New_List (
4244 Make_Attribute_Reference (Loc,
4245 Prefix => Duplicate_Subexpr (Pref),
4246 Attribute_Name => Name_Last,
4247 Expressions => New_List (
4248 Make_Integer_Literal (Loc, Xnum))))),
4249
4250 Right_Opnd =>
4251 Make_Attribute_Reference (Loc,
4252 Prefix => New_Occurrence_Of (Ityp, Loc),
4253 Attribute_Name => Name_Pos,
4254
4255 Expressions => New_List (
4256 Make_Attribute_Reference (Loc,
4257 Prefix =>
4258 Duplicate_Subexpr_No_Checks (Pref),
4259 Attribute_Name => Name_First,
4260 Expressions => New_List (
4261 Make_Integer_Literal (Loc, Xnum)))))),
4262
4263 Right_Opnd => Make_Integer_Literal (Loc, 1)))));
4264
4265 Analyze_And_Resolve (N, Typ, Suppress => All_Checks);
4266 return;
4267
4268 -- If the prefix type is a constrained packed array type which
4269 -- already has a Packed_Array_Impl_Type representation defined,
4270 -- then replace this attribute with a reference to 'Range_Length
4271 -- of the appropriate index subtype (since otherwise the
4272 -- back end will try to give us the value of 'Length for
4273 -- this implementation type).s
4274
4275 elsif Is_Constrained (Ptyp) then
4276 Rewrite (N,
4277 Make_Attribute_Reference (Loc,
4278 Attribute_Name => Name_Range_Length,
4279 Prefix => New_Occurrence_Of (Ityp, Loc)));
4280 Analyze_And_Resolve (N, Typ);
4281 end if;
4282
4283 -- Access type case
4284
4285 elsif Is_Access_Type (Ptyp) then
4286 Apply_Access_Check (N);
4287
4288 -- If the designated type is a packed array type, then we convert
4289 -- the reference to:
4290
4291 -- typ'Max (0, 1 +
4292 -- xtyp'Pos (Pref'Last (Expr)) -
4293 -- xtyp'Pos (Pref'First (Expr)));
4294
4295 -- This is a bit complex, but it is the easiest thing to do that
4296 -- works in all cases including enum types with holes xtyp here
4297 -- is the appropriate index type.
4298
4299 declare
4300 Dtyp : constant Entity_Id := Designated_Type (Ptyp);
4301 Xtyp : Entity_Id;
4302
4303 begin
4304 if Is_Array_Type (Dtyp) and then Is_Packed (Dtyp) then
4305 Xtyp := Get_Index_Subtype (N);
4306
4307 Rewrite (N,
4308 Make_Attribute_Reference (Loc,
4309 Prefix => New_Occurrence_Of (Typ, Loc),
4310 Attribute_Name => Name_Max,
4311 Expressions => New_List (
4312 Make_Integer_Literal (Loc, 0),
4313
4314 Make_Op_Add (Loc,
4315 Make_Integer_Literal (Loc, 1),
4316 Make_Op_Subtract (Loc,
4317 Left_Opnd =>
4318 Make_Attribute_Reference (Loc,
4319 Prefix => New_Occurrence_Of (Xtyp, Loc),
4320 Attribute_Name => Name_Pos,
4321 Expressions => New_List (
4322 Make_Attribute_Reference (Loc,
4323 Prefix => Duplicate_Subexpr (Pref),
4324 Attribute_Name => Name_Last,
4325 Expressions =>
4326 New_Copy_List (Exprs)))),
4327
4328 Right_Opnd =>
4329 Make_Attribute_Reference (Loc,
4330 Prefix => New_Occurrence_Of (Xtyp, Loc),
4331 Attribute_Name => Name_Pos,
4332 Expressions => New_List (
4333 Make_Attribute_Reference (Loc,
4334 Prefix =>
4335 Duplicate_Subexpr_No_Checks (Pref),
4336 Attribute_Name => Name_First,
4337 Expressions =>
4338 New_Copy_List (Exprs)))))))));
4339
4340 Analyze_And_Resolve (N, Typ);
4341 end if;
4342 end;
4343
4344 -- Otherwise leave it to the back end
4345
4346 else
4347 Apply_Universal_Integer_Attribute_Checks (N);
4348 end if;
4349 end Length;
4350
4351 -- Attribute Loop_Entry is replaced with a reference to a constant value
4352 -- which captures the prefix at the entry point of the related loop. The
4353 -- loop itself may be transformed into a conditional block.
4354
4355 when Attribute_Loop_Entry =>
4356 Expand_Loop_Entry_Attribute (N);
4357
4358 -------------
4359 -- Machine --
4360 -------------
4361
4362 -- Transforms 'Machine into a call to the floating-point attribute
4363 -- function Machine in Fat_xxx (where xxx is the root type).
4364 -- Expansion is avoided for cases the back end can handle directly.
4365
4366 when Attribute_Machine =>
4367 if not Is_Inline_Floating_Point_Attribute (N) then
4368 Expand_Fpt_Attribute_R (N);
4369 end if;
4370
4371 ----------------------
4372 -- Machine_Rounding --
4373 ----------------------
4374
4375 -- Transforms 'Machine_Rounding into a call to the floating-point
4376 -- attribute function Machine_Rounding in Fat_xxx (where xxx is the root
4377 -- type). Expansion is avoided for cases the back end can handle
4378 -- directly.
4379
4380 when Attribute_Machine_Rounding =>
4381 if not Is_Inline_Floating_Point_Attribute (N) then
4382 Expand_Fpt_Attribute_R (N);
4383 end if;
4384
4385 ------------------
4386 -- Machine_Size --
4387 ------------------
4388
4389 -- Machine_Size is equivalent to Object_Size, so transform it into
4390 -- Object_Size and that way the back end never sees Machine_Size.
4391
4392 when Attribute_Machine_Size =>
4393 Rewrite (N,
4394 Make_Attribute_Reference (Loc,
4395 Prefix => Prefix (N),
4396 Attribute_Name => Name_Object_Size));
4397
4398 Analyze_And_Resolve (N, Typ);
4399
4400 --------------
4401 -- Mantissa --
4402 --------------
4403
4404 -- The only case that can get this far is the dynamic case of the old
4405 -- Ada 83 Mantissa attribute for the fixed-point case. For this case,
4406 -- we expand:
4407
4408 -- typ'Mantissa
4409
4410 -- into
4411
4412 -- ityp (System.Mantissa.Mantissa_Value
4413 -- (Integer'Integer_Value (typ'First),
4414 -- Integer'Integer_Value (typ'Last)));
4415
4416 when Attribute_Mantissa =>
4417 Rewrite (N,
4418 Convert_To (Typ,
4419 Make_Function_Call (Loc,
4420 Name =>
4421 New_Occurrence_Of (RTE (RE_Mantissa_Value), Loc),
4422
4423 Parameter_Associations => New_List (
4424 Make_Attribute_Reference (Loc,
4425 Prefix => New_Occurrence_Of (Standard_Integer, Loc),
4426 Attribute_Name => Name_Integer_Value,
4427 Expressions => New_List (
4428 Make_Attribute_Reference (Loc,
4429 Prefix => New_Occurrence_Of (Ptyp, Loc),
4430 Attribute_Name => Name_First))),
4431
4432 Make_Attribute_Reference (Loc,
4433 Prefix => New_Occurrence_Of (Standard_Integer, Loc),
4434 Attribute_Name => Name_Integer_Value,
4435 Expressions => New_List (
4436 Make_Attribute_Reference (Loc,
4437 Prefix => New_Occurrence_Of (Ptyp, Loc),
4438 Attribute_Name => Name_Last)))))));
4439
4440 Analyze_And_Resolve (N, Typ);
4441
4442 ---------
4443 -- Max --
4444 ---------
4445
4446 when Attribute_Max =>
4447 Expand_Min_Max_Attribute (N);
4448
4449 ----------------------------------
4450 -- Max_Size_In_Storage_Elements --
4451 ----------------------------------
4452
4453 when Attribute_Max_Size_In_Storage_Elements => declare
4454 Typ : constant Entity_Id := Etype (N);
4455 Attr : Node_Id;
4456 Atyp : Entity_Id;
4457
4458 Conversion_Added : Boolean := False;
4459 -- A flag which tracks whether the original attribute has been
4460 -- wrapped inside a type conversion.
4461
4462 begin
4463 -- If the prefix is X'Class, we transform it into a direct reference
4464 -- to the class-wide type, because the back end must not see a 'Class
4465 -- reference. See also 'Size.
4466
4467 if Is_Entity_Name (Pref)
4468 and then Is_Class_Wide_Type (Entity (Pref))
4469 then
4470 Rewrite (Prefix (N), New_Occurrence_Of (Entity (Pref), Loc));
4471 return;
4472 end if;
4473
4474 Apply_Universal_Integer_Attribute_Checks (N);
4475
4476 -- The universal integer check may sometimes add a type conversion,
4477 -- retrieve the original attribute reference from the expression.
4478
4479 Attr := N;
4480
4481 if Nkind (Attr) = N_Type_Conversion then
4482 Attr := Expression (Attr);
4483 Conversion_Added := True;
4484 end if;
4485
4486 pragma Assert (Nkind (Attr) = N_Attribute_Reference);
4487
4488 -- Heap-allocated controlled objects contain two extra pointers which
4489 -- are not part of the actual type. Transform the attribute reference
4490 -- into a runtime expression to add the size of the hidden header.
4491
4492 if Needs_Finalization (Ptyp)
4493 and then not Header_Size_Added (Attr)
4494 then
4495 Set_Header_Size_Added (Attr);
4496
4497 Atyp := Etype (Attr);
4498
4499 -- Generate:
4500 -- P'Max_Size_In_Storage_Elements +
4501 -- Atyp (Header_Size_With_Padding (Ptyp'Alignment))
4502
4503 Rewrite (Attr,
4504 Make_Op_Add (Loc,
4505 Left_Opnd => Relocate_Node (Attr),
4506 Right_Opnd =>
4507 Convert_To (Atyp,
4508 Make_Function_Call (Loc,
4509 Name =>
4510 New_Occurrence_Of
4511 (RTE (RE_Header_Size_With_Padding), Loc),
4512
4513 Parameter_Associations => New_List (
4514 Make_Attribute_Reference (Loc,
4515 Prefix =>
4516 New_Occurrence_Of (Ptyp, Loc),
4517 Attribute_Name => Name_Alignment))))));
4518
4519 Analyze_And_Resolve (Attr, Atyp);
4520
4521 -- Add a conversion to the target type
4522
4523 if not Conversion_Added then
4524 Convert_To_And_Rewrite (Typ, Attr);
4525 end if;
4526
4527 return;
4528 end if;
4529 end;
4530
4531 --------------------
4532 -- Mechanism_Code --
4533 --------------------
4534
4535 when Attribute_Mechanism_Code =>
4536
4537 -- We must replace the prefix in the renamed case
4538
4539 if Is_Entity_Name (Pref)
4540 and then Present (Alias (Entity (Pref)))
4541 then
4542 Set_Renamed_Subprogram (Pref, Alias (Entity (Pref)));
4543 end if;
4544
4545 ---------
4546 -- Min --
4547 ---------
4548
4549 when Attribute_Min =>
4550 Expand_Min_Max_Attribute (N);
4551
4552 ---------
4553 -- Mod --
4554 ---------
4555
4556 when Attribute_Mod => Mod_Case : declare
4557 Arg : constant Node_Id := Relocate_Node (First (Exprs));
4558 Hi : constant Node_Id := Type_High_Bound (Etype (Arg));
4559 Modv : constant Uint := Modulus (Btyp);
4560
4561 begin
4562
4563 -- This is not so simple. The issue is what type to use for the
4564 -- computation of the modular value.
4565
4566 -- The easy case is when the modulus value is within the bounds
4567 -- of the signed integer type of the argument. In this case we can
4568 -- just do the computation in that signed integer type, and then
4569 -- do an ordinary conversion to the target type.
4570
4571 if Modv <= Expr_Value (Hi) then
4572 Rewrite (N,
4573 Convert_To (Btyp,
4574 Make_Op_Mod (Loc,
4575 Left_Opnd => Arg,
4576 Right_Opnd => Make_Integer_Literal (Loc, Modv))));
4577
4578 -- Here we know that the modulus is larger than type'Last of the
4579 -- integer type. There are two cases to consider:
4580
4581 -- a) The integer value is non-negative. In this case, it is
4582 -- returned as the result (since it is less than the modulus).
4583
4584 -- b) The integer value is negative. In this case, we know that the
4585 -- result is modulus + value, where the value might be as small as
4586 -- -modulus. The trouble is what type do we use to do the subtract.
4587 -- No type will do, since modulus can be as big as 2**64, and no
4588 -- integer type accommodates this value. Let's do bit of algebra
4589
4590 -- modulus + value
4591 -- = modulus - (-value)
4592 -- = (modulus - 1) - (-value - 1)
4593
4594 -- Now modulus - 1 is certainly in range of the modular type.
4595 -- -value is in the range 1 .. modulus, so -value -1 is in the
4596 -- range 0 .. modulus-1 which is in range of the modular type.
4597 -- Furthermore, (-value - 1) can be expressed as -(value + 1)
4598 -- which we can compute using the integer base type.
4599
4600 -- Once this is done we analyze the if expression without range
4601 -- checks, because we know everything is in range, and we want
4602 -- to prevent spurious warnings on either branch.
4603
4604 else
4605 Rewrite (N,
4606 Make_If_Expression (Loc,
4607 Expressions => New_List (
4608 Make_Op_Ge (Loc,
4609 Left_Opnd => Duplicate_Subexpr (Arg),
4610 Right_Opnd => Make_Integer_Literal (Loc, 0)),
4611
4612 Convert_To (Btyp,
4613 Duplicate_Subexpr_No_Checks (Arg)),
4614
4615 Make_Op_Subtract (Loc,
4616 Left_Opnd =>
4617 Make_Integer_Literal (Loc,
4618 Intval => Modv - 1),
4619 Right_Opnd =>
4620 Convert_To (Btyp,
4621 Make_Op_Minus (Loc,
4622 Right_Opnd =>
4623 Make_Op_Add (Loc,
4624 Left_Opnd => Duplicate_Subexpr_No_Checks (Arg),
4625 Right_Opnd =>
4626 Make_Integer_Literal (Loc,
4627 Intval => 1))))))));
4628
4629 end if;
4630
4631 Analyze_And_Resolve (N, Btyp, Suppress => All_Checks);
4632 end Mod_Case;
4633
4634 -----------
4635 -- Model --
4636 -----------
4637
4638 -- Transforms 'Model into a call to the floating-point attribute
4639 -- function Model in Fat_xxx (where xxx is the root type).
4640 -- Expansion is avoided for cases the back end can handle directly.
4641
4642 when Attribute_Model =>
4643 if not Is_Inline_Floating_Point_Attribute (N) then
4644 Expand_Fpt_Attribute_R (N);
4645 end if;
4646
4647 -----------------
4648 -- Object_Size --
4649 -----------------
4650
4651 -- The processing for Object_Size shares the processing for Size
4652
4653 ---------
4654 -- Old --
4655 ---------
4656
4657 when Attribute_Old => Old : declare
4658 Typ : constant Entity_Id := Etype (N);
4659 CW_Temp : Entity_Id;
4660 CW_Typ : Entity_Id;
4661 Ins_Nod : Node_Id;
4662 Subp : Node_Id;
4663 Temp : Entity_Id;
4664
4665 begin
4666 -- Generating C code we don't need to expand this attribute when
4667 -- we are analyzing the internally built nested postconditions
4668 -- procedure since it will be expanded inline (and later it will
4669 -- be removed by Expand_N_Subprogram_Body). It this expansion is
4670 -- performed in such case then the compiler generates unreferenced
4671 -- extra temporaries.
4672
4673 if Modify_Tree_For_C
4674 and then Chars (Current_Scope) = Name_uPostconditions
4675 then
4676 return;
4677 end if;
4678
4679 -- Climb the parent chain looking for subprogram _Postconditions
4680
4681 Subp := N;
4682 while Present (Subp) loop
4683 exit when Nkind (Subp) = N_Subprogram_Body
4684 and then Chars (Defining_Entity (Subp)) = Name_uPostconditions;
4685
4686 -- If assertions are disabled, no need to create the declaration
4687 -- that preserves the value. The postcondition pragma in which
4688 -- 'Old appears will be checked or disabled according to the
4689 -- current policy in effect.
4690
4691 if Nkind (Subp) = N_Pragma and then not Is_Checked (Subp) then
4692 return;
4693 end if;
4694
4695 Subp := Parent (Subp);
4696 end loop;
4697
4698 -- 'Old can only appear in a postcondition, the generated body of
4699 -- _Postconditions must be in the tree (or inlined if we are
4700 -- generating C code).
4701
4702 pragma Assert
4703 (Present (Subp)
4704 or else (Modify_Tree_For_C and then In_Inlined_Body));
4705
4706 Temp := Make_Temporary (Loc, 'T', Pref);
4707
4708 -- Set the entity kind now in order to mark the temporary as a
4709 -- handler of attribute 'Old's prefix.
4710
4711 Set_Ekind (Temp, E_Constant);
4712 Set_Stores_Attribute_Old_Prefix (Temp);
4713
4714 -- Push the scope of the related subprogram where _Postcondition
4715 -- resides as this ensures that the object will be analyzed in the
4716 -- proper context.
4717
4718 if Present (Subp) then
4719 Push_Scope (Scope (Defining_Entity (Subp)));
4720
4721 -- No need to push the scope when generating C code since the
4722 -- _Postcondition procedure has been inlined.
4723
4724 else pragma Assert (Modify_Tree_For_C);
4725 pragma Assert (In_Inlined_Body);
4726 null;
4727 end if;
4728
4729 -- Locate the insertion place of the internal temporary that saves
4730 -- the 'Old value.
4731
4732 if Present (Subp) then
4733 Ins_Nod := Subp;
4734
4735 -- Generating C, the postcondition procedure has been inlined and the
4736 -- temporary is added before the first declaration of the enclosing
4737 -- subprogram.
4738
4739 else pragma Assert (Modify_Tree_For_C);
4740 Ins_Nod := N;
4741 while Nkind (Ins_Nod) /= N_Subprogram_Body loop
4742 Ins_Nod := Parent (Ins_Nod);
4743 end loop;
4744
4745 Ins_Nod := First (Declarations (Ins_Nod));
4746 end if;
4747
4748 -- Preserve the tag of the prefix by offering a specific view of the
4749 -- class-wide version of the prefix.
4750
4751 if Is_Tagged_Type (Typ) then
4752
4753 -- Generate:
4754 -- CW_Temp : constant Typ'Class := Typ'Class (Pref);
4755
4756 CW_Temp := Make_Temporary (Loc, 'T');
4757 CW_Typ := Class_Wide_Type (Typ);
4758
4759 Insert_Before_And_Analyze (Ins_Nod,
4760 Make_Object_Declaration (Loc,
4761 Defining_Identifier => CW_Temp,
4762 Constant_Present => True,
4763 Object_Definition => New_Occurrence_Of (CW_Typ, Loc),
4764 Expression =>
4765 Convert_To (CW_Typ, Relocate_Node (Pref))));
4766
4767 -- Generate:
4768 -- Temp : Typ renames Typ (CW_Temp);
4769
4770 Insert_Before_And_Analyze (Ins_Nod,
4771 Make_Object_Renaming_Declaration (Loc,
4772 Defining_Identifier => Temp,
4773 Subtype_Mark => New_Occurrence_Of (Typ, Loc),
4774 Name =>
4775 Convert_To (Typ, New_Occurrence_Of (CW_Temp, Loc))));
4776
4777 -- Non-tagged case
4778
4779 else
4780 -- Generate:
4781 -- Temp : constant Typ := Pref;
4782
4783 Insert_Before_And_Analyze (Ins_Nod,
4784 Make_Object_Declaration (Loc,
4785 Defining_Identifier => Temp,
4786 Constant_Present => True,
4787 Object_Definition => New_Occurrence_Of (Typ, Loc),
4788 Expression => Relocate_Node (Pref)));
4789 end if;
4790
4791 if Present (Subp) then
4792 Pop_Scope;
4793 end if;
4794
4795 -- Ensure that the prefix of attribute 'Old is valid. The check must
4796 -- be inserted after the expansion of the attribute has taken place
4797 -- to reflect the new placement of the prefix.
4798
4799 if Validity_Checks_On and then Validity_Check_Operands then
4800 Ensure_Valid (Pref);
4801 end if;
4802
4803 Rewrite (N, New_Occurrence_Of (Temp, Loc));
4804 end Old;
4805
4806 ----------------------
4807 -- Overlaps_Storage --
4808 ----------------------
4809
4810 when Attribute_Overlaps_Storage => Overlaps_Storage : declare
4811 Loc : constant Source_Ptr := Sloc (N);
4812
4813 X : constant Node_Id := Prefix (N);
4814 Y : constant Node_Id := First (Expressions (N));
4815 -- The arguments
4816
4817 X_Addr, Y_Addr : Node_Id;
4818 -- the expressions for their integer addresses
4819
4820 X_Size, Y_Size : Node_Id;
4821 -- the expressions for their sizes
4822
4823 Cond : Node_Id;
4824
4825 begin
4826 -- Attribute expands into:
4827
4828 -- if X'Address < Y'address then
4829 -- (X'address + X'Size - 1) >= Y'address
4830 -- else
4831 -- (Y'address + Y'size - 1) >= X'Address
4832 -- end if;
4833
4834 -- with the proper address operations. We convert addresses to
4835 -- integer addresses to use predefined arithmetic. The size is
4836 -- expressed in storage units. We add copies of X_Addr and Y_Addr
4837 -- to prevent the appearance of the same node in two places in
4838 -- the tree.
4839
4840 X_Addr :=
4841 Unchecked_Convert_To (RTE (RE_Integer_Address),
4842 Make_Attribute_Reference (Loc,
4843 Attribute_Name => Name_Address,
4844 Prefix => New_Copy_Tree (X)));
4845
4846 Y_Addr :=
4847 Unchecked_Convert_To (RTE (RE_Integer_Address),
4848 Make_Attribute_Reference (Loc,
4849 Attribute_Name => Name_Address,
4850 Prefix => New_Copy_Tree (Y)));
4851
4852 X_Size :=
4853 Make_Op_Divide (Loc,
4854 Left_Opnd =>
4855 Make_Attribute_Reference (Loc,
4856 Attribute_Name => Name_Size,
4857 Prefix => New_Copy_Tree (X)),
4858 Right_Opnd =>
4859 Make_Integer_Literal (Loc, System_Storage_Unit));
4860
4861 Y_Size :=
4862 Make_Op_Divide (Loc,
4863 Left_Opnd =>
4864 Make_Attribute_Reference (Loc,
4865 Attribute_Name => Name_Size,
4866 Prefix => New_Copy_Tree (Y)),
4867 Right_Opnd =>
4868 Make_Integer_Literal (Loc, System_Storage_Unit));
4869
4870 Cond :=
4871 Make_Op_Le (Loc,
4872 Left_Opnd => X_Addr,
4873 Right_Opnd => Y_Addr);
4874
4875 Rewrite (N,
4876 Make_If_Expression (Loc, New_List (
4877 Cond,
4878
4879 Make_Op_Ge (Loc,
4880 Left_Opnd =>
4881 Make_Op_Add (Loc,
4882 Left_Opnd => New_Copy_Tree (X_Addr),
4883 Right_Opnd =>
4884 Make_Op_Subtract (Loc,
4885 Left_Opnd => X_Size,
4886 Right_Opnd => Make_Integer_Literal (Loc, 1))),
4887 Right_Opnd => Y_Addr),
4888
4889 Make_Op_Ge (Loc,
4890 Left_Opnd =>
4891 Make_Op_Add (Loc,
4892 Left_Opnd => New_Copy_Tree (Y_Addr),
4893 Right_Opnd =>
4894 Make_Op_Subtract (Loc,
4895 Left_Opnd => Y_Size,
4896 Right_Opnd => Make_Integer_Literal (Loc, 1))),
4897 Right_Opnd => X_Addr))));
4898
4899 Analyze_And_Resolve (N, Standard_Boolean);
4900 end Overlaps_Storage;
4901
4902 ------------
4903 -- Output --
4904 ------------
4905
4906 when Attribute_Output => Output : declare
4907 P_Type : constant Entity_Id := Entity (Pref);
4908 U_Type : constant Entity_Id := Underlying_Type (P_Type);
4909 Pname : Entity_Id;
4910 Decl : Node_Id;
4911 Prag : Node_Id;
4912 Arg3 : Node_Id;
4913 Wfunc : Node_Id;
4914
4915 begin
4916 -- If no underlying type, we have an error that will be diagnosed
4917 -- elsewhere, so here we just completely ignore the expansion.
4918
4919 if No (U_Type) then
4920 return;
4921 end if;
4922
4923 -- Stream operations can appear in user code even if the restriction
4924 -- No_Streams is active (for example, when instantiating a predefined
4925 -- container). In that case rewrite the attribute as a Raise to
4926 -- prevent any run-time use.
4927
4928 if Restriction_Active (No_Streams) then
4929 Rewrite (N,
4930 Make_Raise_Program_Error (Sloc (N),
4931 Reason => PE_Stream_Operation_Not_Allowed));
4932 Set_Etype (N, Standard_Void_Type);
4933 return;
4934 end if;
4935
4936 -- If TSS for Output is present, just call it
4937
4938 Pname := Find_Stream_Subprogram (P_Type, TSS_Stream_Output);
4939
4940 if Present (Pname) then
4941 null;
4942
4943 else
4944 -- If there is a Stream_Convert pragma, use it, we rewrite
4945
4946 -- sourcetyp'Output (stream, Item)
4947
4948 -- as
4949
4950 -- strmtyp'Output (Stream, strmwrite (acttyp (Item)));
4951
4952 -- where strmwrite is the given Write function that converts an
4953 -- argument of type sourcetyp or a type acctyp, from which it is
4954 -- derived to type strmtyp. The conversion to acttyp is required
4955 -- for the derived case.
4956
4957 Prag := Get_Stream_Convert_Pragma (P_Type);
4958
4959 if Present (Prag) then
4960 Arg3 :=
4961 Next (Next (First (Pragma_Argument_Associations (Prag))));
4962 Wfunc := Entity (Expression (Arg3));
4963
4964 Rewrite (N,
4965 Make_Attribute_Reference (Loc,
4966 Prefix => New_Occurrence_Of (Etype (Wfunc), Loc),
4967 Attribute_Name => Name_Output,
4968 Expressions => New_List (
4969 Relocate_Node (First (Exprs)),
4970 Make_Function_Call (Loc,
4971 Name => New_Occurrence_Of (Wfunc, Loc),
4972 Parameter_Associations => New_List (
4973 OK_Convert_To (Etype (First_Formal (Wfunc)),
4974 Relocate_Node (Next (First (Exprs)))))))));
4975
4976 Analyze (N);
4977 return;
4978
4979 -- For elementary types, we call the W_xxx routine directly. Note
4980 -- that the effect of Write and Output is identical for the case
4981 -- of an elementary type (there are no discriminants or bounds).
4982
4983 elsif Is_Elementary_Type (U_Type) then
4984
4985 -- A special case arises if we have a defined _Write routine,
4986 -- since in this case we are required to call this routine.
4987
4988 declare
4989 Typ : Entity_Id := P_Type;
4990 begin
4991 if Present (Full_View (Typ)) then
4992 Typ := Full_View (Typ);
4993 end if;
4994
4995 if Present (TSS (Base_Type (Typ), TSS_Stream_Write)) then
4996 Build_Record_Or_Elementary_Output_Procedure
4997 (Loc, Typ, Decl, Pname);
4998 Insert_Action (N, Decl);
4999
5000 -- For normal cases, we call the W_xxx routine directly
5001
5002 else
5003 Rewrite (N, Build_Elementary_Write_Call (N));
5004 Analyze (N);
5005 return;
5006 end if;
5007 end;
5008
5009 -- Array type case
5010
5011 elsif Is_Array_Type (U_Type) then
5012 Build_Array_Output_Procedure (Loc, U_Type, Decl, Pname);
5013 Compile_Stream_Body_In_Scope (N, Decl, U_Type, Check => False);
5014
5015 -- Class-wide case, first output external tag, then dispatch
5016 -- to the appropriate primitive Output function (RM 13.13.2(31)).
5017
5018 elsif Is_Class_Wide_Type (P_Type) then
5019
5020 -- No need to do anything else compiling under restriction
5021 -- No_Dispatching_Calls. During the semantic analysis we
5022 -- already notified such violation.
5023
5024 if Restriction_Active (No_Dispatching_Calls) then
5025 return;
5026 end if;
5027
5028 Tag_Write : declare
5029 Strm : constant Node_Id := First (Exprs);
5030 Item : constant Node_Id := Next (Strm);
5031
5032 begin
5033 -- Ada 2005 (AI-344): Check that the accessibility level
5034 -- of the type of the output object is not deeper than
5035 -- that of the attribute's prefix type.
5036
5037 -- if Get_Access_Level (Item'Tag)
5038 -- /= Get_Access_Level (P_Type'Tag)
5039 -- then
5040 -- raise Tag_Error;
5041 -- end if;
5042
5043 -- String'Output (Strm, External_Tag (Item'Tag));
5044
5045 -- We cannot figure out a practical way to implement this
5046 -- accessibility check on virtual machines, so we omit it.
5047
5048 if Ada_Version >= Ada_2005
5049 and then Tagged_Type_Expansion
5050 then
5051 Insert_Action (N,
5052 Make_Implicit_If_Statement (N,
5053 Condition =>
5054 Make_Op_Ne (Loc,
5055 Left_Opnd =>
5056 Build_Get_Access_Level (Loc,
5057 Make_Attribute_Reference (Loc,
5058 Prefix =>
5059 Relocate_Node (
5060 Duplicate_Subexpr (Item,
5061 Name_Req => True)),
5062 Attribute_Name => Name_Tag)),
5063
5064 Right_Opnd =>
5065 Make_Integer_Literal (Loc,
5066 Type_Access_Level (P_Type))),
5067
5068 Then_Statements =>
5069 New_List (Make_Raise_Statement (Loc,
5070 New_Occurrence_Of (
5071 RTE (RE_Tag_Error), Loc)))));
5072 end if;
5073
5074 Insert_Action (N,
5075 Make_Attribute_Reference (Loc,
5076 Prefix => New_Occurrence_Of (Standard_String, Loc),
5077 Attribute_Name => Name_Output,
5078 Expressions => New_List (
5079 Relocate_Node (Duplicate_Subexpr (Strm)),
5080 Make_Function_Call (Loc,
5081 Name =>
5082 New_Occurrence_Of (RTE (RE_External_Tag), Loc),
5083 Parameter_Associations => New_List (
5084 Make_Attribute_Reference (Loc,
5085 Prefix =>
5086 Relocate_Node
5087 (Duplicate_Subexpr (Item, Name_Req => True)),
5088 Attribute_Name => Name_Tag))))));
5089 end Tag_Write;
5090
5091 Pname := Find_Prim_Op (U_Type, TSS_Stream_Output);
5092
5093 -- Tagged type case, use the primitive Output function
5094
5095 elsif Is_Tagged_Type (U_Type) then
5096 Pname := Find_Prim_Op (U_Type, TSS_Stream_Output);
5097
5098 -- All other record type cases, including protected records.
5099 -- The latter only arise for expander generated code for
5100 -- handling shared passive partition access.
5101
5102 else
5103 pragma Assert
5104 (Is_Record_Type (U_Type) or else Is_Protected_Type (U_Type));
5105
5106 -- Ada 2005 (AI-216): Program_Error is raised when executing
5107 -- the default implementation of the Output attribute of an
5108 -- unchecked union type if the type lacks default discriminant
5109 -- values.
5110
5111 if Is_Unchecked_Union (Base_Type (U_Type))
5112 and then No (Discriminant_Constraint (U_Type))
5113 then
5114 Insert_Action (N,
5115 Make_Raise_Program_Error (Loc,
5116 Reason => PE_Unchecked_Union_Restriction));
5117
5118 return;
5119 end if;
5120
5121 Build_Record_Or_Elementary_Output_Procedure
5122 (Loc, Base_Type (U_Type), Decl, Pname);
5123 Insert_Action (N, Decl);
5124 end if;
5125 end if;
5126
5127 -- If we fall through, Pname is the name of the procedure to call
5128
5129 Rewrite_Stream_Proc_Call (Pname);
5130 end Output;
5131
5132 ---------
5133 -- Pos --
5134 ---------
5135
5136 -- For enumeration types with a standard representation, Pos is handled
5137 -- by the back end.
5138
5139 -- For enumeration types, with a non-standard representation we generate
5140 -- a call to the _Rep_To_Pos function created when the type was frozen.
5141 -- The call has the form:
5142
5143 -- _rep_to_pos (expr, flag)
5144
5145 -- The parameter flag is True if range checks are enabled, causing
5146 -- Program_Error to be raised if the expression has an invalid
5147 -- representation, and False if range checks are suppressed.
5148
5149 -- For integer types, Pos is equivalent to a simple integer conversion
5150 -- and we rewrite it as such.
5151
5152 when Attribute_Pos => Pos : declare
5153 Etyp : Entity_Id := Base_Type (Ptyp);
5154
5155 begin
5156 -- Deal with zero/non-zero boolean values
5157
5158 if Is_Boolean_Type (Etyp) then
5159 Adjust_Condition (First (Exprs));
5160 Etyp := Standard_Boolean;
5161 Set_Prefix (N, New_Occurrence_Of (Standard_Boolean, Loc));
5162 end if;
5163
5164 -- Case of enumeration type
5165
5166 if Is_Enumeration_Type (Etyp) then
5167
5168 -- Non-standard enumeration type (generate call)
5169
5170 if Present (Enum_Pos_To_Rep (Etyp)) then
5171 Append_To (Exprs, Rep_To_Pos_Flag (Etyp, Loc));
5172 Rewrite (N,
5173 Convert_To (Typ,
5174 Make_Function_Call (Loc,
5175 Name =>
5176 New_Occurrence_Of (TSS (Etyp, TSS_Rep_To_Pos), Loc),
5177 Parameter_Associations => Exprs)));
5178
5179 Analyze_And_Resolve (N, Typ);
5180
5181 -- Standard enumeration type (do universal integer check)
5182
5183 else
5184 Apply_Universal_Integer_Attribute_Checks (N);
5185 end if;
5186
5187 -- Deal with integer types (replace by conversion)
5188
5189 elsif Is_Integer_Type (Etyp) then
5190 Rewrite (N, Convert_To (Typ, First (Exprs)));
5191 Analyze_And_Resolve (N, Typ);
5192 end if;
5193
5194 end Pos;
5195
5196 --------------
5197 -- Position --
5198 --------------
5199
5200 -- We compute this if a component clause was present, otherwise we leave
5201 -- the computation up to the back end, since we don't know what layout
5202 -- will be chosen.
5203
5204 when Attribute_Position => Position_Attr : declare
5205 CE : constant Entity_Id := Entity (Selector_Name (Pref));
5206
5207 begin
5208 if Present (Component_Clause (CE)) then
5209
5210 -- In Ada 2005 (or later) if we have the non-default bit order,
5211 -- then we return the original value as given in the component
5212 -- clause (RM 2005 13.5.2(2/2)).
5213
5214 if Ada_Version >= Ada_2005
5215 and then Reverse_Bit_Order (Scope (CE))
5216 then
5217 Rewrite (N,
5218 Make_Integer_Literal (Loc,
5219 Intval => Expr_Value (Position (Component_Clause (CE)))));
5220
5221 -- Otherwise (Ada 83 or 95, or default bit order specified in
5222 -- later Ada version), return the normalized value.
5223
5224 else
5225 Rewrite (N,
5226 Make_Integer_Literal (Loc,
5227 Intval => Component_Bit_Offset (CE) / System_Storage_Unit));
5228 end if;
5229
5230 Analyze_And_Resolve (N, Typ);
5231
5232 -- If back end is doing things, just apply universal integer checks
5233
5234 else
5235 Apply_Universal_Integer_Attribute_Checks (N);
5236 end if;
5237 end Position_Attr;
5238
5239 ----------
5240 -- Pred --
5241 ----------
5242
5243 -- 1. Deal with enumeration types with holes.
5244 -- 2. For floating-point, generate call to attribute function.
5245 -- 3. For other cases, deal with constraint checking.
5246
5247 when Attribute_Pred => Pred : declare
5248 Etyp : constant Entity_Id := Base_Type (Ptyp);
5249
5250 begin
5251
5252 -- For enumeration types with non-standard representations, we
5253 -- expand typ'Pred (x) into
5254
5255 -- Pos_To_Rep (Rep_To_Pos (x) - 1)
5256
5257 -- If the representation is contiguous, we compute instead
5258 -- Lit1 + Rep_to_Pos (x -1), to catch invalid representations.
5259 -- The conversion function Enum_Pos_To_Rep is defined on the
5260 -- base type, not the subtype, so we have to use the base type
5261 -- explicitly for this and other enumeration attributes.
5262
5263 if Is_Enumeration_Type (Ptyp)
5264 and then Present (Enum_Pos_To_Rep (Etyp))
5265 then
5266 if Has_Contiguous_Rep (Etyp) then
5267 Rewrite (N,
5268 Unchecked_Convert_To (Ptyp,
5269 Make_Op_Add (Loc,
5270 Left_Opnd =>
5271 Make_Integer_Literal (Loc,
5272 Enumeration_Rep (First_Literal (Ptyp))),
5273 Right_Opnd =>
5274 Make_Function_Call (Loc,
5275 Name =>
5276 New_Occurrence_Of
5277 (TSS (Etyp, TSS_Rep_To_Pos), Loc),
5278
5279 Parameter_Associations =>
5280 New_List (
5281 Unchecked_Convert_To (Ptyp,
5282 Make_Op_Subtract (Loc,
5283 Left_Opnd =>
5284 Unchecked_Convert_To (Standard_Integer,
5285 Relocate_Node (First (Exprs))),
5286 Right_Opnd =>
5287 Make_Integer_Literal (Loc, 1))),
5288 Rep_To_Pos_Flag (Ptyp, Loc))))));
5289
5290 else
5291 -- Add Boolean parameter True, to request program error if
5292 -- we have a bad representation on our hands. If checks are
5293 -- suppressed, then add False instead
5294
5295 Append_To (Exprs, Rep_To_Pos_Flag (Ptyp, Loc));
5296 Rewrite (N,
5297 Make_Indexed_Component (Loc,
5298 Prefix =>
5299 New_Occurrence_Of
5300 (Enum_Pos_To_Rep (Etyp), Loc),
5301 Expressions => New_List (
5302 Make_Op_Subtract (Loc,
5303 Left_Opnd =>
5304 Make_Function_Call (Loc,
5305 Name =>
5306 New_Occurrence_Of
5307 (TSS (Etyp, TSS_Rep_To_Pos), Loc),
5308 Parameter_Associations => Exprs),
5309 Right_Opnd => Make_Integer_Literal (Loc, 1)))));
5310 end if;
5311
5312 Analyze_And_Resolve (N, Typ);
5313
5314 -- For floating-point, we transform 'Pred into a call to the Pred
5315 -- floating-point attribute function in Fat_xxx (xxx is root type).
5316 -- Note that this function takes care of the overflow case.
5317
5318 elsif Is_Floating_Point_Type (Ptyp) then
5319 Expand_Fpt_Attribute_R (N);
5320 Analyze_And_Resolve (N, Typ);
5321
5322 -- For modular types, nothing to do (no overflow, since wraps)
5323
5324 elsif Is_Modular_Integer_Type (Ptyp) then
5325 null;
5326
5327 -- For other types, if argument is marked as needing a range check or
5328 -- overflow checking is enabled, we must generate a check.
5329
5330 elsif not Overflow_Checks_Suppressed (Ptyp)
5331 or else Do_Range_Check (First (Exprs))
5332 then
5333 Set_Do_Range_Check (First (Exprs), False);
5334 Expand_Pred_Succ_Attribute (N);
5335 end if;
5336 end Pred;
5337
5338 --------------
5339 -- Priority --
5340 --------------
5341
5342 -- Ada 2005 (AI-327): Dynamic ceiling priorities
5343
5344 -- We rewrite X'Priority as the following run-time call:
5345
5346 -- Get_Ceiling (X._Object)
5347
5348 -- Note that although X'Priority is notionally an object, it is quite
5349 -- deliberately not defined as an aliased object in the RM. This means
5350 -- that it works fine to rewrite it as a call, without having to worry
5351 -- about complications that would other arise from X'Priority'Access,
5352 -- which is illegal, because of the lack of aliasing.
5353
5354 when Attribute_Priority => Priority : declare
5355 Call : Node_Id;
5356 Conctyp : Entity_Id;
5357 New_Itype : Entity_Id;
5358 Object_Parm : Node_Id;
5359 Subprg : Entity_Id;
5360 RT_Subprg_Name : Node_Id;
5361
5362 begin
5363 -- Look for the enclosing concurrent type
5364
5365 Conctyp := Current_Scope;
5366 while not Is_Concurrent_Type (Conctyp) loop
5367 Conctyp := Scope (Conctyp);
5368 end loop;
5369
5370 pragma Assert (Is_Protected_Type (Conctyp));
5371
5372 -- Generate the actual of the call
5373
5374 Subprg := Current_Scope;
5375 while not Present (Protected_Body_Subprogram (Subprg)) loop
5376 Subprg := Scope (Subprg);
5377 end loop;
5378
5379 -- Use of 'Priority inside protected entries and barriers (in both
5380 -- cases the type of the first formal of their expanded subprogram
5381 -- is Address)
5382
5383 if Etype (First_Entity (Protected_Body_Subprogram (Subprg))) =
5384 RTE (RE_Address)
5385 then
5386 -- In the expansion of protected entries the type of the first
5387 -- formal of the Protected_Body_Subprogram is an Address. In order
5388 -- to reference the _object component we generate:
5389
5390 -- type T is access p__ptTV;
5391 -- freeze T []
5392
5393 New_Itype := Create_Itype (E_Access_Type, N);
5394 Set_Etype (New_Itype, New_Itype);
5395 Set_Directly_Designated_Type (New_Itype,
5396 Corresponding_Record_Type (Conctyp));
5397 Freeze_Itype (New_Itype, N);
5398
5399 -- Generate:
5400 -- T!(O)._object'unchecked_access
5401
5402 Object_Parm :=
5403 Make_Attribute_Reference (Loc,
5404 Prefix =>
5405 Make_Selected_Component (Loc,
5406 Prefix =>
5407 Unchecked_Convert_To (New_Itype,
5408 New_Occurrence_Of
5409 (First_Entity (Protected_Body_Subprogram (Subprg)),
5410 Loc)),
5411 Selector_Name => Make_Identifier (Loc, Name_uObject)),
5412 Attribute_Name => Name_Unchecked_Access);
5413
5414 -- Use of 'Priority inside a protected subprogram
5415
5416 else
5417 Object_Parm :=
5418 Make_Attribute_Reference (Loc,
5419 Prefix =>
5420 Make_Selected_Component (Loc,
5421 Prefix =>
5422 New_Occurrence_Of
5423 (First_Entity (Protected_Body_Subprogram (Subprg)),
5424 Loc),
5425 Selector_Name => Make_Identifier (Loc, Name_uObject)),
5426 Attribute_Name => Name_Unchecked_Access);
5427 end if;
5428
5429 -- Select the appropriate run-time subprogram
5430
5431 if Number_Entries (Conctyp) = 0 then
5432 RT_Subprg_Name := New_Occurrence_Of (RTE (RE_Get_Ceiling), Loc);
5433 else
5434 RT_Subprg_Name := New_Occurrence_Of (RTE (RO_PE_Get_Ceiling), Loc);
5435 end if;
5436
5437 Call :=
5438 Make_Function_Call (Loc,
5439 Name => RT_Subprg_Name,
5440 Parameter_Associations => New_List (Object_Parm));
5441
5442 Rewrite (N, Call);
5443
5444 -- Avoid the generation of extra checks on the pointer to the
5445 -- protected object.
5446
5447 Analyze_And_Resolve (N, Typ, Suppress => Access_Check);
5448 end Priority;
5449
5450 ------------------
5451 -- Range_Length --
5452 ------------------
5453
5454 when Attribute_Range_Length =>
5455
5456 -- The only special processing required is for the case where
5457 -- Range_Length is applied to an enumeration type with holes.
5458 -- In this case we transform
5459
5460 -- X'Range_Length
5461
5462 -- to
5463
5464 -- X'Pos (X'Last) - X'Pos (X'First) + 1
5465
5466 -- So that the result reflects the proper Pos values instead
5467 -- of the underlying representations.
5468
5469 if Is_Enumeration_Type (Ptyp)
5470 and then Has_Non_Standard_Rep (Ptyp)
5471 then
5472 Rewrite (N,
5473 Make_Op_Add (Loc,
5474 Left_Opnd =>
5475 Make_Op_Subtract (Loc,
5476 Left_Opnd =>
5477 Make_Attribute_Reference (Loc,
5478 Attribute_Name => Name_Pos,
5479 Prefix => New_Occurrence_Of (Ptyp, Loc),
5480 Expressions => New_List (
5481 Make_Attribute_Reference (Loc,
5482 Attribute_Name => Name_Last,
5483 Prefix =>
5484 New_Occurrence_Of (Ptyp, Loc)))),
5485
5486 Right_Opnd =>
5487 Make_Attribute_Reference (Loc,
5488 Attribute_Name => Name_Pos,
5489 Prefix => New_Occurrence_Of (Ptyp, Loc),
5490 Expressions => New_List (
5491 Make_Attribute_Reference (Loc,
5492 Attribute_Name => Name_First,
5493 Prefix =>
5494 New_Occurrence_Of (Ptyp, Loc))))),
5495
5496 Right_Opnd => Make_Integer_Literal (Loc, 1)));
5497
5498 Analyze_And_Resolve (N, Typ);
5499
5500 -- For all other cases, the attribute is handled by the back end, but
5501 -- we need to deal with the case of the range check on a universal
5502 -- integer.
5503
5504 else
5505 Apply_Universal_Integer_Attribute_Checks (N);
5506 end if;
5507
5508 ------------
5509 -- Reduce --
5510 ------------
5511
5512 when Attribute_Reduce =>
5513 declare
5514 Loc : constant Source_Ptr := Sloc (N);
5515 E1 : constant Node_Id := First (Expressions (N));
5516 E2 : constant Node_Id := Next (E1);
5517 Bnn : constant Entity_Id := Make_Temporary (Loc, 'B', N);
5518 Typ : constant Entity_Id := Etype (N);
5519 New_Loop : Node_Id;
5520
5521 -- If the prefix is an aggregate, its unique component is an
5522 -- Iterated_Element, and we create a loop out of its iterator.
5523
5524 begin
5525 if Nkind (Prefix (N)) = N_Aggregate then
5526 declare
5527 Stream : constant Node_Id :=
5528 First (Component_Associations (Prefix (N)));
5529 Id : constant Node_Id := Defining_Identifier (Stream);
5530 Expr : constant Node_Id := Expression (Stream);
5531 Ch : constant Node_Id :=
5532 First (Discrete_Choices (Stream));
5533 begin
5534 New_Loop := Make_Loop_Statement (Loc,
5535 Iteration_Scheme =>
5536 Make_Iteration_Scheme (Loc,
5537 Iterator_Specification => Empty,
5538 Loop_Parameter_Specification =>
5539 Make_Loop_Parameter_Specification (Loc,
5540 Defining_Identifier => New_Copy (Id),
5541 Discrete_Subtype_Definition =>
5542 Relocate_Node (Ch))),
5543 End_Label => Empty,
5544 Statements => New_List (
5545 Make_Assignment_Statement (Loc,
5546 Name => New_Occurrence_Of (Bnn, Loc),
5547 Expression => Make_Function_Call (Loc,
5548 Name => New_Occurrence_Of (Entity (E1), Loc),
5549 Parameter_Associations => New_List (
5550 New_Occurrence_Of (Bnn, Loc),
5551 Relocate_Node (Expr))))));
5552 end;
5553 else
5554 -- If the prefix is a name, we construct an element iterator
5555 -- over it. Its expansion will verify that it is an array or
5556 -- a container with the proper aspects.
5557
5558 declare
5559 Iter : Node_Id;
5560 Elem : constant Entity_Id := Make_Temporary (Loc, 'E', N);
5561
5562 begin
5563 Iter :=
5564 Make_Iterator_Specification (Loc,
5565 Defining_Identifier => Elem,
5566 Name => Relocate_Node (Prefix (N)),
5567 Subtype_Indication => Empty);
5568 Set_Of_Present (Iter);
5569
5570 New_Loop := Make_Loop_Statement (Loc,
5571 Iteration_Scheme =>
5572 Make_Iteration_Scheme (Loc,
5573 Iterator_Specification => Iter,
5574 Loop_Parameter_Specification => Empty),
5575 End_Label => Empty,
5576 Statements => New_List (
5577 Make_Assignment_Statement (Loc,
5578 Name => New_Occurrence_Of (Bnn, Loc),
5579 Expression => Make_Function_Call (Loc,
5580 Name => New_Occurrence_Of (Entity (E1), Loc),
5581 Parameter_Associations => New_List (
5582 New_Occurrence_Of (Bnn, Loc),
5583 New_Occurrence_Of (Elem, Loc))))));
5584 end;
5585 end if;
5586
5587 Rewrite (N,
5588 Make_Expression_With_Actions (Loc,
5589 Actions => New_List (
5590 Make_Object_Declaration (Loc,
5591 Defining_Identifier => Bnn,
5592 Object_Definition =>
5593 New_Occurrence_Of (Typ, Loc),
5594 Expression => Relocate_Node (E2)), New_Loop),
5595 Expression => New_Occurrence_Of (Bnn, Loc)));
5596 Analyze_And_Resolve (N, Typ);
5597 end;
5598
5599 ----------
5600 -- Read --
5601 ----------
5602
5603 when Attribute_Read => Read : declare
5604 P_Type : constant Entity_Id := Entity (Pref);
5605 B_Type : constant Entity_Id := Base_Type (P_Type);
5606 U_Type : constant Entity_Id := Underlying_Type (P_Type);
5607 Pname : Entity_Id;
5608 Decl : Node_Id;
5609 Prag : Node_Id;
5610 Arg2 : Node_Id;
5611 Rfunc : Node_Id;
5612 Lhs : Node_Id;
5613 Rhs : Node_Id;
5614
5615 begin
5616 -- If no underlying type, we have an error that will be diagnosed
5617 -- elsewhere, so here we just completely ignore the expansion.
5618
5619 if No (U_Type) then
5620 return;
5621 end if;
5622
5623 -- Stream operations can appear in user code even if the restriction
5624 -- No_Streams is active (for example, when instantiating a predefined
5625 -- container). In that case rewrite the attribute as a Raise to
5626 -- prevent any run-time use.
5627
5628 if Restriction_Active (No_Streams) then
5629 Rewrite (N,
5630 Make_Raise_Program_Error (Sloc (N),
5631 Reason => PE_Stream_Operation_Not_Allowed));
5632 Set_Etype (N, B_Type);
5633 return;
5634 end if;
5635
5636 -- The simple case, if there is a TSS for Read, just call it
5637
5638 Pname := Find_Stream_Subprogram (P_Type, TSS_Stream_Read);
5639
5640 if Present (Pname) then
5641 null;
5642
5643 else
5644 -- If there is a Stream_Convert pragma, use it, we rewrite
5645
5646 -- sourcetyp'Read (stream, Item)
5647
5648 -- as
5649
5650 -- Item := sourcetyp (strmread (strmtyp'Input (Stream)));
5651
5652 -- where strmread is the given Read function that converts an
5653 -- argument of type strmtyp to type sourcetyp or a type from which
5654 -- it is derived. The conversion to sourcetyp is required in the
5655 -- latter case.
5656
5657 -- A special case arises if Item is a type conversion in which
5658 -- case, we have to expand to:
5659
5660 -- Itemx := typex (strmread (strmtyp'Input (Stream)));
5661
5662 -- where Itemx is the expression of the type conversion (i.e.
5663 -- the actual object), and typex is the type of Itemx.
5664
5665 Prag := Get_Stream_Convert_Pragma (P_Type);
5666
5667 if Present (Prag) then
5668 Arg2 := Next (First (Pragma_Argument_Associations (Prag)));
5669 Rfunc := Entity (Expression (Arg2));
5670 Lhs := Relocate_Node (Next (First (Exprs)));
5671 Rhs :=
5672 OK_Convert_To (B_Type,
5673 Make_Function_Call (Loc,
5674 Name => New_Occurrence_Of (Rfunc, Loc),
5675 Parameter_Associations => New_List (
5676 Make_Attribute_Reference (Loc,
5677 Prefix =>
5678 New_Occurrence_Of
5679 (Etype (First_Formal (Rfunc)), Loc),
5680 Attribute_Name => Name_Input,
5681 Expressions => New_List (
5682 Relocate_Node (First (Exprs)))))));
5683
5684 if Nkind (Lhs) = N_Type_Conversion then
5685 Lhs := Expression (Lhs);
5686 Rhs := Convert_To (Etype (Lhs), Rhs);
5687 end if;
5688
5689 Rewrite (N,
5690 Make_Assignment_Statement (Loc,
5691 Name => Lhs,
5692 Expression => Rhs));
5693 Set_Assignment_OK (Lhs);
5694 Analyze (N);
5695 return;
5696
5697 -- For elementary types, we call the I_xxx routine using the first
5698 -- parameter and then assign the result into the second parameter.
5699 -- We set Assignment_OK to deal with the conversion case.
5700
5701 elsif Is_Elementary_Type (U_Type) then
5702 declare
5703 Lhs : Node_Id;
5704 Rhs : Node_Id;
5705
5706 begin
5707 Lhs := Relocate_Node (Next (First (Exprs)));
5708 Rhs := Build_Elementary_Input_Call (N);
5709
5710 if Nkind (Lhs) = N_Type_Conversion then
5711 Lhs := Expression (Lhs);
5712 Rhs := Convert_To (Etype (Lhs), Rhs);
5713 end if;
5714
5715 Set_Assignment_OK (Lhs);
5716
5717 Rewrite (N,
5718 Make_Assignment_Statement (Loc,
5719 Name => Lhs,
5720 Expression => Rhs));
5721
5722 Analyze (N);
5723 return;
5724 end;
5725
5726 -- Array type case
5727
5728 elsif Is_Array_Type (U_Type) then
5729 Build_Array_Read_Procedure (N, U_Type, Decl, Pname);
5730 Compile_Stream_Body_In_Scope (N, Decl, U_Type, Check => False);
5731
5732 -- Tagged type case, use the primitive Read function. Note that
5733 -- this will dispatch in the class-wide case which is what we want
5734
5735 elsif Is_Tagged_Type (U_Type) then
5736 Pname := Find_Prim_Op (U_Type, TSS_Stream_Read);
5737
5738 -- All other record type cases, including protected records. The
5739 -- latter only arise for expander generated code for handling
5740 -- shared passive partition access.
5741
5742 else
5743 pragma Assert
5744 (Is_Record_Type (U_Type) or else Is_Protected_Type (U_Type));
5745
5746 -- Ada 2005 (AI-216): Program_Error is raised when executing
5747 -- the default implementation of the Read attribute of an
5748 -- Unchecked_Union type. We replace the attribute with a
5749 -- raise statement (rather than inserting it before) to handle
5750 -- properly the case of an unchecked union that is a record
5751 -- component.
5752
5753 if Is_Unchecked_Union (Base_Type (U_Type)) then
5754 Rewrite (N,
5755 Make_Raise_Program_Error (Loc,
5756 Reason => PE_Unchecked_Union_Restriction));
5757 Set_Etype (N, B_Type);
5758 return;
5759 end if;
5760
5761 if Has_Discriminants (U_Type)
5762 and then Present
5763 (Discriminant_Default_Value (First_Discriminant (U_Type)))
5764 then
5765 Build_Mutable_Record_Read_Procedure
5766 (Loc, Full_Base (U_Type), Decl, Pname);
5767 else
5768 Build_Record_Read_Procedure
5769 (Loc, Full_Base (U_Type), Decl, Pname);
5770 end if;
5771
5772 -- Suppress checks, uninitialized or otherwise invalid
5773 -- data does not cause constraint errors to be raised for
5774 -- a complete record read.
5775
5776 Insert_Action (N, Decl, All_Checks);
5777 end if;
5778 end if;
5779
5780 Rewrite_Stream_Proc_Call (Pname);
5781 end Read;
5782
5783 ---------
5784 -- Ref --
5785 ---------
5786
5787 -- Ref is identical to To_Address, see To_Address for processing
5788
5789 ---------------
5790 -- Remainder --
5791 ---------------
5792
5793 -- Transforms 'Remainder into a call to the floating-point attribute
5794 -- function Remainder in Fat_xxx (where xxx is the root type)
5795
5796 when Attribute_Remainder =>
5797 Expand_Fpt_Attribute_RR (N);
5798
5799 ------------
5800 -- Result --
5801 ------------
5802
5803 -- Transform 'Result into reference to _Result formal. At the point
5804 -- where a legal 'Result attribute is expanded, we know that we are in
5805 -- the context of a _Postcondition function with a _Result parameter.
5806
5807 when Attribute_Result =>
5808 Rewrite (N, Make_Identifier (Loc, Chars => Name_uResult));
5809 Analyze_And_Resolve (N, Typ);
5810
5811 -----------
5812 -- Round --
5813 -----------
5814
5815 -- The handling of the Round attribute is quite delicate. The processing
5816 -- in Sem_Attr introduced a conversion to universal real, reflecting the
5817 -- semantics of Round, but we do not want anything to do with universal
5818 -- real at runtime, since this corresponds to using floating-point
5819 -- arithmetic.
5820
5821 -- What we have now is that the Etype of the Round attribute correctly
5822 -- indicates the final result type. The operand of the Round is the
5823 -- conversion to universal real, described above, and the operand of
5824 -- this conversion is the actual operand of Round, which may be the
5825 -- special case of a fixed point multiplication or division (Etype =
5826 -- universal fixed)
5827
5828 -- The exapander will expand first the operand of the conversion, then
5829 -- the conversion, and finally the round attribute itself, since we
5830 -- always work inside out. But we cannot simply process naively in this
5831 -- order. In the semantic world where universal fixed and real really
5832 -- exist and have infinite precision, there is no problem, but in the
5833 -- implementation world, where universal real is a floating-point type,
5834 -- we would get the wrong result.
5835
5836 -- So the approach is as follows. First, when expanding a multiply or
5837 -- divide whose type is universal fixed, we do nothing at all, instead
5838 -- deferring the operation till later.
5839
5840 -- The actual processing is done in Expand_N_Type_Conversion which
5841 -- handles the special case of Round by looking at its parent to see if
5842 -- it is a Round attribute, and if it is, handling the conversion (or
5843 -- its fixed multiply/divide child) in an appropriate manner.
5844
5845 -- This means that by the time we get to expanding the Round attribute
5846 -- itself, the Round is nothing more than a type conversion (and will
5847 -- often be a null type conversion), so we just replace it with the
5848 -- appropriate conversion operation.
5849
5850 when Attribute_Round =>
5851 Rewrite (N,
5852 Convert_To (Etype (N), Relocate_Node (First (Exprs))));
5853 Analyze_And_Resolve (N);
5854
5855 --------------
5856 -- Rounding --
5857 --------------
5858
5859 -- Transforms 'Rounding into a call to the floating-point attribute
5860 -- function Rounding in Fat_xxx (where xxx is the root type)
5861 -- Expansion is avoided for cases the back end can handle directly.
5862
5863 when Attribute_Rounding =>
5864 if not Is_Inline_Floating_Point_Attribute (N) then
5865 Expand_Fpt_Attribute_R (N);
5866 end if;
5867
5868 -------------
5869 -- Scaling --
5870 -------------
5871
5872 -- Transforms 'Scaling into a call to the floating-point attribute
5873 -- function Scaling in Fat_xxx (where xxx is the root type)
5874
5875 when Attribute_Scaling =>
5876 Expand_Fpt_Attribute_RI (N);
5877
5878 -------------------------
5879 -- Simple_Storage_Pool --
5880 -------------------------
5881
5882 when Attribute_Simple_Storage_Pool =>
5883 Rewrite (N,
5884 Make_Type_Conversion (Loc,
5885 Subtype_Mark => New_Occurrence_Of (Etype (N), Loc),
5886 Expression => New_Occurrence_Of (Entity (N), Loc)));
5887 Analyze_And_Resolve (N, Typ);
5888
5889 ----------
5890 -- Size --
5891 ----------
5892
5893 when Attribute_Object_Size
5894 | Attribute_Size
5895 | Attribute_Value_Size
5896 | Attribute_VADS_Size
5897 =>
5898 Size : declare
5899 New_Node : Node_Id;
5900
5901 begin
5902 -- Processing for VADS_Size case. Note that this processing
5903 -- removes all traces of VADS_Size from the tree, and completes
5904 -- all required processing for VADS_Size by translating the
5905 -- attribute reference to an appropriate Size or Object_Size
5906 -- reference.
5907
5908 if Id = Attribute_VADS_Size
5909 or else (Use_VADS_Size and then Id = Attribute_Size)
5910 then
5911 -- If the size is specified, then we simply use the specified
5912 -- size. This applies to both types and objects. The size of an
5913 -- object can be specified in the following ways:
5914
5915 -- An explicit size object is given for an object
5916 -- A component size is specified for an indexed component
5917 -- A component clause is specified for a selected component
5918 -- The object is a component of a packed composite object
5919
5920 -- If the size is specified, then VADS_Size of an object
5921
5922 if (Is_Entity_Name (Pref)
5923 and then Present (Size_Clause (Entity (Pref))))
5924 or else
5925 (Nkind (Pref) = N_Component_Clause
5926 and then (Present (Component_Clause
5927 (Entity (Selector_Name (Pref))))
5928 or else Is_Packed (Etype (Prefix (Pref)))))
5929 or else
5930 (Nkind (Pref) = N_Indexed_Component
5931 and then (Component_Size (Etype (Prefix (Pref))) /= 0
5932 or else Is_Packed (Etype (Prefix (Pref)))))
5933 then
5934 Set_Attribute_Name (N, Name_Size);
5935
5936 -- Otherwise if we have an object rather than a type, then
5937 -- the VADS_Size attribute applies to the type of the object,
5938 -- rather than the object itself. This is one of the respects
5939 -- in which VADS_Size differs from Size.
5940
5941 else
5942 if (not Is_Entity_Name (Pref)
5943 or else not Is_Type (Entity (Pref)))
5944 and then (Is_Scalar_Type (Ptyp)
5945 or else Is_Constrained (Ptyp))
5946 then
5947 Rewrite (Pref, New_Occurrence_Of (Ptyp, Loc));
5948 end if;
5949
5950 -- For a scalar type for which no size was explicitly given,
5951 -- VADS_Size means Object_Size. This is the other respect in
5952 -- which VADS_Size differs from Size.
5953
5954 if Is_Scalar_Type (Ptyp)
5955 and then No (Size_Clause (Ptyp))
5956 then
5957 Set_Attribute_Name (N, Name_Object_Size);
5958
5959 -- In all other cases, Size and VADS_Size are the sane
5960
5961 else
5962 Set_Attribute_Name (N, Name_Size);
5963 end if;
5964 end if;
5965 end if;
5966
5967 -- If the prefix is X'Class, transform it into a direct reference
5968 -- to the class-wide type, because the back end must not see a
5969 -- 'Class reference.
5970
5971 if Is_Entity_Name (Pref)
5972 and then Is_Class_Wide_Type (Entity (Pref))
5973 then
5974 Rewrite (Prefix (N), New_Occurrence_Of (Entity (Pref), Loc));
5975 return;
5976
5977 -- For X'Size applied to an object of a class-wide type, transform
5978 -- X'Size into a call to the primitive operation _Size applied to
5979 -- X.
5980
5981 elsif Is_Class_Wide_Type (Ptyp) then
5982
5983 -- No need to do anything else compiling under restriction
5984 -- No_Dispatching_Calls. During the semantic analysis we
5985 -- already noted this restriction violation.
5986
5987 if Restriction_Active (No_Dispatching_Calls) then
5988 return;
5989 end if;
5990
5991 New_Node :=
5992 Make_Function_Call (Loc,
5993 Name =>
5994 New_Occurrence_Of (Find_Prim_Op (Ptyp, Name_uSize), Loc),
5995 Parameter_Associations => New_List (Pref));
5996
5997 if Typ /= Standard_Long_Long_Integer then
5998
5999 -- The context is a specific integer type with which the
6000 -- original attribute was compatible. The function has a
6001 -- specific type as well, so to preserve the compatibility
6002 -- we must convert explicitly.
6003
6004 New_Node := Convert_To (Typ, New_Node);
6005 end if;
6006
6007 Rewrite (N, New_Node);
6008 Analyze_And_Resolve (N, Typ);
6009 return;
6010 end if;
6011
6012 -- Call Expand_Size_Attribute to do the final part of the
6013 -- expansion which is shared with GNATprove expansion.
6014
6015 Expand_Size_Attribute (N);
6016 end Size;
6017
6018 ------------------
6019 -- Storage_Pool --
6020 ------------------
6021
6022 when Attribute_Storage_Pool =>
6023 Rewrite (N,
6024 Make_Type_Conversion (Loc,
6025 Subtype_Mark => New_Occurrence_Of (Etype (N), Loc),
6026 Expression => New_Occurrence_Of (Entity (N), Loc)));
6027 Analyze_And_Resolve (N, Typ);
6028
6029 ------------------
6030 -- Storage_Size --
6031 ------------------
6032
6033 when Attribute_Storage_Size => Storage_Size : declare
6034 Alloc_Op : Entity_Id := Empty;
6035
6036 begin
6037
6038 -- Access type case, always go to the root type
6039
6040 -- The case of access types results in a value of zero for the case
6041 -- where no storage size attribute clause has been given. If a
6042 -- storage size has been given, then the attribute is converted
6043 -- to a reference to the variable used to hold this value.
6044
6045 if Is_Access_Type (Ptyp) then
6046 if Present (Storage_Size_Variable (Root_Type (Ptyp))) then
6047 Rewrite (N,
6048 Convert_To (Typ,
6049 Make_Attribute_Reference (Loc,
6050 Prefix => New_Occurrence_Of
6051 (Etype (Storage_Size_Variable (Root_Type (Ptyp))), Loc),
6052 Attribute_Name => Name_Max,
6053 Expressions => New_List (
6054 Make_Integer_Literal (Loc, 0),
6055 New_Occurrence_Of
6056 (Storage_Size_Variable (Root_Type (Ptyp)), Loc)))));
6057
6058 elsif Present (Associated_Storage_Pool (Root_Type (Ptyp))) then
6059
6060 -- If the access type is associated with a simple storage pool
6061 -- object, then attempt to locate the optional Storage_Size
6062 -- function of the simple storage pool type. If not found,
6063 -- then the result will default to zero.
6064
6065 if Present (Get_Rep_Pragma (Root_Type (Ptyp),
6066 Name_Simple_Storage_Pool_Type))
6067 then
6068 declare
6069 Pool_Type : constant Entity_Id :=
6070 Base_Type (Etype (Entity (N)));
6071
6072 begin
6073 Alloc_Op := Get_Name_Entity_Id (Name_Storage_Size);
6074 while Present (Alloc_Op) loop
6075 if Scope (Alloc_Op) = Scope (Pool_Type)
6076 and then Present (First_Formal (Alloc_Op))
6077 and then Etype (First_Formal (Alloc_Op)) = Pool_Type
6078 then
6079 exit;
6080 end if;
6081
6082 Alloc_Op := Homonym (Alloc_Op);
6083 end loop;
6084 end;
6085
6086 -- In the normal Storage_Pool case, retrieve the primitive
6087 -- function associated with the pool type.
6088
6089 else
6090 Alloc_Op :=
6091 Find_Prim_Op
6092 (Etype (Associated_Storage_Pool (Root_Type (Ptyp))),
6093 Attribute_Name (N));
6094 end if;
6095
6096 -- If Storage_Size wasn't found (can only occur in the simple
6097 -- storage pool case), then simply use zero for the result.
6098
6099 if not Present (Alloc_Op) then
6100 Rewrite (N, Make_Integer_Literal (Loc, 0));
6101
6102 -- Otherwise, rewrite the allocator as a call to pool type's
6103 -- Storage_Size function.
6104
6105 else
6106 Rewrite (N,
6107 Convert_To (Typ,
6108 Make_Function_Call (Loc,
6109 Name =>
6110 New_Occurrence_Of (Alloc_Op, Loc),
6111
6112 Parameter_Associations => New_List (
6113 New_Occurrence_Of
6114 (Associated_Storage_Pool
6115 (Root_Type (Ptyp)), Loc)))));
6116 end if;
6117
6118 else
6119 Rewrite (N, Make_Integer_Literal (Loc, 0));
6120 end if;
6121
6122 Analyze_And_Resolve (N, Typ);
6123
6124 -- For tasks, we retrieve the size directly from the TCB. The
6125 -- size may depend on a discriminant of the type, and therefore
6126 -- can be a per-object expression, so type-level information is
6127 -- not sufficient in general. There are four cases to consider:
6128
6129 -- a) If the attribute appears within a task body, the designated
6130 -- TCB is obtained by a call to Self.
6131
6132 -- b) If the prefix of the attribute is the name of a task object,
6133 -- the designated TCB is the one stored in the corresponding record.
6134
6135 -- c) If the prefix is a task type, the size is obtained from the
6136 -- size variable created for each task type
6137
6138 -- d) If no Storage_Size was specified for the type, there is no
6139 -- size variable, and the value is a system-specific default.
6140
6141 else
6142 if In_Open_Scopes (Ptyp) then
6143
6144 -- Storage_Size (Self)
6145
6146 Rewrite (N,
6147 Convert_To (Typ,
6148 Make_Function_Call (Loc,
6149 Name =>
6150 New_Occurrence_Of (RTE (RE_Storage_Size), Loc),
6151 Parameter_Associations =>
6152 New_List (
6153 Make_Function_Call (Loc,
6154 Name =>
6155 New_Occurrence_Of (RTE (RE_Self), Loc))))));
6156
6157 elsif not Is_Entity_Name (Pref)
6158 or else not Is_Type (Entity (Pref))
6159 then
6160 -- Storage_Size (Rec (Obj).Size)
6161
6162 Rewrite (N,
6163 Convert_To (Typ,
6164 Make_Function_Call (Loc,
6165 Name =>
6166 New_Occurrence_Of (RTE (RE_Storage_Size), Loc),
6167 Parameter_Associations =>
6168 New_List (
6169 Make_Selected_Component (Loc,
6170 Prefix =>
6171 Unchecked_Convert_To (
6172 Corresponding_Record_Type (Ptyp),
6173 New_Copy_Tree (Pref)),
6174 Selector_Name =>
6175 Make_Identifier (Loc, Name_uTask_Id))))));
6176
6177 elsif Present (Storage_Size_Variable (Ptyp)) then
6178
6179 -- Static Storage_Size pragma given for type: retrieve value
6180 -- from its allocated storage variable.
6181
6182 Rewrite (N,
6183 Convert_To (Typ,
6184 Make_Function_Call (Loc,
6185 Name => New_Occurrence_Of (
6186 RTE (RE_Adjust_Storage_Size), Loc),
6187 Parameter_Associations =>
6188 New_List (
6189 New_Occurrence_Of (
6190 Storage_Size_Variable (Ptyp), Loc)))));
6191 else
6192 -- Get system default
6193
6194 Rewrite (N,
6195 Convert_To (Typ,
6196 Make_Function_Call (Loc,
6197 Name =>
6198 New_Occurrence_Of (
6199 RTE (RE_Default_Stack_Size), Loc))));
6200 end if;
6201
6202 Analyze_And_Resolve (N, Typ);
6203 end if;
6204 end Storage_Size;
6205
6206 -----------------
6207 -- Stream_Size --
6208 -----------------
6209
6210 when Attribute_Stream_Size =>
6211 Rewrite (N,
6212 Make_Integer_Literal (Loc, Intval => Get_Stream_Size (Ptyp)));
6213 Analyze_And_Resolve (N, Typ);
6214
6215 ----------
6216 -- Succ --
6217 ----------
6218
6219 -- 1. Deal with enumeration types with holes.
6220 -- 2. For floating-point, generate call to attribute function.
6221 -- 3. For other cases, deal with constraint checking.
6222
6223 when Attribute_Succ => Succ : declare
6224 Etyp : constant Entity_Id := Base_Type (Ptyp);
6225
6226 begin
6227 -- For enumeration types with non-standard representations, we
6228 -- expand typ'Succ (x) into
6229
6230 -- Pos_To_Rep (Rep_To_Pos (x) + 1)
6231
6232 -- If the representation is contiguous, we compute instead
6233 -- Lit1 + Rep_to_Pos (x+1), to catch invalid representations.
6234
6235 if Is_Enumeration_Type (Ptyp)
6236 and then Present (Enum_Pos_To_Rep (Etyp))
6237 then
6238 if Has_Contiguous_Rep (Etyp) then
6239 Rewrite (N,
6240 Unchecked_Convert_To (Ptyp,
6241 Make_Op_Add (Loc,
6242 Left_Opnd =>
6243 Make_Integer_Literal (Loc,
6244 Enumeration_Rep (First_Literal (Ptyp))),
6245 Right_Opnd =>
6246 Make_Function_Call (Loc,
6247 Name =>
6248 New_Occurrence_Of
6249 (TSS (Etyp, TSS_Rep_To_Pos), Loc),
6250
6251 Parameter_Associations =>
6252 New_List (
6253 Unchecked_Convert_To (Ptyp,
6254 Make_Op_Add (Loc,
6255 Left_Opnd =>
6256 Unchecked_Convert_To (Standard_Integer,
6257 Relocate_Node (First (Exprs))),
6258 Right_Opnd =>
6259 Make_Integer_Literal (Loc, 1))),
6260 Rep_To_Pos_Flag (Ptyp, Loc))))));
6261 else
6262 -- Add Boolean parameter True, to request program error if
6263 -- we have a bad representation on our hands. Add False if
6264 -- checks are suppressed.
6265
6266 Append_To (Exprs, Rep_To_Pos_Flag (Ptyp, Loc));
6267 Rewrite (N,
6268 Make_Indexed_Component (Loc,
6269 Prefix =>
6270 New_Occurrence_Of
6271 (Enum_Pos_To_Rep (Etyp), Loc),
6272 Expressions => New_List (
6273 Make_Op_Add (Loc,
6274 Left_Opnd =>
6275 Make_Function_Call (Loc,
6276 Name =>
6277 New_Occurrence_Of
6278 (TSS (Etyp, TSS_Rep_To_Pos), Loc),
6279 Parameter_Associations => Exprs),
6280 Right_Opnd => Make_Integer_Literal (Loc, 1)))));
6281 end if;
6282
6283 Analyze_And_Resolve (N, Typ);
6284
6285 -- For floating-point, we transform 'Succ into a call to the Succ
6286 -- floating-point attribute function in Fat_xxx (xxx is root type)
6287
6288 elsif Is_Floating_Point_Type (Ptyp) then
6289 Expand_Fpt_Attribute_R (N);
6290 Analyze_And_Resolve (N, Typ);
6291
6292 -- For modular types, nothing to do (no overflow, since wraps)
6293
6294 elsif Is_Modular_Integer_Type (Ptyp) then
6295 null;
6296
6297 -- For other types, if argument is marked as needing a range check or
6298 -- overflow checking is enabled, we must generate a check.
6299
6300 elsif not Overflow_Checks_Suppressed (Ptyp)
6301 or else Do_Range_Check (First (Exprs))
6302 then
6303 Set_Do_Range_Check (First (Exprs), False);
6304 Expand_Pred_Succ_Attribute (N);
6305 end if;
6306 end Succ;
6307
6308 ---------
6309 -- Tag --
6310 ---------
6311
6312 -- Transforms X'Tag into a direct reference to the tag of X
6313
6314 when Attribute_Tag => Tag : declare
6315 Ttyp : Entity_Id;
6316 Prefix_Is_Type : Boolean;
6317
6318 begin
6319 if Is_Entity_Name (Pref) and then Is_Type (Entity (Pref)) then
6320 Ttyp := Entity (Pref);
6321 Prefix_Is_Type := True;
6322 else
6323 Ttyp := Ptyp;
6324 Prefix_Is_Type := False;
6325 end if;
6326
6327 if Is_Class_Wide_Type (Ttyp) then
6328 Ttyp := Root_Type (Ttyp);
6329 end if;
6330
6331 Ttyp := Underlying_Type (Ttyp);
6332
6333 -- Ada 2005: The type may be a synchronized tagged type, in which
6334 -- case the tag information is stored in the corresponding record.
6335
6336 if Is_Concurrent_Type (Ttyp) then
6337 Ttyp := Corresponding_Record_Type (Ttyp);
6338 end if;
6339
6340 if Prefix_Is_Type then
6341
6342 -- For VMs we leave the type attribute unexpanded because
6343 -- there's not a dispatching table to reference.
6344
6345 if Tagged_Type_Expansion then
6346 Rewrite (N,
6347 Unchecked_Convert_To (RTE (RE_Tag),
6348 New_Occurrence_Of
6349 (Node (First_Elmt (Access_Disp_Table (Ttyp))), Loc)));
6350 Analyze_And_Resolve (N, RTE (RE_Tag));
6351 end if;
6352
6353 -- Ada 2005 (AI-251): The use of 'Tag in the sources always
6354 -- references the primary tag of the actual object. If 'Tag is
6355 -- applied to class-wide interface objects we generate code that
6356 -- displaces "this" to reference the base of the object.
6357
6358 elsif Comes_From_Source (N)
6359 and then Is_Class_Wide_Type (Etype (Prefix (N)))
6360 and then Is_Interface (Underlying_Type (Etype (Prefix (N))))
6361 then
6362 -- Generate:
6363 -- (To_Tag_Ptr (Prefix'Address)).all
6364
6365 -- Note that Prefix'Address is recursively expanded into a call
6366 -- to Base_Address (Obj.Tag)
6367
6368 -- Not needed for VM targets, since all handled by the VM
6369
6370 if Tagged_Type_Expansion then
6371 Rewrite (N,
6372 Make_Explicit_Dereference (Loc,
6373 Unchecked_Convert_To (RTE (RE_Tag_Ptr),
6374 Make_Attribute_Reference (Loc,
6375 Prefix => Relocate_Node (Pref),
6376 Attribute_Name => Name_Address))));
6377 Analyze_And_Resolve (N, RTE (RE_Tag));
6378 end if;
6379
6380 else
6381 Rewrite (N,
6382 Make_Selected_Component (Loc,
6383 Prefix => Relocate_Node (Pref),
6384 Selector_Name =>
6385 New_Occurrence_Of (First_Tag_Component (Ttyp), Loc)));
6386 Analyze_And_Resolve (N, RTE (RE_Tag));
6387 end if;
6388 end Tag;
6389
6390 ----------------
6391 -- Terminated --
6392 ----------------
6393
6394 -- Transforms 'Terminated attribute into a call to Terminated function
6395
6396 when Attribute_Terminated => Terminated : begin
6397
6398 -- The prefix of Terminated is of a task interface class-wide type.
6399 -- Generate:
6400 -- terminated (Task_Id (_disp_get_task_id (Pref)));
6401
6402 if Ada_Version >= Ada_2005
6403 and then Ekind (Ptyp) = E_Class_Wide_Type
6404 and then Is_Interface (Ptyp)
6405 and then Is_Task_Interface (Ptyp)
6406 then
6407 Rewrite (N,
6408 Make_Function_Call (Loc,
6409 Name =>
6410 New_Occurrence_Of (RTE (RE_Terminated), Loc),
6411 Parameter_Associations => New_List (
6412 Make_Unchecked_Type_Conversion (Loc,
6413 Subtype_Mark =>
6414 New_Occurrence_Of (RTE (RO_ST_Task_Id), Loc),
6415 Expression => Build_Disp_Get_Task_Id_Call (Pref)))));
6416
6417 elsif Restricted_Profile then
6418 Rewrite (N,
6419 Build_Call_With_Task (Pref, RTE (RE_Restricted_Terminated)));
6420
6421 else
6422 Rewrite (N,
6423 Build_Call_With_Task (Pref, RTE (RE_Terminated)));
6424 end if;
6425
6426 Analyze_And_Resolve (N, Standard_Boolean);
6427 end Terminated;
6428
6429 ----------------
6430 -- To_Address --
6431 ----------------
6432
6433 -- Transforms System'To_Address (X) and System.Address'Ref (X) into
6434 -- unchecked conversion from (integral) type of X to type address. If
6435 -- the To_Address is a static expression, the transformed expression
6436 -- also needs to be static, because we do some legality checks (e.g.
6437 -- for Thread_Local_Storage) after this transformation.
6438
6439 when Attribute_Ref
6440 | Attribute_To_Address
6441 =>
6442 To_Address : declare
6443 Is_Static : constant Boolean := Is_Static_Expression (N);
6444
6445 begin
6446 Rewrite (N,
6447 Unchecked_Convert_To (RTE (RE_Address),
6448 Relocate_Node (First (Exprs))));
6449 Set_Is_Static_Expression (N, Is_Static);
6450
6451 Analyze_And_Resolve (N, RTE (RE_Address));
6452 end To_Address;
6453
6454 ------------
6455 -- To_Any --
6456 ------------
6457
6458 when Attribute_To_Any => To_Any : declare
6459 Decls : constant List_Id := New_List;
6460 begin
6461 Rewrite (N,
6462 Build_To_Any_Call
6463 (Loc,
6464 Convert_To (Ptyp,
6465 Relocate_Node (First (Exprs))), Decls));
6466 Insert_Actions (N, Decls);
6467 Analyze_And_Resolve (N, RTE (RE_Any));
6468 end To_Any;
6469
6470 ----------------
6471 -- Truncation --
6472 ----------------
6473
6474 -- Transforms 'Truncation into a call to the floating-point attribute
6475 -- function Truncation in Fat_xxx (where xxx is the root type).
6476 -- Expansion is avoided for cases the back end can handle directly.
6477
6478 when Attribute_Truncation =>
6479 if not Is_Inline_Floating_Point_Attribute (N) then
6480 Expand_Fpt_Attribute_R (N);
6481 end if;
6482
6483 --------------
6484 -- TypeCode --
6485 --------------
6486
6487 when Attribute_TypeCode => TypeCode : declare
6488 Decls : constant List_Id := New_List;
6489 begin
6490 Rewrite (N, Build_TypeCode_Call (Loc, Ptyp, Decls));
6491 Insert_Actions (N, Decls);
6492 Analyze_And_Resolve (N, RTE (RE_TypeCode));
6493 end TypeCode;
6494
6495 -----------------------
6496 -- Unbiased_Rounding --
6497 -----------------------
6498
6499 -- Transforms 'Unbiased_Rounding into a call to the floating-point
6500 -- attribute function Unbiased_Rounding in Fat_xxx (where xxx is the
6501 -- root type). Expansion is avoided for cases the back end can handle
6502 -- directly.
6503
6504 when Attribute_Unbiased_Rounding =>
6505 if not Is_Inline_Floating_Point_Attribute (N) then
6506 Expand_Fpt_Attribute_R (N);
6507 end if;
6508
6509 ------------
6510 -- Update --
6511 ------------
6512
6513 when Attribute_Update =>
6514 Expand_Update_Attribute (N);
6515
6516 ---------------
6517 -- VADS_Size --
6518 ---------------
6519
6520 -- The processing for VADS_Size is shared with Size
6521
6522 ---------
6523 -- Val --
6524 ---------
6525
6526 -- For enumeration types with a standard representation, Val is handled
6527 -- by the back end.
6528
6529 -- For enumeration types with a non-standard representation we use the
6530 -- _Pos_To_Rep array that was created when the type was frozen, unless
6531 -- the representation is contiguous in which case we use an addition.
6532
6533 -- For integer types, Val is equivalent to a simple integer conversion
6534 -- and we rewrite it as such.
6535
6536 when Attribute_Val => Val : declare
6537 Etyp : constant Entity_Id := Base_Type (Ptyp);
6538 Expr : constant Node_Id := First (Exprs);
6539
6540 begin
6541 -- Case of enumeration type
6542
6543 if Is_Enumeration_Type (Etyp) then
6544
6545 -- Non-standard enumeration type
6546
6547 if Present (Enum_Pos_To_Rep (Etyp)) then
6548 if Has_Contiguous_Rep (Etyp) then
6549 declare
6550 Rep_Node : constant Node_Id :=
6551 Unchecked_Convert_To (Etyp,
6552 Make_Op_Add (Loc,
6553 Left_Opnd =>
6554 Make_Integer_Literal (Loc,
6555 Enumeration_Rep (First_Literal (Etyp))),
6556 Right_Opnd =>
6557 Convert_To (Standard_Integer, Expr)));
6558
6559 begin
6560 Rewrite (N,
6561 Unchecked_Convert_To (Etyp,
6562 Make_Op_Add (Loc,
6563 Left_Opnd =>
6564 Make_Integer_Literal (Loc,
6565 Enumeration_Rep (First_Literal (Etyp))),
6566 Right_Opnd =>
6567 Make_Function_Call (Loc,
6568 Name =>
6569 New_Occurrence_Of
6570 (TSS (Etyp, TSS_Rep_To_Pos), Loc),
6571 Parameter_Associations => New_List (
6572 Rep_Node,
6573 Rep_To_Pos_Flag (Etyp, Loc))))));
6574 end;
6575
6576 else
6577 Rewrite (N,
6578 Make_Indexed_Component (Loc,
6579 Prefix =>
6580 New_Occurrence_Of (Enum_Pos_To_Rep (Etyp), Loc),
6581 Expressions => New_List (
6582 Convert_To (Standard_Integer, Expr))));
6583 end if;
6584
6585 Analyze_And_Resolve (N, Typ);
6586
6587 -- Standard enumeration type
6588
6589 -- If the argument is marked as requiring a range check then
6590 -- generate it here, after looking through a conversion to
6591 -- universal integer, if any.
6592
6593 elsif Do_Range_Check (Expr) then
6594 if Nkind (Expr) = N_Type_Conversion
6595 and then Entity (Subtype_Mark (Expr)) = Universal_Integer
6596 then
6597 Generate_Range_Check
6598 (Expression (Expr), Etyp, CE_Range_Check_Failed);
6599 Set_Do_Range_Check (Expr, False);
6600
6601 else
6602 Generate_Range_Check (Expr, Etyp, CE_Range_Check_Failed);
6603 end if;
6604 end if;
6605
6606 -- Deal with integer types
6607
6608 elsif Is_Integer_Type (Etyp) then
6609 Rewrite (N, Convert_To (Typ, Expr));
6610 Analyze_And_Resolve (N, Typ);
6611 end if;
6612 end Val;
6613
6614 -----------
6615 -- Valid --
6616 -----------
6617
6618 -- The code for valid is dependent on the particular types involved.
6619 -- See separate sections below for the generated code in each case.
6620
6621 when Attribute_Valid => Valid : declare
6622 PBtyp : Entity_Id := Base_Type (Ptyp);
6623
6624 Save_Validity_Checks_On : constant Boolean := Validity_Checks_On;
6625 -- Save the validity checking mode. We always turn off validity
6626 -- checking during process of 'Valid since this is one place
6627 -- where we do not want the implicit validity checks to interfere
6628 -- with the explicit validity check that the programmer is doing.
6629
6630 function Make_Range_Test return Node_Id;
6631 -- Build the code for a range test of the form
6632 -- PBtyp!(Pref) in PBtyp!(Ptyp'First) .. PBtyp!(Ptyp'Last)
6633
6634 ---------------------
6635 -- Make_Range_Test --
6636 ---------------------
6637
6638 function Make_Range_Test return Node_Id is
6639 Temp : Node_Id;
6640
6641 begin
6642 -- The prefix of attribute 'Valid should always denote an object
6643 -- reference. The reference is either coming directly from source
6644 -- or is produced by validity check expansion. The object may be
6645 -- wrapped in a conversion in which case the call to Unqual_Conv
6646 -- will yield it.
6647
6648 -- If the prefix denotes a variable which captures the value of
6649 -- an object for validation purposes, use the variable in the
6650 -- range test. This ensures that no extra copies or extra reads
6651 -- are produced as part of the test. Generate:
6652
6653 -- Temp : ... := Object;
6654 -- if not Temp in ... then
6655
6656 if Is_Validation_Variable_Reference (Pref) then
6657 Temp := New_Occurrence_Of (Entity (Unqual_Conv (Pref)), Loc);
6658
6659 -- Otherwise the prefix is either a source object or a constant
6660 -- produced by validity check expansion. Generate:
6661
6662 -- Temp : constant ... := Pref;
6663 -- if not Temp in ... then
6664
6665 else
6666 Temp := Duplicate_Subexpr (Pref);
6667 end if;
6668
6669 return
6670 Make_In (Loc,
6671 Left_Opnd => Unchecked_Convert_To (PBtyp, Temp),
6672 Right_Opnd =>
6673 Make_Range (Loc,
6674 Low_Bound =>
6675 Unchecked_Convert_To (PBtyp,
6676 Make_Attribute_Reference (Loc,
6677 Prefix => New_Occurrence_Of (Ptyp, Loc),
6678 Attribute_Name => Name_First)),
6679 High_Bound =>
6680 Unchecked_Convert_To (PBtyp,
6681 Make_Attribute_Reference (Loc,
6682 Prefix => New_Occurrence_Of (Ptyp, Loc),
6683 Attribute_Name => Name_Last))));
6684 end Make_Range_Test;
6685
6686 -- Local variables
6687
6688 Tst : Node_Id;
6689
6690 -- Start of processing for Attribute_Valid
6691
6692 begin
6693 -- Do not expand sourced code 'Valid reference in CodePeer mode,
6694 -- will be handled by the back-end directly.
6695
6696 if CodePeer_Mode and then Comes_From_Source (N) then
6697 return;
6698 end if;
6699
6700 -- Turn off validity checks. We do not want any implicit validity
6701 -- checks to intefere with the explicit check from the attribute
6702
6703 Validity_Checks_On := False;
6704
6705 -- Retrieve the base type. Handle the case where the base type is a
6706 -- private enumeration type.
6707
6708 if Is_Private_Type (PBtyp) and then Present (Full_View (PBtyp)) then
6709 PBtyp := Full_View (PBtyp);
6710 end if;
6711
6712 -- Floating-point case. This case is handled by the Valid attribute
6713 -- code in the floating-point attribute run-time library.
6714
6715 if Is_Floating_Point_Type (Ptyp) then
6716 Float_Valid : declare
6717 Pkg : RE_Id;
6718 Ftp : Entity_Id;
6719
6720 function Get_Fat_Entity (Nam : Name_Id) return Entity_Id;
6721 -- Return entity for Pkg.Nam
6722
6723 --------------------
6724 -- Get_Fat_Entity --
6725 --------------------
6726
6727 function Get_Fat_Entity (Nam : Name_Id) return Entity_Id is
6728 Exp_Name : constant Node_Id :=
6729 Make_Selected_Component (Loc,
6730 Prefix => New_Occurrence_Of (RTE (Pkg), Loc),
6731 Selector_Name => Make_Identifier (Loc, Nam));
6732 begin
6733 Find_Selected_Component (Exp_Name);
6734 return Entity (Exp_Name);
6735 end Get_Fat_Entity;
6736
6737 -- Start of processing for Float_Valid
6738
6739 begin
6740 -- The C and AAMP back-ends handle Valid for fpt types
6741
6742 if Modify_Tree_For_C or else Float_Rep (PBtyp) = AAMP then
6743 Analyze_And_Resolve (Pref, Ptyp);
6744 Set_Etype (N, Standard_Boolean);
6745 Set_Analyzed (N);
6746
6747 else
6748 Find_Fat_Info (Ptyp, Ftp, Pkg);
6749
6750 -- If the prefix is a reverse SSO component, or is possibly
6751 -- unaligned, first create a temporary copy that is in
6752 -- native SSO, and properly aligned. Make it Volatile to
6753 -- prevent folding in the back-end. Note that we use an
6754 -- intermediate constrained string type to initialize the
6755 -- temporary, as the value at hand might be invalid, and in
6756 -- that case it cannot be copied using a floating point
6757 -- register.
6758
6759 if In_Reverse_Storage_Order_Object (Pref)
6760 or else Is_Possibly_Unaligned_Object (Pref)
6761 then
6762 declare
6763 Temp : constant Entity_Id :=
6764 Make_Temporary (Loc, 'F');
6765
6766 Fat_S : constant Entity_Id :=
6767 Get_Fat_Entity (Name_S);
6768 -- Constrained string subtype of appropriate size
6769
6770 Fat_P : constant Entity_Id :=
6771 Get_Fat_Entity (Name_P);
6772 -- Access to Fat_S
6773
6774 Decl : constant Node_Id :=
6775 Make_Object_Declaration (Loc,
6776 Defining_Identifier => Temp,
6777 Aliased_Present => True,
6778 Object_Definition =>
6779 New_Occurrence_Of (Ptyp, Loc));
6780
6781 begin
6782 Set_Aspect_Specifications (Decl, New_List (
6783 Make_Aspect_Specification (Loc,
6784 Identifier =>
6785 Make_Identifier (Loc, Name_Volatile))));
6786
6787 Insert_Actions (N,
6788 New_List (
6789 Decl,
6790
6791 Make_Assignment_Statement (Loc,
6792 Name =>
6793 Make_Explicit_Dereference (Loc,
6794 Prefix =>
6795 Unchecked_Convert_To (Fat_P,
6796 Make_Attribute_Reference (Loc,
6797 Prefix =>
6798 New_Occurrence_Of (Temp, Loc),
6799 Attribute_Name =>
6800 Name_Unrestricted_Access))),
6801 Expression =>
6802 Unchecked_Convert_To (Fat_S,
6803 Relocate_Node (Pref)))),
6804
6805 Suppress => All_Checks);
6806
6807 Rewrite (Pref, New_Occurrence_Of (Temp, Loc));
6808 end;
6809 end if;
6810
6811 -- We now have an object of the proper endianness and
6812 -- alignment, and can construct a Valid attribute.
6813
6814 -- We make sure the prefix of this valid attribute is
6815 -- marked as not coming from source, to avoid losing
6816 -- warnings from 'Valid looking like a possible update.
6817
6818 Set_Comes_From_Source (Pref, False);
6819
6820 Expand_Fpt_Attribute
6821 (N, Pkg, Name_Valid,
6822 New_List (
6823 Make_Attribute_Reference (Loc,
6824 Prefix => Unchecked_Convert_To (Ftp, Pref),
6825 Attribute_Name => Name_Unrestricted_Access)));
6826 end if;
6827
6828 -- One more task, we still need a range check. Required
6829 -- only if we have a constraint, since the Valid routine
6830 -- catches infinities properly (infinities are never valid).
6831
6832 -- The way we do the range check is simply to create the
6833 -- expression: Valid (N) and then Base_Type(Pref) in Typ.
6834
6835 if not Subtypes_Statically_Match (Ptyp, PBtyp) then
6836 Rewrite (N,
6837 Make_And_Then (Loc,
6838 Left_Opnd => Relocate_Node (N),
6839 Right_Opnd =>
6840 Make_In (Loc,
6841 Left_Opnd => Convert_To (PBtyp, Pref),
6842 Right_Opnd => New_Occurrence_Of (Ptyp, Loc))));
6843 end if;
6844 end Float_Valid;
6845
6846 -- Enumeration type with holes
6847
6848 -- For enumeration types with holes, the Pos value constructed by
6849 -- the Enum_Rep_To_Pos function built in Exp_Ch3 called with a
6850 -- second argument of False returns minus one for an invalid value,
6851 -- and the non-negative pos value for a valid value, so the
6852 -- expansion of X'Valid is simply:
6853
6854 -- type(X)'Pos (X) >= 0
6855
6856 -- We can't quite generate it that way because of the requirement
6857 -- for the non-standard second argument of False in the resulting
6858 -- rep_to_pos call, so we have to explicitly create:
6859
6860 -- _rep_to_pos (X, False) >= 0
6861
6862 -- If we have an enumeration subtype, we also check that the
6863 -- value is in range:
6864
6865 -- _rep_to_pos (X, False) >= 0
6866 -- and then
6867 -- (X >= type(X)'First and then type(X)'Last <= X)
6868
6869 elsif Is_Enumeration_Type (Ptyp)
6870 and then Present (Enum_Pos_To_Rep (PBtyp))
6871 then
6872 Tst :=
6873 Make_Op_Ge (Loc,
6874 Left_Opnd =>
6875 Make_Function_Call (Loc,
6876 Name =>
6877 New_Occurrence_Of (TSS (PBtyp, TSS_Rep_To_Pos), Loc),
6878 Parameter_Associations => New_List (
6879 Pref,
6880 New_Occurrence_Of (Standard_False, Loc))),
6881 Right_Opnd => Make_Integer_Literal (Loc, 0));
6882
6883 if Ptyp /= PBtyp
6884 and then
6885 (Type_Low_Bound (Ptyp) /= Type_Low_Bound (PBtyp)
6886 or else
6887 Type_High_Bound (Ptyp) /= Type_High_Bound (PBtyp))
6888 then
6889 -- The call to Make_Range_Test will create declarations
6890 -- that need a proper insertion point, but Pref is now
6891 -- attached to a node with no ancestor. Attach to tree
6892 -- even if it is to be rewritten below.
6893
6894 Set_Parent (Tst, Parent (N));
6895
6896 Tst :=
6897 Make_And_Then (Loc,
6898 Left_Opnd => Make_Range_Test,
6899 Right_Opnd => Tst);
6900 end if;
6901
6902 Rewrite (N, Tst);
6903
6904 -- Fortran convention booleans
6905
6906 -- For the very special case of Fortran convention booleans, the
6907 -- value is always valid, since it is an integer with the semantics
6908 -- that non-zero is true, and any value is permissible.
6909
6910 elsif Is_Boolean_Type (Ptyp)
6911 and then Convention (Ptyp) = Convention_Fortran
6912 then
6913 Rewrite (N, New_Occurrence_Of (Standard_True, Loc));
6914
6915 -- For biased representations, we will be doing an unchecked
6916 -- conversion without unbiasing the result. That means that the range
6917 -- test has to take this into account, and the proper form of the
6918 -- test is:
6919
6920 -- PBtyp!(Pref) < PBtyp!(Ptyp'Range_Length)
6921
6922 elsif Has_Biased_Representation (Ptyp) then
6923 PBtyp := RTE (RE_Unsigned_32);
6924 Rewrite (N,
6925 Make_Op_Lt (Loc,
6926 Left_Opnd =>
6927 Unchecked_Convert_To (PBtyp, Duplicate_Subexpr (Pref)),
6928 Right_Opnd =>
6929 Unchecked_Convert_To (PBtyp,
6930 Make_Attribute_Reference (Loc,
6931 Prefix => New_Occurrence_Of (Ptyp, Loc),
6932 Attribute_Name => Name_Range_Length))));
6933
6934 -- For all other scalar types, what we want logically is a
6935 -- range test:
6936
6937 -- X in type(X)'First .. type(X)'Last
6938
6939 -- But that's precisely what won't work because of possible
6940 -- unwanted optimization (and indeed the basic motivation for
6941 -- the Valid attribute is exactly that this test does not work).
6942 -- What will work is:
6943
6944 -- PBtyp!(X) >= PBtyp!(type(X)'First)
6945 -- and then
6946 -- PBtyp!(X) <= PBtyp!(type(X)'Last)
6947
6948 -- where PBtyp is an integer type large enough to cover the full
6949 -- range of possible stored values (i.e. it is chosen on the basis
6950 -- of the size of the type, not the range of the values). We write
6951 -- this as two tests, rather than a range check, so that static
6952 -- evaluation will easily remove either or both of the checks if
6953 -- they can be -statically determined to be true (this happens
6954 -- when the type of X is static and the range extends to the full
6955 -- range of stored values).
6956
6957 -- Unsigned types. Note: it is safe to consider only whether the
6958 -- subtype is unsigned, since we will in that case be doing all
6959 -- unsigned comparisons based on the subtype range. Since we use the
6960 -- actual subtype object size, this is appropriate.
6961
6962 -- For example, if we have
6963
6964 -- subtype x is integer range 1 .. 200;
6965 -- for x'Object_Size use 8;
6966
6967 -- Now the base type is signed, but objects of this type are bits
6968 -- unsigned, and doing an unsigned test of the range 1 to 200 is
6969 -- correct, even though a value greater than 127 looks signed to a
6970 -- signed comparison.
6971
6972 elsif Is_Unsigned_Type (Ptyp)
6973 or else (Is_Private_Type (Ptyp) and then Is_Unsigned_Type (Btyp))
6974 then
6975 if Esize (Ptyp) <= 32 then
6976 PBtyp := RTE (RE_Unsigned_32);
6977 else
6978 PBtyp := RTE (RE_Unsigned_64);
6979 end if;
6980
6981 Rewrite (N, Make_Range_Test);
6982
6983 -- Signed types
6984
6985 else
6986 if Esize (Ptyp) <= Esize (Standard_Integer) then
6987 PBtyp := Standard_Integer;
6988 else
6989 PBtyp := Standard_Long_Long_Integer;
6990 end if;
6991
6992 Rewrite (N, Make_Range_Test);
6993 end if;
6994
6995 -- If a predicate is present, then we do the predicate test, even if
6996 -- within the predicate function (infinite recursion is warned about
6997 -- in Sem_Attr in that case).
6998
6999 declare
7000 Pred_Func : constant Entity_Id := Predicate_Function (Ptyp);
7001
7002 begin
7003 if Present (Pred_Func) then
7004 Rewrite (N,
7005 Make_And_Then (Loc,
7006 Left_Opnd => Relocate_Node (N),
7007 Right_Opnd => Make_Predicate_Call (Ptyp, Pref)));
7008 end if;
7009 end;
7010
7011 Analyze_And_Resolve (N, Standard_Boolean);
7012 Validity_Checks_On := Save_Validity_Checks_On;
7013 end Valid;
7014
7015 -------------------
7016 -- Valid_Scalars --
7017 -------------------
7018
7019 when Attribute_Valid_Scalars => Valid_Scalars : declare
7020 Val_Typ : constant Entity_Id := Validated_View (Ptyp);
7021 Comp_Typ : Entity_Id;
7022 Expr : Node_Id;
7023
7024 begin
7025 -- Assume that the prefix does not need validation
7026
7027 Expr := Empty;
7028
7029 -- Attribute 'Valid_Scalars is not supported on private tagged types
7030
7031 if Is_Private_Type (Ptyp) and then Is_Tagged_Type (Ptyp) then
7032 null;
7033
7034 -- Attribute 'Valid_Scalars evaluates to True when the type lacks
7035 -- scalars.
7036
7037 elsif not Scalar_Part_Present (Val_Typ) then
7038 null;
7039
7040 -- Attribute 'Valid_Scalars is the same as attribute 'Valid when the
7041 -- validated type is a scalar type. Generate:
7042
7043 -- Val_Typ (Pref)'Valid
7044
7045 elsif Is_Scalar_Type (Val_Typ) then
7046 Expr :=
7047 Make_Attribute_Reference (Loc,
7048 Prefix =>
7049 Unchecked_Convert_To (Val_Typ, New_Copy_Tree (Pref)),
7050 Attribute_Name => Name_Valid);
7051
7052 -- Validate the scalar components of an array by iterating over all
7053 -- dimensions of the array while checking individual components.
7054
7055 elsif Is_Array_Type (Val_Typ) then
7056 Comp_Typ := Validated_View (Component_Type (Val_Typ));
7057
7058 if Scalar_Part_Present (Comp_Typ) then
7059 Expr :=
7060 Make_Function_Call (Loc,
7061 Name =>
7062 New_Occurrence_Of
7063 (Build_Array_VS_Func
7064 (Attr => N,
7065 Formal_Typ => Ptyp,
7066 Array_Typ => Val_Typ,
7067 Comp_Typ => Comp_Typ),
7068 Loc),
7069 Parameter_Associations => New_List (Pref));
7070 end if;
7071
7072 -- Validate the scalar components, discriminants of a record type by
7073 -- examining the structure of a record type.
7074
7075 elsif Is_Record_Type (Val_Typ) then
7076 Expr :=
7077 Make_Function_Call (Loc,
7078 Name =>
7079 New_Occurrence_Of
7080 (Build_Record_VS_Func
7081 (Attr => N,
7082 Formal_Typ => Ptyp,
7083 Rec_Typ => Val_Typ),
7084 Loc),
7085 Parameter_Associations => New_List (Pref));
7086 end if;
7087
7088 -- Default the attribute to True when the type of the prefix does not
7089 -- need validation.
7090
7091 if No (Expr) then
7092 Expr := New_Occurrence_Of (Standard_True, Loc);
7093 end if;
7094
7095 Rewrite (N, Expr);
7096 Analyze_And_Resolve (N, Standard_Boolean);
7097 Set_Is_Static_Expression (N, False);
7098 end Valid_Scalars;
7099
7100 -----------
7101 -- Value --
7102 -----------
7103
7104 -- Value attribute is handled in separate unit Exp_Imgv
7105
7106 when Attribute_Value =>
7107 Exp_Imgv.Expand_Value_Attribute (N);
7108
7109 -----------------
7110 -- Value_Size --
7111 -----------------
7112
7113 -- The processing for Value_Size shares the processing for Size
7114
7115 -------------
7116 -- Version --
7117 -------------
7118
7119 -- The processing for Version shares the processing for Body_Version
7120
7121 ----------------
7122 -- Wide_Image --
7123 ----------------
7124
7125 -- Wide_Image attribute is handled in separate unit Exp_Imgv
7126
7127 when Attribute_Wide_Image =>
7128 -- Leave attribute unexpanded in CodePeer mode: the gnat2scil
7129 -- back-end knows how to handle this attribute directly.
7130
7131 if CodePeer_Mode then
7132 return;
7133 end if;
7134
7135 Exp_Imgv.Expand_Wide_Image_Attribute (N);
7136
7137 ---------------------
7138 -- Wide_Wide_Image --
7139 ---------------------
7140
7141 -- Wide_Wide_Image attribute is handled in separate unit Exp_Imgv
7142
7143 when Attribute_Wide_Wide_Image =>
7144 -- Leave attribute unexpanded in CodePeer mode: the gnat2scil
7145 -- back-end knows how to handle this attribute directly.
7146
7147 if CodePeer_Mode then
7148 return;
7149 end if;
7150
7151 Exp_Imgv.Expand_Wide_Wide_Image_Attribute (N);
7152
7153 ----------------
7154 -- Wide_Value --
7155 ----------------
7156
7157 -- We expand typ'Wide_Value (X) into
7158
7159 -- typ'Value
7160 -- (Wide_String_To_String (X, Wide_Character_Encoding_Method))
7161
7162 -- Wide_String_To_String is a runtime function that converts its wide
7163 -- string argument to String, converting any non-translatable characters
7164 -- into appropriate escape sequences. This preserves the required
7165 -- semantics of Wide_Value in all cases, and results in a very simple
7166 -- implementation approach.
7167
7168 -- Note: for this approach to be fully standard compliant for the cases
7169 -- where typ is Wide_Character and Wide_Wide_Character, the encoding
7170 -- method must cover the entire character range (e.g. UTF-8). But that
7171 -- is a reasonable requirement when dealing with encoded character
7172 -- sequences. Presumably if one of the restrictive encoding mechanisms
7173 -- is in use such as Shift-JIS, then characters that cannot be
7174 -- represented using this encoding will not appear in any case.
7175
7176 when Attribute_Wide_Value =>
7177 Rewrite (N,
7178 Make_Attribute_Reference (Loc,
7179 Prefix => Pref,
7180 Attribute_Name => Name_Value,
7181
7182 Expressions => New_List (
7183 Make_Function_Call (Loc,
7184 Name =>
7185 New_Occurrence_Of (RTE (RE_Wide_String_To_String), Loc),
7186
7187 Parameter_Associations => New_List (
7188 Relocate_Node (First (Exprs)),
7189 Make_Integer_Literal (Loc,
7190 Intval => Int (Wide_Character_Encoding_Method)))))));
7191
7192 Analyze_And_Resolve (N, Typ);
7193
7194 ---------------------
7195 -- Wide_Wide_Value --
7196 ---------------------
7197
7198 -- We expand typ'Wide_Value_Value (X) into
7199
7200 -- typ'Value
7201 -- (Wide_Wide_String_To_String (X, Wide_Character_Encoding_Method))
7202
7203 -- Wide_Wide_String_To_String is a runtime function that converts its
7204 -- wide string argument to String, converting any non-translatable
7205 -- characters into appropriate escape sequences. This preserves the
7206 -- required semantics of Wide_Wide_Value in all cases, and results in a
7207 -- very simple implementation approach.
7208
7209 -- It's not quite right where typ = Wide_Wide_Character, because the
7210 -- encoding method may not cover the whole character type ???
7211
7212 when Attribute_Wide_Wide_Value =>
7213 Rewrite (N,
7214 Make_Attribute_Reference (Loc,
7215 Prefix => Pref,
7216 Attribute_Name => Name_Value,
7217
7218 Expressions => New_List (
7219 Make_Function_Call (Loc,
7220 Name =>
7221 New_Occurrence_Of
7222 (RTE (RE_Wide_Wide_String_To_String), Loc),
7223
7224 Parameter_Associations => New_List (
7225 Relocate_Node (First (Exprs)),
7226 Make_Integer_Literal (Loc,
7227 Intval => Int (Wide_Character_Encoding_Method)))))));
7228
7229 Analyze_And_Resolve (N, Typ);
7230
7231 ---------------------
7232 -- Wide_Wide_Width --
7233 ---------------------
7234
7235 -- Wide_Wide_Width attribute is handled in separate unit Exp_Imgv
7236
7237 when Attribute_Wide_Wide_Width =>
7238 Exp_Imgv.Expand_Width_Attribute (N, Wide_Wide);
7239
7240 ----------------
7241 -- Wide_Width --
7242 ----------------
7243
7244 -- Wide_Width attribute is handled in separate unit Exp_Imgv
7245
7246 when Attribute_Wide_Width =>
7247 Exp_Imgv.Expand_Width_Attribute (N, Wide);
7248
7249 -----------
7250 -- Width --
7251 -----------
7252
7253 -- Width attribute is handled in separate unit Exp_Imgv
7254
7255 when Attribute_Width =>
7256 Exp_Imgv.Expand_Width_Attribute (N, Normal);
7257
7258 -----------
7259 -- Write --
7260 -----------
7261
7262 when Attribute_Write => Write : declare
7263 P_Type : constant Entity_Id := Entity (Pref);
7264 U_Type : constant Entity_Id := Underlying_Type (P_Type);
7265 Pname : Entity_Id;
7266 Decl : Node_Id;
7267 Prag : Node_Id;
7268 Arg3 : Node_Id;
7269 Wfunc : Node_Id;
7270
7271 begin
7272 -- If no underlying type, we have an error that will be diagnosed
7273 -- elsewhere, so here we just completely ignore the expansion.
7274
7275 if No (U_Type) then
7276 return;
7277 end if;
7278
7279 -- Stream operations can appear in user code even if the restriction
7280 -- No_Streams is active (for example, when instantiating a predefined
7281 -- container). In that case rewrite the attribute as a Raise to
7282 -- prevent any run-time use.
7283
7284 if Restriction_Active (No_Streams) then
7285 Rewrite (N,
7286 Make_Raise_Program_Error (Sloc (N),
7287 Reason => PE_Stream_Operation_Not_Allowed));
7288 Set_Etype (N, U_Type);
7289 return;
7290 end if;
7291
7292 -- The simple case, if there is a TSS for Write, just call it
7293
7294 Pname := Find_Stream_Subprogram (P_Type, TSS_Stream_Write);
7295
7296 if Present (Pname) then
7297 null;
7298
7299 else
7300 -- If there is a Stream_Convert pragma, use it, we rewrite
7301
7302 -- sourcetyp'Output (stream, Item)
7303
7304 -- as
7305
7306 -- strmtyp'Output (Stream, strmwrite (acttyp (Item)));
7307
7308 -- where strmwrite is the given Write function that converts an
7309 -- argument of type sourcetyp or a type acctyp, from which it is
7310 -- derived to type strmtyp. The conversion to acttyp is required
7311 -- for the derived case.
7312
7313 Prag := Get_Stream_Convert_Pragma (P_Type);
7314
7315 if Present (Prag) then
7316 Arg3 :=
7317 Next (Next (First (Pragma_Argument_Associations (Prag))));
7318 Wfunc := Entity (Expression (Arg3));
7319
7320 Rewrite (N,
7321 Make_Attribute_Reference (Loc,
7322 Prefix => New_Occurrence_Of (Etype (Wfunc), Loc),
7323 Attribute_Name => Name_Output,
7324 Expressions => New_List (
7325 Relocate_Node (First (Exprs)),
7326 Make_Function_Call (Loc,
7327 Name => New_Occurrence_Of (Wfunc, Loc),
7328 Parameter_Associations => New_List (
7329 OK_Convert_To (Etype (First_Formal (Wfunc)),
7330 Relocate_Node (Next (First (Exprs)))))))));
7331
7332 Analyze (N);
7333 return;
7334
7335 -- For elementary types, we call the W_xxx routine directly
7336
7337 elsif Is_Elementary_Type (U_Type) then
7338 Rewrite (N, Build_Elementary_Write_Call (N));
7339 Analyze (N);
7340 return;
7341
7342 -- Array type case
7343
7344 elsif Is_Array_Type (U_Type) then
7345 Build_Array_Write_Procedure (N, U_Type, Decl, Pname);
7346 Compile_Stream_Body_In_Scope (N, Decl, U_Type, Check => False);
7347
7348 -- Tagged type case, use the primitive Write function. Note that
7349 -- this will dispatch in the class-wide case which is what we want
7350
7351 elsif Is_Tagged_Type (U_Type) then
7352 Pname := Find_Prim_Op (U_Type, TSS_Stream_Write);
7353
7354 -- All other record type cases, including protected records.
7355 -- The latter only arise for expander generated code for
7356 -- handling shared passive partition access.
7357
7358 else
7359 pragma Assert
7360 (Is_Record_Type (U_Type) or else Is_Protected_Type (U_Type));
7361
7362 -- Ada 2005 (AI-216): Program_Error is raised when executing
7363 -- the default implementation of the Write attribute of an
7364 -- Unchecked_Union type. However, if the 'Write reference is
7365 -- within the generated Output stream procedure, Write outputs
7366 -- the components, and the default values of the discriminant
7367 -- are streamed by the Output procedure itself. If there are
7368 -- no default values this is also erroneous.
7369
7370 if Is_Unchecked_Union (Base_Type (U_Type)) then
7371 if (not Is_TSS (Current_Scope, TSS_Stream_Output)
7372 and not Is_TSS (Current_Scope, TSS_Stream_Write))
7373 or else No (Discriminant_Default_Value
7374 (First_Discriminant (U_Type)))
7375 then
7376 Rewrite (N,
7377 Make_Raise_Program_Error (Loc,
7378 Reason => PE_Unchecked_Union_Restriction));
7379 Set_Etype (N, U_Type);
7380 return;
7381 end if;
7382 end if;
7383
7384 if Has_Discriminants (U_Type)
7385 and then Present
7386 (Discriminant_Default_Value (First_Discriminant (U_Type)))
7387 then
7388 Build_Mutable_Record_Write_Procedure
7389 (Loc, Full_Base (U_Type), Decl, Pname);
7390 else
7391 Build_Record_Write_Procedure
7392 (Loc, Full_Base (U_Type), Decl, Pname);
7393 end if;
7394
7395 Insert_Action (N, Decl);
7396 end if;
7397 end if;
7398
7399 -- If we fall through, Pname is the procedure to be called
7400
7401 Rewrite_Stream_Proc_Call (Pname);
7402 end Write;
7403
7404 -- Component_Size is handled by the back end, unless the component size
7405 -- is known at compile time, which is always true in the packed array
7406 -- case. It is important that the packed array case is handled in the
7407 -- front end (see Eval_Attribute) since the back end would otherwise get
7408 -- confused by the equivalent packed array type.
7409
7410 when Attribute_Component_Size =>
7411 null;
7412
7413 -- The following attributes are handled by the back end (except that
7414 -- static cases have already been evaluated during semantic processing,
7415 -- but in any case the back end should not count on this).
7416
7417 -- The back end also handles the non-class-wide cases of Size
7418
7419 when Attribute_Bit_Order
7420 | Attribute_Code_Address
7421 | Attribute_Definite
7422 | Attribute_Deref
7423 | Attribute_Null_Parameter
7424 | Attribute_Passed_By_Reference
7425 | Attribute_Pool_Address
7426 | Attribute_Scalar_Storage_Order
7427 =>
7428 null;
7429
7430 -- The following attributes are also handled by the back end, but return
7431 -- a universal integer result, so may need a conversion for checking
7432 -- that the result is in range.
7433
7434 when Attribute_Aft
7435 | Attribute_Max_Alignment_For_Allocation
7436 =>
7437 Apply_Universal_Integer_Attribute_Checks (N);
7438
7439 -- The following attributes should not appear at this stage, since they
7440 -- have already been handled by the analyzer (and properly rewritten
7441 -- with corresponding values or entities to represent the right values)
7442
7443 when Attribute_Abort_Signal
7444 | Attribute_Address_Size
7445 | Attribute_Atomic_Always_Lock_Free
7446 | Attribute_Base
7447 | Attribute_Class
7448 | Attribute_Compiler_Version
7449 | Attribute_Default_Bit_Order
7450 | Attribute_Default_Scalar_Storage_Order
7451 | Attribute_Delta
7452 | Attribute_Denorm
7453 | Attribute_Digits
7454 | Attribute_Emax
7455 | Attribute_Enabled
7456 | Attribute_Epsilon
7457 | Attribute_Fast_Math
7458 | Attribute_First_Valid
7459 | Attribute_Has_Access_Values
7460 | Attribute_Has_Discriminants
7461 | Attribute_Has_Tagged_Values
7462 | Attribute_Large
7463 | Attribute_Last_Valid
7464 | Attribute_Library_Level
7465 | Attribute_Lock_Free
7466 | Attribute_Machine_Emax
7467 | Attribute_Machine_Emin
7468 | Attribute_Machine_Mantissa
7469 | Attribute_Machine_Overflows
7470 | Attribute_Machine_Radix
7471 | Attribute_Machine_Rounds
7472 | Attribute_Maximum_Alignment
7473 | Attribute_Model_Emin
7474 | Attribute_Model_Epsilon
7475 | Attribute_Model_Mantissa
7476 | Attribute_Model_Small
7477 | Attribute_Modulus
7478 | Attribute_Partition_ID
7479 | Attribute_Range
7480 | Attribute_Restriction_Set
7481 | Attribute_Safe_Emax
7482 | Attribute_Safe_First
7483 | Attribute_Safe_Large
7484 | Attribute_Safe_Last
7485 | Attribute_Safe_Small
7486 | Attribute_Scale
7487 | Attribute_Signed_Zeros
7488 | Attribute_Small
7489 | Attribute_Storage_Unit
7490 | Attribute_Stub_Type
7491 | Attribute_System_Allocator_Alignment
7492 | Attribute_Target_Name
7493 | Attribute_Type_Class
7494 | Attribute_Type_Key
7495 | Attribute_Unconstrained_Array
7496 | Attribute_Universal_Literal_String
7497 | Attribute_Wchar_T_Size
7498 | Attribute_Word_Size
7499 =>
7500 raise Program_Error;
7501
7502 -- The Asm_Input and Asm_Output attributes are not expanded at this
7503 -- stage, but will be eliminated in the expansion of the Asm call, see
7504 -- Exp_Intr for details. So the back end will never see these either.
7505
7506 when Attribute_Asm_Input
7507 | Attribute_Asm_Output
7508 =>
7509 null;
7510 end case;
7511
7512 -- Note: as mentioned earlier, individual sections of the above case
7513 -- statement assume there is no code after the case statement, and are
7514 -- legitimately allowed to execute return statements if they have nothing
7515 -- more to do, so DO NOT add code at this point.
7516
7517 exception
7518 when RE_Not_Available =>
7519 return;
7520 end Expand_N_Attribute_Reference;
7521
7522 --------------------------------
7523 -- Expand_Pred_Succ_Attribute --
7524 --------------------------------
7525
7526 -- For typ'Pred (exp), we generate the check
7527
7528 -- [constraint_error when exp = typ'Base'First]
7529
7530 -- Similarly, for typ'Succ (exp), we generate the check
7531
7532 -- [constraint_error when exp = typ'Base'Last]
7533
7534 -- These checks are not generated for modular types, since the proper
7535 -- semantics for Succ and Pred on modular types is to wrap, not raise CE.
7536 -- We also suppress these checks if we are the right side of an assignment
7537 -- statement or the expression of an object declaration, where the flag
7538 -- Suppress_Assignment_Checks is set for the assignment/declaration.
7539
7540 procedure Expand_Pred_Succ_Attribute (N : Node_Id) is
7541 Loc : constant Source_Ptr := Sloc (N);
7542 P : constant Node_Id := Parent (N);
7543 Cnam : Name_Id;
7544
7545 begin
7546 if Attribute_Name (N) = Name_Pred then
7547 Cnam := Name_First;
7548 else
7549 Cnam := Name_Last;
7550 end if;
7551
7552 if not Nkind_In (P, N_Assignment_Statement, N_Object_Declaration)
7553 or else not Suppress_Assignment_Checks (P)
7554 then
7555 Insert_Action (N,
7556 Make_Raise_Constraint_Error (Loc,
7557 Condition =>
7558 Make_Op_Eq (Loc,
7559 Left_Opnd =>
7560 Duplicate_Subexpr_Move_Checks (First (Expressions (N))),
7561 Right_Opnd =>
7562 Make_Attribute_Reference (Loc,
7563 Prefix =>
7564 New_Occurrence_Of (Base_Type (Etype (Prefix (N))), Loc),
7565 Attribute_Name => Cnam)),
7566 Reason => CE_Overflow_Check_Failed));
7567 end if;
7568 end Expand_Pred_Succ_Attribute;
7569
7570 ---------------------------
7571 -- Expand_Size_Attribute --
7572 ---------------------------
7573
7574 procedure Expand_Size_Attribute (N : Node_Id) is
7575 Loc : constant Source_Ptr := Sloc (N);
7576 Typ : constant Entity_Id := Etype (N);
7577 Pref : constant Node_Id := Prefix (N);
7578 Ptyp : constant Entity_Id := Etype (Pref);
7579 Id : constant Attribute_Id := Get_Attribute_Id (Attribute_Name (N));
7580 Siz : Uint;
7581
7582 begin
7583 -- Case of known RM_Size of a type
7584
7585 if (Id = Attribute_Size or else Id = Attribute_Value_Size)
7586 and then Is_Entity_Name (Pref)
7587 and then Is_Type (Entity (Pref))
7588 and then Known_Static_RM_Size (Entity (Pref))
7589 then
7590 Siz := RM_Size (Entity (Pref));
7591
7592 -- Case of known Esize of a type
7593
7594 elsif Id = Attribute_Object_Size
7595 and then Is_Entity_Name (Pref)
7596 and then Is_Type (Entity (Pref))
7597 and then Known_Static_Esize (Entity (Pref))
7598 then
7599 Siz := Esize (Entity (Pref));
7600
7601 -- Case of known size of object
7602
7603 elsif Id = Attribute_Size
7604 and then Is_Entity_Name (Pref)
7605 and then Is_Object (Entity (Pref))
7606 and then Known_Esize (Entity (Pref))
7607 and then Known_Static_Esize (Entity (Pref))
7608 then
7609 Siz := Esize (Entity (Pref));
7610
7611 -- For an array component, we can do Size in the front end if the
7612 -- component_size of the array is set.
7613
7614 elsif Nkind (Pref) = N_Indexed_Component then
7615 Siz := Component_Size (Etype (Prefix (Pref)));
7616
7617 -- For a record component, we can do Size in the front end if there is a
7618 -- component clause, or if the record is packed and the component's size
7619 -- is known at compile time.
7620
7621 elsif Nkind (Pref) = N_Selected_Component then
7622 declare
7623 Rec : constant Entity_Id := Etype (Prefix (Pref));
7624 Comp : constant Entity_Id := Entity (Selector_Name (Pref));
7625
7626 begin
7627 if Present (Component_Clause (Comp)) then
7628 Siz := Esize (Comp);
7629
7630 elsif Is_Packed (Rec) then
7631 Siz := RM_Size (Ptyp);
7632
7633 else
7634 Apply_Universal_Integer_Attribute_Checks (N);
7635 return;
7636 end if;
7637 end;
7638
7639 -- All other cases are handled by the back end
7640
7641 else
7642 -- If Size is applied to a formal parameter that is of a packed
7643 -- array subtype, then apply Size to the actual subtype.
7644
7645 if Is_Entity_Name (Pref)
7646 and then Is_Formal (Entity (Pref))
7647 and then Is_Array_Type (Ptyp)
7648 and then Is_Packed (Ptyp)
7649 then
7650 Rewrite (N,
7651 Make_Attribute_Reference (Loc,
7652 Prefix =>
7653 New_Occurrence_Of (Get_Actual_Subtype (Pref), Loc),
7654 Attribute_Name => Name_Size));
7655 Analyze_And_Resolve (N, Typ);
7656
7657 -- If Size is applied to a dereference of an access to unconstrained
7658 -- packed array, the back end needs to see its unconstrained nominal
7659 -- type, but also a hint to the actual constrained type.
7660
7661 elsif Nkind (Pref) = N_Explicit_Dereference
7662 and then Is_Array_Type (Ptyp)
7663 and then not Is_Constrained (Ptyp)
7664 and then Is_Packed (Ptyp)
7665 then
7666 Set_Actual_Designated_Subtype (Pref, Get_Actual_Subtype (Pref));
7667
7668 -- If Size was applied to a slice of a bit-packed array, we rewrite
7669 -- it into the product of Length and Component_Size. We need to do so
7670 -- because bit-packed arrays are represented internally as arrays of
7671 -- System.Unsigned_Types.Packed_Byte for code generation purposes so
7672 -- the size is always rounded up in the back end.
7673
7674 elsif Nkind (Pref) = N_Slice and then Is_Bit_Packed_Array (Ptyp) then
7675 Rewrite (N,
7676 Make_Op_Multiply (Loc,
7677 Make_Attribute_Reference (Loc,
7678 Prefix => Duplicate_Subexpr (Pref, True),
7679 Attribute_Name => Name_Length),
7680 Make_Attribute_Reference (Loc,
7681 Prefix => Duplicate_Subexpr (Pref, True),
7682 Attribute_Name => Name_Component_Size)));
7683 Analyze_And_Resolve (N, Typ);
7684 end if;
7685
7686 -- Apply the required checks last, after rewriting has taken place
7687
7688 Apply_Universal_Integer_Attribute_Checks (N);
7689 return;
7690 end if;
7691
7692 -- Common processing for record and array component case
7693
7694 if Siz /= No_Uint and then Siz /= 0 then
7695 declare
7696 CS : constant Boolean := Comes_From_Source (N);
7697
7698 begin
7699 Rewrite (N, Make_Integer_Literal (Loc, Siz));
7700
7701 -- This integer literal is not a static expression. We do not
7702 -- call Analyze_And_Resolve here, because this would activate
7703 -- the circuit for deciding that a static value was out of range,
7704 -- and we don't want that.
7705
7706 -- So just manually set the type, mark the expression as
7707 -- nonstatic, and then ensure that the result is checked
7708 -- properly if the attribute comes from source (if it was
7709 -- internally generated, we never need a constraint check).
7710
7711 Set_Etype (N, Typ);
7712 Set_Is_Static_Expression (N, False);
7713
7714 if CS then
7715 Apply_Constraint_Check (N, Typ);
7716 end if;
7717 end;
7718 end if;
7719 end Expand_Size_Attribute;
7720
7721 -----------------------------
7722 -- Expand_Update_Attribute --
7723 -----------------------------
7724
7725 procedure Expand_Update_Attribute (N : Node_Id) is
7726 procedure Process_Component_Or_Element_Update
7727 (Temp : Entity_Id;
7728 Comp : Node_Id;
7729 Expr : Node_Id;
7730 Typ : Entity_Id);
7731 -- Generate the statements necessary to update a single component or an
7732 -- element of the prefix. The code is inserted before the attribute N.
7733 -- Temp denotes the entity of the anonymous object created to reflect
7734 -- the changes in values. Comp is the component/index expression to be
7735 -- updated. Expr is an expression yielding the new value of Comp. Typ
7736 -- is the type of the prefix of attribute Update.
7737
7738 procedure Process_Range_Update
7739 (Temp : Entity_Id;
7740 Comp : Node_Id;
7741 Expr : Node_Id;
7742 Typ : Entity_Id);
7743 -- Generate the statements necessary to update a slice of the prefix.
7744 -- The code is inserted before the attribute N. Temp denotes the entity
7745 -- of the anonymous object created to reflect the changes in values.
7746 -- Comp is range of the slice to be updated. Expr is an expression
7747 -- yielding the new value of Comp. Typ is the type of the prefix of
7748 -- attribute Update.
7749
7750 -----------------------------------------
7751 -- Process_Component_Or_Element_Update --
7752 -----------------------------------------
7753
7754 procedure Process_Component_Or_Element_Update
7755 (Temp : Entity_Id;
7756 Comp : Node_Id;
7757 Expr : Node_Id;
7758 Typ : Entity_Id)
7759 is
7760 Loc : constant Source_Ptr := Sloc (Comp);
7761 Exprs : List_Id;
7762 LHS : Node_Id;
7763
7764 begin
7765 -- An array element may be modified by the following relations
7766 -- depending on the number of dimensions:
7767
7768 -- 1 => Expr -- one dimensional update
7769 -- (1, ..., N) => Expr -- multi dimensional update
7770
7771 -- The above forms are converted in assignment statements where the
7772 -- left hand side is an indexed component:
7773
7774 -- Temp (1) := Expr; -- one dimensional update
7775 -- Temp (1, ..., N) := Expr; -- multi dimensional update
7776
7777 if Is_Array_Type (Typ) then
7778
7779 -- The index expressions of a multi dimensional array update
7780 -- appear as an aggregate.
7781
7782 if Nkind (Comp) = N_Aggregate then
7783 Exprs := New_Copy_List_Tree (Expressions (Comp));
7784 else
7785 Exprs := New_List (Relocate_Node (Comp));
7786 end if;
7787
7788 LHS :=
7789 Make_Indexed_Component (Loc,
7790 Prefix => New_Occurrence_Of (Temp, Loc),
7791 Expressions => Exprs);
7792
7793 -- A record component update appears in the following form:
7794
7795 -- Comp => Expr
7796
7797 -- The above relation is transformed into an assignment statement
7798 -- where the left hand side is a selected component:
7799
7800 -- Temp.Comp := Expr;
7801
7802 else pragma Assert (Is_Record_Type (Typ));
7803 LHS :=
7804 Make_Selected_Component (Loc,
7805 Prefix => New_Occurrence_Of (Temp, Loc),
7806 Selector_Name => Relocate_Node (Comp));
7807 end if;
7808
7809 Insert_Action (N,
7810 Make_Assignment_Statement (Loc,
7811 Name => LHS,
7812 Expression => Relocate_Node (Expr)));
7813 end Process_Component_Or_Element_Update;
7814
7815 --------------------------
7816 -- Process_Range_Update --
7817 --------------------------
7818
7819 procedure Process_Range_Update
7820 (Temp : Entity_Id;
7821 Comp : Node_Id;
7822 Expr : Node_Id;
7823 Typ : Entity_Id)
7824 is
7825 Index_Typ : constant Entity_Id := Etype (First_Index (Typ));
7826 Loc : constant Source_Ptr := Sloc (Comp);
7827 Index : Entity_Id;
7828
7829 begin
7830 -- A range update appears as
7831
7832 -- (Low .. High => Expr)
7833
7834 -- The above construct is transformed into a loop that iterates over
7835 -- the given range and modifies the corresponding array values to the
7836 -- value of Expr:
7837
7838 -- for Index in Low .. High loop
7839 -- Temp (<Index_Typ> (Index)) := Expr;
7840 -- end loop;
7841
7842 Index := Make_Temporary (Loc, 'I');
7843
7844 Insert_Action (N,
7845 Make_Loop_Statement (Loc,
7846 Iteration_Scheme =>
7847 Make_Iteration_Scheme (Loc,
7848 Loop_Parameter_Specification =>
7849 Make_Loop_Parameter_Specification (Loc,
7850 Defining_Identifier => Index,
7851 Discrete_Subtype_Definition => Relocate_Node (Comp))),
7852
7853 Statements => New_List (
7854 Make_Assignment_Statement (Loc,
7855 Name =>
7856 Make_Indexed_Component (Loc,
7857 Prefix => New_Occurrence_Of (Temp, Loc),
7858 Expressions => New_List (
7859 Convert_To (Index_Typ,
7860 New_Occurrence_Of (Index, Loc)))),
7861 Expression => Relocate_Node (Expr))),
7862
7863 End_Label => Empty));
7864 end Process_Range_Update;
7865
7866 -- Local variables
7867
7868 Aggr : constant Node_Id := First (Expressions (N));
7869 Loc : constant Source_Ptr := Sloc (N);
7870 Pref : constant Node_Id := Prefix (N);
7871 Typ : constant Entity_Id := Etype (Pref);
7872 Assoc : Node_Id;
7873 Comp : Node_Id;
7874 CW_Temp : Entity_Id;
7875 CW_Typ : Entity_Id;
7876 Expr : Node_Id;
7877 Temp : Entity_Id;
7878
7879 -- Start of processing for Expand_Update_Attribute
7880
7881 begin
7882 -- Create the anonymous object to store the value of the prefix and
7883 -- capture subsequent changes in value.
7884
7885 Temp := Make_Temporary (Loc, 'T', Pref);
7886
7887 -- Preserve the tag of the prefix by offering a specific view of the
7888 -- class-wide version of the prefix.
7889
7890 if Is_Tagged_Type (Typ) then
7891
7892 -- Generate:
7893 -- CW_Temp : Typ'Class := Typ'Class (Pref);
7894
7895 CW_Temp := Make_Temporary (Loc, 'T');
7896 CW_Typ := Class_Wide_Type (Typ);
7897
7898 Insert_Action (N,
7899 Make_Object_Declaration (Loc,
7900 Defining_Identifier => CW_Temp,
7901 Object_Definition => New_Occurrence_Of (CW_Typ, Loc),
7902 Expression =>
7903 Convert_To (CW_Typ, Relocate_Node (Pref))));
7904
7905 -- Generate:
7906 -- Temp : Typ renames Typ (CW_Temp);
7907
7908 Insert_Action (N,
7909 Make_Object_Renaming_Declaration (Loc,
7910 Defining_Identifier => Temp,
7911 Subtype_Mark => New_Occurrence_Of (Typ, Loc),
7912 Name =>
7913 Convert_To (Typ, New_Occurrence_Of (CW_Temp, Loc))));
7914
7915 -- Non-tagged case
7916
7917 else
7918 -- Generate:
7919 -- Temp : Typ := Pref;
7920
7921 Insert_Action (N,
7922 Make_Object_Declaration (Loc,
7923 Defining_Identifier => Temp,
7924 Object_Definition => New_Occurrence_Of (Typ, Loc),
7925 Expression => Relocate_Node (Pref)));
7926 end if;
7927
7928 -- Process the update aggregate
7929
7930 Assoc := First (Component_Associations (Aggr));
7931 while Present (Assoc) loop
7932 Comp := First (Choices (Assoc));
7933 Expr := Expression (Assoc);
7934 while Present (Comp) loop
7935 if Nkind (Comp) = N_Range then
7936 Process_Range_Update (Temp, Comp, Expr, Typ);
7937 else
7938 Process_Component_Or_Element_Update (Temp, Comp, Expr, Typ);
7939 end if;
7940
7941 Next (Comp);
7942 end loop;
7943
7944 Next (Assoc);
7945 end loop;
7946
7947 -- The attribute is replaced by a reference to the anonymous object
7948
7949 Rewrite (N, New_Occurrence_Of (Temp, Loc));
7950 Analyze (N);
7951 end Expand_Update_Attribute;
7952
7953 -------------------
7954 -- Find_Fat_Info --
7955 -------------------
7956
7957 procedure Find_Fat_Info
7958 (T : Entity_Id;
7959 Fat_Type : out Entity_Id;
7960 Fat_Pkg : out RE_Id)
7961 is
7962 Rtyp : constant Entity_Id := Root_Type (T);
7963
7964 begin
7965 -- All we do is use the root type (historically this dealt with
7966 -- VAX-float .. to be cleaned up further later ???)
7967
7968 Fat_Type := Rtyp;
7969
7970 if Fat_Type = Standard_Short_Float then
7971 Fat_Pkg := RE_Attr_Short_Float;
7972
7973 elsif Fat_Type = Standard_Float then
7974 Fat_Pkg := RE_Attr_Float;
7975
7976 elsif Fat_Type = Standard_Long_Float then
7977 Fat_Pkg := RE_Attr_Long_Float;
7978
7979 elsif Fat_Type = Standard_Long_Long_Float then
7980 Fat_Pkg := RE_Attr_Long_Long_Float;
7981
7982 -- Universal real (which is its own root type) is treated as being
7983 -- equivalent to Standard.Long_Long_Float, since it is defined to
7984 -- have the same precision as the longest Float type.
7985
7986 elsif Fat_Type = Universal_Real then
7987 Fat_Type := Standard_Long_Long_Float;
7988 Fat_Pkg := RE_Attr_Long_Long_Float;
7989
7990 else
7991 raise Program_Error;
7992 end if;
7993 end Find_Fat_Info;
7994
7995 ----------------------------
7996 -- Find_Stream_Subprogram --
7997 ----------------------------
7998
7999 function Find_Stream_Subprogram
8000 (Typ : Entity_Id;
8001 Nam : TSS_Name_Type) return Entity_Id
8002 is
8003 Base_Typ : constant Entity_Id := Base_Type (Typ);
8004 Ent : constant Entity_Id := TSS (Typ, Nam);
8005 begin
8006 if Present (Ent) then
8007 return Ent;
8008 end if;
8009
8010 -- Stream attributes for strings are expanded into library calls. The
8011 -- following checks are disabled when the run-time is not available or
8012 -- when compiling predefined types due to bootstrap issues. As a result,
8013 -- the compiler will generate in-place stream routines for string types
8014 -- that appear in GNAT's library, but will generate calls via rtsfind
8015 -- to library routines for user code.
8016
8017 -- Note: In the case of using a configurable run time, it is very likely
8018 -- that stream routines for string types are not present (they require
8019 -- file system support). In this case, the specific stream routines for
8020 -- strings are not used, relying on the regular stream mechanism
8021 -- instead. That is why we include the test RTE_Available when dealing
8022 -- with these cases.
8023
8024 if not Is_Predefined_Unit (Current_Sem_Unit) then
8025 -- Storage_Array as defined in package System.Storage_Elements
8026
8027 if Is_RTE (Base_Typ, RE_Storage_Array) then
8028
8029 -- Case of No_Stream_Optimizations restriction active
8030
8031 if Restriction_Active (No_Stream_Optimizations) then
8032 if Nam = TSS_Stream_Input
8033 and then RTE_Available (RE_Storage_Array_Input)
8034 then
8035 return RTE (RE_Storage_Array_Input);
8036
8037 elsif Nam = TSS_Stream_Output
8038 and then RTE_Available (RE_Storage_Array_Output)
8039 then
8040 return RTE (RE_Storage_Array_Output);
8041
8042 elsif Nam = TSS_Stream_Read
8043 and then RTE_Available (RE_Storage_Array_Read)
8044 then
8045 return RTE (RE_Storage_Array_Read);
8046
8047 elsif Nam = TSS_Stream_Write
8048 and then RTE_Available (RE_Storage_Array_Write)
8049 then
8050 return RTE (RE_Storage_Array_Write);
8051
8052 elsif Nam /= TSS_Stream_Input and then
8053 Nam /= TSS_Stream_Output and then
8054 Nam /= TSS_Stream_Read and then
8055 Nam /= TSS_Stream_Write
8056 then
8057 raise Program_Error;
8058 end if;
8059
8060 -- Restriction No_Stream_Optimizations is not set, so we can go
8061 -- ahead and optimize using the block IO forms of the routines.
8062
8063 else
8064 if Nam = TSS_Stream_Input
8065 and then RTE_Available (RE_Storage_Array_Input_Blk_IO)
8066 then
8067 return RTE (RE_Storage_Array_Input_Blk_IO);
8068
8069 elsif Nam = TSS_Stream_Output
8070 and then RTE_Available (RE_Storage_Array_Output_Blk_IO)
8071 then
8072 return RTE (RE_Storage_Array_Output_Blk_IO);
8073
8074 elsif Nam = TSS_Stream_Read
8075 and then RTE_Available (RE_Storage_Array_Read_Blk_IO)
8076 then
8077 return RTE (RE_Storage_Array_Read_Blk_IO);
8078
8079 elsif Nam = TSS_Stream_Write
8080 and then RTE_Available (RE_Storage_Array_Write_Blk_IO)
8081 then
8082 return RTE (RE_Storage_Array_Write_Blk_IO);
8083
8084 elsif Nam /= TSS_Stream_Input and then
8085 Nam /= TSS_Stream_Output and then
8086 Nam /= TSS_Stream_Read and then
8087 Nam /= TSS_Stream_Write
8088 then
8089 raise Program_Error;
8090 end if;
8091 end if;
8092
8093 -- Stream_Element_Array as defined in package Ada.Streams
8094
8095 elsif Is_RTE (Base_Typ, RE_Stream_Element_Array) then
8096
8097 -- Case of No_Stream_Optimizations restriction active
8098
8099 if Restriction_Active (No_Stream_Optimizations) then
8100 if Nam = TSS_Stream_Input
8101 and then RTE_Available (RE_Stream_Element_Array_Input)
8102 then
8103 return RTE (RE_Stream_Element_Array_Input);
8104
8105 elsif Nam = TSS_Stream_Output
8106 and then RTE_Available (RE_Stream_Element_Array_Output)
8107 then
8108 return RTE (RE_Stream_Element_Array_Output);
8109
8110 elsif Nam = TSS_Stream_Read
8111 and then RTE_Available (RE_Stream_Element_Array_Read)
8112 then
8113 return RTE (RE_Stream_Element_Array_Read);
8114
8115 elsif Nam = TSS_Stream_Write
8116 and then RTE_Available (RE_Stream_Element_Array_Write)
8117 then
8118 return RTE (RE_Stream_Element_Array_Write);
8119
8120 elsif Nam /= TSS_Stream_Input and then
8121 Nam /= TSS_Stream_Output and then
8122 Nam /= TSS_Stream_Read and then
8123 Nam /= TSS_Stream_Write
8124 then
8125 raise Program_Error;
8126 end if;
8127
8128 -- Restriction No_Stream_Optimizations is not set, so we can go
8129 -- ahead and optimize using the block IO forms of the routines.
8130
8131 else
8132 if Nam = TSS_Stream_Input
8133 and then RTE_Available (RE_Stream_Element_Array_Input_Blk_IO)
8134 then
8135 return RTE (RE_Stream_Element_Array_Input_Blk_IO);
8136
8137 elsif Nam = TSS_Stream_Output
8138 and then RTE_Available (RE_Stream_Element_Array_Output_Blk_IO)
8139 then
8140 return RTE (RE_Stream_Element_Array_Output_Blk_IO);
8141
8142 elsif Nam = TSS_Stream_Read
8143 and then RTE_Available (RE_Stream_Element_Array_Read_Blk_IO)
8144 then
8145 return RTE (RE_Stream_Element_Array_Read_Blk_IO);
8146
8147 elsif Nam = TSS_Stream_Write
8148 and then RTE_Available (RE_Stream_Element_Array_Write_Blk_IO)
8149 then
8150 return RTE (RE_Stream_Element_Array_Write_Blk_IO);
8151
8152 elsif Nam /= TSS_Stream_Input and then
8153 Nam /= TSS_Stream_Output and then
8154 Nam /= TSS_Stream_Read and then
8155 Nam /= TSS_Stream_Write
8156 then
8157 raise Program_Error;
8158 end if;
8159 end if;
8160
8161 -- String as defined in package Ada
8162
8163 elsif Base_Typ = Standard_String then
8164
8165 -- Case of No_Stream_Optimizations restriction active
8166
8167 if Restriction_Active (No_Stream_Optimizations) then
8168 if Nam = TSS_Stream_Input
8169 and then RTE_Available (RE_String_Input)
8170 then
8171 return RTE (RE_String_Input);
8172
8173 elsif Nam = TSS_Stream_Output
8174 and then RTE_Available (RE_String_Output)
8175 then
8176 return RTE (RE_String_Output);
8177
8178 elsif Nam = TSS_Stream_Read
8179 and then RTE_Available (RE_String_Read)
8180 then
8181 return RTE (RE_String_Read);
8182
8183 elsif Nam = TSS_Stream_Write
8184 and then RTE_Available (RE_String_Write)
8185 then
8186 return RTE (RE_String_Write);
8187
8188 elsif Nam /= TSS_Stream_Input and then
8189 Nam /= TSS_Stream_Output and then
8190 Nam /= TSS_Stream_Read and then
8191 Nam /= TSS_Stream_Write
8192 then
8193 raise Program_Error;
8194 end if;
8195
8196 -- Restriction No_Stream_Optimizations is not set, so we can go
8197 -- ahead and optimize using the block IO forms of the routines.
8198
8199 else
8200 if Nam = TSS_Stream_Input
8201 and then RTE_Available (RE_String_Input_Blk_IO)
8202 then
8203 return RTE (RE_String_Input_Blk_IO);
8204
8205 elsif Nam = TSS_Stream_Output
8206 and then RTE_Available (RE_String_Output_Blk_IO)
8207 then
8208 return RTE (RE_String_Output_Blk_IO);
8209
8210 elsif Nam = TSS_Stream_Read
8211 and then RTE_Available (RE_String_Read_Blk_IO)
8212 then
8213 return RTE (RE_String_Read_Blk_IO);
8214
8215 elsif Nam = TSS_Stream_Write
8216 and then RTE_Available (RE_String_Write_Blk_IO)
8217 then
8218 return RTE (RE_String_Write_Blk_IO);
8219
8220 elsif Nam /= TSS_Stream_Input and then
8221 Nam /= TSS_Stream_Output and then
8222 Nam /= TSS_Stream_Read and then
8223 Nam /= TSS_Stream_Write
8224 then
8225 raise Program_Error;
8226 end if;
8227 end if;
8228
8229 -- Wide_String as defined in package Ada
8230
8231 elsif Base_Typ = Standard_Wide_String then
8232
8233 -- Case of No_Stream_Optimizations restriction active
8234
8235 if Restriction_Active (No_Stream_Optimizations) then
8236 if Nam = TSS_Stream_Input
8237 and then RTE_Available (RE_Wide_String_Input)
8238 then
8239 return RTE (RE_Wide_String_Input);
8240
8241 elsif Nam = TSS_Stream_Output
8242 and then RTE_Available (RE_Wide_String_Output)
8243 then
8244 return RTE (RE_Wide_String_Output);
8245
8246 elsif Nam = TSS_Stream_Read
8247 and then RTE_Available (RE_Wide_String_Read)
8248 then
8249 return RTE (RE_Wide_String_Read);
8250
8251 elsif Nam = TSS_Stream_Write
8252 and then RTE_Available (RE_Wide_String_Write)
8253 then
8254 return RTE (RE_Wide_String_Write);
8255
8256 elsif Nam /= TSS_Stream_Input and then
8257 Nam /= TSS_Stream_Output and then
8258 Nam /= TSS_Stream_Read and then
8259 Nam /= TSS_Stream_Write
8260 then
8261 raise Program_Error;
8262 end if;
8263
8264 -- Restriction No_Stream_Optimizations is not set, so we can go
8265 -- ahead and optimize using the block IO forms of the routines.
8266
8267 else
8268 if Nam = TSS_Stream_Input
8269 and then RTE_Available (RE_Wide_String_Input_Blk_IO)
8270 then
8271 return RTE (RE_Wide_String_Input_Blk_IO);
8272
8273 elsif Nam = TSS_Stream_Output
8274 and then RTE_Available (RE_Wide_String_Output_Blk_IO)
8275 then
8276 return RTE (RE_Wide_String_Output_Blk_IO);
8277
8278 elsif Nam = TSS_Stream_Read
8279 and then RTE_Available (RE_Wide_String_Read_Blk_IO)
8280 then
8281 return RTE (RE_Wide_String_Read_Blk_IO);
8282
8283 elsif Nam = TSS_Stream_Write
8284 and then RTE_Available (RE_Wide_String_Write_Blk_IO)
8285 then
8286 return RTE (RE_Wide_String_Write_Blk_IO);
8287
8288 elsif Nam /= TSS_Stream_Input and then
8289 Nam /= TSS_Stream_Output and then
8290 Nam /= TSS_Stream_Read and then
8291 Nam /= TSS_Stream_Write
8292 then
8293 raise Program_Error;
8294 end if;
8295 end if;
8296
8297 -- Wide_Wide_String as defined in package Ada
8298
8299 elsif Base_Typ = Standard_Wide_Wide_String then
8300
8301 -- Case of No_Stream_Optimizations restriction active
8302
8303 if Restriction_Active (No_Stream_Optimizations) then
8304 if Nam = TSS_Stream_Input
8305 and then RTE_Available (RE_Wide_Wide_String_Input)
8306 then
8307 return RTE (RE_Wide_Wide_String_Input);
8308
8309 elsif Nam = TSS_Stream_Output
8310 and then RTE_Available (RE_Wide_Wide_String_Output)
8311 then
8312 return RTE (RE_Wide_Wide_String_Output);
8313
8314 elsif Nam = TSS_Stream_Read
8315 and then RTE_Available (RE_Wide_Wide_String_Read)
8316 then
8317 return RTE (RE_Wide_Wide_String_Read);
8318
8319 elsif Nam = TSS_Stream_Write
8320 and then RTE_Available (RE_Wide_Wide_String_Write)
8321 then
8322 return RTE (RE_Wide_Wide_String_Write);
8323
8324 elsif Nam /= TSS_Stream_Input and then
8325 Nam /= TSS_Stream_Output and then
8326 Nam /= TSS_Stream_Read and then
8327 Nam /= TSS_Stream_Write
8328 then
8329 raise Program_Error;
8330 end if;
8331
8332 -- Restriction No_Stream_Optimizations is not set, so we can go
8333 -- ahead and optimize using the block IO forms of the routines.
8334
8335 else
8336 if Nam = TSS_Stream_Input
8337 and then RTE_Available (RE_Wide_Wide_String_Input_Blk_IO)
8338 then
8339 return RTE (RE_Wide_Wide_String_Input_Blk_IO);
8340
8341 elsif Nam = TSS_Stream_Output
8342 and then RTE_Available (RE_Wide_Wide_String_Output_Blk_IO)
8343 then
8344 return RTE (RE_Wide_Wide_String_Output_Blk_IO);
8345
8346 elsif Nam = TSS_Stream_Read
8347 and then RTE_Available (RE_Wide_Wide_String_Read_Blk_IO)
8348 then
8349 return RTE (RE_Wide_Wide_String_Read_Blk_IO);
8350
8351 elsif Nam = TSS_Stream_Write
8352 and then RTE_Available (RE_Wide_Wide_String_Write_Blk_IO)
8353 then
8354 return RTE (RE_Wide_Wide_String_Write_Blk_IO);
8355
8356 elsif Nam /= TSS_Stream_Input and then
8357 Nam /= TSS_Stream_Output and then
8358 Nam /= TSS_Stream_Read and then
8359 Nam /= TSS_Stream_Write
8360 then
8361 raise Program_Error;
8362 end if;
8363 end if;
8364 end if;
8365 end if;
8366
8367 if Is_Tagged_Type (Typ) and then Is_Derived_Type (Typ) then
8368 return Find_Prim_Op (Typ, Nam);
8369 else
8370 return Find_Inherited_TSS (Typ, Nam);
8371 end if;
8372 end Find_Stream_Subprogram;
8373
8374 ---------------
8375 -- Full_Base --
8376 ---------------
8377
8378 function Full_Base (T : Entity_Id) return Entity_Id is
8379 BT : Entity_Id;
8380
8381 begin
8382 BT := Base_Type (T);
8383
8384 if Is_Private_Type (BT)
8385 and then Present (Full_View (BT))
8386 then
8387 BT := Full_View (BT);
8388 end if;
8389
8390 return BT;
8391 end Full_Base;
8392
8393 -----------------------
8394 -- Get_Index_Subtype --
8395 -----------------------
8396
8397 function Get_Index_Subtype (N : Node_Id) return Node_Id is
8398 P_Type : Entity_Id := Etype (Prefix (N));
8399 Indx : Node_Id;
8400 J : Int;
8401
8402 begin
8403 if Is_Access_Type (P_Type) then
8404 P_Type := Designated_Type (P_Type);
8405 end if;
8406
8407 if No (Expressions (N)) then
8408 J := 1;
8409 else
8410 J := UI_To_Int (Expr_Value (First (Expressions (N))));
8411 end if;
8412
8413 Indx := First_Index (P_Type);
8414 while J > 1 loop
8415 Next_Index (Indx);
8416 J := J - 1;
8417 end loop;
8418
8419 return Etype (Indx);
8420 end Get_Index_Subtype;
8421
8422 -------------------------------
8423 -- Get_Stream_Convert_Pragma --
8424 -------------------------------
8425
8426 function Get_Stream_Convert_Pragma (T : Entity_Id) return Node_Id is
8427 Typ : Entity_Id;
8428 N : Node_Id;
8429
8430 begin
8431 -- Note: we cannot use Get_Rep_Pragma here because of the peculiarity
8432 -- that a stream convert pragma for a tagged type is not inherited from
8433 -- its parent. Probably what is wrong here is that it is basically
8434 -- incorrect to consider a stream convert pragma to be a representation
8435 -- pragma at all ???
8436
8437 N := First_Rep_Item (Implementation_Base_Type (T));
8438 while Present (N) loop
8439 if Nkind (N) = N_Pragma
8440 and then Pragma_Name (N) = Name_Stream_Convert
8441 then
8442 -- For tagged types this pragma is not inherited, so we
8443 -- must verify that it is defined for the given type and
8444 -- not an ancestor.
8445
8446 Typ :=
8447 Entity (Expression (First (Pragma_Argument_Associations (N))));
8448
8449 if not Is_Tagged_Type (T)
8450 or else T = Typ
8451 or else (Is_Private_Type (Typ) and then T = Full_View (Typ))
8452 then
8453 return N;
8454 end if;
8455 end if;
8456
8457 Next_Rep_Item (N);
8458 end loop;
8459
8460 return Empty;
8461 end Get_Stream_Convert_Pragma;
8462
8463 ---------------------------------
8464 -- Is_Constrained_Packed_Array --
8465 ---------------------------------
8466
8467 function Is_Constrained_Packed_Array (Typ : Entity_Id) return Boolean is
8468 Arr : Entity_Id := Typ;
8469
8470 begin
8471 if Is_Access_Type (Arr) then
8472 Arr := Designated_Type (Arr);
8473 end if;
8474
8475 return Is_Array_Type (Arr)
8476 and then Is_Constrained (Arr)
8477 and then Present (Packed_Array_Impl_Type (Arr));
8478 end Is_Constrained_Packed_Array;
8479
8480 ----------------------------------------
8481 -- Is_Inline_Floating_Point_Attribute --
8482 ----------------------------------------
8483
8484 function Is_Inline_Floating_Point_Attribute (N : Node_Id) return Boolean is
8485 Id : constant Attribute_Id := Get_Attribute_Id (Attribute_Name (N));
8486
8487 function Is_GCC_Target return Boolean;
8488 -- Return True if we are using a GCC target/back-end
8489 -- ??? Note: the implementation is kludgy/fragile
8490
8491 -------------------
8492 -- Is_GCC_Target --
8493 -------------------
8494
8495 function Is_GCC_Target return Boolean is
8496 begin
8497 return not CodePeer_Mode
8498 and then not Modify_Tree_For_C;
8499 end Is_GCC_Target;
8500
8501 -- Start of processing for Is_Inline_Floating_Point_Attribute
8502
8503 begin
8504 -- Machine and Model can be expanded by the GCC back end only
8505
8506 if Id = Attribute_Machine or else Id = Attribute_Model then
8507 return Is_GCC_Target;
8508
8509 -- Remaining cases handled by all back ends are Rounding and Truncation
8510 -- when appearing as the operand of a conversion to some integer type.
8511
8512 elsif Nkind (Parent (N)) /= N_Type_Conversion
8513 or else not Is_Integer_Type (Etype (Parent (N)))
8514 then
8515 return False;
8516 end if;
8517
8518 -- Here we are in the integer conversion context. We reuse Rounding for
8519 -- Machine_Rounding as System.Fat_Gen, which is a permissible behavior.
8520
8521 return
8522 Id = Attribute_Rounding
8523 or else Id = Attribute_Machine_Rounding
8524 or else Id = Attribute_Truncation;
8525 end Is_Inline_Floating_Point_Attribute;
8526
8527 end Exp_Attr;