home *** CD-ROM | disk | FTP | other *** search
/ Geek Gadgets 1 / ADE-1.bin / ade-dist / gnat-2.06-src.tgz / tar.out / fsf / gnat / ada / exp_attr.adb < prev    next >
Text File  |  1996-09-28  |  78KB  |  2,307 lines

  1. ------------------------------------------------------------------------------
  2. --                                                                          --
  3. --                         GNAT COMPILER COMPONENTS                         --
  4. --                                                                          --
  5. --                             E X P _ A T T R                              --
  6. --                                                                          --
  7. --                                 B o d y                                  --
  8. --                                                                          --
  9. --                            $Revision: 1.119 $                            --
  10. --                                                                          --
  11. --        Copyright (c) 1992,1993,1994,1995 NYU, All Rights Reserved        --
  12. --                                                                          --
  13. -- GNAT is free software;  you can  redistribute it  and/or modify it under --
  14. -- terms of the  GNU General Public License as published  by the Free Soft- --
  15. -- ware  Foundation;  either version 2,  or (at your option) any later ver- --
  16. -- sion.  GNAT is distributed in the hope that it will be useful, but WITH- --
  17. -- OUT ANY WARRANTY;  without even the  implied warranty of MERCHANTABILITY --
  18. -- or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License --
  19. -- for  more details.  You should have  received  a copy of the GNU General --
  20. -- Public License  distributed with GNAT;  see file COPYING.  If not, write --
  21. -- to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. --
  22. --                                                                          --
  23. ------------------------------------------------------------------------------
  24.  
  25. with Atree;    use Atree;
  26. with Einfo;    use Einfo;
  27. with Exp_Ch9;  use Exp_Ch9;
  28. with Exp_TSS;  use Exp_TSS;
  29. with Exp_Util; use Exp_Util;
  30. with Itypes;   use Itypes;
  31. with Namet;    use Namet;
  32. with Nmake;    use Nmake;
  33. with Nlists;   use Nlists;
  34. with Opt;      use Opt;
  35. with Output;   use Output;
  36. with Rtsfind;  use Rtsfind;
  37. with Sem;      use Sem;
  38. with Sem_Eval; use Sem_Eval;
  39. with Sem_Res;  use Sem_Res;
  40. with Sem_Util; use Sem_Util;
  41. with Sinfo;    use Sinfo;
  42. with Snames;   use Snames;
  43. with Stand;    use Stand;
  44. with Stringt;  use Stringt;
  45. with Tbuild;   use Tbuild;
  46. with Ttypes;   use Ttypes;
  47. with Uintp;    use Uintp;
  48. with Uname;    use Uname;
  49. with Urealp;   use Urealp;
  50.  
  51. package body Exp_Attr is
  52.  
  53.    -----------------------
  54.    -- Local Subprograms --
  55.    -----------------------
  56.  
  57.    procedure Expand_Fpt_Attribute (N : Node_Id; Args : List_Id);
  58.    --  This procedure expands a call to a floating-point attribute function.
  59.    --  N is the attribute reference node, and Args is a list of arguments to
  60.    --  be passed to the function call.
  61.  
  62.    procedure Expand_Fpt_Attribute_R (N : Node_Id);
  63.    --  This procedure expands a call to a floating-point attribute function
  64.    --  that takes a single floating-point argument.
  65.  
  66.    procedure Expand_Fpt_Attribute_RI (N : Node_Id);
  67.    --  This procedure expands a call to a floating-point attribute function
  68.    --  that takes one floating-point argument and one integer argument.
  69.  
  70.    procedure Expand_Fpt_Attribute_RR (N : Node_Id);
  71.    --  This procedure expands a call to a floating-point attribute function
  72.    --  that takes two floating-point arguments.
  73.  
  74.    procedure Expand_Pred_Succ (N : Node_Id);
  75.    --  Handles expansion of Pred or Succ attributes for case of non-real
  76.    --  operand with overflow checking required.
  77.  
  78.    function Get_Index_Subtype (N : Node_Id) return Entity_Id;
  79.    --  Used for Last, Last, and Length, when the prefix is an array type,
  80.    --  Obtains the corresponding index subtype.
  81.  
  82.    --------------------------
  83.    -- Expand_Fpt_Attribute --
  84.    --------------------------
  85.  
  86.    procedure Expand_Fpt_Attribute (N : Node_Id; Args : List_Id) is
  87.       Loc : constant Source_Ptr := Sloc (N);
  88.       Typ : constant Entity_Id  := Etype (N);
  89.       Rtp : constant Entity_Id  := Root_Type (Typ);
  90.       Pkg : RE_Id;
  91.       Fnm : Node_Id;
  92.  
  93.    begin
  94.       --  The function name is the selected component Fat_xxx.yyy where xxx
  95.       --  is the floating-point root type, and yyy is the attribute name
  96.  
  97.       --  Note: it would be more usual to have separate RE entries for each
  98.       --  of the entities in the Fat packages, but first they have identical
  99.       --  names (so we would have to have lots of renaming declarations to
  100.       --  meet the normal RE rule of separate names for all runtime entities),
  101.       --  and second there would be an awful lot of them!
  102.  
  103.       if Rtp = Standard_Short_Float then
  104.          Pkg := RE_Fat_Short_Float;
  105.       elsif Rtp = Standard_Float then
  106.          Pkg := RE_Fat_Float;
  107.       elsif Rtp = Standard_Long_Float then
  108.          Pkg := RE_Fat_Long_Float;
  109.       else
  110.          Pkg := RE_Fat_Long_Long_Float;
  111.       end if;
  112.  
  113.       Fnm :=
  114.         Make_Selected_Component (Loc,
  115.           Prefix        => New_Reference_To (RTE (Pkg), Loc),
  116.           Selector_Name => Make_Identifier (Loc, Attribute_Name (N)));
  117.  
  118.       --  The generated call is given the provided set of parameters, and then
  119.       --  wrapped in a conversion which converts the result to the target type
  120.  
  121.       Rewrite_Substitute_Tree (N,
  122.         Unchecked_Convert_To (Etype (N),
  123.           Make_Function_Call (Loc,
  124.             Name => Fnm,
  125.             Parameter_Associations => Args)));
  126.  
  127.       Analyze (N);
  128.       Resolve (N, Typ);
  129.  
  130.    end Expand_Fpt_Attribute;
  131.  
  132.    ----------------------------
  133.    -- Expand_Fpt_Attribute_R --
  134.    ----------------------------
  135.  
  136.    --  The single argument is converted to its root type to call the
  137.    --  appropriate runtime function, with the actual call being built
  138.    --  by Expand_Fpt_Attribute
  139.  
  140.    procedure Expand_Fpt_Attribute_R (N : Node_Id) is
  141.       Loc : constant Source_Ptr := Sloc (N);
  142.       Rtp : constant Entity_Id  := Root_Type (Etype (N));
  143.       E1  : constant Node_Id    := First (Expressions (N));
  144.  
  145.    begin
  146.       Expand_Fpt_Attribute (N, New_List (
  147.         Unchecked_Convert_To (Rtp, Relocate_Node (E1))));
  148.  
  149.    end Expand_Fpt_Attribute_R;
  150.  
  151.    -----------------------------
  152.    -- Expand_Fpt_Attribute_RI --
  153.    -----------------------------
  154.  
  155.    --  The first argument is converted to its root type and the second
  156.    --  argument is converted to standard long long integer to call the
  157.    --  appropriate runtime function, with the actual call being built
  158.    --  by Expand_Fpt_Attribute
  159.  
  160.    procedure Expand_Fpt_Attribute_RI (N : Node_Id) is
  161.       Loc : constant Source_Ptr := Sloc (N);
  162.       Rtp : constant Entity_Id  := Root_Type (Etype (N));
  163.       E1  : constant Node_Id    := First (Expressions (N));
  164.       E2  : constant Node_Id    := Next (E1);
  165.  
  166.    begin
  167.       Expand_Fpt_Attribute (N, New_List (
  168.         Unchecked_Convert_To (Rtp, Relocate_Node (E1)),
  169.         Unchecked_Convert_To (Standard_Integer, Relocate_Node (E2))));
  170.  
  171.    end Expand_Fpt_Attribute_RI;
  172.  
  173.    -----------------------------
  174.    -- Expand_Fpt_Attribute_RR --
  175.    -----------------------------
  176.  
  177.    --  The two arguments is converted to their root types to call the
  178.    --  appropriate runtime function, with the actual call being built
  179.    --  by Expand_Fpt_Attribute
  180.  
  181.    procedure Expand_Fpt_Attribute_RR (N : Node_Id) is
  182.       Loc : constant Source_Ptr := Sloc (N);
  183.       Rtp : constant Entity_Id  := Root_Type (Etype (N));
  184.       E1  : constant Node_Id    := First (Expressions (N));
  185.       E2  : constant Node_Id    := Next (E1);
  186.  
  187.    begin
  188.       Expand_Fpt_Attribute (N, New_List (
  189.         Unchecked_Convert_To (Rtp, Relocate_Node (E1)),
  190.         Unchecked_Convert_To (Rtp, Relocate_Node (E2))));
  191.  
  192.    end Expand_Fpt_Attribute_RR;
  193.  
  194.    ----------------------------------
  195.    -- Expand_N_Attribute_Reference --
  196.    ----------------------------------
  197.  
  198.    procedure Expand_N_Attribute_Reference (N : Node_Id) is
  199.       Loc   : constant Source_Ptr   := Sloc (N);
  200.       Typ   : constant Entity_Id    := Etype (N);
  201.       Pref  : constant Node_Id      := Prefix (N);
  202.       Exprs : constant List_Id      := Expressions (N);
  203.       Id    : constant Attribute_Id := Get_Attribute_Id (Attribute_Name (N));
  204.  
  205.    begin
  206.       case Id is
  207.  
  208.       --------------
  209.       -- Adjacent --
  210.       --------------
  211.  
  212.       --  Transforms 'Adjacent into a call to the floating-point attribute
  213.       --  function Adjacent in Fat_xxx (where xxx is the root type)
  214.  
  215.       when Attribute_Adjacent =>
  216.          Expand_Fpt_Attribute_RR (N);
  217.  
  218.       -------------
  219.       -- Address --
  220.       -------------
  221.  
  222.       --  If the prefix is a task or a task type, the useful address is that
  223.       --  of the procedure for the task body, i.e. the actual program unit.
  224.       --  We replace the orignal entity with that of the procedure.
  225.  
  226.       when Attribute_Address => Address : declare
  227.          Task_Proc : Entity_Id;
  228.  
  229.       begin
  230.          if Is_Task_Type (Etype (Pref)) then
  231.             Task_Proc := Next_Entity (Root_Type (Etype (Pref)));
  232.  
  233.             while Present (Task_Proc) loop
  234.                exit when Ekind (Task_Proc) = E_Procedure
  235.                  and then Etype (First_Formal (Task_Proc)) =
  236.                                   Corresponding_Record_Type (Etype (Pref));
  237.                Task_Proc := Next_Entity (Task_Proc);
  238.             end loop;
  239.  
  240.             if Present (Task_Proc) then
  241.                Set_Entity (Pref, Task_Proc);
  242.                Set_Etype  (Pref, Etype (Task_Proc));
  243.             end if;
  244.          end if;
  245.       end Address;
  246.  
  247.       ------------------
  248.       -- Body_Version --
  249.       ------------------
  250.  
  251.       --  A reference to x'Body_Version or x'Version is expanded to
  252.  
  253.       --    [xnn : Unsigned;
  254.       --     pragma Import (C, xnn, "uuuuT");
  255.       --     Get_Version_String (xnn)]
  256.  
  257.       --  where uuuu is the unit name (with dots replaced by double underscore
  258.       --  and T is B for the cases of Body_Version, or Version applied to a
  259.       --  subprogram acting as its own spec, and S for Version applied to a
  260.       --  subprogram spec or package. This sequence of code references the
  261.       --  the unsigned constant created in the main program by the binder.
  262.  
  263.       when Attribute_Body_Version | Attribute_Version => Version : declare
  264.          E    : constant Entity_Id :=
  265.                   Make_Defining_Identifier (Loc, New_Internal_Name ('X'));
  266.          Pent : constant Entity_Id := Entity (Pref);
  267.          S    : String_Id;
  268.          Spec : Node_Id;
  269.  
  270.       begin
  271.          --  Build required string constant
  272.  
  273.          Get_Name_String (Get_Unit_Name (Pent));
  274.  
  275.          Start_String;
  276.          for J in 1 .. Name_Len - 2 loop
  277.             if Name_Buffer (J) = '.' then
  278.                Store_String_Chars ("__");
  279.             else
  280.                Store_String_Char (Get_Char_Code (Name_Buffer (J)));
  281.             end if;
  282.          end loop;
  283.  
  284.          if Id = Attribute_Body_Version
  285.            or else
  286.              (Nkind (Declaration_Node (Pent)) in N_Subprogram_Specification
  287.                and then Nkind (Parent (Declaration_Node (Pent))) =
  288.                                                     N_Subprogram_Body
  289.                and then Acts_As_Spec (Parent (Declaration_Node (Pent))))
  290.          then
  291.             Store_String_Chars ("B");
  292.          else
  293.             Store_String_Chars ("S");
  294.          end if;
  295.  
  296.          S := End_String;
  297.  
  298.          --  Now we can do the replacement
  299.  
  300.          Rewrite_Substitute_Tree (N,
  301.            Make_Expression_Actions (Loc,
  302.              Actions => New_List (
  303.                Make_Object_Declaration (Loc,
  304.                  Defining_Identifier => E,
  305.                  Object_Definition   =>
  306.                    New_Occurrence_Of (RTE (RE_Unsigned), Loc)),
  307.  
  308.                Make_Pragma (Loc,
  309.                  Chars => Name_Import,
  310.                  Pragma_Argument_Associations => New_List (
  311.                    Make_Pragma_Argument_Association (Loc,
  312.                      Expression => Make_Identifier (Loc, Name_C)),
  313.  
  314.                    Make_Pragma_Argument_Association (Loc,
  315.                      Expression => New_Occurrence_Of (E, Loc)),
  316.  
  317.                    Make_Pragma_Argument_Association (Loc,
  318.                      Expression => Make_String_Literal (Loc, S))))),
  319.  
  320.              Expression =>
  321.                Make_Function_Call (Loc,
  322.                  Name => New_Reference_To (RTE (RE_Get_Version_String), Loc),
  323.                  Parameter_Associations => New_List (
  324.                    New_Occurrence_Of (E, Loc)))));
  325.  
  326.          Analyze (N);
  327.          Resolve (N, RTE (RE_Version_String));
  328.       end Version;
  329.  
  330.       -------------
  331.       -- Ceiling --
  332.       -------------
  333.  
  334.       --  Transforms 'Ceiling into a call to the floating-point attribute
  335.       --  function Ceiling in Fat_xxx (where xxx is the root type)
  336.  
  337.       when Attribute_Ceiling =>
  338.          Expand_Fpt_Attribute_R (N);
  339.  
  340.       --------------
  341.       -- Callable --
  342.       --------------
  343.  
  344.       --  Transforms 'Callable attribute into a call to the Callable function.
  345.  
  346.       when Attribute_Callable => Callable :
  347.       begin
  348.          Rewrite_Substitute_Tree (N,
  349.            Build_Call_With_Task (Pref, RTE (RE_Callable)));
  350.          Analyze (N);
  351.          Resolve (N, Standard_Boolean);
  352.       end Callable;
  353.  
  354.       -------------
  355.       -- Compose --
  356.       -------------
  357.  
  358.       --  Transforms 'Compose into a call to the floating-point attribute
  359.       --  function Compose in Fat_xxx (where xxx is the root type)
  360.  
  361.       --  Note: we strictly should have special code here to deal with the
  362.       --  case of absurdly negative arguments (less than Integer'First)
  363.       --  which will return a (signed) zero value, but it hardly seems
  364.       --  worth the effort. Absurdly large positive arguments will raise
  365.       --  constraint error which is fine.
  366.  
  367.       when Attribute_Compose =>
  368.          Expand_Fpt_Attribute_RI (N);
  369.  
  370.       -----------------
  371.       -- Constrained --
  372.       -----------------
  373.  
  374.       --  A very temporary implementation!
  375.  
  376.       when Attribute_Constrained =>
  377.          if Is_Entity_Name (Pref) then  Constrained :
  378.             declare
  379.                Ent  : constant Entity_Id   := Entity (Pref);
  380.                Kind : constant Entity_Kind := Ekind (Ent);
  381.                Res  : Boolean;
  382.  
  383.             begin
  384.                --  Always return False for the obsolescent case. This is a
  385.                --  temporary kludge to be fixed later ???
  386.  
  387.                if Is_Private_Type (Ent) then
  388.                   Res := False;
  389.  
  390.                --  If the prefix is not a variable, then definitely true
  391.  
  392.                elsif not Is_Variable (Pref) then
  393.                   Res := True;
  394.  
  395.                --  For a variable other than a procedure formal, we can
  396.                --  determine the result at compile time accurately.
  397.  
  398.                elsif Kind not in Formal_Kind then
  399.                   Res := Is_Constrained (Etype (Ent));
  400.  
  401.                --  For a procedure parameter, always return True, this is
  402.                --  a temporary kludge to be fixed later ???
  403.  
  404.                else
  405.                   Res := True;
  406.                end if;
  407.  
  408.                if Res then
  409.                   Rewrite_Substitute_Tree (N,
  410.                     New_Reference_To (Standard_True, Loc));
  411.                else
  412.                   Rewrite_Substitute_Tree (N,
  413.                     New_Reference_To (Standard_False, Loc));
  414.                end if;
  415.  
  416.                Analyze (N);
  417.                Resolve (N, Standard_Boolean);
  418.             end Constrained;
  419.  
  420.          else
  421.             if not Is_Variable (Pref)
  422.               or else Nkind (Pref) = N_Explicit_Dereference
  423.               or else Is_Constrained (Etype (Pref))
  424.             then
  425.                Rewrite_Substitute_Tree (N,
  426.                  New_Reference_To (Standard_True, Loc));
  427.             else
  428.                Rewrite_Substitute_Tree (N,
  429.                  New_Reference_To (Standard_False, Loc));
  430.             end if;
  431.  
  432.             Analyze (N);
  433.             Resolve (N, Standard_Boolean);
  434.          end if;
  435.  
  436.       ---------------
  437.       -- Copy_Sign --
  438.       ---------------
  439.  
  440.       --  Transforms 'Copy_Sign into a call to the floating-point attribute
  441.       --  function Copy_Sign in Fat_xxx (where xxx is the root type)
  442.  
  443.       when Attribute_Copy_Sign =>
  444.          Expand_Fpt_Attribute_RR (N);
  445.  
  446.       -----------
  447.       -- Count --
  448.       -----------
  449.  
  450.       --  Transforms 'Count attribute into a call to the Count function
  451.  
  452.       when Attribute_Count => Count :
  453.       declare
  454.          Entnam  : Node_Id;
  455.          Index   : Node_Id;
  456.          Call    : Node_Id;
  457.          Conctyp : Entity_Id;
  458.  
  459.       begin
  460.          --  This needs comments ???
  461.  
  462.          if Nkind (Pref) = N_Indexed_Component then
  463.             Entnam := Prefix (Pref);
  464.             Index := First (Expressions (Pref));
  465.          else
  466.             Entnam := Pref;
  467.             Index := Empty;
  468.          end if;
  469.  
  470.          --  Find the concurrent type in which this attribute is referenced
  471.          --  (there had better be one).
  472.  
  473.          Conctyp := Current_Scope;
  474.          while not Is_Concurrent_Type (Conctyp) loop
  475.             Conctyp := Scope (Conctyp);
  476.          end loop;
  477.  
  478.          if Is_Protected_Type (Conctyp) then
  479.             Call :=
  480.               Make_Function_Call (Loc,
  481.                 Name => New_Reference_To (RTE (RE_Protected_Count), Loc),
  482.                 Parameter_Associations => New_List (
  483.                   New_Reference_To (
  484.                     Object_Ref (Corresponding_Body (Parent (Conctyp))), Loc),
  485.                   Entry_Index_Expression
  486.                     (Loc, Entity (Entnam), Index, Scope (Entity (Entnam)))));
  487.          else
  488.             Call :=
  489.               Make_Function_Call (Loc,
  490.                 Name => New_Reference_To (RTE (RE_Task_Count), Loc),
  491.                 Parameter_Associations => New_List (
  492.                   Entry_Index_Expression
  493.                     (Loc, Entity (Entnam), Index, Scope (Entity (Entnam)))));
  494.          end if;
  495.  
  496.          --  The call returns type Natural but the context is universal integer
  497.          --  so any integer type is allowed. The attribute was already resolved
  498.          --  so its Etype is the required result type. If the base type of the
  499.          --  context type is other than Standard.Integer we put in a conversion
  500.          --  to the required type. This can be a normal typed conversion since
  501.          --  both input and output types of the conversion are integer types
  502.  
  503.          if Base_Type (Typ) /= Standard_Integer then
  504.             Rewrite_Substitute_Tree (N, Convert_To (Typ, Call));
  505.          else
  506.             Rewrite_Substitute_Tree (N, Call);
  507.          end if;
  508.  
  509.          Analyze (N);
  510.          Resolve (N, Typ);
  511.  
  512.       end Count;
  513.  
  514.       --------------
  515.       -- Enum_Rep --
  516.       --------------
  517.  
  518.       --  X'Enum_Rep (Y) expands to
  519.  
  520.       --    target-type (Y)
  521.  
  522.       --  This is simply a direct conversion from the enumeration type
  523.       --  to the target integer type, which is treated by Gigi as a normal
  524.       --  integer conversion, treating the enumeration type as an integer,
  525.       --  which is exactly what we want! We set Conversion_OK to make sure
  526.       --  that the analyzer does not complain about what otherwise would be
  527.       --  a clearly illegal conversion.
  528.  
  529.       when Attribute_Enum_Rep => Enum_Rep :
  530.       begin
  531.          Rewrite_Substitute_Tree (N,
  532.            Convert_To (Typ, Relocate_Node (First (Exprs))));
  533.          Set_Etype (N, Typ);
  534.          Set_Conversion_OK (N);
  535.          Analyze (N);
  536.          Resolve (N, Typ);
  537.       end Enum_Rep;
  538.  
  539.       --------------
  540.       -- Exponent --
  541.       --------------
  542.  
  543.       --  Transforms 'Exponent into a call to the floating-point attribute
  544.       --  function Exponent in Fat_xxx (where xxx is the root type)
  545.  
  546.       when Attribute_Exponent =>
  547.          Expand_Fpt_Attribute_R (N);
  548.  
  549.       -----------
  550.       -- First --
  551.       -----------
  552.  
  553.       when Attribute_First =>
  554.  
  555.          --  If the prefix type is a packed array type which already has a
  556.          --  Packed_Array_Type representation defined, then replace this
  557.          --  attribute with a direct reference to 'First of the appropriate
  558.          --  index subtype (since otherwise Gigi will try to give us the
  559.          --  value of 'First for this implementation type).
  560.  
  561.          if Is_Array_Type (Etype (Pref))
  562.            and then Present (Packed_Array_Type (Etype (Pref)))
  563.          then
  564.             Rewrite_Substitute_Tree (N,
  565.               Make_Attribute_Reference (Loc,
  566.                 Attribute_Name => Name_First,
  567.                 Prefix => New_Reference_To (Get_Index_Subtype (N), Loc)));
  568.             Analyze (N);
  569.             Resolve (N, Typ);
  570.          end if;
  571.  
  572.       ---------------
  573.       -- First_Bit --
  574.       ---------------
  575.  
  576.       --  We compute this if a component clause was present, otherwise
  577.       --  we leave the computation up to Gigi, since we don't know what
  578.       --  layout will be chosen.
  579.  
  580.       when Attribute_First_Bit => First_Bit :
  581.       declare
  582.          CE : constant Entity_Id := Entity (Selector_Name (Pref));
  583.  
  584.       begin
  585.          if Present (Component_Clause (CE)) then
  586.             Rewrite_Substitute_Tree (N,
  587.               Make_Integer_Literal (Loc,
  588.                 Component_First_Bit (CE) mod System_Storage_Unit));
  589.          end if;
  590.  
  591.          Analyze (N);
  592.          Resolve (N, Typ);
  593.       end First_Bit;
  594.  
  595.       -----------------
  596.       -- Fixed_Value --
  597.       -----------------
  598.  
  599.       --  fixtype'Fixed_Value (integer-value)
  600.  
  601.       --    is transformed into
  602.  
  603.       --  fixtype(integer-value)
  604.  
  605.       --  where the conversion has Conversion_OK set, so that it will be
  606.       --  treated as a direct numeric conversion by Gigi, which is what we
  607.       --  want (i.e. it will not be further modified by analysis).
  608.  
  609.       when Attribute_Fixed_Value => Fixed_Value :
  610.       begin
  611.          Rewrite_Substitute_Tree (N,
  612.            Convert_To (Base_Type (Entity (Pref)),
  613.                        Relocate_Node (First (Exprs))));
  614.  
  615.          Set_Etype (N, Typ);
  616.          Set_Conversion_OK (N);
  617.          Analyze (N);
  618.          Resolve (N, Typ);
  619.       end Fixed_Value;
  620.  
  621.       -----------
  622.       -- Floor --
  623.       -----------
  624.  
  625.       --  Transforms 'Floor into a call to the floating-point attribute
  626.       --  function Floor in Fat_xxx (where xxx is the root type)
  627.  
  628.       when Attribute_Floor =>
  629.          Expand_Fpt_Attribute_R (N);
  630.  
  631.       ----------
  632.       -- Fore --
  633.       ----------
  634.  
  635.       --  For the fixed-point type Typ:
  636.  
  637.       --    Typ'Fore
  638.  
  639.       --  expands into
  640.  
  641.       --    Result_Type (System.Fore (Long_Long_Float (Type'First)),
  642.       --                              Long_Long_Float (Type'Last))
  643.  
  644.       --  Note that we know that the type is a non-static subtype, or Fore
  645.       --  would have itself been computed dynamically in Eval_Attribute.
  646.  
  647.       when Attribute_Fore => Fore :
  648.       declare
  649.          Ptyp : constant Entity_Id := Etype (Pref);
  650.  
  651.       begin
  652.          Rewrite_Substitute_Tree (N,
  653.            Convert_To (Typ,
  654.              Make_Function_Call (Loc,
  655.                Name => New_Reference_To (RTE (RE_Fore), Loc),
  656.  
  657.                Parameter_Associations => New_List (
  658.                  Convert_To (Standard_Long_Long_Float,
  659.                    Make_Attribute_Reference (Loc,
  660.                      Prefix => New_Reference_To (Ptyp, Loc),
  661.                      Attribute_Name => Name_First)),
  662.  
  663.                  Convert_To (Standard_Long_Long_Float,
  664.                    Make_Attribute_Reference (Loc,
  665.                      Prefix => New_Reference_To (Ptyp, Loc),
  666.                      Attribute_Name => Name_Last))))));
  667.  
  668.          Analyze (N);
  669.          Resolve (N, Typ);
  670.       end Fore;
  671.  
  672.       --------------
  673.       -- Fraction --
  674.       --------------
  675.  
  676.       --  Transforms 'Fraction into a call to the floating-point attribute
  677.       --  function Fraction in Fat_xxx (where xxx is the root type)
  678.  
  679.       when Attribute_Fraction =>
  680.          Expand_Fpt_Attribute_R (N);
  681.  
  682.       -----------
  683.       -- Image --
  684.       -----------
  685.  
  686.       --  For types other than user defined enumeration types,
  687.       --  typ'Image (Val) expands into:
  688.  
  689.       --     Image_xx (tp (Val) [, pm])
  690.  
  691.       --  The name xx and type conversion tp (Val) (called tv below) depend on
  692.       --  the root type of Val. The argument pm is an extra type dependent
  693.       --  parameter only used in some cases as follows:
  694.  
  695.       --    For types whose root type is Character
  696.       --      xx = Character
  697.       --      tv = Character (Val)
  698.  
  699.       --    For types whose root type is Boolean
  700.       --      xx = Boolean
  701.       --      tv = Boolean (Val)
  702.  
  703.       --    For signed integer types with size <= Integer'Size
  704.       --      xx = Integer
  705.       --      tv = Integer (Val)
  706.  
  707.       --    For other signed integer types
  708.       --      xx = Long_Long_Integer
  709.       --      tv = Long_Long_Integer (Val)
  710.  
  711.       --    For modular types with modulus <= System.Unsigned_Types.Unsigned
  712.       --      xx = Unsigned
  713.       --      tv = System.Unsigned_Types.Unsigned (Val)
  714.  
  715.       --    For other modular integer types
  716.       --      xx = Long_Long_Unsigned
  717.       --      tv = System.Unsigned_Types.Long_Long_Unsigned (Val)
  718.  
  719.       --    For types whose root type is Wide_Character
  720.       --      xx = Wide_Character
  721.       --      tv = Wide_Character (Val)
  722.       --      pm = Wide_Character_Encoding_Method
  723.  
  724.       --    For floating-point types
  725.       --      xx = Floating_Point
  726.       --      tv = Long_Long_Float (Val)
  727.       --      pm = typ'Digits
  728.  
  729.       --    For ordinary fixed-point types
  730.       --      xx = Ordinary_Fixed_Point
  731.       --      tv = Long_Long_Float (Val)
  732.       --      pm = typ'Aft
  733.  
  734.       --    For decimal fixed-point types with size = Integer'Size
  735.       --      xx = Decimal
  736.       --      tv = Integer (Val)
  737.       --      pm = typ'Scale
  738.  
  739.       --    For decimal fixed-point types with size > Integer'Size
  740.       --      xx = Long_Long_Decimal
  741.       --      tv = Long_Long_Integer (Val)
  742.       --      pm = typ'Scale
  743.  
  744.       --  For enumeration types other than those derived from types Boolean,
  745.       --  Character, and Wide_Character in Standard, typ'Image (X) expands to:
  746.  
  747.       --    Table (Enum'Pos (X)).all
  748.  
  749.       --  where table is the special table declared in the front end and
  750.       --  constructed by special code in Gigi.
  751.  
  752.       when Attribute_Image => Image :
  753.       declare
  754.          Ptyp    : constant Entity_Id := Entity (Pref);
  755.          Rtyp    : constant Entity_Id := Root_Type (Ptyp);
  756.          Expr    : constant Node_Id   := Relocate_Node (First (Exprs));
  757.          Imid    : RE_Id;
  758.          Tent    : Entity_Id;
  759.          Arglist : List_Id;
  760.          Snn     : Entity_Id;
  761.  
  762.       begin
  763.          if Rtyp = Standard_Boolean then
  764.             Imid := RE_Image_Boolean;
  765.             Tent := Rtyp;
  766.  
  767.          elsif Rtyp = Standard_Character then
  768.             Imid := RE_Image_Character;
  769.             Tent := Rtyp;
  770.  
  771.          elsif Rtyp = Standard_Wide_Character then
  772.             Imid := RE_Image_Wide_Character;
  773.             Tent := Rtyp;
  774.  
  775.          elsif Is_Signed_Integer_Type (Rtyp) then
  776.             if Esize (Rtyp) <= Esize (Standard_Integer) then
  777.                Imid := RE_Image_Integer;
  778.                Tent := Standard_Integer;
  779.             else
  780.                Imid := RE_Image_Long_Long_Integer;
  781.                Tent := Standard_Long_Long_Integer;
  782.             end if;
  783.  
  784.          elsif Is_Modular_Integer_Type (Rtyp) then
  785.             if Modulus (Rtyp) <= Modulus (RTE (RE_Unsigned)) then
  786.                Imid := RE_Image_Unsigned;
  787.                Tent := RTE (RE_Unsigned);
  788.             else
  789.                Imid := RE_Image_Long_Long_Unsigned;
  790.                Tent := RTE (RE_Long_Long_Unsigned);
  791.             end if;
  792.  
  793.          elsif Is_Decimal_Fixed_Point_Type (Rtyp) then
  794.             if UI_To_Int (Esize (Rtyp)) <= Standard_Integer_Size then
  795.                Imid := RE_Image_Decimal;
  796.                Tent := Standard_Integer;
  797.             else
  798.                Imid := RE_Image_Long_Long_Decimal;
  799.                Tent := Standard_Long_Long_Integer;
  800.             end if;
  801.  
  802.          elsif Is_Ordinary_Fixed_Point_Type (Rtyp) then
  803.             Imid := RE_Image_Ordinary_Fixed_Point;
  804.             Tent := Standard_Long_Long_Float;
  805.  
  806.          elsif Is_Floating_Point_Type (Rtyp) then
  807.             Imid := RE_Image_Floating_Point;
  808.             Tent := Standard_Long_Long_Float;
  809.  
  810.          --  Only other possibility is user defined enumeration type
  811.  
  812.          else
  813.             Rewrite_Substitute_Tree (N,
  814.               Make_Explicit_Dereference (Loc,
  815.                 Prefix =>
  816.                   Make_Indexed_Component (Loc,
  817.                     Prefix =>
  818.                       New_Reference_To (Lit_Name_Table (Entity (Pref)), Loc),
  819.  
  820.                     Expressions => New_List (
  821.                       Make_Attribute_Reference (Loc,
  822.                         Prefix         => Pref,
  823.                         Attribute_Name => Name_Pos,
  824.                         Expressions    => New_List (Expr))))));
  825.             Analyze (N);
  826.             Resolve (N, Standard_String);
  827.             return;
  828.  
  829.          end if;
  830.  
  831.          --  If we fall through, we have one of the cases that is handled by
  832.          --  calling one of the System.Img_xx routines.
  833.  
  834.          Arglist := New_List (Convert_To (Tent, Relocate_Node (Expr)));
  835.  
  836.          --  For floating-point types, append Digits argument
  837.  
  838.          if Is_Floating_Point_Type (Rtyp) then
  839.             Append_To (Arglist,
  840.               Make_Attribute_Reference (Loc,
  841.                 Prefix         => New_Reference_To (Ptyp, Loc),
  842.                 Attribute_Name => Name_Digits));
  843.  
  844.          --  For ordinary fixed-point types, append Aft parameter
  845.  
  846.          elsif Is_Ordinary_Fixed_Point_Type (Rtyp) then
  847.             Append_To (Arglist,
  848.               Make_Attribute_Reference (Loc,
  849.                 Prefix         => New_Reference_To (Ptyp, Loc),
  850.                 Attribute_Name => Name_Aft));
  851.  
  852.          --  For wide character, append encoding method
  853.  
  854.          elsif Rtyp = Standard_Wide_Character then
  855.             Append_To (Arglist,
  856.               Make_Integer_Literal (Loc,
  857.                 Intval =>
  858.                   UI_From_Int (Int (Wide_Character_Encoding_Method))));
  859.  
  860.          --  For decimal, append Scale
  861.  
  862.          elsif Is_Decimal_Fixed_Point_Type (Rtyp) then
  863.             Append_To (Arglist,
  864.               Make_Attribute_Reference (Loc,
  865.                 Prefix => New_Reference_To (Ptyp, Loc),
  866.                 Attribute_Name => Name_Scale));
  867.          end if;
  868.  
  869.          Rewrite_Substitute_Tree (N,
  870.            Make_Function_Call (Loc,
  871.              Name => New_Reference_To (RTE (Imid), Loc),
  872.              Parameter_Associations => Arglist));
  873.  
  874.          Analyze (N);
  875.          Resolve (N, Standard_String);
  876.       end Image;
  877.  
  878.       ---------
  879.       -- Img --
  880.       ---------
  881.  
  882.       --  X'Img is expanded to typ'Image (X), where typ is the type of X
  883.  
  884.       when Attribute_Img => Img :
  885.       begin
  886.          Rewrite_Substitute_Tree (N,
  887.            Make_Attribute_Reference (Loc,
  888.              Prefix => New_Reference_To (Etype (Pref), Loc),
  889.              Attribute_Name => Name_Image,
  890.              Expressions => New_List (Relocate_Node (Pref))));
  891.  
  892.          Analyze (N);
  893.          Resolve (N, Standard_String);
  894.       end Img;
  895.  
  896.       -------------------
  897.       -- Integer_Value --
  898.       -------------------
  899.  
  900.       --  inttype'Fixed_Value (fixed-value)
  901.  
  902.       --    is transformed into
  903.  
  904.       --  inttype(integer-value))
  905.       --  where the conversion has Conversion_OK set, so that it will be
  906.       --  treated as a direct numeric conversion by Gigi, which is what we
  907.       --  want (i.e. it will not be further modified by analysis).
  908.  
  909.       when Attribute_Integer_Value => Integer_Value :
  910.       begin
  911.          Rewrite_Substitute_Tree (N,
  912.            Convert_To (Base_Type (Entity (Pref)),
  913.                        Relocate_Node (First (Exprs))));
  914.  
  915.          Set_Etype (N, Typ);
  916.          Set_Conversion_OK (N);
  917.          Analyze (N);
  918.          Resolve (N, Typ);
  919.       end Integer_Value;
  920.  
  921.       ----------
  922.       -- Last --
  923.       ----------
  924.  
  925.       when Attribute_Last =>
  926.  
  927.          --  If the prefix type is a packed array type which already has a
  928.          --  Packed_Array_Type representation defined, then replace this
  929.          --  attribute with a direct reference to 'Last of the appropriate
  930.          --  index subtype (since otherwise Gigi will try to give us the
  931.          --  value of 'First for this implementation type).
  932.  
  933.          if Is_Array_Type (Etype (Pref))
  934.            and then Present (Packed_Array_Type (Etype (Pref)))
  935.          then
  936.             Rewrite_Substitute_Tree (N,
  937.               Make_Attribute_Reference (Loc,
  938.                 Attribute_Name => Name_Last,
  939.                 Prefix => New_Reference_To (Get_Index_Subtype (N), Loc)));
  940.             Analyze (N);
  941.             Resolve (N, Typ);
  942.          end if;
  943.  
  944.       --------------
  945.       -- Last_Bit --
  946.       --------------
  947.  
  948.       when Attribute_Last_Bit => Last_Bit :
  949.       declare
  950.          CE : constant Entity_Id := Entity (Selector_Name (Pref));
  951.  
  952.       begin
  953.          if Present (Component_Clause (CE)) then
  954.             Rewrite_Substitute_Tree (N,
  955.               Make_Integer_Literal (Loc,
  956.                Intval => (Component_First_Bit (CE) mod System_Storage_Unit)
  957.                                 + Esize (CE) - 1));
  958.          end if;
  959.  
  960.          Analyze (N);
  961.          Resolve (N, Typ);
  962.       end Last_Bit;
  963.  
  964.       ------------------
  965.       -- Leading_Part --
  966.       ------------------
  967.  
  968.       --  Transforms 'Leading_Part into a call to the floating-point attribute
  969.       --  function Leading_Part in Fat_xxx (where xxx is the root type)
  970.  
  971.       --  Note: strictly, we should have special case code to deal with
  972.       --  absurdly large positive arguments (greater than Integer'Last),
  973.       --  which result in returning the first argument unchanged, but it
  974.       --  hardly seems worth the effort. We raise constraint error for
  975.       --  absurdly negative arguments which is fine.
  976.  
  977.       when Attribute_Leading_Part =>
  978.          Expand_Fpt_Attribute_RI (N);
  979.  
  980.       ------------
  981.       -- Length --
  982.       ------------
  983.  
  984.       when Attribute_Length =>
  985.  
  986.          --  If the prefix type is a packed array type which already has a
  987.          --  Packed_Array_Type representation defined, then replace this
  988.          --  attribute with a direct reference to 'Range_Length of the
  989.          --  appropriate index subtype (since otherwise Gigi will try to
  990.          --  give us the value of 'First for this implementation type).
  991.  
  992.          if Is_Array_Type (Etype (Pref))
  993.            and then Present (Packed_Array_Type (Etype (Pref)))
  994.          then
  995.             Rewrite_Substitute_Tree (N,
  996.               Make_Attribute_Reference (Loc,
  997.                 Attribute_Name => Name_Range_Length,
  998.                 Prefix => New_Reference_To (Get_Index_Subtype (N), Loc)));
  999.             Analyze (N);
  1000.             Resolve (N, Typ);
  1001.          end if;
  1002.  
  1003.       -------------
  1004.       -- Machine --
  1005.       -------------
  1006.  
  1007.       --  Transforms 'Machine into a call to the floating-point attribute
  1008.       --  function Machine in Fat_xxx (where xxx is the root type)
  1009.  
  1010.       when Attribute_Machine =>
  1011.          Expand_Fpt_Attribute_R (N);
  1012.  
  1013.       -----------
  1014.       -- Model --
  1015.       -----------
  1016.  
  1017.       --  Transforms 'Model into a call to the floating-point attribute
  1018.       --  function Model in Fat_xxx (where xxx is the root type)
  1019.  
  1020.       when Attribute_Model =>
  1021.          Expand_Fpt_Attribute_R (N);
  1022.  
  1023.       ---------
  1024.       -- Pos --
  1025.       ---------
  1026.  
  1027.       --  For enumeration types with a standard representation, and for all
  1028.       --  other types, Pos is handled by Gigi. For enumeration types with
  1029.       --  a non-standard representation we call the _Rep_To_Pos function
  1030.       --  created when the type was frozen.
  1031.  
  1032.       when Attribute_Pos => Pos :
  1033.       declare
  1034.          Etyp : constant Entity_Id := Base_Type (Entity (Pref));
  1035.  
  1036.       begin
  1037.          if Is_Enumeration_Type (Etyp)
  1038.            and then Present (Enum_Pos_To_Rep (Etyp))
  1039.          then
  1040.             Rewrite_Substitute_Tree (N,
  1041.               Convert_To (Typ,
  1042.                 Make_Function_Call (Loc,
  1043.                   Name =>
  1044.                     New_Reference_To (TSS (Etyp, Name_uRep_To_Pos), Loc),
  1045.                   Parameter_Associations => New_List (
  1046.                     Relocate_Node (First (Exprs))))));
  1047.  
  1048.             Analyze (N);
  1049.             Resolve (N, Typ);
  1050.          end if;
  1051.  
  1052.       end Pos;
  1053.  
  1054.       --------------
  1055.       -- Position --
  1056.       --------------
  1057.  
  1058.       --  We compute this if a component clause was present, otherwise
  1059.       --  we leave the computation up to Gigi, since we don't know what
  1060.       --  layout will be chosen.
  1061.  
  1062.       when Attribute_Position => Position :
  1063.       declare
  1064.          CE : constant Entity_Id := Entity (Selector_Name (Pref));
  1065.  
  1066.       begin
  1067.          if Present (Component_Clause (CE)) then
  1068.             Rewrite_Substitute_Tree (N,
  1069.               Make_Integer_Literal (Loc,
  1070.                 Intval => Component_First_Bit (CE) / System_Storage_Unit));
  1071.             Analyze (N);
  1072.             Resolve (N, Typ);
  1073.          end if;
  1074.       end Position;
  1075.  
  1076.       ----------
  1077.       -- Pred --
  1078.       ----------
  1079.  
  1080.       --  1. Deal with enumeration types with holes
  1081.       --  2. For floating-point, generate call to attribute function
  1082.       --  3. For other cases, deal with constraint checking
  1083.  
  1084.       when Attribute_Pred => Pred :
  1085.       declare
  1086.          Ptyp : constant Entity_Id := Base_Type (Etype (Pref));
  1087.  
  1088.       begin
  1089.          --  For enumeration types with non-standard representations, we
  1090.          --  expand typ'Pred (x) into
  1091.  
  1092.          --    Pos_To_Rep (Rep_To_Pos (x) - 1)
  1093.  
  1094.          if Is_Enumeration_Type (Ptyp)
  1095.            and then Present (Enum_Pos_To_Rep (Ptyp))
  1096.          then
  1097.             Rewrite_Substitute_Tree (N,
  1098.               Make_Indexed_Component (Loc,
  1099.                 Prefix => New_Reference_To (Enum_Pos_To_Rep (Ptyp), Loc),
  1100.                 Expressions => New_List (
  1101.                   Make_Op_Subtract (Loc,
  1102.                     Left_Opnd =>
  1103.                       Make_Function_Call (Loc,
  1104.                         Name =>
  1105.                           New_Reference_To (TSS (Ptyp, Name_uRep_To_Pos), Loc),
  1106.                         Parameter_Associations => Exprs),
  1107.                     Right_Opnd => Make_Integer_Literal (Loc, Uint_1)))));
  1108.  
  1109.          --  For floating-point, we transform 'Pred into a call to the Pred
  1110.          --  floating-point attribute function in Fat_xxx (xxx is root type)
  1111.  
  1112.          elsif Is_Floating_Point_Type (Ptyp) then
  1113.             Expand_Fpt_Attribute_R (N);
  1114.  
  1115.          --  For other types, if range checking is enabled, then we convert
  1116.          --  typ'Pred (exp) into:
  1117.  
  1118.          --    if exp = typ'Base'First then
  1119.          --       raise constraint_error
  1120.          --    else
  1121.          --       typ'Pred (exp)
  1122.          --    end;
  1123.  
  1124.          --  with the overflow check bit off in the new Pred attribute
  1125.  
  1126.          elsif Do_Overflow_Check (N) then
  1127.             Expand_Pred_Succ (N);
  1128.  
  1129.          --  Otherwise nothing to do
  1130.  
  1131.          else
  1132.             return;
  1133.          end if;
  1134.  
  1135.          Analyze (N);
  1136.          Resolve (N, Typ);
  1137.       end Pred;
  1138.  
  1139.       ---------------
  1140.       -- Remainder --
  1141.       ---------------
  1142.  
  1143.       --  Transforms 'Remainder into a call to the floating-point attribute
  1144.       --  function Remainder in Fat_xxx (where xxx is the root type)
  1145.  
  1146.       when Attribute_Remainder =>
  1147.          Expand_Fpt_Attribute_RR (N);
  1148.  
  1149.       -----------
  1150.       -- Round --
  1151.       -----------
  1152.  
  1153.       --  A round attribute is replaced by a divide, multiply or type
  1154.       --  conversion node (depending on its operand), with the appropriate
  1155.       --  result type set, and the Rounded_Result flag set.
  1156.  
  1157.       when Attribute_Round => Round :
  1158.       declare
  1159.          Expr : constant Node_Id := Relocate_Node (First (Exprs));
  1160.          Typ  : constant Entity_Id := Etype (N);
  1161.          Rep  : Node_Id;
  1162.  
  1163.       begin
  1164.          if Nkind (Expr) = N_Op_Divide then
  1165.             Rep :=
  1166.               Make_Op_Divide (Loc,
  1167.                 Left_Opnd  => Left_Opnd (Expr),
  1168.                 Right_Opnd => Right_Opnd (Expr));
  1169.  
  1170.          elsif Nkind (Expr) = N_Op_Multiply then
  1171.             Rep :=
  1172.               Make_Op_Multiply (Loc,
  1173.                 Left_Opnd  => Left_Opnd (Expr),
  1174.                 Right_Opnd => Right_Opnd (Expr));
  1175.          else
  1176.             Rep := Convert_To (Typ, Expr);
  1177.          end if;
  1178.  
  1179.          Set_Rounded_Result (N);
  1180.          Analyze (N);
  1181.          Resolve (N, Typ);
  1182.  
  1183.       end Round;
  1184.  
  1185.       --------------
  1186.       -- Rounding --
  1187.       --------------
  1188.  
  1189.       --  Transforms 'Rounding into a call to the floating-point attribute
  1190.       --  function Rounding in Fat_xxx (where xxx is the root type)
  1191.  
  1192.       when Attribute_Rounding =>
  1193.          Expand_Fpt_Attribute_R (N);
  1194.  
  1195.       -------------
  1196.       -- Scaling --
  1197.       -------------
  1198.  
  1199.       --  Transforms 'Scaling into a call to the floating-point attribute
  1200.       --  function Scaling in Fat_xxx (where xxx is the root type)
  1201.  
  1202.       when Attribute_Scaling =>
  1203.          Expand_Fpt_Attribute_R (N);
  1204.  
  1205.       ----------
  1206.       -- Size --
  1207.       ----------
  1208.  
  1209.       --  Transforms X'Size into a call to the primitive operation _Size.
  1210.       --  for class-wide types.
  1211.  
  1212.       --  For other types, nothing to do, to be handled by Gigi
  1213.  
  1214.       when Attribute_Size => Size :
  1215.       declare
  1216.          Ptyp     : constant Entity_Id := Etype (Pref);
  1217.          New_Node : Node_Id;
  1218.  
  1219.       begin
  1220.          if Is_Class_Wide_Type (Ptyp) then
  1221.             New_Node :=
  1222.               Make_Function_Call (Loc,
  1223.                 Name => New_Reference_To
  1224.                   (Find_Prim_Op (Ptyp, Name_uSize), Loc),
  1225.                 Parameter_Associations => New_List (Pref));
  1226.  
  1227.             if Typ /= Universal_Integer then
  1228.                New_Node := Convert_To (Typ, New_Node);
  1229.             end if;
  1230.  
  1231.             Rewrite_Substitute_Tree (N, New_Node);
  1232.             Analyze (N);
  1233.             Resolve (N, Typ);
  1234.          end if;
  1235.       end Size;
  1236.  
  1237.       ------------------
  1238.       -- Storage_Pool --
  1239.       ------------------
  1240.  
  1241.       when Attribute_Storage_Pool => Storage_Pool :
  1242.       declare
  1243.          Ptyp : constant Entity_Id := Base_Type (Entity (Pref));
  1244.  
  1245.       begin
  1246.          Rewrite_Substitute_Tree (N,
  1247.            New_Reference_To (Associated_Storage_Pool (Ptyp), Loc));
  1248.  
  1249.          Analyze (N);
  1250.          Resolve (N, Typ);
  1251.       end Storage_Pool;
  1252.  
  1253.       ------------------
  1254.       -- Storage_Size --
  1255.       ------------------
  1256.  
  1257.       --  The case of access types results in a value of zero for the case
  1258.       --  where no storage size attribute clause has been given. If a storage
  1259.       --  size has been given, then the attribute is converted to a reference
  1260.       --  to the variable used to hold this value.
  1261.  
  1262.       --  The case of a task type (an obsolescent feature) is handled the
  1263.       --  same way, seems as reasonable as anything, and it is what the
  1264.       --  ACVC tests (e.g. CD1009K) seem to expect.
  1265.  
  1266.       --  For the case of a task object, if there is no pragma Storage_Size,
  1267.       --  then we also return the literal zero, otherwise if there is a
  1268.       --  Storage_Size pragma, then we replace the attribute reference by
  1269.       --  the expression:
  1270.  
  1271.       --    Universal_Integer (taskV!(name)._Size)
  1272.  
  1273.       --  to get the Size field of the record object associated with the task
  1274.  
  1275.       when Attribute_Storage_Size => Storage_Size :
  1276.       declare
  1277.          Ptyp : constant Entity_Id := Etype (Pref);
  1278.  
  1279.       begin
  1280.          if Is_Access_Type (Ptyp)
  1281.            or else (Is_Entity_Name (Pref)
  1282.                      and then Is_Task_Type (Entity (Pref)))
  1283.          then
  1284.             if not Present (Storage_Size_Variable (Ptyp)) then
  1285.                Rewrite_Substitute_Tree (N,
  1286.                  Make_Integer_Literal (Loc, Uint_0));
  1287.             else
  1288.                Rewrite_Substitute_Tree (N,
  1289.                  Convert_To (Typ,
  1290.                    New_Reference_To (Storage_Size_Variable (Ptyp), Loc)));
  1291.             end if;
  1292.  
  1293.             Analyze (N);
  1294.             Resolve (N, Typ);
  1295.  
  1296.          --  Task object case
  1297.  
  1298.          else
  1299.             pragma Assert (Is_Task_Type (Ptyp));
  1300.  
  1301.             declare
  1302.                Rtyp : constant Entity_Id :=
  1303.                  Corresponding_Record_Type (Ptyp);
  1304.  
  1305.             begin
  1306.                --  Task object which has Storage_Size pragma
  1307.  
  1308.                if Chars (Last_Entity (Rtyp)) = Name_uSize then
  1309.  
  1310.                   Rewrite_Substitute_Tree (N,
  1311.                     Convert_To (Universal_Integer,
  1312.                       Make_Selected_Component (Loc,
  1313.                         Prefix =>
  1314.                           Unchecked_Convert_To (
  1315.                             Corresponding_Record_Type (Ptyp),
  1316.                             New_Copy_Tree (Pref)),
  1317.                         Selector_Name =>
  1318.                           Make_Identifier (Loc, Name_uSize))));
  1319.  
  1320.                --  Task object not having Storage_Size pragma
  1321.  
  1322.                else
  1323.                   Rewrite_Substitute_Tree (N,
  1324.                     Make_Integer_Literal (Loc, Uint_0));
  1325.                end if;
  1326.             end;
  1327.  
  1328.             Analyze (N);
  1329.             Resolve (N, Typ);
  1330.          end if;
  1331.  
  1332.       end Storage_Size;
  1333.  
  1334.       ----------
  1335.       -- Succ --
  1336.       ----------
  1337.  
  1338.       --  1. Deal with enumeration types with holes
  1339.       --  2. For floating-point, generate call to attribute function
  1340.       --  3. For other cases, deal with constraint checking
  1341.  
  1342.       when Attribute_Succ => Succ :
  1343.       declare
  1344.          Ptyp : constant Entity_Id := Base_Type (Etype (Pref));
  1345.  
  1346.       begin
  1347.          --  For enumeration types with non-standard representations, we
  1348.          --  expand typ'Succ (x) into
  1349.  
  1350.          --    Pos_To_Rep (Rep_To_Pos (x) + 1)
  1351.  
  1352.          if Is_Enumeration_Type (Ptyp)
  1353.            and then Present (Enum_Pos_To_Rep (Ptyp))
  1354.          then
  1355.             Rewrite_Substitute_Tree (N,
  1356.               Make_Indexed_Component (Loc,
  1357.                 Prefix => New_Reference_To (Enum_Pos_To_Rep (Ptyp), Loc),
  1358.                 Expressions => New_List (
  1359.                   Make_Op_Add (Loc,
  1360.                     Left_Opnd =>
  1361.                       Make_Function_Call (Loc,
  1362.                         Name =>
  1363.                           New_Reference_To (TSS (Ptyp, Name_uRep_To_Pos), Loc),
  1364.                         Parameter_Associations => Exprs),
  1365.                     Right_Opnd => Make_Integer_Literal (Loc, Uint_1)))));
  1366.  
  1367.          --  For floating-point, we transform 'Succ into a call to the Succ
  1368.          --  floating-point attribute function in Fat_xxx (xxx is root type)
  1369.  
  1370.          elsif Is_Floating_Point_Type (Ptyp) then
  1371.             Expand_Fpt_Attribute_R (N);
  1372.  
  1373.          --  For other types, if range checking is enabled, then we convert
  1374.          --  typ'Succ (exp) into:
  1375.  
  1376.          --    if exp = typ'Base'Last then
  1377.          --       raise constraint_error
  1378.          --    else
  1379.          --       typ'Succ (exp)
  1380.          --    end;
  1381.  
  1382.          --  with the overflow check bit off in the new Succ attribute
  1383.  
  1384.          elsif Do_Overflow_Check (N) then
  1385.             Expand_Pred_Succ (N);
  1386.  
  1387.          --  Otherwise nothing to do
  1388.  
  1389.          else
  1390.             return;
  1391.          end if;
  1392.  
  1393.          Analyze (N);
  1394.          Resolve (N, Typ);
  1395.       end Succ;
  1396.  
  1397.       ---------
  1398.       -- Tag --
  1399.       ---------
  1400.  
  1401.       --  Transforms X'Tag into a direct reference to the tag of X
  1402.  
  1403.       when Attribute_Tag => Tag :
  1404.       declare
  1405.          Ttyp           : Entity_Id;
  1406.          Prefix_Is_Type : Boolean;
  1407.  
  1408.       begin
  1409.          if Is_Entity_Name (Pref) and then Is_Type (Entity (Pref)) then
  1410.             Ttyp := Entity (Pref);
  1411.             Prefix_Is_Type := True;
  1412.          else
  1413.             Ttyp := Etype (Pref);
  1414.             Prefix_Is_Type := False;
  1415.          end if;
  1416.  
  1417.          if Is_Class_Wide_Type (Ttyp) then
  1418.             Ttyp := Root_Type (Ttyp);
  1419.          end if;
  1420.  
  1421.          Ttyp := Underlying_Type (Ttyp);
  1422.  
  1423.          if Prefix_Is_Type then
  1424.             Rewrite_Substitute_Tree (N,
  1425.               Unchecked_Convert_To (RTE (RE_Tag),
  1426.                 New_Reference_To (Access_Disp_Table (Ttyp), Loc)));
  1427.  
  1428.          else
  1429.             Rewrite_Substitute_Tree (N,
  1430.               Make_Selected_Component (Loc,
  1431.                 Prefix => Relocate_Node (Pref),
  1432.                 Selector_Name =>
  1433.                   New_Reference_To (Tag_Component (Ttyp), Loc)));
  1434.          end if;
  1435.  
  1436.          Analyze (N);
  1437.          Resolve (N, RTE (RE_Tag));
  1438.       end Tag;
  1439.  
  1440.       ----------------
  1441.       -- Terminated --
  1442.       ----------------
  1443.  
  1444.       --  Transforms 'Terminated attribute into a call to Terminated function.
  1445.  
  1446.       when Attribute_Terminated => Terminated :
  1447.       begin
  1448.          Rewrite_Substitute_Tree (N,
  1449.            Build_Call_With_Task (Pref, RTE (RE_Terminated)));
  1450.          Analyze (N);
  1451.          Resolve (N, Standard_Boolean);
  1452.       end Terminated;
  1453.  
  1454.       ----------------
  1455.       -- Truncation --
  1456.       ----------------
  1457.  
  1458.       --  Transforms 'Truncation into a call to the floating-point attribute
  1459.       --  function Truncation in Fat_xxx (where xxx is the root type)
  1460.  
  1461.       when Attribute_Truncation =>
  1462.          Expand_Fpt_Attribute_R (N);
  1463.  
  1464.       -----------------------
  1465.       -- Unbiased_Rounding --
  1466.       -----------------------
  1467.  
  1468.       --  Transforms 'Unbiased_Rounding into a call to the floating-point
  1469.       --  attribute function Unbiased_Rounding in Fat_xxx (where xxx is the
  1470.       --  root type)
  1471.  
  1472.       when Attribute_Unbiased_Rounding =>
  1473.          Expand_Fpt_Attribute_R (N);
  1474.  
  1475.       ---------
  1476.       -- Val --
  1477.       ---------
  1478.  
  1479.       --  For enumeration types with a standard representation, and for all
  1480.       --  other types, Val is handled by Gigi. For enumeration types with
  1481.       --  a non-standard representation we use the _Pos_To_Rep array that
  1482.       --  was created when the type was frozen.
  1483.  
  1484.       when Attribute_Val => Val :
  1485.       declare
  1486.          Etyp : constant Entity_Id := Base_Type (Entity (Pref));
  1487.  
  1488.       begin
  1489.          if Is_Enumeration_Type (Etyp)
  1490.            and then Present (Enum_Pos_To_Rep (Etyp))
  1491.          then
  1492.             Rewrite_Substitute_Tree (N,
  1493.               Make_Indexed_Component (Loc,
  1494.                 Prefix => New_Reference_To (Enum_Pos_To_Rep (Etyp), Loc),
  1495.                 Expressions => New_List (Relocate_Node (First (Exprs)))));
  1496.  
  1497.             Analyze (N);
  1498.             Resolve (N, Typ);
  1499.          end if;
  1500.       end Val;
  1501.  
  1502.       -----------
  1503.       -- Valid --
  1504.       -----------
  1505.  
  1506.       --  For enumeration types with holes, the Pos value constructed by the
  1507.       --  Enum_Rep_To_Pos function built in Exp_Ch3 returns minus one for an
  1508.       --  invalid value, and the non-negative pos value for a valid value, so
  1509.       --  the expansion of X'Valid is simply:
  1510.  
  1511.       --     type(X)'Pos (X) >= 0
  1512.  
  1513.       --  For floating-point types, we assume we are operating in IEEE mode,
  1514.       --  i.e. with infinities and NaN's being generated. Any valid non-zero
  1515.       --  floating-point value will give 1.0 when divided by itself, so we
  1516.       --  can expand X'Valid to:
  1517.  
  1518.       --     X = 0.0 or else X / X = 1.0
  1519.  
  1520.       --  For all other scalar types, what we want logically is a range test:
  1521.  
  1522.       --     X in type(X)'First .. type(X)'Last
  1523.  
  1524.       --  But that's precisely what won't work because of possible unwanted
  1525.       --  optimization (and indeed the basic motivation for the Valid attribute
  1526.       --  is exactly that this test does not work. What will work is:
  1527.  
  1528.       --     Btyp!(X) >= Btyp!(type(X)'First)
  1529.       --       and then
  1530.       --     Btyp!(X) <= Btyp!(type(X)'Last)
  1531.  
  1532.       --  where Btyp is an integer type large enough to cover the full range
  1533.       --  of possible stored values (i.e. it is chosen on the basis of the
  1534.       --  size of the type, not the range of the values). We write this as
  1535.       --  two tests, rather than a range check, so that static evaluation
  1536.       --  will easily remove either or both of the checks if they can be
  1537.       --  statically determined to be true (this happens when the type of
  1538.       --  X is static and the range extends to the full range of stored
  1539.       --  values).
  1540.  
  1541.       when Attribute_Valid => Valid :
  1542.       declare
  1543.          Ptyp : constant Entity_Id := Etype (Pref);
  1544.          Btyp : Entity_Id;
  1545.          Exp  : Multi_Use.Exp_Id;
  1546.          Cod  : List_Id;
  1547.  
  1548.       begin
  1549.          --  Floating-point case
  1550.  
  1551.          if Is_Floating_Point_Type (Ptyp) then
  1552.             Multi_Use.Prepare (Pref, Exp, Cod);
  1553.  
  1554.             Rewrite_Substitute_Tree (N,
  1555.               Multi_Use.Wrap (Cod,
  1556.                 Make_Or_Else (Loc,
  1557.                   Left_Opnd =>
  1558.                     Make_Op_Eq (Loc,
  1559.                       Left_Opnd  => Multi_Use.New_Ref (Exp),
  1560.                       Right_Opnd => Make_Real_Literal (Loc, Ureal_0)),
  1561.  
  1562.                   Right_Opnd =>
  1563.                     Make_Op_Eq (Loc,
  1564.                       Left_Opnd =>
  1565.                         Make_Op_Divide (Loc,
  1566.                           Left_Opnd  => Multi_Use.New_Ref (Exp),
  1567.                           Right_Opnd => Multi_Use.New_Ref (Exp)),
  1568.                       Right_Opnd => Make_Real_Literal (Loc, Ureal_1)))));
  1569.  
  1570.          --  Enumeration type with holes
  1571.  
  1572.          elsif Is_Enumeration_Type (Ptyp)
  1573.            and then Present (Enum_Pos_To_Rep (Base_Type (Ptyp)))
  1574.          then
  1575.             Rewrite_Substitute_Tree (N,
  1576.               Make_Op_Ge (Loc,
  1577.                 Left_Opnd =>
  1578.                   Make_Attribute_Reference (Loc,
  1579.                     Prefix => New_Occurrence_Of (Base_Type (Ptyp), Loc),
  1580.                     Attribute_Name => Name_Pos,
  1581.                     Expressions => New_List (Pref)),
  1582.                 Right_Opnd => Make_Integer_Literal (Loc, Uint_0)));
  1583.  
  1584.          --  Other scalar types
  1585.  
  1586.          else
  1587.             Multi_Use.Prepare (Pref, Exp, Cod);
  1588.  
  1589.             if Esize (Ptyp) <= Esize (Standard_Integer) then
  1590.                Btyp := Standard_Integer;
  1591.             else
  1592.                Btyp := Universal_Integer;
  1593.             end if;
  1594.  
  1595.             --  Note below that we cannot do Unchecked_Convert_To, because
  1596.             --  this may subvert the required conversions and subject us to
  1597.             --  the dreaded optimization we are working to avoid!
  1598.  
  1599.             Rewrite_Substitute_Tree (N,
  1600.               Multi_Use.Wrap (Cod,
  1601.                 Make_And_Then (Loc,
  1602.                   Left_Opnd =>
  1603.                     Make_Op_Ge (Loc,
  1604.                       Left_Opnd =>
  1605.                         Make_Unchecked_Type_Conversion (Loc,
  1606.                           Subtype_Mark => New_Reference_To (Btyp, Loc),
  1607.                           Expression => Multi_Use.New_Ref (Exp)),
  1608.  
  1609.                       Right_Opnd =>
  1610.                         Make_Unchecked_Type_Conversion (Loc,
  1611.                           Subtype_Mark => New_Reference_To (Btyp, Loc),
  1612.                           Expression =>
  1613.                             Make_Attribute_Reference (Loc,
  1614.                               Prefix => New_Occurrence_Of (Ptyp, Loc),
  1615.                               Attribute_Name => Name_First))),
  1616.  
  1617.                   Right_Opnd =>
  1618.                     Make_Op_Le (Loc,
  1619.                       Left_Opnd =>
  1620.                         Make_Unchecked_Type_Conversion (Loc,
  1621.                           Subtype_Mark => New_Reference_To (Btyp, Loc),
  1622.                           Expression => Multi_Use.New_Ref (Exp)),
  1623.  
  1624.                       Right_Opnd =>
  1625.                         Make_Unchecked_Type_Conversion (Loc,
  1626.                           Subtype_Mark => New_Reference_To (Btyp, Loc),
  1627.                           Expression =>
  1628.                             Make_Attribute_Reference (Loc,
  1629.                               Prefix => New_Occurrence_Of (Ptyp, Loc),
  1630.                               Attribute_Name => Name_Last))))));
  1631.  
  1632.          end if;
  1633.  
  1634.          Analyze (N);
  1635.          Resolve (N, Standard_Boolean);
  1636.       end Valid;
  1637.  
  1638.       -----------
  1639.       -- Value --
  1640.       -----------
  1641.  
  1642.       --  For scalar types derived from Boolean, Character and integer types
  1643.       --  in package Standard, typ'Value (X) expands into:
  1644.  
  1645.       --    typ (Value_xx (X))
  1646.  
  1647.       --  where
  1648.  
  1649.       --    For types whose root type is Character
  1650.       --      xx = Character
  1651.  
  1652.       --    For types whose root type is Boolean
  1653.       --      xx = Boolean
  1654.  
  1655.       --    For signed integer types with size <= Integer'Size
  1656.       --      xx = Integer
  1657.  
  1658.       --    For other signed integer types
  1659.       --      xx = Long_Long_Integer
  1660.  
  1661.       --    For modular types with modulus <= System.Unsigned_Types.Unsigned
  1662.       --      xx = Unsigned
  1663.  
  1664.       --    For other modular integer types
  1665.       --      xx = Long_Long_Unsigned
  1666.  
  1667.       --    For floating-point types and ordinary fixed-point types
  1668.       --      xx = Real
  1669.  
  1670.       --  For types derived from Wide_Character, typ'Value (X) expands into
  1671.  
  1672.       --    Value_Wide_Character (X, Wide_Character_Encoding_Method)
  1673.  
  1674.       --  For decimal types with size <= Integer'Size, typ'Value (X)
  1675.       --  expands into
  1676.  
  1677.       --    typ!(ctype (Value_Decimal (X, typ'Scale)));
  1678.  
  1679.       --  For all other decimal types, typ'Value (X) expands into
  1680.  
  1681.       --    typ!(ctype (Value_Long_Long_Decimal (X, typ'Scale)))
  1682.  
  1683.       --  For enumeration types other than those derived from types Boolean,
  1684.       --  Character, and Wide_Character in Standard, typ'Value (X) expands to:
  1685.  
  1686.       --    T'Val (Value_Enumeration (Table'Address, T'Pos (T'Last), X))
  1687.  
  1688.       --  where Table is the table of access to string built for each
  1689.       --  enumeration type by Gigi (see description under documentation
  1690.       --  in Einfo for Lit_Name_Table). The Value_Enum procedure will
  1691.       --  search the table looking for X and return the position number
  1692.       --  in the table if found and then we will use that with the 'Val
  1693.       --  to return the actual enumeration value.
  1694.  
  1695.       when Attribute_Value => Value :
  1696.       declare
  1697.          Btyp : constant Entity_Id  := Base_Type (Typ);
  1698.          Rtyp : constant Entity_Id  := Root_Type (Typ);
  1699.          Vid  : RE_Id;
  1700.          Args : List_Id := Exprs;
  1701.          Ctyp : Entity_Id;
  1702.  
  1703.       begin
  1704.          if Rtyp = Standard_Character then
  1705.             Vid := RE_Value_Character;
  1706.  
  1707.          elsif Rtyp = Standard_Boolean then
  1708.             Vid := RE_Value_Boolean;
  1709.  
  1710.          elsif Rtyp = Standard_Wide_Character then
  1711.             Vid := RE_Value_Wide_Character;
  1712.             Append_To (Args,
  1713.               Make_Integer_Literal (Loc,
  1714.                 Intval =>
  1715.                   UI_From_Int (Int (Wide_Character_Encoding_Method))));
  1716.  
  1717.          elsif Rtyp = Standard_Short_Short_Integer
  1718.            or else Rtyp = Standard_Short_Integer
  1719.            or else Rtyp = Standard_Integer
  1720.          then
  1721.             Vid := RE_Value_Integer;
  1722.  
  1723.          elsif Is_Signed_Integer_Type (Rtyp) then
  1724.             Vid := RE_Value_Long_Long_Integer;
  1725.  
  1726.          elsif Is_Modular_Integer_Type (Rtyp) then
  1727.             if Modulus (Rtyp) <= Modulus (RTE (RE_Unsigned)) then
  1728.                Vid := RE_Value_Unsigned;
  1729.             else
  1730.                Vid := RE_Value_Long_Long_Unsigned;
  1731.             end if;
  1732.  
  1733.          elsif Is_Decimal_Fixed_Point_Type (Rtyp) then
  1734.             if UI_To_Int (Esize (Rtyp)) <= Standard_Integer_Size then
  1735.                Vid := RE_Value_Decimal;
  1736.             else
  1737.                Vid := RE_Value_Long_Long_Decimal;
  1738.             end if;
  1739.  
  1740.             Append_To (Args,
  1741.               Make_Attribute_Reference (Loc,
  1742.                 Prefix => New_Reference_To (Typ, Loc),
  1743.                 Attribute_Name => Name_Scale));
  1744.  
  1745.             Rewrite_Substitute_Tree (N,
  1746.               Unchecked_Convert_To (Typ,
  1747.                 Convert_To (Ctyp,
  1748.                   Make_Function_Call (Loc,
  1749.                     Name => New_Reference_To (RTE (Vid), Loc),
  1750.                     Parameter_Associations => Args))));
  1751.  
  1752.             Analyze (N);
  1753.             Resolve (N, Typ);
  1754.  
  1755.          elsif Is_Real_Type (Rtyp) then
  1756.             Vid := RE_Value_Real;
  1757.  
  1758.          --  Only other possibility is user defined enumeration type
  1759.  
  1760.          else
  1761.             pragma Assert (Is_Enumeration_Type (Rtyp));
  1762.  
  1763.             Prepend_To (Args,
  1764.               Make_Attribute_Reference (Loc,
  1765.                 Prefix => New_Reference_To (Btyp, Loc),
  1766.                 Attribute_Name => Name_Pos,
  1767.                 Expressions => New_List (
  1768.                   Make_Attribute_Reference (Loc,
  1769.                     Prefix => New_Reference_To (Btyp, Loc),
  1770.                     Attribute_Name => Name_Last))));
  1771.  
  1772.             Prepend_To (Args,
  1773.               Make_Attribute_Reference (Loc,
  1774.                 Prefix =>
  1775.                   New_Reference_To (Lit_Name_Table (Typ), Loc),
  1776.                 Attribute_Name => Name_Address));
  1777.  
  1778.             Rewrite_Substitute_Tree (N,
  1779.               Make_Attribute_Reference (Loc,
  1780.                 Prefix => New_Reference_To (Typ, Loc),
  1781.                 Attribute_Name => Name_Val,
  1782.                 Expressions => New_List (
  1783.                   Make_Function_Call (Loc,
  1784.                     Name => New_Reference_To (RTE (RE_Value_Enumeration), Loc),
  1785.                     Parameter_Associations => Args))));
  1786.  
  1787.             Analyze (N);
  1788.             Resolve (N, Typ);
  1789.             return;
  1790.          end if;
  1791.  
  1792.          --  Fall through for all cases except user defined enumeration type
  1793.          --  and decimal types, with Vid set to the Id of the entity for the
  1794.          --  Value routine and Args set to the list of parameters for the call.
  1795.  
  1796.          Rewrite_Substitute_Tree (N,
  1797.            Convert_To (Btyp,
  1798.              Make_Function_Call (Loc,
  1799.                Name => New_Reference_To (RTE (Vid), Loc),
  1800.                Parameter_Associations => Args)));
  1801.  
  1802.          Analyze (N);
  1803.          Resolve (N, Typ);
  1804.       end Value;
  1805.  
  1806.       -------------
  1807.       -- Version --
  1808.       -------------
  1809.  
  1810.       --  The processing for Version shares the processing for Body_Version
  1811.  
  1812.       ----------------
  1813.       -- Wide_Image --
  1814.       ----------------
  1815.  
  1816.       --  We expand typ'Wide_Image (X) into
  1817.  
  1818.       --    String_To_Wide_String
  1819.       --      (typ'Image (X), Wide_Character_Encoding_Method)
  1820.  
  1821.       --  This works in all cases because String_To_Wide_String converts any
  1822.       --  wide character escape sequences resulting from the Image call to the
  1823.       --  proper Wide_Character equivalent
  1824.  
  1825.       --  not quite right for typ = Wide_Character ???
  1826.  
  1827.       when Attribute_Wide_Image => Wide_Image :
  1828.       begin
  1829.          Rewrite_Substitute_Tree (N,
  1830.            Make_Function_Call (Loc,
  1831.              Name => New_Reference_To (RTE (RE_String_To_Wide_String), Loc),
  1832.              Parameter_Associations => New_List (
  1833.                Make_Attribute_Reference (Loc,
  1834.                  Prefix         => Pref,
  1835.                  Attribute_Name => Name_Image,
  1836.                  Expressions    => Exprs),
  1837.  
  1838.                Make_Integer_Literal (Loc,
  1839.                  Intval =>
  1840.                    UI_From_Int (Int (Wide_Character_Encoding_Method))))));
  1841.  
  1842.          Analyze (N);
  1843.          Resolve (N, Standard_Wide_String);
  1844.       end Wide_Image;
  1845.  
  1846.       ----------------
  1847.       -- Wide_Value --
  1848.       ----------------
  1849.  
  1850.       --  We expand typ'Wide_Value (X) into
  1851.  
  1852.       --    typ'Value
  1853.       --      (Wide_String_To_String (X, Wide_Character_Encoding_Method))
  1854.  
  1855.       --  Wide_String_To_String is a runtime function that converts its wide
  1856.       --  string argument to String, converting any non-translatable characters
  1857.       --  into appropriate escape sequences. This preserves the required
  1858.       --  semantics of Wide_Value in all cases, and results in a very simple
  1859.       --  implementation approach.
  1860.  
  1861.       --  It's not quite right where typ = Wide_Character, because the encoding
  1862.       --  method may not cover the whole character type ???
  1863.  
  1864.       when Attribute_Wide_Value => Wide_Value :
  1865.       begin
  1866.          Rewrite_Substitute_Tree (N,
  1867.            Make_Attribute_Reference (Loc,
  1868.              Prefix         => Pref,
  1869.              Attribute_Name => Name_Value,
  1870.  
  1871.              Expressions    => New_List (
  1872.                Make_Function_Call (Loc,
  1873.                  Name =>
  1874.                    New_Reference_To (RTE (RE_Wide_String_To_String), Loc),
  1875.                  Parameter_Associations => Exprs),
  1876.  
  1877.                Make_Integer_Literal (Loc,
  1878.                  Intval =>
  1879.                    UI_From_Int (Int (Wide_Character_Encoding_Method))))));
  1880.  
  1881.          Analyze (N);
  1882.          Resolve (N, Typ);
  1883.       end Wide_Value;
  1884.  
  1885.       ----------------
  1886.       -- Wide_Width --
  1887.       ----------------
  1888.  
  1889.       --  Processing for this attribute is combined with Width
  1890.  
  1891.       -----------
  1892.       -- Width --
  1893.       -----------
  1894.  
  1895.       --  The processing here also handles the case of Wide_Width. With the
  1896.       --  exceptions noted, the processing is identical
  1897.  
  1898.       --  For scalar types derived from Boolean, character and integer types
  1899.       --  in package Standard. Note that the Width attribute is computed at
  1900.       --  compile time for all cases except those involving non-static sub-
  1901.       --  types. For such subtypes, typ'Width and typ'Wide_Width expands into:
  1902.  
  1903.       --    Result_Type (xx (yy (Ptyp'First), yy (Ptyp'Last)))
  1904.  
  1905.       --  where
  1906.  
  1907.       --    For types whose root type is Character
  1908.       --      xx = Width_Character (Wide_Width_Character for Wide_Width case)
  1909.       --      yy = Character
  1910.  
  1911.       --    For types whose root type is Boolean
  1912.       --      xx = Width_Boolean
  1913.       --      yy = Boolean
  1914.  
  1915.       --    For signed integer types
  1916.       --      xx = Width_Long_Long_Integer
  1917.       --      yy = Long_Long_Integer
  1918.  
  1919.       --    For modular integer types
  1920.       --      xx = Width_Long_Long_Unsigned
  1921.       --      yy = Long_Long_Unsigned
  1922.  
  1923.       --  For types derived from Wide_Character, typ'Width expands into
  1924.  
  1925.       --    Result_Type (Width_Wide_Character (
  1926.       --      Wide_Character (typ'First),
  1927.       --      Wide_Character (typ'Last),
  1928.       --      Wide_Character_Encoding_Method);
  1929.  
  1930.       --  and typ'Wide_Width expands into:
  1931.  
  1932.       --    Result_Type (Wide_Width_Wide_Character (
  1933.       --      Wide_Character (typ'First),
  1934.       --      Wide_Character (typ'Last));
  1935.  
  1936.       --  For real types, typ'Width and typ'Wide_Width expand into
  1937.  
  1938.       --    if Ptyp'First > Ptyp'Last then 0 else btyp'Width end if
  1939.  
  1940.       --  where btyp is the base type. This looks recursive but it isn't
  1941.       --  because the base type is always static, and hence the expression
  1942.       --  in the else is reduced to an integer literal.
  1943.  
  1944.       --  For user defined enumeration types, typ'Width expands into
  1945.  
  1946.       --    Result_Type (Width_Enumeration (Table'Address,
  1947.       --                                    typ'Pos (typ'First),
  1948.       --                                    typ'Pos (Typ'Last)));
  1949.  
  1950.       --  and typ'Wide_Width expands into:
  1951.  
  1952.       --    Result_Type (Wide_Width_Enumeration
  1953.       --                  (Table'Address,
  1954.       --                   typ'Pos (typ'First),
  1955.       --                   typ'Pos (Typ'Last))
  1956.       --                   Wide_Character_Encoding_Method);
  1957.  
  1958.  
  1959.       when Attribute_Width | Attribute_Wide_Width => Width :
  1960.       declare
  1961.          Ptyp    : constant Entity_Id := Etype (Pref);
  1962.          Rtyp    : constant Entity_Id := Root_Type (Ptyp);
  1963.          XX      : RE_Id;
  1964.          YY      : Entity_Id;
  1965.          Arglist : List_Id;
  1966.  
  1967.       begin
  1968.          --  Types derived from Standard.Boolean
  1969.  
  1970.          if Rtyp = Standard_Boolean then
  1971.             XX := RE_Width_Boolean;
  1972.             YY := Rtyp;
  1973.  
  1974.          --  Types derived from Standard.Character
  1975.  
  1976.          elsif Rtyp = Standard_Character then
  1977.             if Id = Attribute_Width then
  1978.                XX := RE_Width_Character;
  1979.             else
  1980.                XX := RE_Wide_Width_Character;
  1981.             end if;
  1982.  
  1983.             YY := Rtyp;
  1984.  
  1985.          --  Types derived from Standard.Wide_Character
  1986.  
  1987.          elsif Rtyp = Standard_Wide_Character then
  1988.             if Id = Attribute_Width then
  1989.                XX := RE_Width_Wide_Character;
  1990.             else
  1991.                XX := RE_Wide_Width_Wide_Character;
  1992.             end if;
  1993.  
  1994.             YY := Rtyp;
  1995.  
  1996.          --  Signed integer types
  1997.  
  1998.          elsif Is_Signed_Integer_Type (Rtyp) then
  1999.             XX := RE_Width_Long_Long_Integer;
  2000.             YY := Standard_Long_Long_Integer;
  2001.  
  2002.          --  Modular integer types
  2003.  
  2004.          elsif Is_Modular_Integer_Type (Rtyp) then
  2005.             XX := RE_Width_Long_Long_Unsigned;
  2006.             YY := RTE (RE_Long_Long_Unsigned);
  2007.  
  2008.          --  Real types
  2009.  
  2010.          elsif Is_Real_Type (Rtyp) then
  2011.  
  2012.             Rewrite_Substitute_Tree (N,
  2013.               Make_Conditional_Expression (Loc,
  2014.                 Expressions => New_List (
  2015.  
  2016.                   Make_Op_Gt (Loc,
  2017.                     Left_Opnd =>
  2018.                       Make_Attribute_Reference (Loc,
  2019.                         Prefix => New_Reference_To (Ptyp, Loc),
  2020.                         Attribute_Name => Name_First),
  2021.  
  2022.                     Right_Opnd =>
  2023.                       Make_Attribute_Reference (Loc,
  2024.                         Prefix => New_Reference_To (Ptyp, Loc),
  2025.                         Attribute_Name => Name_Last)),
  2026.  
  2027.                   Make_Integer_Literal (Loc, Uint_0),
  2028.  
  2029.                   Make_Attribute_Reference (Loc,
  2030.                     Prefix => New_Reference_To (Base_Type (Ptyp), Loc),
  2031.                     Attribute_Name => Name_Width))));
  2032.  
  2033.             Analyze (N);
  2034.             Resolve (N, Typ);
  2035.             return;
  2036.  
  2037.          --  User defined enumeration types
  2038.  
  2039.          else
  2040.             pragma Assert (Is_Enumeration_Type (Rtyp));
  2041.  
  2042.             if Id = Attribute_Width then
  2043.                XX := RE_Width_Enumeration;
  2044.             else
  2045.                XX := RE_Wide_Width_Enumeration;
  2046.             end if;
  2047.  
  2048.             Arglist :=
  2049.               New_List (
  2050.                 Make_Attribute_Reference (Loc,
  2051.                   Prefix =>
  2052.                     New_Reference_To (Lit_Name_Table (Ptyp), Loc),
  2053.                   Attribute_Name => Name_Address),
  2054.  
  2055.                 Make_Attribute_Reference (Loc,
  2056.                   Prefix => New_Reference_To (Ptyp, Loc),
  2057.                   Attribute_Name => Name_Pos,
  2058.  
  2059.                   Expressions => New_List (
  2060.                     Make_Attribute_Reference (Loc,
  2061.                       Prefix => New_Reference_To (Ptyp, Loc),
  2062.                       Attribute_Name => Name_First))),
  2063.  
  2064.                 Make_Attribute_Reference (Loc,
  2065.                   Prefix => New_Reference_To (Ptyp, Loc),
  2066.                   Attribute_Name => Name_Pos,
  2067.  
  2068.                   Expressions => New_List (
  2069.                     Make_Attribute_Reference (Loc,
  2070.                       Prefix => New_Reference_To (Ptyp, Loc),
  2071.                       Attribute_Name => Name_Last))));
  2072.  
  2073.             --  For enumeration'Wide_Width, add encoding method parameter
  2074.  
  2075.             if Id = Attribute_Wide_Width then
  2076.                Append_To (Arglist,
  2077.                  Make_Integer_Literal (Loc,
  2078.                    Intval =>
  2079.                      UI_From_Int (Int (Wide_Character_Encoding_Method))));
  2080.             end if;
  2081.  
  2082.             Rewrite_Substitute_Tree (N,
  2083.               Convert_To (Typ,
  2084.                 Make_Function_Call (Loc,
  2085.                   Name => New_Reference_To (RTE (XX), Loc),
  2086.                   Parameter_Associations => Arglist)));
  2087.  
  2088.             Analyze (N);
  2089.             Resolve (N, Typ);
  2090.             return;
  2091.          end if;
  2092.  
  2093.          --  If we fall through XX and YY are set
  2094.  
  2095.          Arglist := New_List (
  2096.            Convert_To (YY,
  2097.              Make_Attribute_Reference (Loc,
  2098.                Prefix => New_Reference_To (Ptyp, Loc),
  2099.                Attribute_Name => Name_First)),
  2100.  
  2101.            Convert_To (YY,
  2102.              Make_Attribute_Reference (Loc,
  2103.                Prefix => New_Reference_To (Ptyp, Loc),
  2104.                Attribute_Name => Name_Last)));
  2105.  
  2106.          --  For Wide_Character'Width, add encoding method parameter
  2107.  
  2108.          if Rtyp = Standard_Wide_Character
  2109.            and Id = Attribute_Width
  2110.          then
  2111.             Append_To (Arglist,
  2112.               Make_Integer_Literal (Loc,
  2113.                 Intval =>
  2114.                   UI_From_Int (Int (Wide_Character_Encoding_Method))));
  2115.          end if;
  2116.  
  2117.          Rewrite_Substitute_Tree (N,
  2118.            Convert_To (Typ,
  2119.              Make_Function_Call (Loc,
  2120.                Name => New_Reference_To (RTE (XX), Loc),
  2121.                Parameter_Associations => Arglist)));
  2122.  
  2123.          Analyze (N);
  2124.          Resolve (N, Typ);
  2125.       end Width;
  2126.  
  2127.       --  The following attributes are handled by Gigi (except that static
  2128.       --  cases have already been evaluated by the semantics, but in any
  2129.       --  case Gigi should not count on that).
  2130.  
  2131.       --  In addition Gigi handles the non-floating-point cases of Pred
  2132.       --  and Succ (including the fixed-point cases, which can just be
  2133.       --  treated as integer increment/decrement operations)
  2134.  
  2135.       --  Gigi also handles the non-class-wide cases of Size
  2136.  
  2137.       when Attribute_Access                       |
  2138.            Attribute_Aft                          |
  2139.            Attribute_Alignment                    |
  2140.            Attribute_Bit_Order                    |
  2141.            Attribute_Component_Size               |
  2142.            Attribute_Definite                     |
  2143.            Attribute_Elab_Body                    |
  2144.            Attribute_Elab_Spec                    |
  2145.            Attribute_Max                          |
  2146.            Attribute_Max_Size_In_Storage_Elements |
  2147.            Attribute_Min                          |
  2148.            Attribute_Passed_By_Reference          |
  2149.            Attribute_Range_Length                 |
  2150.            Attribute_Unchecked_Access             |
  2151.            Attribute_Unrestricted_Access          =>
  2152.  
  2153.          null;
  2154.  
  2155.       --  The following attributes should not appear at this stage, since they
  2156.       --  have already been handled by the analyzer (and properly rewritten
  2157.       --  with corresponding values or entities to represent the right values)
  2158.  
  2159.       when Attribute_Abort_Signal                 |
  2160.            Attribute_Address_Size                 |
  2161.            Attribute_Base                         |
  2162.            Attribute_Caller                       |
  2163.            Attribute_Class                        |
  2164.            Attribute_Default_Bit_Order            |
  2165.            Attribute_Delta                        |
  2166.            Attribute_Denorm                       |
  2167.            Attribute_Digits                       |
  2168.            Attribute_Emax                         |
  2169.            Attribute_Epsilon                      |
  2170.            Attribute_External_Tag                 |
  2171.            Attribute_Identity                     |
  2172.            Attribute_Input                        |
  2173.            Attribute_Large                        |
  2174.            Attribute_Machine_Emax                 |
  2175.            Attribute_Machine_Emin                 |
  2176.            Attribute_Machine_Mantissa             |
  2177.            Attribute_Machine_Overflows            |
  2178.            Attribute_Machine_Radix                |
  2179.            Attribute_Machine_Rounds               |
  2180.            Attribute_Mantissa                     |
  2181.            Attribute_Max_Interrupt_Priority       |
  2182.            Attribute_Max_Priority                 |
  2183.            Attribute_Maximum_Alignment            |
  2184.            Attribute_Model_Emin                   |
  2185.            Attribute_Model_Epsilon                |
  2186.            Attribute_Model_Mantissa               |
  2187.            Attribute_Model_Small                  |
  2188.            Attribute_Modulus                      |
  2189.            Attribute_Output                       |
  2190.            Attribute_Partition_ID                 |
  2191.            Attribute_Range                        |
  2192.            Attribute_Read                         |
  2193.            Attribute_Safe_Emax                    |
  2194.            Attribute_Safe_First                   |
  2195.            Attribute_Safe_Large                   |
  2196.            Attribute_Safe_Last                    |
  2197.            Attribute_Safe_Small                   |
  2198.            Attribute_Scale                        |
  2199.            Attribute_Signed_Zeros                 |
  2200.            Attribute_Small                        |
  2201.            Attribute_Storage_Unit                 |
  2202.            Attribute_Tick                         |
  2203.            Attribute_Universal_Literal_String     |
  2204.            Attribute_Word_Size                    |
  2205.            Attribute_Write                        =>
  2206.  
  2207.          pragma Assert (False); null;
  2208.  
  2209.       end case;
  2210.  
  2211.    end Expand_N_Attribute_Reference;
  2212.  
  2213.    ----------------------
  2214.    -- Expand_Pred_Succ --
  2215.    ----------------------
  2216.  
  2217.    --  We expand typ'Pred (exp) into:
  2218.  
  2219.    --    if exp = typ'Base'First then
  2220.    --       raise constraint_error
  2221.    --    else
  2222.    --       typ'Pred (exp)
  2223.    --    end;
  2224.  
  2225.    --  Similarly, we expand typ'Succ (exp) into:
  2226.  
  2227.    --    if exp = typ'Base'Last then
  2228.    --       raise constraint_error
  2229.    --    else
  2230.    --       typ'Succ (exp)
  2231.    --    end
  2232.  
  2233.    procedure Expand_Pred_Succ (N : Node_Id) is
  2234.       Loc  : constant Source_Ptr := Sloc (N);
  2235.       Exp  : Multi_Use.Exp_Id;
  2236.       Cod  : List_Id;
  2237.       Cnam : Name_Id;
  2238.       Typ  : constant Entity_Id := Base_Type (Etype (Prefix (N)));
  2239.  
  2240.    begin
  2241.       --  Avoid the infinite recursion implicit in the above expansion:
  2242.  
  2243.       if Nkind (Parent (N)) = N_Conditional_Expression then
  2244.          Set_Analyzed (N);
  2245.          return;
  2246.       end if;
  2247.  
  2248.       if Attribute_Name (N) = Name_Pred then
  2249.          Cnam := Name_First;
  2250.       else
  2251.          Cnam := Name_Last;
  2252.       end if;
  2253.  
  2254.       Multi_Use.Prepare (First (Expressions (N)), Exp, Cod);
  2255.  
  2256.       Rewrite_Substitute_Tree (N,
  2257.         Make_Conditional_Expression (Loc,
  2258.           Expressions => New_List (
  2259.             Make_Op_Eq (Loc,
  2260.               Left_Opnd => Multi_Use.Wrap (Cod, Multi_Use.New_Ref (Exp)),
  2261.               Right_Opnd =>
  2262.                 Make_Attribute_Reference (Loc,
  2263.                   Prefix =>
  2264.                     New_Reference_To (Base_Type (Etype (Prefix (N))), Loc),
  2265.                   Attribute_Name => Cnam)),
  2266.  
  2267.             Make_Raise_Constraint_Error (Loc),
  2268.  
  2269.             Make_Attribute_Reference (Loc,
  2270.               Prefix => Prefix (N),
  2271.               Attribute_Name => Attribute_Name (N),
  2272.               Expressions => New_List (Multi_Use.New_Ref (Exp))))));
  2273.  
  2274.       --  The type of the conditional expression is the type of the Then
  2275.       --  expression, so we must set it here, because a Raise node has
  2276.       --  otherwise no semantic information.
  2277.  
  2278.       Set_Etype (Next (First (Expressions (N))), Typ);
  2279.    end Expand_Pred_Succ;
  2280.  
  2281.    -----------------------
  2282.    -- Get_Index_Subtype --
  2283.    -----------------------
  2284.  
  2285.    function Get_Index_Subtype (N : Node_Id) return Node_Id is
  2286.       P_Type : constant Entity_Id := Etype (Prefix (N));
  2287.       Indx   : Node_Id;
  2288.       J      : Int;
  2289.  
  2290.    begin
  2291.       if No (Expressions (N)) then
  2292.          J := 1;
  2293.       else
  2294.          J := UI_To_Int (Expr_Value (First (Expressions (N))));
  2295.       end if;
  2296.  
  2297.       Indx := First_Index (P_Type);
  2298.       while J > 1 loop
  2299.          Indx := Next_Index (Indx);
  2300.          J := J - 1;
  2301.       end loop;
  2302.  
  2303.       return Etype (Indx);
  2304.    end Get_Index_Subtype;
  2305.  
  2306. end Exp_Attr;
  2307.