OSDN Git Service

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