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