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