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