]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/ada/exp_attr.adb
2003-10-21 Arnaud Charlet <charlet@act-europe.fr>
[thirdparty/gcc.git] / gcc / ada / exp_attr.adb
CommitLineData
ee6ba406 1------------------------------------------------------------------------------
2-- --
3-- GNAT COMPILER COMPONENTS --
4-- --
5-- E X P _ A T T R --
6-- --
7-- B o d y --
8-- --
9dfe12ae 9-- Copyright (C) 1992-2003 Free Software Foundation, Inc. --
ee6ba406 10-- --
11-- GNAT is free software; you can redistribute it and/or modify it under --
12-- terms of the GNU General Public License as published by the Free Soft- --
13-- ware Foundation; either version 2, or (at your option) any later ver- --
14-- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
15-- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
16-- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License --
17-- for more details. You should have received a copy of the GNU General --
18-- Public License distributed with GNAT; see file COPYING. If not, write --
19-- to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, --
20-- MA 02111-1307, USA. --
21-- --
22-- GNAT was originally developed by the GNAT team at New York University. --
e78e8c8e 23-- Extensive contributions were provided by Ada Core Technologies Inc. --
ee6ba406 24-- --
25------------------------------------------------------------------------------
26
27with Atree; use Atree;
28with Checks; use Checks;
29with Einfo; use Einfo;
30with Exp_Ch2; use Exp_Ch2;
31with Exp_Ch9; use Exp_Ch9;
32with Exp_Imgv; use Exp_Imgv;
33with Exp_Pakd; use Exp_Pakd;
34with Exp_Strm; use Exp_Strm;
35with Exp_Tss; use Exp_Tss;
36with Exp_Util; use Exp_Util;
37with Gnatvsn; use Gnatvsn;
38with Hostparm; use Hostparm;
39with Lib; use Lib;
40with Namet; use Namet;
41with Nmake; use Nmake;
42with Nlists; use Nlists;
43with Opt; use Opt;
44with Restrict; use Restrict;
45with Rtsfind; use Rtsfind;
46with Sem; use Sem;
47with Sem_Ch7; use Sem_Ch7;
48with Sem_Ch8; use Sem_Ch8;
ee6ba406 49with Sem_Eval; use Sem_Eval;
50with Sem_Res; use Sem_Res;
51with Sem_Util; use Sem_Util;
52with Sinfo; use Sinfo;
53with Snames; use Snames;
54with Stand; use Stand;
55with Stringt; use Stringt;
56with Tbuild; use Tbuild;
57with Ttypes; use Ttypes;
58with Uintp; use Uintp;
59with Uname; use Uname;
60with Validsw; use Validsw;
61
62package body Exp_Attr is
63
64 -----------------------
65 -- Local Subprograms --
66 -----------------------
67
68 procedure Compile_Stream_Body_In_Scope
69 (N : Node_Id;
70 Decl : Node_Id;
71 Arr : Entity_Id;
72 Check : Boolean);
73 -- The body for a stream subprogram may be generated outside of the scope
74 -- of the type. If the type is fully private, it may depend on the full
75 -- view of other types (e.g. indices) that are currently private as well.
76 -- We install the declarations of the package in which the type is declared
77 -- before compiling the body in what is its proper environment. The Check
78 -- parameter indicates if checks are to be suppressed for the stream body.
79 -- We suppress checks for array/record reads, since the rule is that these
80 -- are like assignments, out of range values due to uninitialized storage,
81 -- or other invalid values do NOT cause a Constraint_Error to be raised.
82
83 procedure Expand_Fpt_Attribute
9dfe12ae 84 (N : Node_Id;
85 Rtp : Entity_Id;
86 Nam : Name_Id;
ee6ba406 87 Args : List_Id);
88 -- This procedure expands a call to a floating-point attribute function.
89 -- N is the attribute reference node, and Args is a list of arguments to
90 -- be passed to the function call. Rtp is the root type of the floating
91 -- point type involved (used to select the proper generic instantiation
9dfe12ae 92 -- of the package containing the attribute routines). The Nam argument
93 -- is the attribute processing routine to be called. This is normally
94 -- the same as the attribute name, except in the Unaligned_Valid case.
ee6ba406 95
96 procedure Expand_Fpt_Attribute_R (N : Node_Id);
97 -- This procedure expands a call to a floating-point attribute function
9dfe12ae 98 -- that takes a single floating-point argument. The function to be called
99 -- is always the same as the attribute name.
ee6ba406 100
101 procedure Expand_Fpt_Attribute_RI (N : Node_Id);
102 -- This procedure expands a call to a floating-point attribute function
9dfe12ae 103 -- that takes one floating-point argument and one integer argument. The
104 -- function to be called is always the same as the attribute name.
ee6ba406 105
106 procedure Expand_Fpt_Attribute_RR (N : Node_Id);
107 -- This procedure expands a call to a floating-point attribute function
9dfe12ae 108 -- that takes two floating-point arguments. The function to be called
109 -- is always the same as the attribute name.
ee6ba406 110
111 procedure Expand_Pred_Succ (N : Node_Id);
112 -- Handles expansion of Pred or Succ attributes for case of non-real
113 -- operand with overflow checking required.
114
115 function Get_Index_Subtype (N : Node_Id) return Entity_Id;
116 -- Used for Last, Last, and Length, when the prefix is an array type,
117 -- Obtains the corresponding index subtype.
118
119 procedure Expand_Access_To_Type (N : Node_Id);
120 -- A reference to a type within its own scope is resolved to a reference
121 -- to the current instance of the type in its initialization procedure.
122
123 function Find_Inherited_TSS
124 (Typ : Entity_Id;
9dfe12ae 125 Nam : TSS_Name_Type) return Entity_Id;
126 -- Returns the TSS of name Nam of Typ, or of its closest ancestor defining
127 -- such a TSS. Empty is returned is neither Typ nor any of its ancestors
128 -- have such a TSS.
129
130 function Find_Stream_Subprogram
131 (Typ : Entity_Id;
132 Nam : TSS_Name_Type) return Entity_Id;
133 -- Returns the stream-oriented subprogram attribute for Typ. For tagged
134 -- types, the corresponding primitive operation is looked up, else the
135 -- appropriate TSS from the type itself, or from its closest ancestor
136 -- defining it, is returned. In both cases, inheritance of representation
137 -- aspects is thus taken into account.
ee6ba406 138
139 function Is_Constrained_Packed_Array (Typ : Entity_Id) return Boolean;
140 -- Utility for array attributes, returns true on packed constrained
141 -- arrays, and on access to same.
142
143 ----------------------------------
144 -- Compile_Stream_Body_In_Scope --
145 ----------------------------------
146
147 procedure Compile_Stream_Body_In_Scope
148 (N : Node_Id;
149 Decl : Node_Id;
150 Arr : Entity_Id;
151 Check : Boolean)
152 is
153 Installed : Boolean := False;
154 Scop : constant Entity_Id := Scope (Arr);
155 Curr : constant Entity_Id := Current_Scope;
156
157 begin
158 if Is_Hidden (Arr)
159 and then not In_Open_Scopes (Scop)
160 and then Ekind (Scop) = E_Package
161 then
162 New_Scope (Scop);
163 Install_Visible_Declarations (Scop);
164 Install_Private_Declarations (Scop);
165 Installed := True;
166
167 -- The entities in the package are now visible, but the generated
168 -- stream entity must appear in the current scope (usually an
169 -- enclosing stream function) so that itypes all have their proper
170 -- scopes.
171
172 New_Scope (Curr);
173 end if;
174
175 if Check then
176 Insert_Action (N, Decl);
177 else
178 Insert_Action (N, Decl, All_Checks);
179 end if;
180
181 if Installed then
182
183 -- Remove extra copy of current scope, and package itself
184
185 Pop_Scope;
186 End_Package_Scope (Scop);
187 end if;
188 end Compile_Stream_Body_In_Scope;
189
190 ---------------------------
191 -- Expand_Access_To_Type --
192 ---------------------------
193
194 procedure Expand_Access_To_Type (N : Node_Id) is
195 Loc : constant Source_Ptr := Sloc (N);
196 Typ : constant Entity_Id := Etype (N);
197 Pref : constant Node_Id := Prefix (N);
198 Par : Node_Id;
199 Formal : Entity_Id;
200
201 begin
202 if Is_Entity_Name (Pref)
203 and then Is_Type (Entity (Pref))
204 then
205 -- If the current instance name denotes a task type,
206 -- then the access attribute is rewritten to be the
207 -- name of the "_task" parameter associated with the
208 -- task type's task body procedure. An unchecked
209 -- conversion is applied to ensure a type match in
210 -- cases of expander-generated calls (e.g., init procs).
211
212 if Is_Task_Type (Entity (Pref)) then
213 Formal :=
214 First_Entity (Get_Task_Body_Procedure (Entity (Pref)));
215
216 while Present (Formal) loop
217 exit when Chars (Formal) = Name_uTask;
218 Next_Entity (Formal);
219 end loop;
220
221 pragma Assert (Present (Formal));
222
223 Rewrite (N,
224 Unchecked_Convert_To (Typ, New_Occurrence_Of (Formal, Loc)));
225 Set_Etype (N, Typ);
226
227 -- The expression must appear in a default expression,
228 -- (which in the initialization procedure is the rhs of
229 -- an assignment), and not in a discriminant constraint.
230
231 else
232 Par := Parent (N);
233
234 while Present (Par) loop
235 exit when Nkind (Par) = N_Assignment_Statement;
236
237 if Nkind (Par) = N_Component_Declaration then
238 return;
239 end if;
240
241 Par := Parent (Par);
242 end loop;
243
244 if Present (Par) then
245 Rewrite (N,
246 Make_Attribute_Reference (Loc,
247 Prefix => Make_Identifier (Loc, Name_uInit),
248 Attribute_Name => Attribute_Name (N)));
249
250 Analyze_And_Resolve (N, Typ);
251 end if;
252 end if;
253 end if;
254 end Expand_Access_To_Type;
255
256 --------------------------
257 -- Expand_Fpt_Attribute --
258 --------------------------
259
260 procedure Expand_Fpt_Attribute
261 (N : Node_Id;
262 Rtp : Entity_Id;
9dfe12ae 263 Nam : Name_Id;
ee6ba406 264 Args : List_Id)
265 is
266 Loc : constant Source_Ptr := Sloc (N);
267 Typ : constant Entity_Id := Etype (N);
268 Pkg : RE_Id;
269 Fnm : Node_Id;
270
271 begin
272 -- The function name is the selected component Fat_xxx.yyy where xxx
9dfe12ae 273 -- is the floating-point root type, and yyy is the argument Nam.
ee6ba406 274
275 -- Note: it would be more usual to have separate RE entries for each
276 -- of the entities in the Fat packages, but first they have identical
277 -- names (so we would have to have lots of renaming declarations to
278 -- meet the normal RE rule of separate names for all runtime entities),
279 -- and second there would be an awful lot of them!
280
281 if Rtp = Standard_Short_Float then
282 Pkg := RE_Fat_Short_Float;
283 elsif Rtp = Standard_Float then
284 Pkg := RE_Fat_Float;
285 elsif Rtp = Standard_Long_Float then
286 Pkg := RE_Fat_Long_Float;
287 else
288 Pkg := RE_Fat_Long_Long_Float;
289 end if;
290
291 Fnm :=
292 Make_Selected_Component (Loc,
293 Prefix => New_Reference_To (RTE (Pkg), Loc),
9dfe12ae 294 Selector_Name => Make_Identifier (Loc, Nam));
ee6ba406 295
296 -- The generated call is given the provided set of parameters, and then
297 -- wrapped in a conversion which converts the result to the target type
298
299 Rewrite (N,
300 Unchecked_Convert_To (Etype (N),
301 Make_Function_Call (Loc,
302 Name => Fnm,
303 Parameter_Associations => Args)));
304
305 Analyze_And_Resolve (N, Typ);
ee6ba406 306 end Expand_Fpt_Attribute;
307
308 ----------------------------
309 -- Expand_Fpt_Attribute_R --
310 ----------------------------
311
312 -- The single argument is converted to its root type to call the
313 -- appropriate runtime function, with the actual call being built
314 -- by Expand_Fpt_Attribute
315
316 procedure Expand_Fpt_Attribute_R (N : Node_Id) is
317 E1 : constant Node_Id := First (Expressions (N));
318 Rtp : constant Entity_Id := Root_Type (Etype (E1));
319
320 begin
9dfe12ae 321 Expand_Fpt_Attribute
322 (N, Rtp, Attribute_Name (N),
323 New_List (Unchecked_Convert_To (Rtp, Relocate_Node (E1))));
ee6ba406 324 end Expand_Fpt_Attribute_R;
325
326 -----------------------------
327 -- Expand_Fpt_Attribute_RI --
328 -----------------------------
329
330 -- The first argument is converted to its root type and the second
331 -- argument is converted to standard long long integer to call the
332 -- appropriate runtime function, with the actual call being built
333 -- by Expand_Fpt_Attribute
334
335 procedure Expand_Fpt_Attribute_RI (N : Node_Id) is
336 E1 : constant Node_Id := First (Expressions (N));
337 Rtp : constant Entity_Id := Root_Type (Etype (E1));
338 E2 : constant Node_Id := Next (E1);
339
340 begin
9dfe12ae 341 Expand_Fpt_Attribute
342 (N, Rtp, Attribute_Name (N),
343 New_List (
344 Unchecked_Convert_To (Rtp, Relocate_Node (E1)),
345 Unchecked_Convert_To (Standard_Integer, Relocate_Node (E2))));
ee6ba406 346 end Expand_Fpt_Attribute_RI;
347
348 -----------------------------
349 -- Expand_Fpt_Attribute_RR --
350 -----------------------------
351
352 -- The two arguments is converted to their root types to call the
353 -- appropriate runtime function, with the actual call being built
354 -- by Expand_Fpt_Attribute
355
356 procedure Expand_Fpt_Attribute_RR (N : Node_Id) is
357 E1 : constant Node_Id := First (Expressions (N));
358 Rtp : constant Entity_Id := Root_Type (Etype (E1));
359 E2 : constant Node_Id := Next (E1);
360
361 begin
9dfe12ae 362 Expand_Fpt_Attribute
363 (N, Rtp, Attribute_Name (N),
364 New_List (
365 Unchecked_Convert_To (Rtp, Relocate_Node (E1)),
366 Unchecked_Convert_To (Rtp, Relocate_Node (E2))));
ee6ba406 367 end Expand_Fpt_Attribute_RR;
368
369 ----------------------------------
370 -- Expand_N_Attribute_Reference --
371 ----------------------------------
372
373 procedure Expand_N_Attribute_Reference (N : Node_Id) is
374 Loc : constant Source_Ptr := Sloc (N);
375 Typ : constant Entity_Id := Etype (N);
376 Btyp : constant Entity_Id := Base_Type (Typ);
377 Pref : constant Node_Id := Prefix (N);
378 Exprs : constant List_Id := Expressions (N);
379 Id : constant Attribute_Id := Get_Attribute_Id (Attribute_Name (N));
380
381 procedure Rewrite_Stream_Proc_Call (Pname : Entity_Id);
382 -- Rewrites a stream attribute for Read, Write or Output with the
383 -- procedure call. Pname is the entity for the procedure to call.
384
385 ------------------------------
386 -- Rewrite_Stream_Proc_Call --
387 ------------------------------
388
389 procedure Rewrite_Stream_Proc_Call (Pname : Entity_Id) is
390 Item : constant Node_Id := Next (First (Exprs));
9dfe12ae 391 Formal : constant Entity_Id := Next_Formal (First_Formal (Pname));
392 Formal_Typ : constant Entity_Id := Etype (Formal);
393 Is_Written : constant Boolean := (Ekind (Formal) /= E_In_Parameter);
ee6ba406 394
395 begin
9dfe12ae 396 -- The expansion depends on Item, the second actual, which is
397 -- the object being streamed in or out.
398
399 -- If the item is a component of a packed array type, and
400 -- a conversion is needed on exit, we introduce a temporary to
401 -- hold the value, because otherwise the packed reference will
402 -- not be properly expanded.
403
404 if Nkind (Item) = N_Indexed_Component
405 and then Is_Packed (Base_Type (Etype (Prefix (Item))))
406 and then Base_Type (Etype (Item)) /= Base_Type (Formal_Typ)
407 and then Is_Written
408 then
409 declare
410 Temp : constant Entity_Id :=
411 Make_Defining_Identifier
412 (Loc, New_Internal_Name ('V'));
413 Decl : Node_Id;
414 Assn : Node_Id;
415
416 begin
417 Decl :=
418 Make_Object_Declaration (Loc,
419 Defining_Identifier => Temp,
420 Object_Definition =>
421 New_Occurrence_Of (Formal_Typ, Loc));
422 Set_Etype (Temp, Formal_Typ);
423
424 Assn :=
425 Make_Assignment_Statement (Loc,
426 Name => New_Copy_Tree (Item),
427 Expression =>
428 Unchecked_Convert_To
429 (Etype (Item), New_Occurrence_Of (Temp, Loc)));
430
431 Rewrite (Item, New_Occurrence_Of (Temp, Loc));
432 Insert_Actions (N,
433 New_List (
434 Decl,
435 Make_Procedure_Call_Statement (Loc,
436 Name => New_Occurrence_Of (Pname, Loc),
437 Parameter_Associations => Exprs),
438 Assn));
439
440 Rewrite (N, Make_Null_Statement (Loc));
441 return;
442 end;
443 end if;
ee6ba406 444
445 -- For the class-wide dispatching cases, and for cases in which
446 -- the base type of the second argument matches the base type of
9dfe12ae 447 -- the corresponding formal parameter (that is to say the stream
448 -- operation is not inherited), we are all set, and can use the
449 -- argument unchanged.
ee6ba406 450
451 -- For all other cases we do an unchecked conversion of the second
452 -- parameter to the type of the formal of the procedure we are
453 -- calling. This deals with the private type cases, and with going
454 -- to the root type as required in elementary type case.
455
456 if not Is_Class_Wide_Type (Entity (Pref))
9dfe12ae 457 and then not Is_Class_Wide_Type (Etype (Item))
ee6ba406 458 and then Base_Type (Etype (Item)) /= Base_Type (Formal_Typ)
459 then
460 Rewrite (Item,
461 Unchecked_Convert_To (Formal_Typ, Relocate_Node (Item)));
462
463 -- For untagged derived types set Assignment_OK, to prevent
464 -- copies from being created when the unchecked conversion
465 -- is expanded (which would happen in Remove_Side_Effects
466 -- if Expand_N_Unchecked_Conversion were allowed to call
467 -- Force_Evaluation). The copy could violate Ada semantics
468 -- in cases such as an actual that is an out parameter.
469 -- Note that this approach is also used in exp_ch7 for calls
470 -- to controlled type operations to prevent problems with
471 -- actuals wrapped in unchecked conversions.
472
473 if Is_Untagged_Derivation (Etype (Expression (Item))) then
474 Set_Assignment_OK (Item);
475 end if;
476 end if;
477
478 -- And now rewrite the call
479
480 Rewrite (N,
481 Make_Procedure_Call_Statement (Loc,
482 Name => New_Occurrence_Of (Pname, Loc),
483 Parameter_Associations => Exprs));
484
485 Analyze (N);
486 end Rewrite_Stream_Proc_Call;
487
488 -- Start of processing for Expand_N_Attribute_Reference
489
490 begin
491 -- Do required validity checking
492
493 if Validity_Checks_On and Validity_Check_Operands then
494 declare
495 Expr : Node_Id;
496
497 begin
498 Expr := First (Expressions (N));
499 while Present (Expr) loop
500 Ensure_Valid (Expr);
501 Next (Expr);
502 end loop;
503 end;
504 end if;
505
506 -- Remaining processing depends on specific attribute
507
508 case Id is
509
510 ------------
511 -- Access --
512 ------------
513
514 when Attribute_Access =>
515
516 if Ekind (Btyp) = E_Access_Protected_Subprogram_Type then
517
518 -- The value of the attribute_reference is a record containing
519 -- two fields: an access to the protected object, and an access
520 -- to the subprogram itself. The prefix is a selected component.
521
522 declare
523 Agg : Node_Id;
524 Sub : Entity_Id;
f15731c4 525 E_T : constant Entity_Id := Equivalent_Type (Btyp);
ee6ba406 526 Acc : constant Entity_Id :=
527 Etype (Next_Component (First_Component (E_T)));
528 Obj_Ref : Node_Id;
529 Curr : Entity_Id;
530
531 begin
532 -- Within the body of the protected type, the prefix
533 -- designates a local operation, and the object is the first
534 -- parameter of the corresponding protected body of the
535 -- current enclosing operation.
536
537 if Is_Entity_Name (Pref) then
538 pragma Assert (In_Open_Scopes (Scope (Entity (Pref))));
539 Sub :=
540 New_Occurrence_Of
541 (Protected_Body_Subprogram (Entity (Pref)), Loc);
542 Curr := Current_Scope;
543
544 while Scope (Curr) /= Scope (Entity (Pref)) loop
545 Curr := Scope (Curr);
546 end loop;
547
548 Obj_Ref :=
549 Make_Attribute_Reference (Loc,
550 Prefix =>
551 New_Occurrence_Of
552 (First_Formal
553 (Protected_Body_Subprogram (Curr)), Loc),
554 Attribute_Name => Name_Address);
555
556 -- Case where the prefix is not an entity name. Find the
557 -- version of the protected operation to be called from
558 -- outside the protected object.
559
560 else
561 Sub :=
562 New_Occurrence_Of
563 (External_Subprogram
564 (Entity (Selector_Name (Pref))), Loc);
565
566 Obj_Ref :=
567 Make_Attribute_Reference (Loc,
568 Prefix => Relocate_Node (Prefix (Pref)),
569 Attribute_Name => Name_Address);
570 end if;
571
572 Agg :=
573 Make_Aggregate (Loc,
574 Expressions =>
575 New_List (
576 Obj_Ref,
577 Unchecked_Convert_To (Acc,
578 Make_Attribute_Reference (Loc,
579 Prefix => Sub,
580 Attribute_Name => Name_Address))));
581
582 Rewrite (N, Agg);
583
f15731c4 584 Analyze_And_Resolve (N, E_T);
ee6ba406 585
586 -- For subsequent analysis, the node must retain its type.
587 -- The backend will replace it with the equivalent type where
588 -- needed.
589
590 Set_Etype (N, Typ);
591 end;
592
593 elsif Ekind (Btyp) = E_General_Access_Type then
594 declare
595 Ref_Object : constant Node_Id := Get_Referenced_Object (Pref);
596 Parm_Ent : Entity_Id;
597 Conversion : Node_Id;
598
599 begin
600 -- If the prefix of an Access attribute is a dereference of an
601 -- access parameter (or a renaming of such a dereference) and
602 -- the context is a general access type (but not an anonymous
603 -- access type), then rewrite the attribute as a conversion of
604 -- the access parameter to the context access type. This will
605 -- result in an accessibility check being performed, if needed.
606
607 -- (X.all'Access => Acc_Type (X))
608
609 if Nkind (Ref_Object) = N_Explicit_Dereference
610 and then Is_Entity_Name (Prefix (Ref_Object))
611 then
612 Parm_Ent := Entity (Prefix (Ref_Object));
613
614 if Ekind (Parm_Ent) in Formal_Kind
615 and then Ekind (Etype (Parm_Ent)) = E_Anonymous_Access_Type
616 and then Present (Extra_Accessibility (Parm_Ent))
617 then
618 Conversion :=
619 Convert_To (Typ, New_Copy_Tree (Prefix (Ref_Object)));
620
621 Rewrite (N, Conversion);
622 Analyze_And_Resolve (N, Typ);
623 end if;
624 end if;
625 end;
626
627 -- If the prefix is a type name, this is a reference to the current
628 -- instance of the type, within its initialization procedure.
629
630 else
631 Expand_Access_To_Type (N);
632 end if;
633
634 --------------
635 -- Adjacent --
636 --------------
637
638 -- Transforms 'Adjacent into a call to the floating-point attribute
639 -- function Adjacent in Fat_xxx (where xxx is the root type)
640
641 when Attribute_Adjacent =>
642 Expand_Fpt_Attribute_RR (N);
643
644 -------------
645 -- Address --
646 -------------
647
648 when Attribute_Address => Address : declare
649 Task_Proc : Entity_Id;
650
651 begin
652 -- If the prefix is a task or a task type, the useful address
653 -- is that of the procedure for the task body, i.e. the actual
654 -- program unit. We replace the original entity with that of
655 -- the procedure.
656
657 if Is_Entity_Name (Pref)
658 and then Is_Task_Type (Entity (Pref))
659 then
660 Task_Proc := Next_Entity (Root_Type (Etype (Pref)));
661
662 while Present (Task_Proc) loop
663 exit when Ekind (Task_Proc) = E_Procedure
664 and then Etype (First_Formal (Task_Proc)) =
665 Corresponding_Record_Type (Etype (Pref));
666 Next_Entity (Task_Proc);
667 end loop;
668
669 if Present (Task_Proc) then
670 Set_Entity (Pref, Task_Proc);
671 Set_Etype (Pref, Etype (Task_Proc));
672 end if;
673
674 -- Similarly, the address of a protected operation is the address
675 -- of the corresponding protected body, regardless of the protected
676 -- object from which it is selected.
677
678 elsif Nkind (Pref) = N_Selected_Component
679 and then Is_Subprogram (Entity (Selector_Name (Pref)))
680 and then Is_Protected_Type (Scope (Entity (Selector_Name (Pref))))
681 then
682 Rewrite (Pref,
683 New_Occurrence_Of (
684 External_Subprogram (Entity (Selector_Name (Pref))), Loc));
685
686 elsif Nkind (Pref) = N_Explicit_Dereference
687 and then Ekind (Etype (Pref)) = E_Subprogram_Type
688 and then Convention (Etype (Pref)) = Convention_Protected
689 then
690 -- The prefix is be a dereference of an access_to_protected_
691 -- subprogram. The desired address is the second component of
692 -- the record that represents the access.
693
694 declare
695 Addr : constant Entity_Id := Etype (N);
696 Ptr : constant Node_Id := Prefix (Pref);
697 T : constant Entity_Id :=
698 Equivalent_Type (Base_Type (Etype (Ptr)));
699
700 begin
701 Rewrite (N,
702 Unchecked_Convert_To (Addr,
703 Make_Selected_Component (Loc,
704 Prefix => Unchecked_Convert_To (T, Ptr),
705 Selector_Name => New_Occurrence_Of (
706 Next_Entity (First_Entity (T)), Loc))));
707
708 Analyze_And_Resolve (N, Addr);
709 end;
710 end if;
711
712 -- Deal with packed array reference, other cases are handled by gigi
713
714 if Involves_Packed_Array_Reference (Pref) then
715 Expand_Packed_Address_Reference (N);
716 end if;
717 end Address;
718
9dfe12ae 719 ---------------
720 -- Alignment --
721 ---------------
722
723 when Attribute_Alignment => Alignment : declare
724 Ptyp : constant Entity_Id := Etype (Pref);
725 New_Node : Node_Id;
726
727 begin
728 -- For class-wide types, X'Class'Alignment is transformed into a
729 -- direct reference to the Alignment of the class type, so that the
730 -- back end does not have to deal with the X'Class'Alignment
731 -- reference.
732
733 if Is_Entity_Name (Pref)
734 and then Is_Class_Wide_Type (Entity (Pref))
735 then
736 Rewrite (Prefix (N), New_Occurrence_Of (Entity (Pref), Loc));
737 return;
738
739 -- For x'Alignment applied to an object of a class wide type,
740 -- transform X'Alignment into a call to the predefined primitive
741 -- operation _Alignment applied to X.
742
743 elsif Is_Class_Wide_Type (Ptyp) then
744 New_Node :=
745 Make_Function_Call (Loc,
746 Name => New_Reference_To
747 (Find_Prim_Op (Ptyp, Name_uAlignment), Loc),
748 Parameter_Associations => New_List (Pref));
749
750 if Typ /= Standard_Integer then
751
752 -- The context is a specific integer type with which the
753 -- original attribute was compatible. The function has a
754 -- specific type as well, so to preserve the compatibility
755 -- we must convert explicitly.
756
757 New_Node := Convert_To (Typ, New_Node);
758 end if;
759
760 Rewrite (N, New_Node);
761 Analyze_And_Resolve (N, Typ);
762 return;
763
764 -- For all other cases, we just have to deal with the case of
765 -- the fact that the result can be universal.
766
767 else
768 Apply_Universal_Integer_Attribute_Checks (N);
769 end if;
770 end Alignment;
771
ee6ba406 772 ---------------
773 -- AST_Entry --
774 ---------------
775
776 when Attribute_AST_Entry => AST_Entry : declare
777 Ttyp : Entity_Id;
778 T_Id : Node_Id;
779 Eent : Entity_Id;
780
781 Entry_Ref : Node_Id;
782 -- The reference to the entry or entry family
783
784 Index : Node_Id;
785 -- The index expression for an entry family reference, or
786 -- the Empty if Entry_Ref references a simple entry.
787
788 begin
789 if Nkind (Pref) = N_Indexed_Component then
790 Entry_Ref := Prefix (Pref);
791 Index := First (Expressions (Pref));
792 else
793 Entry_Ref := Pref;
794 Index := Empty;
795 end if;
796
797 -- Get expression for Task_Id and the entry entity
798
799 if Nkind (Entry_Ref) = N_Selected_Component then
800 T_Id :=
801 Make_Attribute_Reference (Loc,
802 Attribute_Name => Name_Identity,
803 Prefix => Prefix (Entry_Ref));
804
805 Ttyp := Etype (Prefix (Entry_Ref));
806 Eent := Entity (Selector_Name (Entry_Ref));
807
808 else
809 T_Id :=
810 Make_Function_Call (Loc,
811 Name => New_Occurrence_Of (RTE (RE_Current_Task), Loc));
812
813 Eent := Entity (Entry_Ref);
814
815 -- We have to find the enclosing task to get the task type
816 -- There must be one, since we already validated this earlier
817
818 Ttyp := Current_Scope;
819 while not Is_Task_Type (Ttyp) loop
820 Ttyp := Scope (Ttyp);
821 end loop;
822 end if;
823
824 -- Now rewrite the attribute with a call to Create_AST_Handler
825
826 Rewrite (N,
827 Make_Function_Call (Loc,
828 Name => New_Occurrence_Of (RTE (RE_Create_AST_Handler), Loc),
829 Parameter_Associations => New_List (
830 T_Id,
831 Entry_Index_Expression (Loc, Eent, Index, Ttyp))));
832
833 Analyze_And_Resolve (N, RTE (RE_AST_Handler));
834 end AST_Entry;
835
836 ------------------
837 -- Bit_Position --
838 ------------------
839
840 -- We compute this if a component clause was present, otherwise
841 -- we leave the computation up to Gigi, since we don't know what
842 -- layout will be chosen.
843
844 -- Note that the attribute can apply to a naked record component
845 -- in generated code (i.e. the prefix is an identifier that
846 -- references the component or discriminant entity).
847
848 when Attribute_Bit_Position => Bit_Position :
849 declare
850 CE : Entity_Id;
851
852 begin
853 if Nkind (Pref) = N_Identifier then
854 CE := Entity (Pref);
855 else
856 CE := Entity (Selector_Name (Pref));
857 end if;
858
859 if Known_Static_Component_Bit_Offset (CE) then
860 Rewrite (N,
861 Make_Integer_Literal (Loc,
862 Intval => Component_Bit_Offset (CE)));
863 Analyze_And_Resolve (N, Typ);
864
865 else
866 Apply_Universal_Integer_Attribute_Checks (N);
867 end if;
868 end Bit_Position;
869
870 ------------------
871 -- Body_Version --
872 ------------------
873
874 -- A reference to P'Body_Version or P'Version is expanded to
875
876 -- Vnn : Unsigned;
877 -- pragma Import (C, Vnn, "uuuuT";
878 -- ...
879 -- Get_Version_String (Vnn)
880
881 -- where uuuu is the unit name (dots replaced by double underscore)
882 -- and T is B for the cases of Body_Version, or Version applied to a
883 -- subprogram acting as its own spec, and S for Version applied to a
884 -- subprogram spec or package. This sequence of code references the
885 -- the unsigned constant created in the main program by the binder.
886
887 -- A special exception occurs for Standard, where the string
888 -- returned is a copy of the library string in gnatvsn.ads.
889
890 when Attribute_Body_Version | Attribute_Version => Version : declare
891 E : constant Entity_Id :=
892 Make_Defining_Identifier (Loc, New_Internal_Name ('V'));
893 Pent : Entity_Id := Entity (Pref);
894 S : String_Id;
895
896 begin
897 -- If not library unit, get to containing library unit
898
899 while Pent /= Standard_Standard
900 and then Scope (Pent) /= Standard_Standard
901 loop
902 Pent := Scope (Pent);
903 end loop;
904
905 -- Special case Standard
906
907 if Pent = Standard_Standard
908 or else Pent = Standard_ASCII
909 then
910 Name_Buffer (1 .. Library_Version'Length) := Library_Version;
911 Name_Len := Library_Version'Length;
912 Rewrite (N,
913 Make_String_Literal (Loc,
914 Strval => String_From_Name_Buffer));
915
916 -- All other cases
917
918 else
919 -- Build required string constant
920
921 Get_Name_String (Get_Unit_Name (Pent));
922
923 Start_String;
924 for J in 1 .. Name_Len - 2 loop
925 if Name_Buffer (J) = '.' then
926 Store_String_Chars ("__");
927 else
928 Store_String_Char (Get_Char_Code (Name_Buffer (J)));
929 end if;
930 end loop;
931
932 -- Case of subprogram acting as its own spec, always use body
933
934 if Nkind (Declaration_Node (Pent)) in N_Subprogram_Specification
935 and then Nkind (Parent (Declaration_Node (Pent))) =
936 N_Subprogram_Body
937 and then Acts_As_Spec (Parent (Declaration_Node (Pent)))
938 then
939 Store_String_Chars ("B");
940
941 -- Case of no body present, always use spec
942
943 elsif not Unit_Requires_Body (Pent) then
944 Store_String_Chars ("S");
945
946 -- Otherwise use B for Body_Version, S for spec
947
948 elsif Id = Attribute_Body_Version then
949 Store_String_Chars ("B");
950 else
951 Store_String_Chars ("S");
952 end if;
953
954 S := End_String;
955 Lib.Version_Referenced (S);
956
957 -- Insert the object declaration
958
959 Insert_Actions (N, New_List (
960 Make_Object_Declaration (Loc,
961 Defining_Identifier => E,
962 Object_Definition =>
963 New_Occurrence_Of (RTE (RE_Unsigned), Loc))));
964
965 -- Set entity as imported with correct external name
966
967 Set_Is_Imported (E);
968 Set_Interface_Name (E, Make_String_Literal (Loc, S));
969
970 -- And now rewrite original reference
971
972 Rewrite (N,
973 Make_Function_Call (Loc,
974 Name => New_Reference_To (RTE (RE_Get_Version_String), Loc),
975 Parameter_Associations => New_List (
976 New_Occurrence_Of (E, Loc))));
977 end if;
978
979 Analyze_And_Resolve (N, RTE (RE_Version_String));
980 end Version;
981
982 -------------
983 -- Ceiling --
984 -------------
985
986 -- Transforms 'Ceiling into a call to the floating-point attribute
987 -- function Ceiling in Fat_xxx (where xxx is the root type)
988
989 when Attribute_Ceiling =>
990 Expand_Fpt_Attribute_R (N);
991
992 --------------
993 -- Callable --
994 --------------
995
996 -- Transforms 'Callable attribute into a call to the Callable function.
997
998 when Attribute_Callable => Callable :
999 begin
1000 Rewrite (N,
1001 Build_Call_With_Task (Pref, RTE (RE_Callable)));
1002 Analyze_And_Resolve (N, Standard_Boolean);
1003 end Callable;
1004
1005 ------------
1006 -- Caller --
1007 ------------
1008
1009 -- Transforms 'Caller attribute into a call to either the
1010 -- Task_Entry_Caller or the Protected_Entry_Caller function.
1011
1012 when Attribute_Caller => Caller : declare
9dfe12ae 1013 Id_Kind : constant Entity_Id := RTE (RO_AT_Task_ID);
1014 Ent : constant Entity_Id := Entity (Pref);
1015 Conctype : constant Entity_Id := Scope (Ent);
1016 Nest_Depth : Integer := 0;
ee6ba406 1017 Name : Node_Id;
1018 S : Entity_Id;
1019
1020 begin
1021 -- Protected case
1022
1023 if Is_Protected_Type (Conctype) then
1024 if Abort_Allowed
1025 or else Restrictions (No_Entry_Queue) = False
1026 or else Number_Entries (Conctype) > 1
1027 then
1028 Name :=
1029 New_Reference_To
1030 (RTE (RE_Protected_Entry_Caller), Loc);
1031 else
1032 Name :=
1033 New_Reference_To
1034 (RTE (RE_Protected_Single_Entry_Caller), Loc);
1035 end if;
1036
1037 Rewrite (N,
1038 Unchecked_Convert_To (Id_Kind,
1039 Make_Function_Call (Loc,
1040 Name => Name,
1041 Parameter_Associations => New_List
1042 (New_Reference_To (
1043 Object_Ref
1044 (Corresponding_Body (Parent (Conctype))), Loc)))));
1045
1046 -- Task case
1047
1048 else
1049 -- Determine the nesting depth of the E'Caller attribute, that
1050 -- is, how many accept statements are nested within the accept
1051 -- statement for E at the point of E'Caller. The runtime uses
1052 -- this depth to find the specified entry call.
1053
1054 for J in reverse 0 .. Scope_Stack.Last loop
1055 S := Scope_Stack.Table (J).Entity;
1056
1057 -- We should not reach the scope of the entry, as it should
1058 -- already have been checked in Sem_Attr that this attribute
1059 -- reference is within a matching accept statement.
1060
1061 pragma Assert (S /= Conctype);
1062
1063 if S = Ent then
1064 exit;
1065
1066 elsif Is_Entry (S) then
1067 Nest_Depth := Nest_Depth + 1;
1068 end if;
1069 end loop;
1070
1071 Rewrite (N,
1072 Unchecked_Convert_To (Id_Kind,
1073 Make_Function_Call (Loc,
1074 Name => New_Reference_To (
1075 RTE (RE_Task_Entry_Caller), Loc),
1076 Parameter_Associations => New_List (
1077 Make_Integer_Literal (Loc,
1078 Intval => Int (Nest_Depth))))));
1079 end if;
1080
1081 Analyze_And_Resolve (N, Id_Kind);
1082 end Caller;
1083
1084 -------------
1085 -- Compose --
1086 -------------
1087
1088 -- Transforms 'Compose into a call to the floating-point attribute
1089 -- function Compose in Fat_xxx (where xxx is the root type)
1090
1091 -- Note: we strictly should have special code here to deal with the
1092 -- case of absurdly negative arguments (less than Integer'First)
1093 -- which will return a (signed) zero value, but it hardly seems
1094 -- worth the effort. Absurdly large positive arguments will raise
1095 -- constraint error which is fine.
1096
1097 when Attribute_Compose =>
1098 Expand_Fpt_Attribute_RI (N);
1099
1100 -----------------
1101 -- Constrained --
1102 -----------------
1103
1104 when Attribute_Constrained => Constrained : declare
1105 Formal_Ent : constant Entity_Id := Param_Entity (Pref);
1106
1107 begin
1108 -- Reference to a parameter where the value is passed as an extra
1109 -- actual, corresponding to the extra formal referenced by the
9dfe12ae 1110 -- Extra_Constrained field of the corresponding formal. If this
1111 -- is an entry in-parameter, it is replaced by a constant renaming
1112 -- for which Extra_Constrained is never created.
ee6ba406 1113
1114 if Present (Formal_Ent)
9dfe12ae 1115 and then Ekind (Formal_Ent) /= E_Constant
ee6ba406 1116 and then Present (Extra_Constrained (Formal_Ent))
1117 then
1118 Rewrite (N,
1119 New_Occurrence_Of
1120 (Extra_Constrained (Formal_Ent), Sloc (N)));
1121
1122 -- For variables with a Extra_Constrained field, we use the
1123 -- corresponding entity.
1124
1125 elsif Nkind (Pref) = N_Identifier
1126 and then Ekind (Entity (Pref)) = E_Variable
1127 and then Present (Extra_Constrained (Entity (Pref)))
1128 then
1129 Rewrite (N,
1130 New_Occurrence_Of
1131 (Extra_Constrained (Entity (Pref)), Sloc (N)));
1132
1133 -- For all other entity names, we can tell at compile time
1134
1135 elsif Is_Entity_Name (Pref) then
1136 declare
1137 Ent : constant Entity_Id := Entity (Pref);
1138 Res : Boolean;
1139
1140 begin
1141 -- (RM J.4) obsolescent cases
1142
1143 if Is_Type (Ent) then
1144
1145 -- Private type
1146
1147 if Is_Private_Type (Ent) then
1148 Res := not Has_Discriminants (Ent)
1149 or else Is_Constrained (Ent);
1150
1151 -- It not a private type, must be a generic actual type
1152 -- that corresponded to a private type. We know that this
1153 -- correspondence holds, since otherwise the reference
1154 -- within the generic template would have been illegal.
1155
1156 else
9dfe12ae 1157 if Is_Composite_Type (Underlying_Type (Ent)) then
1158 Res := Is_Constrained (Ent);
1159 else
1160 Res := True;
1161 end if;
ee6ba406 1162 end if;
1163
1164 -- If the prefix is not a variable or is aliased, then
1165 -- definitely true; if it's a formal parameter without
1166 -- an associated extra formal, then treat it as constrained.
1167
1168 elsif not Is_Variable (Pref)
1169 or else Present (Formal_Ent)
1170 or else Is_Aliased_View (Pref)
1171 then
1172 Res := True;
1173
1174 -- Variable case, just look at type to see if it is
1175 -- constrained. Note that the one case where this is
1176 -- not accurate (the procedure formal case), has been
1177 -- handled above.
1178
1179 else
1180 Res := Is_Constrained (Etype (Ent));
1181 end if;
1182
1183 if Res then
1184 Rewrite (N,
1185 New_Reference_To (Standard_True, Loc));
1186 else
1187 Rewrite (N,
1188 New_Reference_To (Standard_False, Loc));
1189 end if;
1190 end;
1191
1192 -- Prefix is not an entity name. These are also cases where
1193 -- we can always tell at compile time by looking at the form
1194 -- and type of the prefix.
1195
1196 else
1197 if not Is_Variable (Pref)
1198 or else Nkind (Pref) = N_Explicit_Dereference
1199 or else Is_Constrained (Etype (Pref))
1200 then
1201 Rewrite (N,
1202 New_Reference_To (Standard_True, Loc));
1203 else
1204 Rewrite (N,
1205 New_Reference_To (Standard_False, Loc));
1206 end if;
1207 end if;
1208
1209 Analyze_And_Resolve (N, Standard_Boolean);
1210 end Constrained;
1211
1212 ---------------
1213 -- Copy_Sign --
1214 ---------------
1215
1216 -- Transforms 'Copy_Sign into a call to the floating-point attribute
1217 -- function Copy_Sign in Fat_xxx (where xxx is the root type)
1218
1219 when Attribute_Copy_Sign =>
1220 Expand_Fpt_Attribute_RR (N);
1221
1222 -----------
1223 -- Count --
1224 -----------
1225
1226 -- Transforms 'Count attribute into a call to the Count function
1227
1228 when Attribute_Count => Count :
1229 declare
1230 Entnam : Node_Id;
1231 Index : Node_Id;
1232 Name : Node_Id;
1233 Call : Node_Id;
1234 Conctyp : Entity_Id;
1235
1236 begin
1237 -- If the prefix is a member of an entry family, retrieve both
1238 -- entry name and index. For a simple entry there is no index.
1239
1240 if Nkind (Pref) = N_Indexed_Component then
1241 Entnam := Prefix (Pref);
1242 Index := First (Expressions (Pref));
1243 else
1244 Entnam := Pref;
1245 Index := Empty;
1246 end if;
1247
1248 -- Find the concurrent type in which this attribute is referenced
1249 -- (there had better be one).
1250
1251 Conctyp := Current_Scope;
1252 while not Is_Concurrent_Type (Conctyp) loop
1253 Conctyp := Scope (Conctyp);
1254 end loop;
1255
1256 -- Protected case
1257
1258 if Is_Protected_Type (Conctyp) then
1259
1260 if Abort_Allowed
1261 or else Restrictions (No_Entry_Queue) = False
1262 or else Number_Entries (Conctyp) > 1
1263 then
1264 Name := New_Reference_To (RTE (RE_Protected_Count), Loc);
1265
1266 Call :=
1267 Make_Function_Call (Loc,
1268 Name => Name,
1269 Parameter_Associations => New_List (
1270 New_Reference_To (
1271 Object_Ref (
1272 Corresponding_Body (Parent (Conctyp))), Loc),
1273 Entry_Index_Expression (
1274 Loc, Entity (Entnam), Index, Scope (Entity (Entnam)))));
1275 else
1276 Name := New_Reference_To (RTE (RE_Protected_Count_Entry), Loc);
1277
1278 Call := Make_Function_Call (Loc,
1279 Name => Name,
1280 Parameter_Associations => New_List (
1281 New_Reference_To (
1282 Object_Ref (
1283 Corresponding_Body (Parent (Conctyp))), Loc)));
1284 end if;
1285
1286 -- Task case
1287
1288 else
1289 Call :=
1290 Make_Function_Call (Loc,
1291 Name => New_Reference_To (RTE (RE_Task_Count), Loc),
1292 Parameter_Associations => New_List (
1293 Entry_Index_Expression
1294 (Loc, Entity (Entnam), Index, Scope (Entity (Entnam)))));
1295 end if;
1296
1297 -- The call returns type Natural but the context is universal integer
1298 -- so any integer type is allowed. The attribute was already resolved
1299 -- so its Etype is the required result type. If the base type of the
1300 -- context type is other than Standard.Integer we put in a conversion
1301 -- to the required type. This can be a normal typed conversion since
1302 -- both input and output types of the conversion are integer types
1303
1304 if Base_Type (Typ) /= Base_Type (Standard_Integer) then
1305 Rewrite (N, Convert_To (Typ, Call));
1306 else
1307 Rewrite (N, Call);
1308 end if;
1309
1310 Analyze_And_Resolve (N, Typ);
1311 end Count;
1312
1313 ---------------
1314 -- Elab_Body --
1315 ---------------
1316
1317 -- This processing is shared by Elab_Spec
1318
1319 -- What we do is to insert the following declarations
1320
1321 -- procedure tnn;
1322 -- pragma Import (C, enn, "name___elabb/s");
1323
1324 -- and then the Elab_Body/Spec attribute is replaced by a reference
1325 -- to this defining identifier.
1326
1327 when Attribute_Elab_Body |
1328 Attribute_Elab_Spec =>
1329
1330 Elab_Body : declare
1331 Ent : constant Entity_Id :=
1332 Make_Defining_Identifier (Loc,
1333 New_Internal_Name ('E'));
1334 Str : String_Id;
1335 Lang : Node_Id;
1336
1337 procedure Make_Elab_String (Nod : Node_Id);
1338 -- Given Nod, an identifier, or a selected component, put the
1339 -- image into the current string literal, with double underline
1340 -- between components.
1341
1342 procedure Make_Elab_String (Nod : Node_Id) is
1343 begin
1344 if Nkind (Nod) = N_Selected_Component then
1345 Make_Elab_String (Prefix (Nod));
1346 if Java_VM then
1347 Store_String_Char ('$');
1348 else
1349 Store_String_Char ('_');
1350 Store_String_Char ('_');
1351 end if;
1352
1353 Get_Name_String (Chars (Selector_Name (Nod)));
1354
1355 else
1356 pragma Assert (Nkind (Nod) = N_Identifier);
1357 Get_Name_String (Chars (Nod));
1358 end if;
1359
1360 Store_String_Chars (Name_Buffer (1 .. Name_Len));
1361 end Make_Elab_String;
1362
1363 -- Start of processing for Elab_Body/Elab_Spec
1364
1365 begin
1366 -- First we need to prepare the string literal for the name of
1367 -- the elaboration routine to be referenced.
1368
1369 Start_String;
1370 Make_Elab_String (Pref);
1371
1372 if Java_VM then
1373 Store_String_Chars ("._elab");
1374 Lang := Make_Identifier (Loc, Name_Ada);
1375 else
1376 Store_String_Chars ("___elab");
1377 Lang := Make_Identifier (Loc, Name_C);
1378 end if;
1379
1380 if Id = Attribute_Elab_Body then
1381 Store_String_Char ('b');
1382 else
1383 Store_String_Char ('s');
1384 end if;
1385
1386 Str := End_String;
1387
1388 Insert_Actions (N, New_List (
1389 Make_Subprogram_Declaration (Loc,
1390 Specification =>
1391 Make_Procedure_Specification (Loc,
1392 Defining_Unit_Name => Ent)),
1393
1394 Make_Pragma (Loc,
1395 Chars => Name_Import,
1396 Pragma_Argument_Associations => New_List (
1397 Make_Pragma_Argument_Association (Loc,
1398 Expression => Lang),
1399
1400 Make_Pragma_Argument_Association (Loc,
1401 Expression =>
1402 Make_Identifier (Loc, Chars (Ent))),
1403
1404 Make_Pragma_Argument_Association (Loc,
1405 Expression =>
1406 Make_String_Literal (Loc, Str))))));
1407
1408 Set_Entity (N, Ent);
1409 Rewrite (N, New_Occurrence_Of (Ent, Loc));
1410 end Elab_Body;
1411
1412 ----------------
1413 -- Elaborated --
1414 ----------------
1415
1416 -- Elaborated is always True for preelaborated units, predefined
1417 -- units, pure units and units which have Elaborate_Body pragmas.
1418 -- These units have no elaboration entity.
1419
1420 -- Note: The Elaborated attribute is never passed through to Gigi
1421
1422 when Attribute_Elaborated => Elaborated : declare
1423 Ent : constant Entity_Id := Entity (Pref);
1424
1425 begin
1426 if Present (Elaboration_Entity (Ent)) then
1427 Rewrite (N,
1428 New_Occurrence_Of (Elaboration_Entity (Ent), Loc));
1429 else
1430 Rewrite (N, New_Occurrence_Of (Standard_True, Loc));
1431 end if;
1432 end Elaborated;
1433
1434 --------------
1435 -- Enum_Rep --
1436 --------------
1437
1438 when Attribute_Enum_Rep => Enum_Rep :
1439 begin
1440 -- X'Enum_Rep (Y) expands to
1441
1442 -- target-type (Y)
1443
1444 -- This is simply a direct conversion from the enumeration type
1445 -- to the target integer type, which is treated by Gigi as a normal
1446 -- integer conversion, treating the enumeration type as an integer,
1447 -- which is exactly what we want! We set Conversion_OK to make sure
1448 -- that the analyzer does not complain about what otherwise might
1449 -- be an illegal conversion.
1450
1451 if Is_Non_Empty_List (Exprs) then
1452 Rewrite (N,
1453 OK_Convert_To (Typ, Relocate_Node (First (Exprs))));
1454
1455 -- X'Enum_Rep where X is an enumeration literal is replaced by
1456 -- the literal value.
1457
1458 elsif Ekind (Entity (Pref)) = E_Enumeration_Literal then
1459 Rewrite (N,
1460 Make_Integer_Literal (Loc, Enumeration_Rep (Entity (Pref))));
1461
9dfe12ae 1462 -- If this is a renaming of a literal, recover the representation
1463 -- of the original.
1464
1465 elsif Ekind (Entity (Pref)) = E_Constant
1466 and then Present (Renamed_Object (Entity (Pref)))
1467 and then
1468 Ekind (Entity (Renamed_Object (Entity (Pref))))
1469 = E_Enumeration_Literal
1470 then
1471 Rewrite (N,
1472 Make_Integer_Literal (Loc,
1473 Enumeration_Rep (Entity (Renamed_Object (Entity (Pref))))));
1474
ee6ba406 1475 -- X'Enum_Rep where X is an object does a direct unchecked conversion
1476 -- of the object value, as described for the type case above.
1477
1478 else
1479 Rewrite (N,
1480 OK_Convert_To (Typ, Relocate_Node (Pref)));
1481 end if;
1482
1483 Set_Etype (N, Typ);
1484 Analyze_And_Resolve (N, Typ);
1485
1486 end Enum_Rep;
1487
1488 --------------
1489 -- Exponent --
1490 --------------
1491
1492 -- Transforms 'Exponent into a call to the floating-point attribute
1493 -- function Exponent in Fat_xxx (where xxx is the root type)
1494
1495 when Attribute_Exponent =>
1496 Expand_Fpt_Attribute_R (N);
1497
1498 ------------------
1499 -- External_Tag --
1500 ------------------
1501
1502 -- transforme X'External_Tag into Ada.Tags.External_Tag (X'tag)
1503
1504 when Attribute_External_Tag => External_Tag :
1505 begin
1506 Rewrite (N,
1507 Make_Function_Call (Loc,
1508 Name => New_Reference_To (RTE (RE_External_Tag), Loc),
1509 Parameter_Associations => New_List (
1510 Make_Attribute_Reference (Loc,
1511 Attribute_Name => Name_Tag,
1512 Prefix => Prefix (N)))));
1513
1514 Analyze_And_Resolve (N, Standard_String);
1515 end External_Tag;
1516
1517 -----------
1518 -- First --
1519 -----------
1520
1521 when Attribute_First => declare
1522 Ptyp : constant Entity_Id := Etype (Pref);
1523
1524 begin
1525 -- If the prefix type is a constrained packed array type which
1526 -- already has a Packed_Array_Type representation defined, then
1527 -- replace this attribute with a direct reference to 'First of the
1528 -- appropriate index subtype (since otherwise Gigi will try to give
1529 -- us the value of 'First for this implementation type).
1530
1531 if Is_Constrained_Packed_Array (Ptyp) then
1532 Rewrite (N,
1533 Make_Attribute_Reference (Loc,
1534 Attribute_Name => Name_First,
1535 Prefix => New_Reference_To (Get_Index_Subtype (N), Loc)));
1536 Analyze_And_Resolve (N, Typ);
1537
1538 elsif Is_Access_Type (Ptyp) then
1539 Apply_Access_Check (N);
1540 end if;
1541 end;
1542
1543 ---------------
1544 -- First_Bit --
1545 ---------------
1546
1547 -- We compute this if a component clause was present, otherwise
1548 -- we leave the computation up to Gigi, since we don't know what
1549 -- layout will be chosen.
1550
1551 when Attribute_First_Bit => First_Bit :
1552 declare
1553 CE : constant Entity_Id := Entity (Selector_Name (Pref));
1554
1555 begin
1556 if Known_Static_Component_Bit_Offset (CE) then
1557 Rewrite (N,
1558 Make_Integer_Literal (Loc,
1559 Component_Bit_Offset (CE) mod System_Storage_Unit));
1560
1561 Analyze_And_Resolve (N, Typ);
1562
1563 else
1564 Apply_Universal_Integer_Attribute_Checks (N);
1565 end if;
1566 end First_Bit;
1567
1568 -----------------
1569 -- Fixed_Value --
1570 -----------------
1571
1572 -- We transform:
1573
1574 -- fixtype'Fixed_Value (integer-value)
1575
1576 -- into
1577
1578 -- fixtype(integer-value)
1579
1580 -- we do all the required analysis of the conversion here, because
1581 -- we do not want this to go through the fixed-point conversion
1582 -- circuits. Note that gigi always treats fixed-point as equivalent
1583 -- to the corresponding integer type anyway.
1584
1585 when Attribute_Fixed_Value => Fixed_Value :
1586 begin
1587 Rewrite (N,
1588 Make_Type_Conversion (Loc,
1589 Subtype_Mark => New_Occurrence_Of (Entity (Pref), Loc),
1590 Expression => Relocate_Node (First (Exprs))));
1591 Set_Etype (N, Entity (Pref));
1592 Set_Analyzed (N);
9dfe12ae 1593
1594 -- Note: it might appear that a properly analyzed unchecked conversion
1595 -- would be just fine here, but that's not the case, since the full
1596 -- range checks performed by the following call are critical!
1597
ee6ba406 1598 Apply_Type_Conversion_Checks (N);
1599 end Fixed_Value;
1600
1601 -----------
1602 -- Floor --
1603 -----------
1604
1605 -- Transforms 'Floor into a call to the floating-point attribute
1606 -- function Floor in Fat_xxx (where xxx is the root type)
1607
1608 when Attribute_Floor =>
1609 Expand_Fpt_Attribute_R (N);
1610
1611 ----------
1612 -- Fore --
1613 ----------
1614
1615 -- For the fixed-point type Typ:
1616
1617 -- Typ'Fore
1618
1619 -- expands into
1620
1621 -- Result_Type (System.Fore (Long_Long_Float (Type'First)),
1622 -- Long_Long_Float (Type'Last))
1623
1624 -- Note that we know that the type is a non-static subtype, or Fore
1625 -- would have itself been computed dynamically in Eval_Attribute.
1626
1627 when Attribute_Fore => Fore :
1628 declare
1629 Ptyp : constant Entity_Id := Etype (Pref);
1630
1631 begin
1632 Rewrite (N,
1633 Convert_To (Typ,
1634 Make_Function_Call (Loc,
1635 Name => New_Reference_To (RTE (RE_Fore), Loc),
1636
1637 Parameter_Associations => New_List (
1638 Convert_To (Standard_Long_Long_Float,
1639 Make_Attribute_Reference (Loc,
1640 Prefix => New_Reference_To (Ptyp, Loc),
1641 Attribute_Name => Name_First)),
1642
1643 Convert_To (Standard_Long_Long_Float,
1644 Make_Attribute_Reference (Loc,
1645 Prefix => New_Reference_To (Ptyp, Loc),
1646 Attribute_Name => Name_Last))))));
1647
1648 Analyze_And_Resolve (N, Typ);
1649 end Fore;
1650
1651 --------------
1652 -- Fraction --
1653 --------------
1654
1655 -- Transforms 'Fraction into a call to the floating-point attribute
1656 -- function Fraction in Fat_xxx (where xxx is the root type)
1657
1658 when Attribute_Fraction =>
1659 Expand_Fpt_Attribute_R (N);
1660
1661 --------------
1662 -- Identity --
1663 --------------
1664
1665 -- For an exception returns a reference to the exception data:
1666 -- Exception_Id!(Prefix'Reference)
1667
1668 -- For a task it returns a reference to the _task_id component of
1669 -- corresponding record:
1670
1671 -- taskV!(Prefix)._Task_Id, converted to the type Task_ID defined
1672
1673 -- in Ada.Task_Identification.
1674
1675 when Attribute_Identity => Identity : declare
1676 Id_Kind : Entity_Id;
1677
1678 begin
1679 if Etype (Pref) = Standard_Exception_Type then
1680 Id_Kind := RTE (RE_Exception_Id);
1681
1682 if Present (Renamed_Object (Entity (Pref))) then
1683 Set_Entity (Pref, Renamed_Object (Entity (Pref)));
1684 end if;
1685
1686 Rewrite (N,
1687 Unchecked_Convert_To (Id_Kind, Make_Reference (Loc, Pref)));
1688 else
1689 Id_Kind := RTE (RO_AT_Task_ID);
1690
1691 Rewrite (N,
1692 Unchecked_Convert_To (Id_Kind, Concurrent_Ref (Pref)));
1693 end if;
1694
1695 Analyze_And_Resolve (N, Id_Kind);
1696 end Identity;
1697
1698 -----------
1699 -- Image --
1700 -----------
1701
1702 -- Image attribute is handled in separate unit Exp_Imgv
1703
1704 when Attribute_Image =>
1705 Exp_Imgv.Expand_Image_Attribute (N);
1706
1707 ---------
1708 -- Img --
1709 ---------
1710
1711 -- X'Img is expanded to typ'Image (X), where typ is the type of X
1712
1713 when Attribute_Img => Img :
1714 begin
1715 Rewrite (N,
1716 Make_Attribute_Reference (Loc,
1717 Prefix => New_Reference_To (Etype (Pref), Loc),
1718 Attribute_Name => Name_Image,
1719 Expressions => New_List (Relocate_Node (Pref))));
1720
1721 Analyze_And_Resolve (N, Standard_String);
1722 end Img;
1723
1724 -----------
1725 -- Input --
1726 -----------
1727
1728 when Attribute_Input => Input : declare
1729 P_Type : constant Entity_Id := Entity (Pref);
1730 B_Type : constant Entity_Id := Base_Type (P_Type);
1731 U_Type : constant Entity_Id := Underlying_Type (P_Type);
1732 Strm : constant Node_Id := First (Exprs);
1733 Fname : Entity_Id;
1734 Decl : Node_Id;
1735 Call : Node_Id;
1736 Prag : Node_Id;
1737 Arg2 : Node_Id;
1738 Rfunc : Node_Id;
1739
1740 Cntrl : Node_Id := Empty;
1741 -- Value for controlling argument in call. Always Empty except in
1742 -- the dispatching (class-wide type) case, where it is a reference
1743 -- to the dummy object initialized to the right internal tag.
1744
1745 begin
1746 -- If no underlying type, we have an error that will be diagnosed
1747 -- elsewhere, so here we just completely ignore the expansion.
1748
1749 if No (U_Type) then
1750 return;
1751 end if;
1752
1753 -- If there is a TSS for Input, just call it
1754
9dfe12ae 1755 Fname := Find_Stream_Subprogram (P_Type, TSS_Stream_Input);
ee6ba406 1756
1757 if Present (Fname) then
1758 null;
1759
1760 else
1761 -- If there is a Stream_Convert pragma, use it, we rewrite
1762
1763 -- sourcetyp'Input (stream)
1764
1765 -- as
1766
1767 -- sourcetyp (streamread (strmtyp'Input (stream)));
1768
1769 -- where stmrearead is the given Read function that converts
1770 -- an argument of type strmtyp to type sourcetyp or a type
1771 -- from which it is derived. The extra conversion is required
1772 -- for the derived case.
1773
1774 Prag :=
1775 Get_Rep_Pragma
1776 (Implementation_Base_Type (P_Type), Name_Stream_Convert);
1777
1778 if Present (Prag) then
1779 Arg2 := Next (First (Pragma_Argument_Associations (Prag)));
1780 Rfunc := Entity (Expression (Arg2));
1781
1782 Rewrite (N,
1783 Convert_To (B_Type,
1784 Make_Function_Call (Loc,
1785 Name => New_Occurrence_Of (Rfunc, Loc),
1786 Parameter_Associations => New_List (
1787 Make_Attribute_Reference (Loc,
1788 Prefix =>
1789 New_Occurrence_Of
1790 (Etype (First_Formal (Rfunc)), Loc),
1791 Attribute_Name => Name_Input,
1792 Expressions => Exprs)))));
1793
1794 Analyze_And_Resolve (N, B_Type);
1795 return;
1796
1797 -- Elementary types
1798
1799 elsif Is_Elementary_Type (U_Type) then
1800
1801 -- A special case arises if we have a defined _Read routine,
1802 -- since in this case we are required to call this routine.
1803
9dfe12ae 1804 if Present (TSS (Base_Type (U_Type), TSS_Stream_Read)) then
ee6ba406 1805 Build_Record_Or_Elementary_Input_Function
1806 (Loc, U_Type, Decl, Fname);
1807 Insert_Action (N, Decl);
1808
1809 -- For normal cases, we call the I_xxx routine directly
1810
1811 else
1812 Rewrite (N, Build_Elementary_Input_Call (N));
1813 Analyze_And_Resolve (N, P_Type);
1814 return;
1815 end if;
1816
1817 -- Array type case
1818
1819 elsif Is_Array_Type (U_Type) then
1820 Build_Array_Input_Function (Loc, U_Type, Decl, Fname);
1821 Compile_Stream_Body_In_Scope (N, Decl, U_Type, Check => False);
1822
1823 -- Dispatching case with class-wide type
1824
1825 elsif Is_Class_Wide_Type (P_Type) then
1826
1827 declare
1828 Rtyp : constant Entity_Id := Root_Type (P_Type);
1829 Dnn : Entity_Id;
1830 Decl : Node_Id;
1831
1832 begin
1833 -- Read the internal tag (RM 13.13.2(34)) and use it to
1834 -- initialize a dummy tag object:
1835
1836 -- Dnn : Ada.Tags.Tag
1837 -- := Internal_Tag (String'Input (Strm));
1838
1839 -- This dummy object is used only to provide a controlling
1840 -- argument for the eventual _Input call.
1841
1842 Dnn :=
1843 Make_Defining_Identifier (Loc,
1844 Chars => New_Internal_Name ('D'));
1845
1846 Decl :=
1847 Make_Object_Declaration (Loc,
1848 Defining_Identifier => Dnn,
1849 Object_Definition =>
1850 New_Occurrence_Of (RTE (RE_Tag), Loc),
1851 Expression =>
1852 Make_Function_Call (Loc,
1853 Name =>
1854 New_Occurrence_Of (RTE (RE_Internal_Tag), Loc),
1855 Parameter_Associations => New_List (
1856 Make_Attribute_Reference (Loc,
1857 Prefix =>
1858 New_Occurrence_Of (Standard_String, Loc),
1859 Attribute_Name => Name_Input,
1860 Expressions => New_List (
1861 Relocate_Node
1862 (Duplicate_Subexpr (Strm)))))));
1863
1864 Insert_Action (N, Decl);
1865
1866 -- Now we need to get the entity for the call, and construct
1867 -- a function call node, where we preset a reference to Dnn
1868 -- as the controlling argument (doing an unchecked
9dfe12ae 1869 -- conversion to the classwide tagged type to make it
1870 -- look like a real tagged object).
ee6ba406 1871
9dfe12ae 1872 Fname := Find_Prim_Op (Rtyp, TSS_Stream_Input);
1873 Cntrl := Unchecked_Convert_To (P_Type,
ee6ba406 1874 New_Occurrence_Of (Dnn, Loc));
9dfe12ae 1875 Set_Etype (Cntrl, P_Type);
ee6ba406 1876 Set_Parent (Cntrl, N);
1877 end;
1878
1879 -- For tagged types, use the primitive Input function
1880
1881 elsif Is_Tagged_Type (U_Type) then
9dfe12ae 1882 Fname := Find_Prim_Op (U_Type, TSS_Stream_Input);
ee6ba406 1883
1884 -- All other record type cases, including protected records.
1885 -- The latter only arise for expander generated code for
1886 -- handling shared passive partition access.
1887
1888 else
1889 pragma Assert
1890 (Is_Record_Type (U_Type) or else Is_Protected_Type (U_Type));
1891
1892 Build_Record_Or_Elementary_Input_Function
1893 (Loc, Base_Type (U_Type), Decl, Fname);
1894 Insert_Action (N, Decl);
1895 end if;
1896 end if;
1897
1898 -- If we fall through, Fname is the function to be called. The
1899 -- result is obtained by calling the appropriate function, then
1900 -- converting the result. The conversion does a subtype check.
1901
1902 Call :=
1903 Make_Function_Call (Loc,
1904 Name => New_Occurrence_Of (Fname, Loc),
1905 Parameter_Associations => New_List (
1906 Relocate_Node (Strm)));
1907
1908 Set_Controlling_Argument (Call, Cntrl);
1909 Rewrite (N, Unchecked_Convert_To (P_Type, Call));
1910 Analyze_And_Resolve (N, P_Type);
1911 end Input;
1912
1913 -------------------
1914 -- Integer_Value --
1915 -------------------
1916
1917 -- We transform
1918
1919 -- inttype'Fixed_Value (fixed-value)
1920
1921 -- into
1922
1923 -- inttype(integer-value))
1924
1925 -- we do all the required analysis of the conversion here, because
1926 -- we do not want this to go through the fixed-point conversion
1927 -- circuits. Note that gigi always treats fixed-point as equivalent
1928 -- to the corresponding integer type anyway.
1929
1930 when Attribute_Integer_Value => Integer_Value :
1931 begin
1932 Rewrite (N,
1933 Make_Type_Conversion (Loc,
1934 Subtype_Mark => New_Occurrence_Of (Entity (Pref), Loc),
1935 Expression => Relocate_Node (First (Exprs))));
1936 Set_Etype (N, Entity (Pref));
1937 Set_Analyzed (N);
9dfe12ae 1938
1939 -- Note: it might appear that a properly analyzed unchecked conversion
1940 -- would be just fine here, but that's not the case, since the full
1941 -- range checks performed by the following call are critical!
1942
ee6ba406 1943 Apply_Type_Conversion_Checks (N);
1944 end Integer_Value;
1945
1946 ----------
1947 -- Last --
1948 ----------
1949
1950 when Attribute_Last => declare
1951 Ptyp : constant Entity_Id := Etype (Pref);
1952
1953 begin
1954 -- If the prefix type is a constrained packed array type which
1955 -- already has a Packed_Array_Type representation defined, then
1956 -- replace this attribute with a direct reference to 'Last of the
1957 -- appropriate index subtype (since otherwise Gigi will try to give
1958 -- us the value of 'Last for this implementation type).
1959
1960 if Is_Constrained_Packed_Array (Ptyp) then
1961 Rewrite (N,
1962 Make_Attribute_Reference (Loc,
1963 Attribute_Name => Name_Last,
1964 Prefix => New_Reference_To (Get_Index_Subtype (N), Loc)));
1965 Analyze_And_Resolve (N, Typ);
1966
1967 elsif Is_Access_Type (Ptyp) then
1968 Apply_Access_Check (N);
1969 end if;
1970 end;
1971
1972 --------------
1973 -- Last_Bit --
1974 --------------
1975
1976 -- We compute this if a component clause was present, otherwise
1977 -- we leave the computation up to Gigi, since we don't know what
1978 -- layout will be chosen.
1979
1980 when Attribute_Last_Bit => Last_Bit :
1981 declare
1982 CE : constant Entity_Id := Entity (Selector_Name (Pref));
1983
1984 begin
1985 if Known_Static_Component_Bit_Offset (CE)
1986 and then Known_Static_Esize (CE)
1987 then
1988 Rewrite (N,
1989 Make_Integer_Literal (Loc,
1990 Intval => (Component_Bit_Offset (CE) mod System_Storage_Unit)
1991 + Esize (CE) - 1));
1992
1993 Analyze_And_Resolve (N, Typ);
1994
1995 else
1996 Apply_Universal_Integer_Attribute_Checks (N);
1997 end if;
1998 end Last_Bit;
1999
2000 ------------------
2001 -- Leading_Part --
2002 ------------------
2003
2004 -- Transforms 'Leading_Part into a call to the floating-point attribute
2005 -- function Leading_Part in Fat_xxx (where xxx is the root type)
2006
2007 -- Note: strictly, we should have special case code to deal with
2008 -- absurdly large positive arguments (greater than Integer'Last),
2009 -- which result in returning the first argument unchanged, but it
2010 -- hardly seems worth the effort. We raise constraint error for
2011 -- absurdly negative arguments which is fine.
2012
2013 when Attribute_Leading_Part =>
2014 Expand_Fpt_Attribute_RI (N);
2015
2016 ------------
2017 -- Length --
2018 ------------
2019
2020 when Attribute_Length => declare
2021 Ptyp : constant Entity_Id := Etype (Pref);
2022 Ityp : Entity_Id;
2023 Xnum : Uint;
2024
2025 begin
2026 -- Processing for packed array types
2027
2028 if Is_Array_Type (Ptyp) and then Is_Packed (Ptyp) then
2029 Ityp := Get_Index_Subtype (N);
2030
2031 -- If the index type, Ityp, is an enumeration type with
2032 -- holes, then we calculate X'Length explicitly using
2033
2034 -- Typ'Max
2035 -- (0, Ityp'Pos (X'Last (N)) -
2036 -- Ityp'Pos (X'First (N)) + 1);
2037
2038 -- Since the bounds in the template are the representation
2039 -- values and gigi would get the wrong value.
2040
2041 if Is_Enumeration_Type (Ityp)
2042 and then Present (Enum_Pos_To_Rep (Base_Type (Ityp)))
2043 then
2044 if No (Exprs) then
2045 Xnum := Uint_1;
2046 else
2047 Xnum := Expr_Value (First (Expressions (N)));
2048 end if;
2049
2050 Rewrite (N,
2051 Make_Attribute_Reference (Loc,
2052 Prefix => New_Occurrence_Of (Typ, Loc),
2053 Attribute_Name => Name_Max,
2054 Expressions => New_List
2055 (Make_Integer_Literal (Loc, 0),
2056
2057 Make_Op_Add (Loc,
2058 Left_Opnd =>
2059 Make_Op_Subtract (Loc,
2060 Left_Opnd =>
2061 Make_Attribute_Reference (Loc,
2062 Prefix => New_Occurrence_Of (Ityp, Loc),
2063 Attribute_Name => Name_Pos,
2064
2065 Expressions => New_List (
2066 Make_Attribute_Reference (Loc,
2067 Prefix => Duplicate_Subexpr (Pref),
2068 Attribute_Name => Name_Last,
2069 Expressions => New_List (
2070 Make_Integer_Literal (Loc, Xnum))))),
2071
2072 Right_Opnd =>
2073 Make_Attribute_Reference (Loc,
2074 Prefix => New_Occurrence_Of (Ityp, Loc),
2075 Attribute_Name => Name_Pos,
2076
2077 Expressions => New_List (
2078 Make_Attribute_Reference (Loc,
9dfe12ae 2079 Prefix =>
2080 Duplicate_Subexpr_No_Checks (Pref),
ee6ba406 2081 Attribute_Name => Name_First,
2082 Expressions => New_List (
2083 Make_Integer_Literal (Loc, Xnum)))))),
2084
2085 Right_Opnd => Make_Integer_Literal (Loc, 1)))));
2086
2087 Analyze_And_Resolve (N, Typ, Suppress => All_Checks);
2088 return;
2089
2090 -- If the prefix type is a constrained packed array type which
2091 -- already has a Packed_Array_Type representation defined, then
2092 -- replace this attribute with a direct reference to 'Range_Length
2093 -- of the appropriate index subtype (since otherwise Gigi will try
2094 -- to give us the value of 'Length for this implementation type).
2095
2096 elsif Is_Constrained (Ptyp) then
2097 Rewrite (N,
2098 Make_Attribute_Reference (Loc,
2099 Attribute_Name => Name_Range_Length,
2100 Prefix => New_Reference_To (Ityp, Loc)));
2101 Analyze_And_Resolve (N, Typ);
2102 end if;
2103
2104 -- If we have a packed array that is not bit packed, which was
2105
2106 -- Access type case
2107
2108 elsif Is_Access_Type (Ptyp) then
2109 Apply_Access_Check (N);
2110
2111 -- If the designated type is a packed array type, then we
2112 -- convert the reference to:
2113
2114 -- typ'Max (0, 1 +
2115 -- xtyp'Pos (Pref'Last (Expr)) -
2116 -- xtyp'Pos (Pref'First (Expr)));
2117
2118 -- This is a bit complex, but it is the easiest thing to do
2119 -- that works in all cases including enum types with holes
2120 -- xtyp here is the appropriate index type.
2121
2122 declare
2123 Dtyp : constant Entity_Id := Designated_Type (Ptyp);
2124 Xtyp : Entity_Id;
2125
2126 begin
2127 if Is_Array_Type (Dtyp) and then Is_Packed (Dtyp) then
2128 Xtyp := Get_Index_Subtype (N);
2129
2130 Rewrite (N,
2131 Make_Attribute_Reference (Loc,
2132 Prefix => New_Occurrence_Of (Typ, Loc),
2133 Attribute_Name => Name_Max,
2134 Expressions => New_List (
2135 Make_Integer_Literal (Loc, 0),
2136
2137 Make_Op_Add (Loc,
2138 Make_Integer_Literal (Loc, 1),
2139 Make_Op_Subtract (Loc,
2140 Left_Opnd =>
2141 Make_Attribute_Reference (Loc,
2142 Prefix => New_Occurrence_Of (Xtyp, Loc),
2143 Attribute_Name => Name_Pos,
2144 Expressions => New_List (
2145 Make_Attribute_Reference (Loc,
2146 Prefix => Duplicate_Subexpr (Pref),
2147 Attribute_Name => Name_Last,
2148 Expressions =>
2149 New_Copy_List (Exprs)))),
2150
2151 Right_Opnd =>
2152 Make_Attribute_Reference (Loc,
2153 Prefix => New_Occurrence_Of (Xtyp, Loc),
2154 Attribute_Name => Name_Pos,
2155 Expressions => New_List (
2156 Make_Attribute_Reference (Loc,
9dfe12ae 2157 Prefix =>
2158 Duplicate_Subexpr_No_Checks (Pref),
ee6ba406 2159 Attribute_Name => Name_First,
2160 Expressions =>
2161 New_Copy_List (Exprs)))))))));
2162
2163 Analyze_And_Resolve (N, Typ);
2164 end if;
2165 end;
2166
2167 -- Otherwise leave it to gigi
2168
2169 else
2170 Apply_Universal_Integer_Attribute_Checks (N);
2171 end if;
2172 end;
2173
2174 -------------
2175 -- Machine --
2176 -------------
2177
2178 -- Transforms 'Machine into a call to the floating-point attribute
2179 -- function Machine in Fat_xxx (where xxx is the root type)
2180
2181 when Attribute_Machine =>
2182 Expand_Fpt_Attribute_R (N);
2183
2184 ------------------
2185 -- Machine_Size --
2186 ------------------
2187
2188 -- Machine_Size is equivalent to Object_Size, so transform it into
2189 -- Object_Size and that way Gigi never sees Machine_Size.
2190
2191 when Attribute_Machine_Size =>
2192 Rewrite (N,
2193 Make_Attribute_Reference (Loc,
2194 Prefix => Prefix (N),
2195 Attribute_Name => Name_Object_Size));
2196
2197 Analyze_And_Resolve (N, Typ);
2198
2199 --------------
2200 -- Mantissa --
2201 --------------
2202
2203 -- The only case that can get this far is the dynamic case of the
2204 -- old Ada 83 Mantissa attribute for the fixed-point case. For this
2205 -- case, we expand:
2206
2207 -- typ'Mantissa
2208
2209 -- into
2210
2211 -- ityp (System.Mantissa.Mantissa_Value
2212 -- (Integer'Integer_Value (typ'First),
2213 -- Integer'Integer_Value (typ'Last)));
2214
2215 when Attribute_Mantissa => Mantissa : declare
2216 Ptyp : constant Entity_Id := Etype (Pref);
2217
2218 begin
2219 Rewrite (N,
2220 Convert_To (Typ,
2221 Make_Function_Call (Loc,
2222 Name => New_Occurrence_Of (RTE (RE_Mantissa_Value), Loc),
2223
2224 Parameter_Associations => New_List (
2225
2226 Make_Attribute_Reference (Loc,
2227 Prefix => New_Occurrence_Of (Standard_Integer, Loc),
2228 Attribute_Name => Name_Integer_Value,
2229 Expressions => New_List (
2230
2231 Make_Attribute_Reference (Loc,
2232 Prefix => New_Occurrence_Of (Ptyp, Loc),
2233 Attribute_Name => Name_First))),
2234
2235 Make_Attribute_Reference (Loc,
2236 Prefix => New_Occurrence_Of (Standard_Integer, Loc),
2237 Attribute_Name => Name_Integer_Value,
2238 Expressions => New_List (
2239
2240 Make_Attribute_Reference (Loc,
2241 Prefix => New_Occurrence_Of (Ptyp, Loc),
2242 Attribute_Name => Name_Last)))))));
2243
2244 Analyze_And_Resolve (N, Typ);
2245 end Mantissa;
2246
2247 -----------
2248 -- Model --
2249 -----------
2250
2251 -- Transforms 'Model into a call to the floating-point attribute
2252 -- function Model in Fat_xxx (where xxx is the root type)
2253
2254 when Attribute_Model =>
2255 Expand_Fpt_Attribute_R (N);
2256
2257 -----------------
2258 -- Object_Size --
2259 -----------------
2260
2261 -- The processing for Object_Size shares the processing for Size
2262
2263 ------------
2264 -- Output --
2265 ------------
2266
2267 when Attribute_Output => Output : declare
2268 P_Type : constant Entity_Id := Entity (Pref);
ee6ba406 2269 U_Type : constant Entity_Id := Underlying_Type (P_Type);
2270 Pname : Entity_Id;
2271 Decl : Node_Id;
2272 Prag : Node_Id;
2273 Arg3 : Node_Id;
2274 Wfunc : Node_Id;
2275
2276 begin
2277 -- If no underlying type, we have an error that will be diagnosed
2278 -- elsewhere, so here we just completely ignore the expansion.
2279
2280 if No (U_Type) then
2281 return;
2282 end if;
2283
2284 -- If TSS for Output is present, just call it
2285
9dfe12ae 2286 Pname := Find_Stream_Subprogram (P_Type, TSS_Stream_Output);
ee6ba406 2287
2288 if Present (Pname) then
2289 null;
2290
2291 else
2292 -- If there is a Stream_Convert pragma, use it, we rewrite
2293
2294 -- sourcetyp'Output (stream, Item)
2295
2296 -- as
2297
2298 -- strmtyp'Output (Stream, strmwrite (acttyp (Item)));
2299
2300 -- where strmwrite is the given Write function that converts
2301 -- an argument of type sourcetyp or a type acctyp, from which
2302 -- it is derived to type strmtyp. The conversion to acttyp is
2303 -- required for the derived case.
2304
2305 Prag :=
2306 Get_Rep_Pragma
2307 (Implementation_Base_Type (P_Type), Name_Stream_Convert);
2308
2309 if Present (Prag) then
2310 Arg3 :=
2311 Next (Next (First (Pragma_Argument_Associations (Prag))));
2312 Wfunc := Entity (Expression (Arg3));
2313
2314 Rewrite (N,
2315 Make_Attribute_Reference (Loc,
2316 Prefix => New_Occurrence_Of (Etype (Wfunc), Loc),
2317 Attribute_Name => Name_Output,
2318 Expressions => New_List (
2319 Relocate_Node (First (Exprs)),
2320 Make_Function_Call (Loc,
2321 Name => New_Occurrence_Of (Wfunc, Loc),
2322 Parameter_Associations => New_List (
2323 Convert_To (Etype (First_Formal (Wfunc)),
2324 Relocate_Node (Next (First (Exprs)))))))));
2325
2326 Analyze (N);
2327 return;
2328
2329 -- For elementary types, we call the W_xxx routine directly.
2330 -- Note that the effect of Write and Output is identical for
2331 -- the case of an elementary type, since there are no
2332 -- discriminants or bounds.
2333
2334 elsif Is_Elementary_Type (U_Type) then
2335
2336 -- A special case arises if we have a defined _Write routine,
2337 -- since in this case we are required to call this routine.
2338
9dfe12ae 2339 if Present (TSS (Base_Type (U_Type), TSS_Stream_Write)) then
ee6ba406 2340 Build_Record_Or_Elementary_Output_Procedure
2341 (Loc, U_Type, Decl, Pname);
2342 Insert_Action (N, Decl);
2343
2344 -- For normal cases, we call the W_xxx routine directly
2345
2346 else
2347 Rewrite (N, Build_Elementary_Write_Call (N));
2348 Analyze (N);
2349 return;
2350 end if;
2351
2352 -- Array type case
2353
2354 elsif Is_Array_Type (U_Type) then
2355 Build_Array_Output_Procedure (Loc, U_Type, Decl, Pname);
2356 Compile_Stream_Body_In_Scope (N, Decl, U_Type, Check => False);
2357
2358 -- Class-wide case, first output external tag, then dispatch
2359 -- to the appropriate primitive Output function (RM 13.13.2(31)).
2360
2361 elsif Is_Class_Wide_Type (P_Type) then
2362 Tag_Write : declare
2363 Strm : constant Node_Id := First (Exprs);
2364 Item : constant Node_Id := Next (Strm);
2365
2366 begin
2367 -- The code is:
2368 -- String'Output (Strm, External_Tag (Item'Tag))
2369
2370 Insert_Action (N,
2371 Make_Attribute_Reference (Loc,
2372 Prefix => New_Occurrence_Of (Standard_String, Loc),
2373 Attribute_Name => Name_Output,
2374 Expressions => New_List (
2375 Relocate_Node (Duplicate_Subexpr (Strm)),
2376 Make_Function_Call (Loc,
2377 Name =>
2378 New_Occurrence_Of (RTE (RE_External_Tag), Loc),
2379 Parameter_Associations => New_List (
2380 Make_Attribute_Reference (Loc,
2381 Prefix =>
2382 Relocate_Node
2383 (Duplicate_Subexpr (Item, Name_Req => True)),
2384 Attribute_Name => Name_Tag))))));
2385 end Tag_Write;
2386
9dfe12ae 2387 Pname := Find_Prim_Op (U_Type, TSS_Stream_Output);
ee6ba406 2388
2389 -- Tagged type case, use the primitive Output function
2390
2391 elsif Is_Tagged_Type (U_Type) then
9dfe12ae 2392 Pname := Find_Prim_Op (U_Type, TSS_Stream_Output);
ee6ba406 2393
2394 -- All other record type cases, including protected records.
2395 -- The latter only arise for expander generated code for
2396 -- handling shared passive partition access.
2397
2398 else
2399 pragma Assert
2400 (Is_Record_Type (U_Type) or else Is_Protected_Type (U_Type));
2401
2402 Build_Record_Or_Elementary_Output_Procedure
2403 (Loc, Base_Type (U_Type), Decl, Pname);
2404 Insert_Action (N, Decl);
2405 end if;
2406 end if;
2407
2408 -- If we fall through, Pname is the name of the procedure to call
2409
2410 Rewrite_Stream_Proc_Call (Pname);
2411 end Output;
2412
2413 ---------
2414 -- Pos --
2415 ---------
2416
2417 -- For enumeration types with a standard representation, Pos is
2418 -- handled by Gigi.
2419
2420 -- For enumeration types, with a non-standard representation we
2421 -- generate a call to the _Rep_To_Pos function created when the
2422 -- type was frozen. The call has the form
2423
9dfe12ae 2424 -- _rep_to_pos (expr, flag)
ee6ba406 2425
9dfe12ae 2426 -- The parameter flag is True if range checks are enabled, causing
2427 -- Program_Error to be raised if the expression has an invalid
2428 -- representation, and False if range checks are suppressed.
ee6ba406 2429
2430 -- For integer types, Pos is equivalent to a simple integer
2431 -- conversion and we rewrite it as such
2432
2433 when Attribute_Pos => Pos :
2434 declare
2435 Etyp : Entity_Id := Base_Type (Entity (Pref));
2436
2437 begin
2438 -- Deal with zero/non-zero boolean values
2439
2440 if Is_Boolean_Type (Etyp) then
2441 Adjust_Condition (First (Exprs));
2442 Etyp := Standard_Boolean;
2443 Set_Prefix (N, New_Occurrence_Of (Standard_Boolean, Loc));
2444 end if;
2445
2446 -- Case of enumeration type
2447
2448 if Is_Enumeration_Type (Etyp) then
2449
2450 -- Non-standard enumeration type (generate call)
2451
2452 if Present (Enum_Pos_To_Rep (Etyp)) then
9dfe12ae 2453 Append_To (Exprs, Rep_To_Pos_Flag (Etyp, Loc));
ee6ba406 2454 Rewrite (N,
2455 Convert_To (Typ,
2456 Make_Function_Call (Loc,
2457 Name =>
9dfe12ae 2458 New_Reference_To (TSS (Etyp, TSS_Rep_To_Pos), Loc),
ee6ba406 2459 Parameter_Associations => Exprs)));
2460
2461 Analyze_And_Resolve (N, Typ);
2462
2463 -- Standard enumeration type (do universal integer check)
2464
2465 else
2466 Apply_Universal_Integer_Attribute_Checks (N);
2467 end if;
2468
2469 -- Deal with integer types (replace by conversion)
2470
2471 elsif Is_Integer_Type (Etyp) then
2472 Rewrite (N, Convert_To (Typ, First (Exprs)));
2473 Analyze_And_Resolve (N, Typ);
2474 end if;
2475
2476 end Pos;
2477
2478 --------------
2479 -- Position --
2480 --------------
2481
2482 -- We compute this if a component clause was present, otherwise
2483 -- we leave the computation up to Gigi, since we don't know what
2484 -- layout will be chosen.
2485
2486 when Attribute_Position => Position :
2487 declare
2488 CE : constant Entity_Id := Entity (Selector_Name (Pref));
2489
2490 begin
2491 if Present (Component_Clause (CE)) then
2492 Rewrite (N,
2493 Make_Integer_Literal (Loc,
2494 Intval => Component_Bit_Offset (CE) / System_Storage_Unit));
2495 Analyze_And_Resolve (N, Typ);
2496
2497 else
2498 Apply_Universal_Integer_Attribute_Checks (N);
2499 end if;
2500 end Position;
2501
2502 ----------
2503 -- Pred --
2504 ----------
2505
2506 -- 1. Deal with enumeration types with holes
2507 -- 2. For floating-point, generate call to attribute function
2508 -- 3. For other cases, deal with constraint checking
2509
2510 when Attribute_Pred => Pred :
2511 declare
2512 Ptyp : constant Entity_Id := Base_Type (Etype (Pref));
2513
2514 begin
2515 -- For enumeration types with non-standard representations, we
2516 -- expand typ'Pred (x) into
2517
2518 -- Pos_To_Rep (Rep_To_Pos (x) - 1)
2519
9dfe12ae 2520 -- If the representation is contiguous, we compute instead
2521 -- Lit1 + Rep_to_Pos (x -1), to catch invalid representations.
2522
ee6ba406 2523 if Is_Enumeration_Type (Ptyp)
2524 and then Present (Enum_Pos_To_Rep (Ptyp))
2525 then
9dfe12ae 2526 if Has_Contiguous_Rep (Ptyp) then
2527 Rewrite (N,
2528 Unchecked_Convert_To (Ptyp,
2529 Make_Op_Add (Loc,
2530 Left_Opnd =>
2531 Make_Integer_Literal (Loc,
2532 Enumeration_Rep (First_Literal (Ptyp))),
2533 Right_Opnd =>
2534 Make_Function_Call (Loc,
2535 Name =>
2536 New_Reference_To
2537 (TSS (Ptyp, TSS_Rep_To_Pos), Loc),
2538
2539 Parameter_Associations =>
2540 New_List (
2541 Unchecked_Convert_To (Ptyp,
2542 Make_Op_Subtract (Loc,
2543 Left_Opnd =>
2544 Unchecked_Convert_To (Standard_Integer,
2545 Relocate_Node (First (Exprs))),
2546 Right_Opnd =>
2547 Make_Integer_Literal (Loc, 1))),
2548 Rep_To_Pos_Flag (Ptyp, Loc))))));
ee6ba406 2549
9dfe12ae 2550 else
2551 -- Add Boolean parameter True, to request program errror if
2552 -- we have a bad representation on our hands. If checks are
2553 -- suppressed, then add False instead
ee6ba406 2554
9dfe12ae 2555 Append_To (Exprs, Rep_To_Pos_Flag (Ptyp, Loc));
2556 Rewrite (N,
2557 Make_Indexed_Component (Loc,
2558 Prefix => New_Reference_To (Enum_Pos_To_Rep (Ptyp), Loc),
2559 Expressions => New_List (
2560 Make_Op_Subtract (Loc,
ee6ba406 2561 Left_Opnd =>
2562 Make_Function_Call (Loc,
2563 Name =>
9dfe12ae 2564 New_Reference_To (TSS (Ptyp, TSS_Rep_To_Pos), Loc),
2565 Parameter_Associations => Exprs),
ee6ba406 2566 Right_Opnd => Make_Integer_Literal (Loc, 1)))));
9dfe12ae 2567 end if;
ee6ba406 2568
2569 Analyze_And_Resolve (N, Typ);
2570
2571 -- For floating-point, we transform 'Pred into a call to the Pred
2572 -- floating-point attribute function in Fat_xxx (xxx is root type)
2573
2574 elsif Is_Floating_Point_Type (Ptyp) then
2575 Expand_Fpt_Attribute_R (N);
2576 Analyze_And_Resolve (N, Typ);
2577
2578 -- For modular types, nothing to do (no overflow, since wraps)
2579
2580 elsif Is_Modular_Integer_Type (Ptyp) then
2581 null;
2582
2583 -- For other types, if range checking is enabled, we must generate
2584 -- a check if overflow checking is enabled.
2585
2586 elsif not Overflow_Checks_Suppressed (Ptyp) then
2587 Expand_Pred_Succ (N);
2588 end if;
2589
2590 end Pred;
2591
2592 ------------------
2593 -- Range_Length --
2594 ------------------
2595
2596 when Attribute_Range_Length => Range_Length : declare
2597 P_Type : constant Entity_Id := Etype (Pref);
2598
2599 begin
2600 -- The only special processing required is for the case where
2601 -- Range_Length is applied to an enumeration type with holes.
2602 -- In this case we transform
2603
2604 -- X'Range_Length
2605
2606 -- to
2607
2608 -- X'Pos (X'Last) - X'Pos (X'First) + 1
2609
2610 -- So that the result reflects the proper Pos values instead
2611 -- of the underlying representations.
2612
2613 if Is_Enumeration_Type (P_Type)
2614 and then Has_Non_Standard_Rep (P_Type)
2615 then
2616 Rewrite (N,
2617 Make_Op_Add (Loc,
2618 Left_Opnd =>
2619 Make_Op_Subtract (Loc,
2620 Left_Opnd =>
2621 Make_Attribute_Reference (Loc,
2622 Attribute_Name => Name_Pos,
2623 Prefix => New_Occurrence_Of (P_Type, Loc),
2624 Expressions => New_List (
2625 Make_Attribute_Reference (Loc,
2626 Attribute_Name => Name_Last,
2627 Prefix => New_Occurrence_Of (P_Type, Loc)))),
2628
2629 Right_Opnd =>
2630 Make_Attribute_Reference (Loc,
2631 Attribute_Name => Name_Pos,
2632 Prefix => New_Occurrence_Of (P_Type, Loc),
2633 Expressions => New_List (
2634 Make_Attribute_Reference (Loc,
2635 Attribute_Name => Name_First,
2636 Prefix => New_Occurrence_Of (P_Type, Loc))))),
2637
2638 Right_Opnd =>
2639 Make_Integer_Literal (Loc, 1)));
2640
2641 Analyze_And_Resolve (N, Typ);
2642
2643 -- For all other cases, attribute is handled by Gigi, but we need
2644 -- to deal with the case of the range check on a universal integer.
2645
2646 else
2647 Apply_Universal_Integer_Attribute_Checks (N);
2648 end if;
2649
2650 end Range_Length;
2651
2652 ----------
2653 -- Read --
2654 ----------
2655
2656 when Attribute_Read => Read : declare
2657 P_Type : constant Entity_Id := Entity (Pref);
2658 B_Type : constant Entity_Id := Base_Type (P_Type);
2659 U_Type : constant Entity_Id := Underlying_Type (P_Type);
2660 Pname : Entity_Id;
2661 Decl : Node_Id;
2662 Prag : Node_Id;
2663 Arg2 : Node_Id;
2664 Rfunc : Node_Id;
2665 Lhs : Node_Id;
2666 Rhs : Node_Id;
2667
2668 begin
2669 -- If no underlying type, we have an error that will be diagnosed
2670 -- elsewhere, so here we just completely ignore the expansion.
2671
2672 if No (U_Type) then
2673 return;
2674 end if;
2675
2676 -- The simple case, if there is a TSS for Read, just call it
2677
9dfe12ae 2678 Pname := Find_Stream_Subprogram (P_Type, TSS_Stream_Read);
ee6ba406 2679
2680 if Present (Pname) then
2681 null;
2682
2683 else
2684 -- If there is a Stream_Convert pragma, use it, we rewrite
2685
2686 -- sourcetyp'Read (stream, Item)
2687
2688 -- as
2689
2690 -- Item := sourcetyp (strmread (strmtyp'Input (Stream)));
2691
2692 -- where strmread is the given Read function that converts
2693 -- an argument of type strmtyp to type sourcetyp or a type
2694 -- from which it is derived. The conversion to sourcetyp
2695 -- is required in the latter case.
2696
2697 -- A special case arises if Item is a type conversion in which
2698 -- case, we have to expand to:
2699
2700 -- Itemx := typex (strmread (strmtyp'Input (Stream)));
2701
2702 -- where Itemx is the expression of the type conversion (i.e.
2703 -- the actual object), and typex is the type of Itemx.
2704
2705 Prag :=
2706 Get_Rep_Pragma
2707 (Implementation_Base_Type (P_Type), Name_Stream_Convert);
2708
2709 if Present (Prag) then
2710 Arg2 := Next (First (Pragma_Argument_Associations (Prag)));
2711 Rfunc := Entity (Expression (Arg2));
2712 Lhs := Relocate_Node (Next (First (Exprs)));
2713 Rhs :=
2714 Convert_To (B_Type,
2715 Make_Function_Call (Loc,
2716 Name => New_Occurrence_Of (Rfunc, Loc),
2717 Parameter_Associations => New_List (
2718 Make_Attribute_Reference (Loc,
2719 Prefix =>
2720 New_Occurrence_Of
2721 (Etype (First_Formal (Rfunc)), Loc),
2722 Attribute_Name => Name_Input,
2723 Expressions => New_List (
2724 Relocate_Node (First (Exprs)))))));
2725
2726 if Nkind (Lhs) = N_Type_Conversion then
2727 Lhs := Expression (Lhs);
2728 Rhs := Convert_To (Etype (Lhs), Rhs);
2729 end if;
2730
2731 Rewrite (N,
2732 Make_Assignment_Statement (Loc,
9dfe12ae 2733 Name => Lhs,
ee6ba406 2734 Expression => Rhs));
2735 Set_Assignment_OK (Lhs);
2736 Analyze (N);
2737 return;
2738
2739 -- For elementary types, we call the I_xxx routine using the first
2740 -- parameter and then assign the result into the second parameter.
2741 -- We set Assignment_OK to deal with the conversion case.
2742
2743 elsif Is_Elementary_Type (U_Type) then
2744 declare
2745 Lhs : Node_Id;
2746 Rhs : Node_Id;
2747
2748 begin
2749 Lhs := Relocate_Node (Next (First (Exprs)));
2750 Rhs := Build_Elementary_Input_Call (N);
2751
2752 if Nkind (Lhs) = N_Type_Conversion then
2753 Lhs := Expression (Lhs);
2754 Rhs := Convert_To (Etype (Lhs), Rhs);
2755 end if;
2756
2757 Set_Assignment_OK (Lhs);
2758
2759 Rewrite (N,
2760 Make_Assignment_Statement (Loc,
2761 Name => Lhs,
2762 Expression => Rhs));
2763
2764 Analyze (N);
2765 return;
2766 end;
2767
2768 -- Array type case
2769
2770 elsif Is_Array_Type (U_Type) then
2771 Build_Array_Read_Procedure (N, U_Type, Decl, Pname);
2772 Compile_Stream_Body_In_Scope (N, Decl, U_Type, Check => False);
2773
2774 -- Tagged type case, use the primitive Read function. Note that
2775 -- this will dispatch in the class-wide case which is what we want
2776
2777 elsif Is_Tagged_Type (U_Type) then
9dfe12ae 2778 Pname := Find_Prim_Op (U_Type, TSS_Stream_Read);
ee6ba406 2779
2780 -- All other record type cases, including protected records.
2781 -- The latter only arise for expander generated code for
2782 -- handling shared passive partition access.
2783
2784 else
2785 pragma Assert
2786 (Is_Record_Type (U_Type) or else Is_Protected_Type (U_Type));
2787
2788 if Has_Discriminants (U_Type)
2789 and then Present
2790 (Discriminant_Default_Value (First_Discriminant (U_Type)))
2791 then
2792 Build_Mutable_Record_Read_Procedure
2793 (Loc, Base_Type (U_Type), Decl, Pname);
2794
2795 else
2796 Build_Record_Read_Procedure
2797 (Loc, Base_Type (U_Type), Decl, Pname);
2798 end if;
2799
2800 -- Suppress checks, uninitialized or otherwise invalid
2801 -- data does not cause constraint errors to be raised for
2802 -- a complete record read.
2803
2804 Insert_Action (N, Decl, All_Checks);
2805 end if;
2806 end if;
2807
2808 Rewrite_Stream_Proc_Call (Pname);
2809 end Read;
2810
2811 ---------------
2812 -- Remainder --
2813 ---------------
2814
2815 -- Transforms 'Remainder into a call to the floating-point attribute
2816 -- function Remainder in Fat_xxx (where xxx is the root type)
2817
2818 when Attribute_Remainder =>
2819 Expand_Fpt_Attribute_RR (N);
2820
2821 -----------
2822 -- Round --
2823 -----------
2824
2825 -- The handling of the Round attribute is quite delicate. The
2826 -- processing in Sem_Attr introduced a conversion to universal
2827 -- real, reflecting the semantics of Round, but we do not want
2828 -- anything to do with universal real at runtime, since this
2829 -- corresponds to using floating-point arithmetic.
2830
2831 -- What we have now is that the Etype of the Round attribute
2832 -- correctly indicates the final result type. The operand of
2833 -- the Round is the conversion to universal real, described
2834 -- above, and the operand of this conversion is the actual
2835 -- operand of Round, which may be the special case of a fixed
2836 -- point multiplication or division (Etype = universal fixed)
2837
2838 -- The exapander will expand first the operand of the conversion,
2839 -- then the conversion, and finally the round attribute itself,
2840 -- since we always work inside out. But we cannot simply process
2841 -- naively in this order. In the semantic world where universal
2842 -- fixed and real really exist and have infinite precision, there
2843 -- is no problem, but in the implementation world, where universal
2844 -- real is a floating-point type, we would get the wrong result.
2845
2846 -- So the approach is as follows. First, when expanding a multiply
2847 -- or divide whose type is universal fixed, we do nothing at all,
2848 -- instead deferring the operation till later.
2849
2850 -- The actual processing is done in Expand_N_Type_Conversion which
2851 -- handles the special case of Round by looking at its parent to
2852 -- see if it is a Round attribute, and if it is, handling the
2853 -- conversion (or its fixed multiply/divide child) in an appropriate
2854 -- manner.
2855
2856 -- This means that by the time we get to expanding the Round attribute
2857 -- itself, the Round is nothing more than a type conversion (and will
2858 -- often be a null type conversion), so we just replace it with the
2859 -- appropriate conversion operation.
2860
2861 when Attribute_Round =>
2862 Rewrite (N,
2863 Convert_To (Etype (N), Relocate_Node (First (Exprs))));
2864 Analyze_And_Resolve (N);
2865
2866 --------------
2867 -- Rounding --
2868 --------------
2869
2870 -- Transforms 'Rounding into a call to the floating-point attribute
2871 -- function Rounding in Fat_xxx (where xxx is the root type)
2872
2873 when Attribute_Rounding =>
2874 Expand_Fpt_Attribute_R (N);
2875
2876 -------------
2877 -- Scaling --
2878 -------------
2879
2880 -- Transforms 'Scaling into a call to the floating-point attribute
2881 -- function Scaling in Fat_xxx (where xxx is the root type)
2882
2883 when Attribute_Scaling =>
2884 Expand_Fpt_Attribute_RI (N);
2885
2886 ----------
2887 -- Size --
2888 ----------
2889
2890 when Attribute_Size |
2891 Attribute_Object_Size |
2892 Attribute_Value_Size |
2893 Attribute_VADS_Size => Size :
2894
2895 declare
2896 Ptyp : constant Entity_Id := Etype (Pref);
ee6ba406 2897 Siz : Uint;
9dfe12ae 2898 New_Node : Node_Id;
ee6ba406 2899
2900 begin
2901 -- Processing for VADS_Size case. Note that this processing removes
2902 -- all traces of VADS_Size from the tree, and completes all required
2903 -- processing for VADS_Size by translating the attribute reference
2904 -- to an appropriate Size or Object_Size reference.
2905
2906 if Id = Attribute_VADS_Size
2907 or else (Use_VADS_Size and then Id = Attribute_Size)
2908 then
2909 -- If the size is specified, then we simply use the specified
2910 -- size. This applies to both types and objects. The size of an
2911 -- object can be specified in the following ways:
2912
2913 -- An explicit size object is given for an object
2914 -- A component size is specified for an indexed component
2915 -- A component clause is specified for a selected component
2916 -- The object is a component of a packed composite object
2917
2918 -- If the size is specified, then VADS_Size of an object
2919
2920 if (Is_Entity_Name (Pref)
2921 and then Present (Size_Clause (Entity (Pref))))
2922 or else
2923 (Nkind (Pref) = N_Component_Clause
2924 and then (Present (Component_Clause
2925 (Entity (Selector_Name (Pref))))
2926 or else Is_Packed (Etype (Prefix (Pref)))))
2927 or else
2928 (Nkind (Pref) = N_Indexed_Component
2929 and then (Component_Size (Etype (Prefix (Pref))) /= 0
2930 or else Is_Packed (Etype (Prefix (Pref)))))
2931 then
2932 Set_Attribute_Name (N, Name_Size);
2933
2934 -- Otherwise if we have an object rather than a type, then the
2935 -- VADS_Size attribute applies to the type of the object, rather
2936 -- than the object itself. This is one of the respects in which
2937 -- VADS_Size differs from Size.
2938
2939 else
2940 if (not Is_Entity_Name (Pref)
2941 or else not Is_Type (Entity (Pref)))
2942 and then (Is_Scalar_Type (Etype (Pref))
2943 or else Is_Constrained (Etype (Pref)))
2944 then
2945 Rewrite (Pref, New_Occurrence_Of (Etype (Pref), Loc));
2946 end if;
2947
2948 -- For a scalar type for which no size was
2949 -- explicitly given, VADS_Size means Object_Size. This is the
2950 -- other respect in which VADS_Size differs from Size.
2951
2952 if Is_Scalar_Type (Etype (Pref))
2953 and then No (Size_Clause (Etype (Pref)))
2954 then
2955 Set_Attribute_Name (N, Name_Object_Size);
2956
2957 -- In all other cases, Size and VADS_Size are the sane
2958
2959 else
2960 Set_Attribute_Name (N, Name_Size);
2961 end if;
2962 end if;
2963 end if;
2964
9dfe12ae 2965 -- For class-wide types, X'Class'Size is transformed into a
2966 -- direct reference to the Size of the class type, so that gigi
2967 -- does not have to deal with the X'Class'Size reference.
ee6ba406 2968
9dfe12ae 2969 if Is_Entity_Name (Pref)
2970 and then Is_Class_Wide_Type (Entity (Pref))
2971 then
2972 Rewrite (Prefix (N), New_Occurrence_Of (Entity (Pref), Loc));
2973 return;
2974
2975 -- For x'Size applied to an object of a class wide type, transform
2976 -- X'Size into a call to the primitive operation _Size applied to X.
2977
2978 elsif Is_Class_Wide_Type (Ptyp) then
ee6ba406 2979 New_Node :=
2980 Make_Function_Call (Loc,
2981 Name => New_Reference_To
2982 (Find_Prim_Op (Ptyp, Name_uSize), Loc),
2983 Parameter_Associations => New_List (Pref));
2984
2985 if Typ /= Standard_Long_Long_Integer then
2986
2987 -- The context is a specific integer type with which the
2988 -- original attribute was compatible. The function has a
2989 -- specific type as well, so to preserve the compatibility
2990 -- we must convert explicitly.
2991
2992 New_Node := Convert_To (Typ, New_Node);
2993 end if;
2994
2995 Rewrite (N, New_Node);
2996 Analyze_And_Resolve (N, Typ);
2997 return;
2998
2999 -- For an array component, we can do Size in the front end
3000 -- if the component_size of the array is set.
3001
3002 elsif Nkind (Pref) = N_Indexed_Component then
3003 Siz := Component_Size (Etype (Prefix (Pref)));
3004
3005 -- For a record component, we can do Size in the front end
3006 -- if there is a component clause, or if the record is packed
3007 -- and the component's size is known at compile time.
3008
3009 elsif Nkind (Pref) = N_Selected_Component then
3010 declare
3011 Rec : constant Entity_Id := Etype (Prefix (Pref));
3012 Comp : constant Entity_Id := Entity (Selector_Name (Pref));
3013
3014 begin
3015 if Present (Component_Clause (Comp)) then
3016 Siz := Esize (Comp);
3017
3018 elsif Is_Packed (Rec) then
3019 Siz := RM_Size (Ptyp);
3020
3021 else
3022 Apply_Universal_Integer_Attribute_Checks (N);
3023 return;
3024 end if;
3025 end;
3026
3027 -- All other cases are handled by Gigi
3028
3029 else
3030 Apply_Universal_Integer_Attribute_Checks (N);
3031
3032 -- If we have Size applied to a formal parameter, that is a
3033 -- packed array subtype, then apply size to the actual subtype.
3034
3035 if Is_Entity_Name (Pref)
3036 and then Is_Formal (Entity (Pref))
3037 and then Is_Array_Type (Etype (Pref))
3038 and then Is_Packed (Etype (Pref))
3039 then
3040 Rewrite (N,
3041 Make_Attribute_Reference (Loc,
3042 Prefix =>
3043 New_Occurrence_Of (Get_Actual_Subtype (Pref), Loc),
3044 Attribute_Name => Name_Size));
3045 Analyze_And_Resolve (N, Typ);
3046 end if;
3047
3048 return;
3049 end if;
3050
3051 -- Common processing for record and array component case
3052
3053 if Siz /= 0 then
3054 Rewrite (N,
3055 Make_Integer_Literal (Loc, Siz));
3056
3057 Analyze_And_Resolve (N, Typ);
3058
3059 -- The result is not a static expression
3060
3061 Set_Is_Static_Expression (N, False);
3062 end if;
3063 end Size;
3064
3065 ------------------
3066 -- Storage_Pool --
3067 ------------------
3068
3069 when Attribute_Storage_Pool =>
3070 Rewrite (N,
3071 Make_Type_Conversion (Loc,
3072 Subtype_Mark => New_Reference_To (Etype (N), Loc),
3073 Expression => New_Reference_To (Entity (N), Loc)));
3074 Analyze_And_Resolve (N, Typ);
3075
3076 ------------------
3077 -- Storage_Size --
3078 ------------------
3079
3080 when Attribute_Storage_Size => Storage_Size :
3081 declare
3082 Ptyp : constant Entity_Id := Etype (Pref);
3083
3084 begin
3085 -- Access type case, always go to the root type
3086
3087 -- The case of access types results in a value of zero for the case
3088 -- where no storage size attribute clause has been given. If a
3089 -- storage size has been given, then the attribute is converted
3090 -- to a reference to the variable used to hold this value.
3091
3092 if Is_Access_Type (Ptyp) then
3093 if Present (Storage_Size_Variable (Root_Type (Ptyp))) then
3094 Rewrite (N,
3095 Make_Attribute_Reference (Loc,
3096 Prefix => New_Reference_To (Typ, Loc),
3097 Attribute_Name => Name_Max,
3098 Expressions => New_List (
3099 Make_Integer_Literal (Loc, 0),
3100 Convert_To (Typ,
3101 New_Reference_To
3102 (Storage_Size_Variable (Root_Type (Ptyp)), Loc)))));
3103
3104 elsif Present (Associated_Storage_Pool (Root_Type (Ptyp))) then
3105 Rewrite (N,
3106 OK_Convert_To (Typ,
3107 Make_Function_Call (Loc,
9dfe12ae 3108 Name =>
3109 New_Reference_To
3110 (Find_Prim_Op
3111 (Etype (Associated_Storage_Pool (Root_Type (Ptyp))),
3112 Attribute_Name (N)),
3113 Loc),
ee6ba406 3114
3115 Parameter_Associations => New_List (New_Reference_To (
3116 Associated_Storage_Pool (Root_Type (Ptyp)), Loc)))));
3117 else
3118 Rewrite (N, Make_Integer_Literal (Loc, 0));
3119 end if;
3120
3121 Analyze_And_Resolve (N, Typ);
3122
3123 -- The case of a task type (an obsolescent feature) is handled the
3124 -- same way, seems as reasonable as anything, and it is what the
3125 -- ACVC tests (e.g. CD1009K) seem to expect.
3126
3127 -- If there is no Storage_Size variable, then we return the default
3128 -- task stack size, otherwise, expand a Storage_Size attribute as
3129 -- follows:
3130
3131 -- Typ (Adjust_Storage_Size (taskZ))
3132
3133 -- except for the case of a task object which has a Storage_Size
3134 -- pragma:
3135
3136 -- Typ (Adjust_Storage_Size (taskV!(name)._Size))
3137
3138 else
3139 if not Present (Storage_Size_Variable (Ptyp)) then
3140 Rewrite (N,
3141 Convert_To (Typ,
3142 Make_Function_Call (Loc,
3143 Name =>
3144 New_Occurrence_Of (RTE (RE_Default_Stack_Size), Loc))));
3145
3146 else
3147 if not (Is_Entity_Name (Pref) and then
3148 Is_Task_Type (Entity (Pref))) and then
3149 Chars (Last_Entity (Corresponding_Record_Type (Ptyp))) =
3150 Name_uSize
3151 then
3152 Rewrite (N,
3153 Convert_To (Typ,
3154 Make_Function_Call (Loc,
3155 Name => New_Occurrence_Of (
3156 RTE (RE_Adjust_Storage_Size), Loc),
3157 Parameter_Associations =>
3158 New_List (
3159 Make_Selected_Component (Loc,
3160 Prefix =>
3161 Unchecked_Convert_To (
3162 Corresponding_Record_Type (Ptyp),
3163 New_Copy_Tree (Pref)),
3164 Selector_Name =>
3165 Make_Identifier (Loc, Name_uSize))))));
3166
3167 -- Task not having Storage_Size pragma
3168
3169 else
3170 Rewrite (N,
3171 Convert_To (Typ,
3172 Make_Function_Call (Loc,
3173 Name => New_Occurrence_Of (
3174 RTE (RE_Adjust_Storage_Size), Loc),
3175 Parameter_Associations =>
3176 New_List (
3177 New_Reference_To (
3178 Storage_Size_Variable (Ptyp), Loc)))));
3179 end if;
3180
3181 Analyze_And_Resolve (N, Typ);
3182 end if;
3183 end if;
3184 end Storage_Size;
3185
3186 ----------
3187 -- Succ --
3188 ----------
3189
3190 -- 1. Deal with enumeration types with holes
3191 -- 2. For floating-point, generate call to attribute function
3192 -- 3. For other cases, deal with constraint checking
3193
3194 when Attribute_Succ => Succ :
3195 declare
3196 Ptyp : constant Entity_Id := Base_Type (Etype (Pref));
3197
3198 begin
3199 -- For enumeration types with non-standard representations, we
3200 -- expand typ'Succ (x) into
3201
3202 -- Pos_To_Rep (Rep_To_Pos (x) + 1)
3203
9dfe12ae 3204 -- If the representation is contiguous, we compute instead
3205 -- Lit1 + Rep_to_Pos (x+1), to catch invalid representations.
3206
ee6ba406 3207 if Is_Enumeration_Type (Ptyp)
3208 and then Present (Enum_Pos_To_Rep (Ptyp))
3209 then
9dfe12ae 3210 if Has_Contiguous_Rep (Ptyp) then
3211 Rewrite (N,
3212 Unchecked_Convert_To (Ptyp,
3213 Make_Op_Add (Loc,
3214 Left_Opnd =>
3215 Make_Integer_Literal (Loc,
3216 Enumeration_Rep (First_Literal (Ptyp))),
3217 Right_Opnd =>
3218 Make_Function_Call (Loc,
3219 Name =>
3220 New_Reference_To
3221 (TSS (Ptyp, TSS_Rep_To_Pos), Loc),
3222
3223 Parameter_Associations =>
3224 New_List (
3225 Unchecked_Convert_To (Ptyp,
3226 Make_Op_Add (Loc,
3227 Left_Opnd =>
3228 Unchecked_Convert_To (Standard_Integer,
3229 Relocate_Node (First (Exprs))),
3230 Right_Opnd =>
3231 Make_Integer_Literal (Loc, 1))),
3232 Rep_To_Pos_Flag (Ptyp, Loc))))));
3233 else
3234 -- Add Boolean parameter True, to request program errror if
3235 -- we have a bad representation on our hands. Add False if
3236 -- checks are suppressed.
ee6ba406 3237
9dfe12ae 3238 Append_To (Exprs, Rep_To_Pos_Flag (Ptyp, Loc));
3239 Rewrite (N,
3240 Make_Indexed_Component (Loc,
3241 Prefix => New_Reference_To (Enum_Pos_To_Rep (Ptyp), Loc),
3242 Expressions => New_List (
3243 Make_Op_Add (Loc,
3244 Left_Opnd =>
3245 Make_Function_Call (Loc,
3246 Name =>
3247 New_Reference_To
3248 (TSS (Ptyp, TSS_Rep_To_Pos), Loc),
3249 Parameter_Associations => Exprs),
3250 Right_Opnd => Make_Integer_Literal (Loc, 1)))));
3251 end if;
ee6ba406 3252
3253 Analyze_And_Resolve (N, Typ);
3254
3255 -- For floating-point, we transform 'Succ into a call to the Succ
3256 -- floating-point attribute function in Fat_xxx (xxx is root type)
3257
3258 elsif Is_Floating_Point_Type (Ptyp) then
3259 Expand_Fpt_Attribute_R (N);
3260 Analyze_And_Resolve (N, Typ);
3261
3262 -- For modular types, nothing to do (no overflow, since wraps)
3263
3264 elsif Is_Modular_Integer_Type (Ptyp) then
3265 null;
3266
3267 -- For other types, if range checking is enabled, we must generate
3268 -- a check if overflow checking is enabled.
3269
3270 elsif not Overflow_Checks_Suppressed (Ptyp) then
3271 Expand_Pred_Succ (N);
3272 end if;
3273 end Succ;
3274
3275 ---------
3276 -- Tag --
3277 ---------
3278
3279 -- Transforms X'Tag into a direct reference to the tag of X
3280
3281 when Attribute_Tag => Tag :
3282 declare
3283 Ttyp : Entity_Id;
3284 Prefix_Is_Type : Boolean;
3285
3286 begin
3287 if Is_Entity_Name (Pref) and then Is_Type (Entity (Pref)) then
3288 Ttyp := Entity (Pref);
3289 Prefix_Is_Type := True;
3290 else
3291 Ttyp := Etype (Pref);
3292 Prefix_Is_Type := False;
3293 end if;
3294
3295 if Is_Class_Wide_Type (Ttyp) then
3296 Ttyp := Root_Type (Ttyp);
3297 end if;
3298
3299 Ttyp := Underlying_Type (Ttyp);
3300
3301 if Prefix_Is_Type then
1d7e0b5b 3302
3303 -- For JGNAT we leave the type attribute unexpanded because
3304 -- there's not a dispatching table to reference.
3305
3306 if not Java_VM then
3307 Rewrite (N,
3308 Unchecked_Convert_To (RTE (RE_Tag),
3309 New_Reference_To (Access_Disp_Table (Ttyp), Loc)));
3310 Analyze_And_Resolve (N, RTE (RE_Tag));
3311 end if;
ee6ba406 3312
3313 else
3314 Rewrite (N,
3315 Make_Selected_Component (Loc,
3316 Prefix => Relocate_Node (Pref),
3317 Selector_Name =>
3318 New_Reference_To (Tag_Component (Ttyp), Loc)));
1d7e0b5b 3319 Analyze_And_Resolve (N, RTE (RE_Tag));
ee6ba406 3320 end if;
ee6ba406 3321 end Tag;
3322
3323 ----------------
3324 -- Terminated --
3325 ----------------
3326
3327 -- Transforms 'Terminated attribute into a call to Terminated function.
3328
3329 when Attribute_Terminated => Terminated :
3330 begin
3331 if Restricted_Profile then
3332 Rewrite (N,
3333 Build_Call_With_Task (Pref, RTE (RE_Restricted_Terminated)));
3334
3335 else
3336 Rewrite (N,
3337 Build_Call_With_Task (Pref, RTE (RE_Terminated)));
3338 end if;
3339
3340 Analyze_And_Resolve (N, Standard_Boolean);
3341 end Terminated;
3342
3343 ----------------
3344 -- To_Address --
3345 ----------------
3346
3347 -- Transforms System'To_Address (X) into unchecked conversion
3348 -- from (integral) type of X to type address.
3349
3350 when Attribute_To_Address =>
3351 Rewrite (N,
3352 Unchecked_Convert_To (RTE (RE_Address),
3353 Relocate_Node (First (Exprs))));
3354 Analyze_And_Resolve (N, RTE (RE_Address));
3355
3356 ----------------
3357 -- Truncation --
3358 ----------------
3359
3360 -- Transforms 'Truncation into a call to the floating-point attribute
3361 -- function Truncation in Fat_xxx (where xxx is the root type)
3362
3363 when Attribute_Truncation =>
3364 Expand_Fpt_Attribute_R (N);
3365
3366 -----------------------
3367 -- Unbiased_Rounding --
3368 -----------------------
3369
3370 -- Transforms 'Unbiased_Rounding into a call to the floating-point
3371 -- attribute function Unbiased_Rounding in Fat_xxx (where xxx is the
3372 -- root type)
3373
3374 when Attribute_Unbiased_Rounding =>
3375 Expand_Fpt_Attribute_R (N);
3376
3377 ----------------------
3378 -- Unchecked_Access --
3379 ----------------------
3380
3381 when Attribute_Unchecked_Access =>
3382 Expand_Access_To_Type (N);
3383
3384 -----------------
3385 -- UET_Address --
3386 -----------------
3387
3388 when Attribute_UET_Address => UET_Address : declare
3389 Ent : constant Entity_Id :=
3390 Make_Defining_Identifier (Loc, New_Internal_Name ('T'));
3391
3392 begin
3393 Insert_Action (N,
3394 Make_Object_Declaration (Loc,
3395 Defining_Identifier => Ent,
3396 Aliased_Present => True,
3397 Object_Definition =>
3398 New_Occurrence_Of (RTE (RE_Address), Loc)));
3399
3400 -- Construct name __gnat_xxx__SDP, where xxx is the unit name
3401 -- in normal external form.
3402
3403 Get_External_Unit_Name_String (Get_Unit_Name (Pref));
3404 Name_Buffer (1 + 7 .. Name_Len + 7) := Name_Buffer (1 .. Name_Len);
3405 Name_Len := Name_Len + 7;
3406 Name_Buffer (1 .. 7) := "__gnat_";
3407 Name_Buffer (Name_Len + 1 .. Name_Len + 5) := "__SDP";
3408 Name_Len := Name_Len + 5;
3409
3410 Set_Is_Imported (Ent);
3411 Set_Interface_Name (Ent,
3412 Make_String_Literal (Loc,
3413 Strval => String_From_Name_Buffer));
3414
3415 Rewrite (N,
3416 Make_Attribute_Reference (Loc,
3417 Prefix => New_Occurrence_Of (Ent, Loc),
3418 Attribute_Name => Name_Address));
3419
3420 Analyze_And_Resolve (N, Typ);
3421 end UET_Address;
3422
3423 -------------------------
3424 -- Unrestricted_Access --
3425 -------------------------
3426
3427 when Attribute_Unrestricted_Access =>
3428 Expand_Access_To_Type (N);
3429
3430 ---------------
3431 -- VADS_Size --
3432 ---------------
3433
3434 -- The processing for VADS_Size is shared with Size
3435
3436 ---------
3437 -- Val --
3438 ---------
3439
3440 -- For enumeration types with a standard representation, and for all
3441 -- other types, Val is handled by Gigi. For enumeration types with
3442 -- a non-standard representation we use the _Pos_To_Rep array that
3443 -- was created when the type was frozen.
3444
3445 when Attribute_Val => Val :
3446 declare
3447 Etyp : constant Entity_Id := Base_Type (Entity (Pref));
3448
3449 begin
3450 if Is_Enumeration_Type (Etyp)
3451 and then Present (Enum_Pos_To_Rep (Etyp))
3452 then
9dfe12ae 3453 if Has_Contiguous_Rep (Etyp) then
3454 declare
3455 Rep_Node : constant Node_Id :=
3456 Unchecked_Convert_To (Etyp,
3457 Make_Op_Add (Loc,
3458 Left_Opnd =>
3459 Make_Integer_Literal (Loc,
3460 Enumeration_Rep (First_Literal (Etyp))),
3461 Right_Opnd =>
3462 (Convert_To (Standard_Integer,
3463 Relocate_Node (First (Exprs))))));
3464
3465 begin
3466 Rewrite (N,
3467 Unchecked_Convert_To (Etyp,
3468 Make_Op_Add (Loc,
3469 Left_Opnd =>
3470 Make_Integer_Literal (Loc,
3471 Enumeration_Rep (First_Literal (Etyp))),
3472 Right_Opnd =>
3473 Make_Function_Call (Loc,
3474 Name =>
3475 New_Reference_To
3476 (TSS (Etyp, TSS_Rep_To_Pos), Loc),
3477 Parameter_Associations => New_List (
3478 Rep_Node,
3479 Rep_To_Pos_Flag (Etyp, Loc))))));
3480 end;
3481
3482 else
3483 Rewrite (N,
3484 Make_Indexed_Component (Loc,
3485 Prefix => New_Reference_To (Enum_Pos_To_Rep (Etyp), Loc),
3486 Expressions => New_List (
3487 Convert_To (Standard_Integer,
3488 Relocate_Node (First (Exprs))))));
3489 end if;
ee6ba406 3490
3491 Analyze_And_Resolve (N, Typ);
3492 end if;
3493 end Val;
3494
3495 -----------
3496 -- Valid --
3497 -----------
3498
3499 -- The code for valid is dependent on the particular types involved.
3500 -- See separate sections below for the generated code in each case.
3501
3502 when Attribute_Valid => Valid :
3503 declare
3504 Ptyp : constant Entity_Id := Etype (Pref);
9dfe12ae 3505 Btyp : Entity_Id := Base_Type (Ptyp);
ee6ba406 3506 Tst : Node_Id;
3507
9dfe12ae 3508 Save_Validity_Checks_On : constant Boolean := Validity_Checks_On;
3509 -- Save the validity checking mode. We always turn off validity
3510 -- checking during process of 'Valid since this is one place
3511 -- where we do not want the implicit validity checks to intefere
3512 -- with the explicit validity check that the programmer is doing.
3513
ee6ba406 3514 function Make_Range_Test return Node_Id;
3515 -- Build the code for a range test of the form
3516 -- Btyp!(Pref) >= Btyp!(Ptyp'First)
3517 -- and then
3518 -- Btyp!(Pref) <= Btyp!(Ptyp'Last)
3519
9dfe12ae 3520 ---------------------
3521 -- Make_Range_Test --
3522 ---------------------
3523
ee6ba406 3524 function Make_Range_Test return Node_Id is
3525 begin
3526 return
3527 Make_And_Then (Loc,
3528 Left_Opnd =>
3529 Make_Op_Ge (Loc,
3530 Left_Opnd =>
3531 Unchecked_Convert_To (Btyp, Duplicate_Subexpr (Pref)),
3532
3533 Right_Opnd =>
3534 Unchecked_Convert_To (Btyp,
3535 Make_Attribute_Reference (Loc,
3536 Prefix => New_Occurrence_Of (Ptyp, Loc),
3537 Attribute_Name => Name_First))),
3538
3539 Right_Opnd =>
3540 Make_Op_Le (Loc,
3541 Left_Opnd =>
9dfe12ae 3542 Unchecked_Convert_To (Btyp,
3543 Duplicate_Subexpr_No_Checks (Pref)),
ee6ba406 3544
3545 Right_Opnd =>
3546 Unchecked_Convert_To (Btyp,
3547 Make_Attribute_Reference (Loc,
3548 Prefix => New_Occurrence_Of (Ptyp, Loc),
3549 Attribute_Name => Name_Last))));
3550 end Make_Range_Test;
3551
3552 -- Start of processing for Attribute_Valid
3553
3554 begin
9dfe12ae 3555 -- Turn off validity checks. We do not want any implicit validity
3556 -- checks to intefere with the explicit check from the attribute
3557
3558 Validity_Checks_On := False;
3559
ee6ba406 3560 -- Floating-point case. This case is handled by the Valid attribute
3561 -- code in the floating-point attribute run-time library.
3562
3563 if Is_Floating_Point_Type (Ptyp) then
3564 declare
3565 Rtp : constant Entity_Id := Root_Type (Etype (Pref));
3566
3567 begin
9dfe12ae 3568 -- If the floating-point object might be unaligned, we need
3569 -- to call the special routine Unaligned_Valid, which makes
3570 -- the needed copy, being careful not to load the value into
3571 -- any floating-point register. The argument in this case is
3572 -- obj'Address (see Unchecked_Valid routine in s-fatgen.ads).
3573
3574 if Is_Possibly_Unaligned_Object (Pref) then
3575 Set_Attribute_Name (N, Name_Unaligned_Valid);
3576 Expand_Fpt_Attribute
3577 (N, Rtp, Name_Unaligned_Valid,
3578 New_List (
3579 Make_Attribute_Reference (Loc,
3580 Prefix => Relocate_Node (Pref),
3581 Attribute_Name => Name_Address)));
3582
3583 -- In the normal case where we are sure the object is aligned,
3584 -- we generate a caqll to Valid, and the argument in this case
3585 -- is obj'Unrestricted_Access (after converting obj to the
3586 -- right floating-point type).
3587
3588 else
3589 Expand_Fpt_Attribute
3590 (N, Rtp, Name_Valid,
3591 New_List (
3592 Make_Attribute_Reference (Loc,
3593 Prefix => Unchecked_Convert_To (Rtp, Pref),
3594 Attribute_Name => Name_Unrestricted_Access)));
3595 end if;
ee6ba406 3596
3597 -- One more task, we still need a range check. Required
3598 -- only if we have a constraint, since the Valid routine
3599 -- catches infinities properly (infinities are never valid).
3600
3601 -- The way we do the range check is simply to create the
3602 -- expression: Valid (N) and then Base_Type(Pref) in Typ.
3603
3604 if not Subtypes_Statically_Match (Ptyp, Btyp) then
3605 Rewrite (N,
3606 Make_And_Then (Loc,
3607 Left_Opnd => Relocate_Node (N),
3608 Right_Opnd =>
3609 Make_In (Loc,
3610 Left_Opnd => Convert_To (Btyp, Pref),
3611 Right_Opnd => New_Occurrence_Of (Ptyp, Loc))));
3612 end if;
3613 end;
3614
3615 -- Enumeration type with holes
3616
3617 -- For enumeration types with holes, the Pos value constructed by
3618 -- the Enum_Rep_To_Pos function built in Exp_Ch3 called with a
3619 -- second argument of False returns minus one for an invalid value,
3620 -- and the non-negative pos value for a valid value, so the
3621 -- expansion of X'Valid is simply:
3622
3623 -- type(X)'Pos (X) >= 0
3624
3625 -- We can't quite generate it that way because of the requirement
3626 -- for the non-standard second argument of False, so we have to
3627 -- explicitly create:
3628
3629 -- _rep_to_pos (X, False) >= 0
3630
3631 -- If we have an enumeration subtype, we also check that the
3632 -- value is in range:
3633
3634 -- _rep_to_pos (X, False) >= 0
3635 -- and then
3636 -- (X >= type(X)'First and then type(X)'Last <= X)
3637
3638 elsif Is_Enumeration_Type (Ptyp)
3639 and then Present (Enum_Pos_To_Rep (Base_Type (Ptyp)))
3640 then
3641 Tst :=
3642 Make_Op_Ge (Loc,
3643 Left_Opnd =>
3644 Make_Function_Call (Loc,
3645 Name =>
3646 New_Reference_To
9dfe12ae 3647 (TSS (Base_Type (Ptyp), TSS_Rep_To_Pos), Loc),
ee6ba406 3648 Parameter_Associations => New_List (
3649 Pref,
3650 New_Occurrence_Of (Standard_False, Loc))),
3651 Right_Opnd => Make_Integer_Literal (Loc, 0));
3652
3653 if Ptyp /= Btyp
3654 and then
3655 (Type_Low_Bound (Ptyp) /= Type_Low_Bound (Btyp)
3656 or else
3657 Type_High_Bound (Ptyp) /= Type_High_Bound (Btyp))
3658 then
3659 -- The call to Make_Range_Test will create declarations
3660 -- that need a proper insertion point, but Pref is now
3661 -- attached to a node with no ancestor. Attach to tree
3662 -- even if it is to be rewritten below.
3663
3664 Set_Parent (Tst, Parent (N));
3665
3666 Tst :=
3667 Make_And_Then (Loc,
3668 Left_Opnd => Make_Range_Test,
3669 Right_Opnd => Tst);
3670 end if;
3671
3672 Rewrite (N, Tst);
3673
3674 -- Fortran convention booleans
3675
3676 -- For the very special case of Fortran convention booleans, the
3677 -- value is always valid, since it is an integer with the semantics
3678 -- that non-zero is true, and any value is permissible.
3679
3680 elsif Is_Boolean_Type (Ptyp)
3681 and then Convention (Ptyp) = Convention_Fortran
3682 then
3683 Rewrite (N, New_Occurrence_Of (Standard_True, Loc));
3684
3685 -- For biased representations, we will be doing an unchecked
3686 -- conversion without unbiasing the result. That means that
3687 -- the range test has to take this into account, and the
3688 -- proper form of the test is:
3689
3690 -- Btyp!(Pref) < Btyp!(Ptyp'Range_Length)
3691
3692 elsif Has_Biased_Representation (Ptyp) then
3693 Btyp := RTE (RE_Unsigned_32);
3694 Rewrite (N,
3695 Make_Op_Lt (Loc,
3696 Left_Opnd =>
3697 Unchecked_Convert_To (Btyp, Duplicate_Subexpr (Pref)),
3698 Right_Opnd =>
3699 Unchecked_Convert_To (Btyp,
3700 Make_Attribute_Reference (Loc,
3701 Prefix => New_Occurrence_Of (Ptyp, Loc),
3702 Attribute_Name => Name_Range_Length))));
3703
3704 -- For all other scalar types, what we want logically is a
3705 -- range test:
3706
3707 -- X in type(X)'First .. type(X)'Last
3708
3709 -- But that's precisely what won't work because of possible
3710 -- unwanted optimization (and indeed the basic motivation for
3711 -- the Valid attribute -is exactly that this test does not work.
3712 -- What will work is:
3713
3714 -- Btyp!(X) >= Btyp!(type(X)'First)
3715 -- and then
3716 -- Btyp!(X) <= Btyp!(type(X)'Last)
3717
3718 -- where Btyp is an integer type large enough to cover the full
3719 -- range of possible stored values (i.e. it is chosen on the basis
3720 -- of the size of the type, not the range of the values). We write
3721 -- this as two tests, rather than a range check, so that static
3722 -- evaluation will easily remove either or both of the checks if
3723 -- they can be -statically determined to be true (this happens
3724 -- when the type of X is static and the range extends to the full
3725 -- range of stored values).
3726
3727 -- Unsigned types. Note: it is safe to consider only whether the
3728 -- subtype is unsigned, since we will in that case be doing all
3729 -- unsigned comparisons based on the subtype range. Since we use
3730 -- the actual subtype object size, this is appropriate.
3731
3732 -- For example, if we have
3733
3734 -- subtype x is integer range 1 .. 200;
3735 -- for x'Object_Size use 8;
3736
3737 -- Now the base type is signed, but objects of this type are 8
3738 -- bits unsigned, and doing an unsigned test of the range 1 to
3739 -- 200 is correct, even though a value greater than 127 looks
3740 -- signed to a signed comparison.
3741
3742 elsif Is_Unsigned_Type (Ptyp) then
3743 if Esize (Ptyp) <= 32 then
3744 Btyp := RTE (RE_Unsigned_32);
3745 else
3746 Btyp := RTE (RE_Unsigned_64);
3747 end if;
3748
3749 Rewrite (N, Make_Range_Test);
3750
3751 -- Signed types
3752
3753 else
3754 if Esize (Ptyp) <= Esize (Standard_Integer) then
3755 Btyp := Standard_Integer;
3756 else
3757 Btyp := Universal_Integer;
3758 end if;
3759
3760 Rewrite (N, Make_Range_Test);
3761 end if;
3762
3763 Analyze_And_Resolve (N, Standard_Boolean);
9dfe12ae 3764 Validity_Checks_On := Save_Validity_Checks_On;
ee6ba406 3765 end Valid;
3766
3767 -----------
3768 -- Value --
3769 -----------
3770
3771 -- Value attribute is handled in separate unti Exp_Imgv
3772
3773 when Attribute_Value =>
3774 Exp_Imgv.Expand_Value_Attribute (N);
3775
3776 -----------------
3777 -- Value_Size --
3778 -----------------
3779
3780 -- The processing for Value_Size shares the processing for Size
3781
3782 -------------
3783 -- Version --
3784 -------------
3785
3786 -- The processing for Version shares the processing for Body_Version
3787
3788 ----------------
3789 -- Wide_Image --
3790 ----------------
3791
3792 -- We expand typ'Wide_Image (X) into
3793
3794 -- String_To_Wide_String
3795 -- (typ'Image (X), Wide_Character_Encoding_Method)
3796
3797 -- This works in all cases because String_To_Wide_String converts any
3798 -- wide character escape sequences resulting from the Image call to the
3799 -- proper Wide_Character equivalent
3800
3801 -- not quite right for typ = Wide_Character ???
3802
3803 when Attribute_Wide_Image => Wide_Image :
3804 begin
3805 Rewrite (N,
3806 Make_Function_Call (Loc,
3807 Name => New_Reference_To (RTE (RE_String_To_Wide_String), Loc),
3808 Parameter_Associations => New_List (
3809 Make_Attribute_Reference (Loc,
3810 Prefix => Pref,
3811 Attribute_Name => Name_Image,
3812 Expressions => Exprs),
3813
3814 Make_Integer_Literal (Loc,
3815 Intval => Int (Wide_Character_Encoding_Method)))));
3816
3817 Analyze_And_Resolve (N, Standard_Wide_String);
3818 end Wide_Image;
3819
3820 ----------------
3821 -- Wide_Value --
3822 ----------------
3823
3824 -- We expand typ'Wide_Value (X) into
3825
3826 -- typ'Value
3827 -- (Wide_String_To_String (X, Wide_Character_Encoding_Method))
3828
3829 -- Wide_String_To_String is a runtime function that converts its wide
3830 -- string argument to String, converting any non-translatable characters
3831 -- into appropriate escape sequences. This preserves the required
3832 -- semantics of Wide_Value in all cases, and results in a very simple
3833 -- implementation approach.
3834
3835 -- It's not quite right where typ = Wide_Character, because the encoding
3836 -- method may not cover the whole character type ???
3837
3838 when Attribute_Wide_Value => Wide_Value :
3839 begin
3840 Rewrite (N,
3841 Make_Attribute_Reference (Loc,
3842 Prefix => Pref,
3843 Attribute_Name => Name_Value,
3844
3845 Expressions => New_List (
3846 Make_Function_Call (Loc,
3847 Name =>
3848 New_Reference_To (RTE (RE_Wide_String_To_String), Loc),
3849
3850 Parameter_Associations => New_List (
3851 Relocate_Node (First (Exprs)),
3852 Make_Integer_Literal (Loc,
3853 Intval => Int (Wide_Character_Encoding_Method)))))));
3854
3855 Analyze_And_Resolve (N, Typ);
3856 end Wide_Value;
3857
3858 ----------------
3859 -- Wide_Width --
3860 ----------------
3861
3862 -- Wide_Width attribute is handled in separate unit Exp_Imgv
3863
3864 when Attribute_Wide_Width =>
3865 Exp_Imgv.Expand_Width_Attribute (N, Wide => True);
3866
3867 -----------
3868 -- Width --
3869 -----------
3870
3871 -- Width attribute is handled in separate unit Exp_Imgv
3872
3873 when Attribute_Width =>
3874 Exp_Imgv.Expand_Width_Attribute (N, Wide => False);
3875
3876 -----------
3877 -- Write --
3878 -----------
3879
3880 when Attribute_Write => Write : declare
3881 P_Type : constant Entity_Id := Entity (Pref);
3882 U_Type : constant Entity_Id := Underlying_Type (P_Type);
3883 Pname : Entity_Id;
3884 Decl : Node_Id;
3885 Prag : Node_Id;
3886 Arg3 : Node_Id;
3887 Wfunc : Node_Id;
3888
3889 begin
3890 -- If no underlying type, we have an error that will be diagnosed
3891 -- elsewhere, so here we just completely ignore the expansion.
3892
3893 if No (U_Type) then
3894 return;
3895 end if;
3896
3897 -- The simple case, if there is a TSS for Write, just call it
3898
9dfe12ae 3899 Pname := Find_Stream_Subprogram (P_Type, TSS_Stream_Write);
ee6ba406 3900
3901 if Present (Pname) then
3902 null;
3903
3904 else
3905 -- If there is a Stream_Convert pragma, use it, we rewrite
3906
3907 -- sourcetyp'Output (stream, Item)
3908
3909 -- as
3910
3911 -- strmtyp'Output (Stream, strmwrite (acttyp (Item)));
3912
3913 -- where strmwrite is the given Write function that converts
3914 -- an argument of type sourcetyp or a type acctyp, from which
3915 -- it is derived to type strmtyp. The conversion to acttyp is
3916 -- required for the derived case.
3917
3918 Prag :=
3919 Get_Rep_Pragma
3920 (Implementation_Base_Type (P_Type), Name_Stream_Convert);
3921
3922 if Present (Prag) then
3923 Arg3 :=
3924 Next (Next (First (Pragma_Argument_Associations (Prag))));
3925 Wfunc := Entity (Expression (Arg3));
3926
3927 Rewrite (N,
3928 Make_Attribute_Reference (Loc,
3929 Prefix => New_Occurrence_Of (Etype (Wfunc), Loc),
3930 Attribute_Name => Name_Output,
3931 Expressions => New_List (
3932 Relocate_Node (First (Exprs)),
3933 Make_Function_Call (Loc,
3934 Name => New_Occurrence_Of (Wfunc, Loc),
3935 Parameter_Associations => New_List (
3936 Convert_To (Etype (First_Formal (Wfunc)),
3937 Relocate_Node (Next (First (Exprs)))))))));
3938
3939 Analyze (N);
3940 return;
3941
3942 -- For elementary types, we call the W_xxx routine directly
3943
3944 elsif Is_Elementary_Type (U_Type) then
3945 Rewrite (N, Build_Elementary_Write_Call (N));
3946 Analyze (N);
3947 return;
3948
3949 -- Array type case
3950
3951 elsif Is_Array_Type (U_Type) then
3952 Build_Array_Write_Procedure (N, U_Type, Decl, Pname);
3953 Compile_Stream_Body_In_Scope (N, Decl, U_Type, Check => False);
3954
3955 -- Tagged type case, use the primitive Write function. Note that
3956 -- this will dispatch in the class-wide case which is what we want
3957
3958 elsif Is_Tagged_Type (U_Type) then
9dfe12ae 3959 Pname := Find_Prim_Op (U_Type, TSS_Stream_Write);
ee6ba406 3960
3961 -- All other record type cases, including protected records.
3962 -- The latter only arise for expander generated code for
3963 -- handling shared passive partition access.
3964
3965 else
3966 pragma Assert
3967 (Is_Record_Type (U_Type) or else Is_Protected_Type (U_Type));
3968
3969 if Has_Discriminants (U_Type)
3970 and then Present
3971 (Discriminant_Default_Value (First_Discriminant (U_Type)))
3972 then
3973 Build_Mutable_Record_Write_Procedure
3974 (Loc, Base_Type (U_Type), Decl, Pname);
3975
3976 else
3977 Build_Record_Write_Procedure
3978 (Loc, Base_Type (U_Type), Decl, Pname);
3979 end if;
3980
3981 Insert_Action (N, Decl);
3982 end if;
3983 end if;
3984
3985 -- If we fall through, Pname is the procedure to be called
3986
3987 Rewrite_Stream_Proc_Call (Pname);
3988 end Write;
3989
3990 -- Component_Size is handled by Gigi, unless the component size is
3991 -- known at compile time, which is always true in the packed array
3992 -- case. It is important that the packed array case is handled in
3993 -- the front end (see Eval_Attribute) since Gigi would otherwise
3994 -- get confused by the equivalent packed array type.
3995
3996 when Attribute_Component_Size =>
3997 null;
3998
3999 -- The following attributes are handled by Gigi (except that static
4000 -- cases have already been evaluated by the semantics, but in any
4001 -- case Gigi should not count on that).
4002
4003 -- In addition Gigi handles the non-floating-point cases of Pred
4004 -- and Succ (including the fixed-point cases, which can just be
4005 -- treated as integer increment/decrement operations)
4006
4007 -- Gigi also handles the non-class-wide cases of Size
4008
4009 when Attribute_Bit_Order |
4010 Attribute_Code_Address |
4011 Attribute_Definite |
4012 Attribute_Max |
4013 Attribute_Mechanism_Code |
4014 Attribute_Min |
4015 Attribute_Null_Parameter |
9dfe12ae 4016 Attribute_Passed_By_Reference |
4017 Attribute_Pool_Address =>
ee6ba406 4018 null;
4019
4020 -- The following attributes are also handled by Gigi, but return a
4021 -- universal integer result, so may need a conversion for checking
4022 -- that the result is in range.
4023
4024 when Attribute_Aft |
ee6ba406 4025 Attribute_Bit |
4026 Attribute_Max_Size_In_Storage_Elements
4027 =>
4028 Apply_Universal_Integer_Attribute_Checks (N);
4029
4030 -- The following attributes should not appear at this stage, since they
4031 -- have already been handled by the analyzer (and properly rewritten
4032 -- with corresponding values or entities to represent the right values)
4033
4034 when Attribute_Abort_Signal |
4035 Attribute_Address_Size |
4036 Attribute_Base |
4037 Attribute_Class |
4038 Attribute_Default_Bit_Order |
4039 Attribute_Delta |
4040 Attribute_Denorm |
4041 Attribute_Digits |
4042 Attribute_Emax |
4043 Attribute_Epsilon |
4044 Attribute_Has_Discriminants |
4045 Attribute_Large |
4046 Attribute_Machine_Emax |
4047 Attribute_Machine_Emin |
4048 Attribute_Machine_Mantissa |
4049 Attribute_Machine_Overflows |
4050 Attribute_Machine_Radix |
4051 Attribute_Machine_Rounds |
ee6ba406 4052 Attribute_Maximum_Alignment |
4053 Attribute_Model_Emin |
4054 Attribute_Model_Epsilon |
4055 Attribute_Model_Mantissa |
4056 Attribute_Model_Small |
4057 Attribute_Modulus |
4058 Attribute_Partition_ID |
4059 Attribute_Range |
4060 Attribute_Safe_Emax |
4061 Attribute_Safe_First |
4062 Attribute_Safe_Large |
4063 Attribute_Safe_Last |
4064 Attribute_Safe_Small |
4065 Attribute_Scale |
4066 Attribute_Signed_Zeros |
4067 Attribute_Small |
4068 Attribute_Storage_Unit |
9dfe12ae 4069 Attribute_Target_Name |
ee6ba406 4070 Attribute_Type_Class |
9dfe12ae 4071 Attribute_Unconstrained_Array |
ee6ba406 4072 Attribute_Universal_Literal_String |
4073 Attribute_Wchar_T_Size |
4074 Attribute_Word_Size =>
4075
4076 raise Program_Error;
4077
4078 -- The Asm_Input and Asm_Output attributes are not expanded at this
4079 -- stage, but will be eliminated in the expansion of the Asm call,
4080 -- see Exp_Intr for details. So Gigi will never see these either.
4081
4082 when Attribute_Asm_Input |
4083 Attribute_Asm_Output =>
4084
4085 null;
4086
4087 end case;
4088
9dfe12ae 4089 exception
4090 when RE_Not_Available =>
4091 return;
ee6ba406 4092 end Expand_N_Attribute_Reference;
4093
4094 ----------------------
4095 -- Expand_Pred_Succ --
4096 ----------------------
4097
4098 -- For typ'Pred (exp), we generate the check
4099
4100 -- [constraint_error when exp = typ'Base'First]
4101
4102 -- Similarly, for typ'Succ (exp), we generate the check
4103
4104 -- [constraint_error when exp = typ'Base'Last]
4105
4106 -- These checks are not generated for modular types, since the proper
4107 -- semantics for Succ and Pred on modular types is to wrap, not raise CE.
4108
4109 procedure Expand_Pred_Succ (N : Node_Id) is
4110 Loc : constant Source_Ptr := Sloc (N);
4111 Cnam : Name_Id;
4112
4113 begin
4114 if Attribute_Name (N) = Name_Pred then
4115 Cnam := Name_First;
4116 else
4117 Cnam := Name_Last;
4118 end if;
4119
4120 Insert_Action (N,
4121 Make_Raise_Constraint_Error (Loc,
4122 Condition =>
4123 Make_Op_Eq (Loc,
9dfe12ae 4124 Left_Opnd =>
4125 Duplicate_Subexpr_Move_Checks (First (Expressions (N))),
ee6ba406 4126 Right_Opnd =>
4127 Make_Attribute_Reference (Loc,
4128 Prefix =>
4129 New_Reference_To (Base_Type (Etype (Prefix (N))), Loc),
f15731c4 4130 Attribute_Name => Cnam)),
4131 Reason => CE_Overflow_Check_Failed));
ee6ba406 4132
4133 end Expand_Pred_Succ;
4134
4135 ------------------------
4136 -- Find_Inherited_TSS --
4137 ------------------------
4138
4139 function Find_Inherited_TSS
4140 (Typ : Entity_Id;
9dfe12ae 4141 Nam : TSS_Name_Type) return Entity_Id
ee6ba406 4142 is
9dfe12ae 4143 Btyp : Entity_Id := Typ;
4144 Proc : Entity_Id;
ee6ba406 4145
4146 begin
9dfe12ae 4147 loop
4148 Btyp := Base_Type (Btyp);
4149 Proc := TSS (Btyp, Nam);
ee6ba406 4150
9dfe12ae 4151 exit when Present (Proc)
4152 or else not Is_Derived_Type (Btyp);
ee6ba406 4153
9dfe12ae 4154 -- If Typ is a derived type, it may inherit attributes from
4155 -- some ancestor.
ee6ba406 4156
9dfe12ae 4157 Btyp := Etype (Btyp);
4158 end loop;
ee6ba406 4159
9dfe12ae 4160 if No (Proc) then
ee6ba406 4161
9dfe12ae 4162 -- If nothing else, use the TSS of the root type
4163
4164 Proc := TSS (Base_Type (Underlying_Type (Typ)), Nam);
ee6ba406 4165 end if;
4166
9dfe12ae 4167 return Proc;
ee6ba406 4168
ee6ba406 4169 end Find_Inherited_TSS;
4170
9dfe12ae 4171 ----------------------------
4172 -- Find_Stream_Subprogram --
4173 ----------------------------
4174
4175 function Find_Stream_Subprogram
4176 (Typ : Entity_Id;
4177 Nam : TSS_Name_Type) return Entity_Id is
4178 begin
4179 if Is_Tagged_Type (Typ)
4180 and then Is_Derived_Type (Typ)
4181 then
4182 return Find_Prim_Op (Typ, Nam);
4183 else
4184 return Find_Inherited_TSS (Typ, Nam);
4185 end if;
4186 end Find_Stream_Subprogram;
4187
ee6ba406 4188 -----------------------
4189 -- Get_Index_Subtype --
4190 -----------------------
4191
4192 function Get_Index_Subtype (N : Node_Id) return Node_Id is
4193 P_Type : Entity_Id := Etype (Prefix (N));
4194 Indx : Node_Id;
4195 J : Int;
4196
4197 begin
4198 if Is_Access_Type (P_Type) then
4199 P_Type := Designated_Type (P_Type);
4200 end if;
4201
4202 if No (Expressions (N)) then
4203 J := 1;
4204 else
4205 J := UI_To_Int (Expr_Value (First (Expressions (N))));
4206 end if;
4207
4208 Indx := First_Index (P_Type);
4209 while J > 1 loop
4210 Next_Index (Indx);
4211 J := J - 1;
4212 end loop;
4213
4214 return Etype (Indx);
4215 end Get_Index_Subtype;
4216
4217 ---------------------------------
4218 -- Is_Constrained_Packed_Array --
4219 ---------------------------------
4220
4221 function Is_Constrained_Packed_Array (Typ : Entity_Id) return Boolean is
4222 Arr : Entity_Id := Typ;
4223
4224 begin
4225 if Is_Access_Type (Arr) then
4226 Arr := Designated_Type (Arr);
4227 end if;
4228
4229 return Is_Array_Type (Arr)
4230 and then Is_Constrained (Arr)
4231 and then Present (Packed_Array_Type (Arr));
4232 end Is_Constrained_Packed_Array;
4233
4234end Exp_Attr;