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