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