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