OSDN Git Service

PR bootstrap/11932
[pf3gnuchains/gcc-fork.git] / gcc / ada / exp_attr.adb
index 2fada3e..28ece68 100644 (file)
@@ -6,9 +6,7 @@
 --                                                                          --
 --                                 B o d y                                  --
 --                                                                          --
---                            $Revision: 1.304 $
---                                                                          --
---          Copyright (C) 1992-2001 Free Software Foundation, Inc.          --
+--          Copyright (C) 1992-2004 Free Software Foundation, Inc.          --
 --                                                                          --
 -- GNAT is free software;  you can  redistribute it  and/or modify it under --
 -- terms of the  GNU General Public License as published  by the Free Soft- --
@@ -22,7 +20,7 @@
 -- MA 02111-1307, USA.                                                      --
 --                                                                          --
 -- GNAT was originally developed  by the GNAT team at  New York University. --
--- It is now maintained by Ada Core Technologies Inc (http://www.gnat.com). --
+-- Extensive contributions were provided by Ada Core Technologies Inc.      --
 --                                                                          --
 ------------------------------------------------------------------------------
 
@@ -44,11 +42,11 @@ with Nmake;    use Nmake;
 with Nlists;   use Nlists;
 with Opt;      use Opt;
 with Restrict; use Restrict;
+with Rident;   use Rident;
 with Rtsfind;  use Rtsfind;
 with Sem;      use Sem;
 with Sem_Ch7;  use Sem_Ch7;
 with Sem_Ch8;  use Sem_Ch8;
-with Sem_Ch13; use Sem_Ch13;
 with Sem_Eval; use Sem_Eval;
 with Sem_Res;  use Sem_Res;
 with Sem_Util; use Sem_Util;
@@ -84,26 +82,32 @@ package body Exp_Attr is
    --  or other invalid values do NOT cause a Constraint_Error to be raised.
 
    procedure Expand_Fpt_Attribute
-     (N   : Node_Id;
-      Rtp : Entity_Id;
+     (N    : Node_Id;
+      Rtp  : Entity_Id;
+      Nam  : Name_Id;
       Args : List_Id);
    --  This procedure expands a call to a floating-point attribute function.
    --  N is the attribute reference node, and Args is a list of arguments to
    --  be passed to the function call. Rtp is the root type of the floating
    --  point type involved (used to select the proper generic instantiation
-   --  of the package containing the attribute routines).
+   --  of the package containing the attribute routines). The Nam argument
+   --  is the attribute processing routine to be called. This is normally
+   --  the same as the attribute name, except in the Unaligned_Valid case.
 
    procedure Expand_Fpt_Attribute_R (N : Node_Id);
    --  This procedure expands a call to a floating-point attribute function
-   --  that takes a single floating-point argument.
+   --  that takes a single floating-point argument. The function to be called
+   --  is always the same as the attribute name.
 
    procedure Expand_Fpt_Attribute_RI (N : Node_Id);
    --  This procedure expands a call to a floating-point attribute function
-   --  that takes one floating-point argument and one integer argument.
+   --  that takes one floating-point argument and one integer argument. The
+   --  function to be called is always the same as the attribute name.
 
    procedure Expand_Fpt_Attribute_RR (N : Node_Id);
    --  This procedure expands a call to a floating-point attribute function
-   --  that takes two floating-point arguments.
+   --  that takes two floating-point arguments. The function to be called
+   --  is always the same as the attribute name.
 
    procedure Expand_Pred_Succ (N : Node_Id);
    --  Handles expansion of Pred or Succ attributes for case of non-real
@@ -119,7 +123,19 @@ package body Exp_Attr is
 
    function Find_Inherited_TSS
      (Typ : Entity_Id;
-      Nam : Name_Id) return Entity_Id;
+      Nam : TSS_Name_Type) return Entity_Id;
+   --  Returns the TSS of name Nam of Typ, or of its closest ancestor defining
+   --  such a TSS. Empty is returned is neither Typ nor any of its ancestors
+   --  have such a TSS.
+
+   function Find_Stream_Subprogram
+     (Typ : Entity_Id;
+      Nam : TSS_Name_Type) return Entity_Id;
+   --  Returns the stream-oriented subprogram attribute for Typ. For tagged
+   --  types, the corresponding primitive operation is looked up, else the
+   --  appropriate TSS from the type itself, or from its closest ancestor
+   --  defining it, is returned. In both cases, inheritance of representation
+   --  aspects is thus taken into account.
 
    function Is_Constrained_Packed_Array (Typ : Entity_Id) return Boolean;
    --  Utility for array attributes, returns true on packed constrained
@@ -245,6 +261,7 @@ package body Exp_Attr is
    procedure Expand_Fpt_Attribute
      (N    : Node_Id;
       Rtp  : Entity_Id;
+      Nam  : Name_Id;
       Args : List_Id)
    is
       Loc : constant Source_Ptr := Sloc (N);
@@ -254,7 +271,7 @@ package body Exp_Attr is
 
    begin
       --  The function name is the selected component Fat_xxx.yyy where xxx
-      --  is the floating-point root type, and yyy is the attribute name
+      --  is the floating-point root type, and yyy is the argument Nam.
 
       --  Note: it would be more usual to have separate RE entries for each
       --  of the entities in the Fat packages, but first they have identical
@@ -275,7 +292,7 @@ package body Exp_Attr is
       Fnm :=
         Make_Selected_Component (Loc,
           Prefix        => New_Reference_To (RTE (Pkg), Loc),
-          Selector_Name => Make_Identifier (Loc, Attribute_Name (N)));
+          Selector_Name => Make_Identifier (Loc, Nam));
 
       --  The generated call is given the provided set of parameters, and then
       --  wrapped in a conversion which converts the result to the target type
@@ -287,7 +304,6 @@ package body Exp_Attr is
             Parameter_Associations => Args)));
 
       Analyze_And_Resolve (N, Typ);
-
    end Expand_Fpt_Attribute;
 
    ----------------------------
@@ -303,8 +319,9 @@ package body Exp_Attr is
       Rtp : constant Entity_Id  := Root_Type (Etype (E1));
 
    begin
-      Expand_Fpt_Attribute (N, Rtp, New_List (
-        Unchecked_Convert_To (Rtp, Relocate_Node (E1))));
+      Expand_Fpt_Attribute
+        (N, Rtp, Attribute_Name (N),
+         New_List (Unchecked_Convert_To (Rtp, Relocate_Node (E1))));
    end Expand_Fpt_Attribute_R;
 
    -----------------------------
@@ -322,9 +339,11 @@ package body Exp_Attr is
       E2  : constant Node_Id   := Next (E1);
 
    begin
-      Expand_Fpt_Attribute (N, Rtp, New_List (
-        Unchecked_Convert_To (Rtp, Relocate_Node (E1)),
-        Unchecked_Convert_To (Standard_Integer, Relocate_Node (E2))));
+      Expand_Fpt_Attribute
+        (N, Rtp, Attribute_Name (N),
+         New_List (
+           Unchecked_Convert_To (Rtp, Relocate_Node (E1)),
+           Unchecked_Convert_To (Standard_Integer, Relocate_Node (E2))));
    end Expand_Fpt_Attribute_RI;
 
    -----------------------------
@@ -341,9 +360,11 @@ package body Exp_Attr is
       E2  : constant Node_Id   := Next (E1);
 
    begin
-      Expand_Fpt_Attribute (N, Rtp, New_List (
-        Unchecked_Convert_To (Rtp, Relocate_Node (E1)),
-        Unchecked_Convert_To (Rtp, Relocate_Node (E2))));
+      Expand_Fpt_Attribute
+        (N, Rtp, Attribute_Name (N),
+         New_List (
+           Unchecked_Convert_To (Rtp, Relocate_Node (E1)),
+           Unchecked_Convert_To (Rtp, Relocate_Node (E2))));
    end Expand_Fpt_Attribute_RR;
 
    ----------------------------------
@@ -368,16 +389,65 @@ package body Exp_Attr is
 
       procedure Rewrite_Stream_Proc_Call (Pname : Entity_Id) is
          Item       : constant Node_Id   := Next (First (Exprs));
-         Formal_Typ : constant Entity_Id :=
-                        Etype (Next_Formal (First_Formal (Pname)));
+         Formal     : constant Entity_Id := Next_Formal (First_Formal (Pname));
+         Formal_Typ : constant Entity_Id := Etype (Formal);
+         Is_Written : constant Boolean   := (Ekind (Formal) /= E_In_Parameter);
 
       begin
-         --  We have to worry about the type of the second argument
+         --  The expansion depends on Item, the second actual, which is
+         --  the object being streamed in or out.
+
+         --  If the item is a component of a packed array type, and
+         --  a conversion is needed on exit, we introduce a temporary to
+         --  hold the value, because otherwise the packed reference will
+         --  not be properly expanded.
+
+         if Nkind (Item) = N_Indexed_Component
+           and then Is_Packed (Base_Type (Etype (Prefix (Item))))
+           and then Base_Type (Etype (Item)) /= Base_Type (Formal_Typ)
+           and then Is_Written
+         then
+            declare
+               Temp : constant Entity_Id :=
+                        Make_Defining_Identifier
+                          (Loc, New_Internal_Name ('V'));
+               Decl : Node_Id;
+               Assn : Node_Id;
+
+            begin
+               Decl :=
+                 Make_Object_Declaration (Loc,
+                   Defining_Identifier => Temp,
+                   Object_Definition    =>
+                     New_Occurrence_Of (Formal_Typ, Loc));
+               Set_Etype (Temp, Formal_Typ);
+
+               Assn :=
+                 Make_Assignment_Statement (Loc,
+                   Name => New_Copy_Tree (Item),
+                   Expression =>
+                     Unchecked_Convert_To
+                       (Etype (Item), New_Occurrence_Of (Temp, Loc)));
+
+               Rewrite (Item, New_Occurrence_Of (Temp, Loc));
+               Insert_Actions (N,
+                 New_List (
+                   Decl,
+                   Make_Procedure_Call_Statement (Loc,
+                     Name => New_Occurrence_Of (Pname, Loc),
+                     Parameter_Associations => Exprs),
+                   Assn));
+
+               Rewrite (N, Make_Null_Statement (Loc));
+               return;
+            end;
+         end if;
 
          --  For the class-wide dispatching cases, and for cases in which
          --  the base type of the second argument matches the base type of
-         --  the corresponding formal parameter, we are all set, and can use
-         --  the argument unchanged.
+         --  the corresponding formal parameter (that is to say the stream
+         --  operation is not inherited), we are all set, and can use the
+         --  argument unchanged.
 
          --  For all other cases we do an unchecked conversion of the second
          --  parameter to the type of the formal of the procedure we are
@@ -385,6 +455,7 @@ package body Exp_Attr is
          --  to the root type as required in elementary type case.
 
          if not Is_Class_Wide_Type (Entity (Pref))
+           and then not Is_Class_Wide_Type (Etype (Item))
            and then Base_Type (Etype (Item)) /= Base_Type (Formal_Typ)
          then
             Rewrite (Item,
@@ -452,7 +523,7 @@ package body Exp_Attr is
             declare
                Agg     : Node_Id;
                Sub     : Entity_Id;
-               E_T     : constant Entity_Id := Equivalent_Type (Typ);
+               E_T     : constant Entity_Id := Equivalent_Type (Btyp);
                Acc     : constant Entity_Id :=
                            Etype (Next_Component (First_Component (E_T)));
                Obj_Ref : Node_Id;
@@ -511,7 +582,7 @@ package body Exp_Attr is
 
                Rewrite (N, Agg);
 
-               Analyze_And_Resolve (N, Equivalent_Type (Typ));
+               Analyze_And_Resolve (N, E_T);
 
                --  For subsequent analysis,  the node must retain its type.
                --  The backend will replace it with the equivalent type where
@@ -647,6 +718,59 @@ package body Exp_Attr is
       end Address;
 
       ---------------
+      -- Alignment --
+      ---------------
+
+      when Attribute_Alignment => Alignment : declare
+         Ptyp     : constant Entity_Id := Etype (Pref);
+         New_Node : Node_Id;
+
+      begin
+         --  For class-wide types, X'Class'Alignment is transformed into a
+         --  direct reference to the Alignment of the class type, so that the
+         --  back end does not have to deal with the X'Class'Alignment
+         --  reference.
+
+         if Is_Entity_Name (Pref)
+           and then Is_Class_Wide_Type (Entity (Pref))
+         then
+            Rewrite (Prefix (N), New_Occurrence_Of (Entity (Pref), Loc));
+            return;
+
+         --  For x'Alignment applied to an object of a class wide type,
+         --  transform X'Alignment into a call to the predefined primitive
+         --  operation _Alignment applied to X.
+
+         elsif Is_Class_Wide_Type (Ptyp) then
+            New_Node :=
+              Make_Function_Call (Loc,
+                Name => New_Reference_To
+                  (Find_Prim_Op (Ptyp, Name_uAlignment), Loc),
+                Parameter_Associations => New_List (Pref));
+
+            if Typ /= Standard_Integer then
+
+               --  The context is a specific integer type with which the
+               --  original attribute was compatible. The function has a
+               --  specific type as well, so to preserve the compatibility
+               --  we must convert explicitly.
+
+               New_Node := Convert_To (Typ, New_Node);
+            end if;
+
+            Rewrite (N, New_Node);
+            Analyze_And_Resolve (N, Typ);
+            return;
+
+         --  For all other cases, we just have to deal with the case of
+         --  the fact that the result can be universal.
+
+         else
+            Apply_Universal_Integer_Attribute_Checks (N);
+         end if;
+      end Alignment;
+
+      ---------------
       -- AST_Entry --
       ---------------
 
@@ -784,8 +908,9 @@ package body Exp_Attr is
          if Pent = Standard_Standard
            or else Pent = Standard_ASCII
          then
-            Name_Buffer (1 .. Library_Version'Length) := Library_Version;
-            Name_Len := Library_Version'Length;
+            Name_Buffer (1 .. Verbose_Library_Version'Length) :=
+              Verbose_Library_Version;
+            Name_Len := Verbose_Library_Version'Length;
             Rewrite (N,
               Make_String_Literal (Loc,
                 Strval => String_From_Name_Buffer));
@@ -887,10 +1012,10 @@ package body Exp_Attr is
       --  Task_Entry_Caller or the Protected_Entry_Caller function.
 
       when Attribute_Caller => Caller : declare
-         Id_Kind    : Entity_Id := RTE (RO_AT_Task_ID);
-         Ent        : Entity_Id := Entity (Pref);
-         Conctype   : Entity_Id := Scope (Ent);
-         Nest_Depth : Integer   := 0;
+         Id_Kind    : constant Entity_Id := RTE (RO_AT_Task_ID);
+         Ent        : constant Entity_Id := Entity (Pref);
+         Conctype   : constant Entity_Id := Scope (Ent);
+         Nest_Depth : Integer := 0;
          Name       : Node_Id;
          S          : Entity_Id;
 
@@ -899,7 +1024,7 @@ package body Exp_Attr is
 
          if Is_Protected_Type (Conctype) then
             if Abort_Allowed
-              or else Restrictions (No_Entry_Queue) = False
+              or else Restriction_Active (No_Entry_Queue) = False
               or else Number_Entries (Conctype) > 1
             then
                Name :=
@@ -984,9 +1109,12 @@ package body Exp_Attr is
       begin
          --  Reference to a parameter where the value is passed as an extra
          --  actual, corresponding to the extra formal referenced by the
-         --  Extra_Constrained field of the corresponding formal.
+         --  Extra_Constrained field of the corresponding formal. If this
+         --  is an entry in-parameter, it is replaced by a constant renaming
+         --  for which Extra_Constrained is never created.
 
          if Present (Formal_Ent)
+           and then Ekind (Formal_Ent) /= E_Constant
            and then Present (Extra_Constrained (Formal_Ent))
          then
             Rewrite (N,
@@ -1028,16 +1156,11 @@ package body Exp_Attr is
                   --  within the generic template would have been illegal.
 
                   else
-                     declare
-                        UT : Entity_Id := Underlying_Type (Ent);
-
-                     begin
-                        if Is_Composite_Type (UT) then
-                           Res := Is_Constrained (Ent);
-                        else
-                           Res := True;
-                        end if;
-                     end;
+                     if Is_Composite_Type (Underlying_Type (Ent)) then
+                        Res := Is_Constrained (Ent);
+                     else
+                        Res := True;
+                     end if;
                   end if;
 
                --  If the prefix is not a variable or is aliased, then
@@ -1137,7 +1260,7 @@ package body Exp_Attr is
          if Is_Protected_Type (Conctyp) then
 
             if Abort_Allowed
-              or else Restrictions (No_Entry_Queue) = False
+              or else Restriction_Active (No_Entry_Queue) = False
               or else Number_Entries (Conctyp) > 1
             then
                Name := New_Reference_To (RTE (RE_Protected_Count), Loc);
@@ -1338,6 +1461,19 @@ package body Exp_Attr is
             Rewrite (N,
               Make_Integer_Literal (Loc, Enumeration_Rep (Entity (Pref))));
 
+         --  If this is a renaming of a literal, recover the representation
+         --  of the original.
+
+         elsif Ekind (Entity (Pref)) = E_Constant
+           and then Present (Renamed_Object (Entity (Pref)))
+           and then
+             Ekind (Entity (Renamed_Object (Entity (Pref))))
+               = E_Enumeration_Literal
+         then
+            Rewrite (N,
+              Make_Integer_Literal (Loc,
+                Enumeration_Rep (Entity (Renamed_Object (Entity (Pref))))));
+
          --  X'Enum_Rep where X is an object does a direct unchecked conversion
          --  of the object value, as described for the type case above.
 
@@ -1456,6 +1592,11 @@ package body Exp_Attr is
              Expression   => Relocate_Node (First (Exprs))));
          Set_Etype (N, Entity (Pref));
          Set_Analyzed (N);
+
+      --  Note: it might appear that a properly analyzed unchecked conversion
+      --  would be just fine here, but that's not the case, since the full
+      --  range checks performed by the following call are critical!
+
          Apply_Type_Conversion_Checks (N);
       end Fixed_Value;
 
@@ -1613,7 +1754,7 @@ package body Exp_Attr is
 
          --  If there is a TSS for Input, just call it
 
-         Fname := Find_Inherited_TSS (P_Type, Name_uInput);
+         Fname := Find_Stream_Subprogram (P_Type, TSS_Stream_Input);
 
          if Present (Fname) then
             null;
@@ -1662,7 +1803,7 @@ package body Exp_Attr is
                --  A special case arises if we have a defined _Read routine,
                --  since in this case we are required to call this routine.
 
-               if Present (TSS (B_Type, Name_uRead)) then
+               if Present (TSS (Base_Type (U_Type), TSS_Stream_Read)) then
                   Build_Record_Or_Elementary_Input_Function
                     (Loc, U_Type, Decl, Fname);
                   Insert_Action (N, Decl);
@@ -1727,20 +1868,20 @@ package body Exp_Attr is
                   --  Now we need to get the entity for the call, and construct
                   --  a function call node, where we preset a reference to Dnn
                   --  as the controlling argument (doing an unchecked
-                  --  conversion to the tagged type to make it look like
-                  --  a real tagged object).
+                  --  conversion to the classwide tagged type to make it
+                  --  look like a real tagged object).
 
-                  Fname := Find_Prim_Op (Rtyp, Name_uInput);
-                  Cntrl := Unchecked_Convert_To (Rtyp,
+                  Fname := Find_Prim_Op (Rtyp, TSS_Stream_Input);
+                  Cntrl := Unchecked_Convert_To (P_Type,
                              New_Occurrence_Of (Dnn, Loc));
-                  Set_Etype (Cntrl, Rtyp);
+                  Set_Etype (Cntrl, P_Type);
                   Set_Parent (Cntrl, N);
                end;
 
             --  For tagged types, use the primitive Input function
 
             elsif Is_Tagged_Type (U_Type) then
-               Fname := Find_Prim_Op (U_Type, Name_uInput);
+               Fname := Find_Prim_Op (U_Type, TSS_Stream_Input);
 
             --  All other record type cases, including protected records.
             --  The latter only arise for expander generated code for
@@ -1796,6 +1937,11 @@ package body Exp_Attr is
              Expression   => Relocate_Node (First (Exprs))));
          Set_Etype (N, Entity (Pref));
          Set_Analyzed (N);
+
+      --  Note: it might appear that a properly analyzed unchecked conversion
+      --  would be just fine here, but that's not the case, since the full
+      --  range checks performed by the following call are critical!
+
          Apply_Type_Conversion_Checks (N);
       end Integer_Value;
 
@@ -1932,7 +2078,8 @@ package body Exp_Attr is
 
                                 Expressions => New_List (
                                   Make_Attribute_Reference (Loc,
-                                    Prefix => Duplicate_Subexpr (Pref),
+                                    Prefix =>
+                                      Duplicate_Subexpr_No_Checks (Pref),
                                    Attribute_Name => Name_First,
                                     Expressions => New_List (
                                       Make_Integer_Literal (Loc, Xnum)))))),
@@ -2009,7 +2156,8 @@ package body Exp_Attr is
                                 Attribute_Name => Name_Pos,
                                 Expressions    => New_List (
                                   Make_Attribute_Reference (Loc,
-                                    Prefix => Duplicate_Subexpr (Pref),
+                                    Prefix =>
+                                      Duplicate_Subexpr_No_Checks (Pref),
                                     Attribute_Name => Name_First,
                                     Expressions =>
                                       New_Copy_List (Exprs)))))))));
@@ -2120,7 +2268,6 @@ package body Exp_Attr is
 
       when Attribute_Output => Output : declare
          P_Type : constant Entity_Id := Entity (Pref);
-         B_Type : constant Entity_Id := Base_Type (P_Type);
          U_Type : constant Entity_Id := Underlying_Type (P_Type);
          Pname  : Entity_Id;
          Decl   : Node_Id;
@@ -2138,7 +2285,7 @@ package body Exp_Attr is
 
          --  If TSS for Output is present, just call it
 
-         Pname := Find_Inherited_TSS (P_Type, Name_uOutput);
+         Pname := Find_Stream_Subprogram (P_Type, TSS_Stream_Output);
 
          if Present (Pname) then
             null;
@@ -2191,7 +2338,7 @@ package body Exp_Attr is
                --  A special case arises if we have a defined _Write routine,
                --  since in this case we are required to call this routine.
 
-               if Present (TSS (B_Type, Name_uWrite)) then
+               if Present (TSS (Base_Type (U_Type), TSS_Stream_Write)) then
                   Build_Record_Or_Elementary_Output_Procedure
                     (Loc, U_Type, Decl, Pname);
                   Insert_Action (N, Decl);
@@ -2239,12 +2386,12 @@ package body Exp_Attr is
                              Attribute_Name => Name_Tag))))));
                end Tag_Write;
 
-               Pname := Find_Prim_Op (U_Type, Name_uOutput);
+               Pname := Find_Prim_Op (U_Type, TSS_Stream_Output);
 
             --  Tagged type case, use the primitive Output function
 
             elsif Is_Tagged_Type (U_Type) then
-               Pname := Find_Prim_Op (U_Type, Name_uOutput);
+               Pname := Find_Prim_Op (U_Type, TSS_Stream_Output);
 
             --  All other record type cases, including protected records.
             --  The latter only arise for expander generated code for
@@ -2276,10 +2423,11 @@ package body Exp_Attr is
       --  generate a call to the _Rep_To_Pos function created when the
       --  type was frozen. The call has the form
 
-      --    _rep_to_pos (expr, True)
+      --    _rep_to_pos (expr, flag)
 
-      --  The parameter True causes Program_Error to be raised if the
-      --  expression has an invalid representation.
+      --  The parameter flag is True if range checks are enabled, causing
+      --  Program_Error to be raised if the expression has an invalid
+      --  representation, and False if range checks are suppressed.
 
       --  For integer types, Pos is equivalent to a simple integer
       --  conversion and we rewrite it as such
@@ -2304,13 +2452,12 @@ package body Exp_Attr is
             --  Non-standard enumeration type (generate call)
 
             if Present (Enum_Pos_To_Rep (Etyp)) then
-               Append_To (Exprs, New_Occurrence_Of (Standard_True, Loc));
-
+               Append_To (Exprs, Rep_To_Pos_Flag (Etyp, Loc));
                Rewrite (N,
                  Convert_To (Typ,
                    Make_Function_Call (Loc,
                      Name =>
-                       New_Reference_To (TSS (Etyp, Name_uRep_To_Pos), Loc),
+                       New_Reference_To (TSS (Etyp, TSS_Rep_To_Pos), Loc),
                      Parameter_Associations => Exprs)));
 
                Analyze_And_Resolve (N, Typ);
@@ -2372,25 +2519,54 @@ package body Exp_Attr is
 
          --    Pos_To_Rep (Rep_To_Pos (x) - 1)
 
+         --    If the representation is contiguous, we compute instead
+         --    Lit1 + Rep_to_Pos (x -1), to catch invalid representations.
+
          if Is_Enumeration_Type (Ptyp)
            and then Present (Enum_Pos_To_Rep (Ptyp))
          then
-            --  Add Boolean parameter True, to request program errror if
-            --  we have a bad representation on our hands.
+            if Has_Contiguous_Rep (Ptyp) then
+               Rewrite (N,
+                  Unchecked_Convert_To (Ptyp,
+                     Make_Op_Add (Loc,
+                        Left_Opnd  =>
+                         Make_Integer_Literal (Loc,
+                           Enumeration_Rep (First_Literal (Ptyp))),
+                        Right_Opnd =>
+                          Make_Function_Call (Loc,
+                            Name =>
+                              New_Reference_To
+                               (TSS (Ptyp, TSS_Rep_To_Pos), Loc),
+
+                            Parameter_Associations =>
+                              New_List (
+                                Unchecked_Convert_To (Ptyp,
+                                  Make_Op_Subtract (Loc,
+                                    Left_Opnd =>
+                                     Unchecked_Convert_To (Standard_Integer,
+                                       Relocate_Node (First (Exprs))),
+                                    Right_Opnd =>
+                                      Make_Integer_Literal (Loc, 1))),
+                                Rep_To_Pos_Flag (Ptyp, Loc))))));
 
-            Append_To (Exprs, New_Occurrence_Of (Standard_True, Loc));
+            else
+               --  Add Boolean parameter True, to request program errror if
+               --  we have a bad representation on our hands. If checks are
+               --  suppressed, then add False instead
 
-            Rewrite (N,
-              Make_Indexed_Component (Loc,
-                Prefix => New_Reference_To (Enum_Pos_To_Rep (Ptyp), Loc),
-                Expressions => New_List (
-                  Make_Op_Subtract (Loc,
+               Append_To (Exprs, Rep_To_Pos_Flag (Ptyp, Loc));
+               Rewrite (N,
+                 Make_Indexed_Component (Loc,
+                   Prefix => New_Reference_To (Enum_Pos_To_Rep (Ptyp), Loc),
+                   Expressions => New_List (
+                     Make_Op_Subtract (Loc,
                     Left_Opnd =>
                       Make_Function_Call (Loc,
                         Name =>
-                          New_Reference_To (TSS (Ptyp, Name_uRep_To_Pos), Loc),
-                        Parameter_Associations => Exprs),
+                          New_Reference_To (TSS (Ptyp, TSS_Rep_To_Pos), Loc),
+                          Parameter_Associations => Exprs),
                     Right_Opnd => Make_Integer_Literal (Loc, 1)))));
+            end if;
 
             Analyze_And_Resolve (N, Typ);
 
@@ -2501,7 +2677,7 @@ package body Exp_Attr is
 
          --  The simple case, if there is a TSS for Read, just call it
 
-         Pname := Find_Inherited_TSS (P_Type, Name_uRead);
+         Pname := Find_Stream_Subprogram (P_Type, TSS_Stream_Read);
 
          if Present (Pname) then
             null;
@@ -2556,7 +2732,7 @@ package body Exp_Attr is
 
                Rewrite (N,
                  Make_Assignment_Statement (Loc,
-                   Name => Lhs,
+                   Name       => Lhs,
                    Expression => Rhs));
                Set_Assignment_OK (Lhs);
                Analyze (N);
@@ -2601,7 +2777,7 @@ package body Exp_Attr is
             --  this will dispatch in the class-wide case which is what we want
 
             elsif Is_Tagged_Type (U_Type) then
-               Pname := Find_Prim_Op (U_Type, Name_uRead);
+               Pname := Find_Prim_Op (U_Type, TSS_Stream_Read);
 
             --  All other record type cases, including protected records.
             --  The latter only arise for expander generated code for
@@ -2720,8 +2896,8 @@ package body Exp_Attr is
 
       declare
          Ptyp     : constant Entity_Id := Etype (Pref);
-         New_Node : Node_Id;
          Siz      : Uint;
+         New_Node : Node_Id;
 
       begin
          --  Processing for VADS_Size case. Note that this processing removes
@@ -2788,10 +2964,20 @@ package body Exp_Attr is
             end if;
          end if;
 
-         --  For class-wide types, transform X'Size into a call to
-         --  the primitive operation _Size
+         --  For class-wide types,  X'Class'Size is transformed into a
+         --  direct reference to the Size of the class type, so that gigi
+         --  does not have to deal with the X'Class'Size reference.
+
+         if Is_Entity_Name (Pref)
+           and then Is_Class_Wide_Type (Entity (Pref))
+         then
+            Rewrite (Prefix (N), New_Occurrence_Of (Entity (Pref), Loc));
+            return;
+
+         --  For x'Size applied to an object of a class wide type, transform
+         --  X'Size into a call to the primitive operation _Size applied to X.
 
-         if Is_Class_Wide_Type (Ptyp) then
+         elsif Is_Class_Wide_Type (Ptyp) then
             New_Node :=
               Make_Function_Call (Loc,
                 Name => New_Reference_To
@@ -2921,9 +3107,12 @@ package body Exp_Attr is
                Rewrite (N,
                  OK_Convert_To (Typ,
                    Make_Function_Call (Loc,
-                     Name => New_Reference_To (Find_Prim_Op (Etype (
-                       Associated_Storage_Pool (Root_Type (Ptyp))),
-                       Attribute_Name (N)), Loc),
+                     Name =>
+                       New_Reference_To
+                        (Find_Prim_Op
+                          (Etype (Associated_Storage_Pool (Root_Type (Ptyp))),
+                           Attribute_Name (N)),
+                         Loc),
 
                      Parameter_Associations => New_List (New_Reference_To (
                        Associated_Storage_Pool (Root_Type (Ptyp)), Loc)))));
@@ -3014,25 +3203,54 @@ package body Exp_Attr is
 
          --    Pos_To_Rep (Rep_To_Pos (x) + 1)
 
+         --    If the representation is contiguous, we compute instead
+         --    Lit1 + Rep_to_Pos (x+1), to catch invalid representations.
+
          if Is_Enumeration_Type (Ptyp)
            and then Present (Enum_Pos_To_Rep (Ptyp))
          then
-            --  Add Boolean parameter True, to request program errror if
-            --  we have a bad representation on our hands.
-
-            Append_To (Exprs, New_Occurrence_Of (Standard_True, Loc));
+            if Has_Contiguous_Rep (Ptyp) then
+               Rewrite (N,
+                  Unchecked_Convert_To (Ptyp,
+                     Make_Op_Add (Loc,
+                        Left_Opnd  =>
+                         Make_Integer_Literal (Loc,
+                           Enumeration_Rep (First_Literal (Ptyp))),
+                        Right_Opnd =>
+                          Make_Function_Call (Loc,
+                            Name =>
+                              New_Reference_To
+                               (TSS (Ptyp, TSS_Rep_To_Pos), Loc),
+
+                            Parameter_Associations =>
+                              New_List (
+                                Unchecked_Convert_To (Ptyp,
+                                  Make_Op_Add (Loc,
+                                  Left_Opnd =>
+                                    Unchecked_Convert_To (Standard_Integer,
+                                      Relocate_Node (First (Exprs))),
+                                  Right_Opnd =>
+                                    Make_Integer_Literal (Loc, 1))),
+                                Rep_To_Pos_Flag (Ptyp, Loc))))));
+            else
+               --  Add Boolean parameter True, to request program errror if
+               --  we have a bad representation on our hands. Add False if
+               --  checks are suppressed.
 
-            Rewrite (N,
-              Make_Indexed_Component (Loc,
-                Prefix => New_Reference_To (Enum_Pos_To_Rep (Ptyp), Loc),
-                Expressions => New_List (
-                  Make_Op_Add (Loc,
-                    Left_Opnd =>
-                      Make_Function_Call (Loc,
-                        Name =>
-                          New_Reference_To (TSS (Ptyp, Name_uRep_To_Pos), Loc),
-                        Parameter_Associations => Exprs),
-                    Right_Opnd => Make_Integer_Literal (Loc, 1)))));
+               Append_To (Exprs, Rep_To_Pos_Flag (Ptyp, Loc));
+               Rewrite (N,
+                 Make_Indexed_Component (Loc,
+                   Prefix => New_Reference_To (Enum_Pos_To_Rep (Ptyp), Loc),
+                   Expressions => New_List (
+                     Make_Op_Add (Loc,
+                       Left_Opnd =>
+                         Make_Function_Call (Loc,
+                           Name =>
+                             New_Reference_To
+                               (TSS (Ptyp, TSS_Rep_To_Pos), Loc),
+                           Parameter_Associations => Exprs),
+                       Right_Opnd => Make_Integer_Literal (Loc, 1)))));
+            end if;
 
             Analyze_And_Resolve (N, Typ);
 
@@ -3083,9 +3301,16 @@ package body Exp_Attr is
          Ttyp := Underlying_Type (Ttyp);
 
          if Prefix_Is_Type then
-            Rewrite (N,
-              Unchecked_Convert_To (RTE (RE_Tag),
-                New_Reference_To (Access_Disp_Table (Ttyp), Loc)));
+
+            --  For JGNAT we leave the type attribute unexpanded because
+            --  there's not a dispatching table to reference.
+
+            if not Java_VM then
+               Rewrite (N,
+                 Unchecked_Convert_To (RTE (RE_Tag),
+                   New_Reference_To (Access_Disp_Table (Ttyp), Loc)));
+               Analyze_And_Resolve (N, RTE (RE_Tag));
+            end if;
 
          else
             Rewrite (N,
@@ -3093,9 +3318,8 @@ package body Exp_Attr is
                 Prefix => Relocate_Node (Pref),
                 Selector_Name =>
                   New_Reference_To (Tag_Component (Ttyp), Loc)));
+            Analyze_And_Resolve (N, RTE (RE_Tag));
          end if;
-
-         Analyze_And_Resolve (N, RTE (RE_Tag));
       end Tag;
 
       ----------------
@@ -3228,12 +3452,43 @@ package body Exp_Attr is
          if Is_Enumeration_Type (Etyp)
            and then Present (Enum_Pos_To_Rep (Etyp))
          then
-            Rewrite (N,
-              Make_Indexed_Component (Loc,
-                Prefix => New_Reference_To (Enum_Pos_To_Rep (Etyp), Loc),
-                Expressions => New_List (
-                  Convert_To (Standard_Integer,
-                    Relocate_Node (First (Exprs))))));
+            if Has_Contiguous_Rep (Etyp) then
+               declare
+                  Rep_Node : constant Node_Id :=
+                    Unchecked_Convert_To (Etyp,
+                       Make_Op_Add (Loc,
+                         Left_Opnd =>
+                            Make_Integer_Literal (Loc,
+                              Enumeration_Rep (First_Literal (Etyp))),
+                         Right_Opnd =>
+                          (Convert_To (Standard_Integer,
+                             Relocate_Node (First (Exprs))))));
+
+               begin
+                  Rewrite (N,
+                     Unchecked_Convert_To (Etyp,
+                         Make_Op_Add (Loc,
+                           Left_Opnd =>
+                             Make_Integer_Literal (Loc,
+                               Enumeration_Rep (First_Literal (Etyp))),
+                           Right_Opnd =>
+                             Make_Function_Call (Loc,
+                               Name =>
+                                 New_Reference_To
+                                   (TSS (Etyp, TSS_Rep_To_Pos), Loc),
+                               Parameter_Associations => New_List (
+                                 Rep_Node,
+                                 Rep_To_Pos_Flag (Etyp, Loc))))));
+               end;
+
+            else
+               Rewrite (N,
+                 Make_Indexed_Component (Loc,
+                   Prefix => New_Reference_To (Enum_Pos_To_Rep (Etyp), Loc),
+                   Expressions => New_List (
+                     Convert_To (Standard_Integer,
+                       Relocate_Node (First (Exprs))))));
+            end if;
 
             Analyze_And_Resolve (N, Typ);
          end if;
@@ -3249,15 +3504,25 @@ package body Exp_Attr is
       when Attribute_Valid => Valid :
       declare
          Ptyp : constant Entity_Id  := Etype (Pref);
-         Btyp : Entity_Id := Base_Type (Ptyp);
+         Btyp : Entity_Id           := Base_Type (Ptyp);
          Tst  : Node_Id;
 
+         Save_Validity_Checks_On : constant Boolean := Validity_Checks_On;
+         --  Save the validity checking mode. We always turn off validity
+         --  checking during process of 'Valid since this is one place
+         --  where we do not want the implicit validity checks to intefere
+         --  with the explicit validity check that the programmer is doing.
+
          function Make_Range_Test return Node_Id;
          --  Build the code for a range test of the form
          --    Btyp!(Pref) >= Btyp!(Ptyp'First)
          --      and then
          --    Btyp!(Pref) <= Btyp!(Ptyp'Last)
 
+         ---------------------
+         -- Make_Range_Test --
+         ---------------------
+
          function Make_Range_Test return Node_Id is
          begin
             return
@@ -3276,7 +3541,8 @@ package body Exp_Attr is
                 Right_Opnd =>
                   Make_Op_Le (Loc,
                     Left_Opnd =>
-                      Unchecked_Convert_To (Btyp, Duplicate_Subexpr (Pref)),
+                      Unchecked_Convert_To (Btyp,
+                        Duplicate_Subexpr_No_Checks (Pref)),
 
                     Right_Opnd =>
                       Unchecked_Convert_To (Btyp,
@@ -3288,6 +3554,11 @@ package body Exp_Attr is
       --  Start of processing for Attribute_Valid
 
       begin
+         --  Turn off validity checks. We do not want any implicit validity
+         --  checks to intefere with the explicit check from the attribute
+
+         Validity_Checks_On := False;
+
          --  Floating-point case. This case is handled by the Valid attribute
          --  code in the floating-point attribute run-time library.
 
@@ -3296,10 +3567,34 @@ package body Exp_Attr is
                Rtp : constant Entity_Id := Root_Type (Etype (Pref));
 
             begin
-               Expand_Fpt_Attribute (N, Rtp, New_List (
-                 Make_Attribute_Reference (Loc,
-                   Prefix => Unchecked_Convert_To (Rtp, Pref),
-                   Attribute_Name => Name_Unrestricted_Access)));
+               --  If the floating-point object might be unaligned, we need
+               --  to call the special routine Unaligned_Valid, which makes
+               --  the needed copy, being careful not to load the value into
+               --  any floating-point register. The argument in this case is
+               --  obj'Address (see Unchecked_Valid routine in s-fatgen.ads).
+
+               if Is_Possibly_Unaligned_Object (Pref) then
+                  Set_Attribute_Name (N, Name_Unaligned_Valid);
+                  Expand_Fpt_Attribute
+                    (N, Rtp, Name_Unaligned_Valid,
+                     New_List (
+                       Make_Attribute_Reference (Loc,
+                         Prefix         => Relocate_Node (Pref),
+                         Attribute_Name => Name_Address)));
+
+               --  In the normal case where we are sure the object is aligned,
+               --  we generate a caqll to Valid, and the argument in this case
+               --  is obj'Unrestricted_Access (after converting obj to the
+               --  right floating-point type).
+
+               else
+                  Expand_Fpt_Attribute
+                    (N, Rtp, Name_Valid,
+                     New_List (
+                       Make_Attribute_Reference (Loc,
+                         Prefix         => Unchecked_Convert_To (Rtp, Pref),
+                         Attribute_Name => Name_Unrestricted_Access)));
+               end if;
 
                --  One more task, we still need a range check. Required
                --  only if we have a constraint, since the Valid routine
@@ -3351,7 +3646,7 @@ package body Exp_Attr is
                   Make_Function_Call (Loc,
                     Name =>
                       New_Reference_To
-                        (TSS (Base_Type (Ptyp), Name_uRep_To_Pos), Loc),
+                        (TSS (Base_Type (Ptyp), TSS_Rep_To_Pos), Loc),
                     Parameter_Associations => New_List (
                       Pref,
                       New_Occurrence_Of (Standard_False, Loc))),
@@ -3468,6 +3763,7 @@ package body Exp_Attr is
          end if;
 
          Analyze_And_Resolve (N, Standard_Boolean);
+         Validity_Checks_On := Save_Validity_Checks_On;
       end Valid;
 
       -----------
@@ -3602,7 +3898,7 @@ package body Exp_Attr is
 
          --  The simple case, if there is a TSS for Write, just call it
 
-         Pname := Find_Inherited_TSS (P_Type, Name_uWrite);
+         Pname := Find_Stream_Subprogram (P_Type, TSS_Stream_Write);
 
          if Present (Pname) then
             null;
@@ -3662,7 +3958,7 @@ package body Exp_Attr is
             --  this will dispatch in the class-wide case which is what we want
 
             elsif Is_Tagged_Type (U_Type) then
-               Pname := Find_Prim_Op (U_Type, Name_uWrite);
+               Pname := Find_Prim_Op (U_Type, TSS_Stream_Write);
 
             --  All other record type cases, including protected records.
             --  The latter only arise for expander generated code for
@@ -3719,7 +4015,8 @@ package body Exp_Attr is
            Attribute_Mechanism_Code               |
            Attribute_Min                          |
            Attribute_Null_Parameter               |
-           Attribute_Passed_By_Reference          =>
+           Attribute_Passed_By_Reference          |
+           Attribute_Pool_Address                 =>
          null;
 
       --  The following attributes are also handled by Gigi, but return a
@@ -3727,7 +4024,6 @@ package body Exp_Attr is
       --  that the result is in range.
 
       when Attribute_Aft                          |
-           Attribute_Alignment                    |
            Attribute_Bit                          |
            Attribute_Max_Size_In_Storage_Elements
       =>
@@ -3755,8 +4051,6 @@ package body Exp_Attr is
            Attribute_Machine_Overflows            |
            Attribute_Machine_Radix                |
            Attribute_Machine_Rounds               |
-           Attribute_Max_Interrupt_Priority       |
-           Attribute_Max_Priority                 |
            Attribute_Maximum_Alignment            |
            Attribute_Model_Emin                   |
            Attribute_Model_Epsilon                |
@@ -3774,8 +4068,9 @@ package body Exp_Attr is
            Attribute_Signed_Zeros                 |
            Attribute_Small                        |
            Attribute_Storage_Unit                 |
-           Attribute_Tick                         |
+           Attribute_Target_Name                  |
            Attribute_Type_Class                   |
+           Attribute_Unconstrained_Array          |
            Attribute_Universal_Literal_String     |
            Attribute_Wchar_T_Size                 |
            Attribute_Word_Size                    =>
@@ -3793,6 +4088,9 @@ package body Exp_Attr is
 
       end case;
 
+   exception
+      when RE_Not_Available =>
+         return;
    end Expand_N_Attribute_Reference;
 
    ----------------------
@@ -3825,12 +4123,14 @@ package body Exp_Attr is
         Make_Raise_Constraint_Error (Loc,
           Condition =>
             Make_Op_Eq (Loc,
-              Left_Opnd => Duplicate_Subexpr (First (Expressions (N))),
+              Left_Opnd =>
+                Duplicate_Subexpr_Move_Checks (First (Expressions (N))),
               Right_Opnd =>
                 Make_Attribute_Reference (Loc,
                   Prefix =>
                     New_Reference_To (Base_Type (Etype (Prefix (N))), Loc),
-                  Attribute_Name => Cnam))));
+                  Attribute_Name => Cnam)),
+          Reason => CE_Overflow_Check_Failed));
 
    end Expand_Pred_Succ;
 
@@ -3840,41 +4140,53 @@ package body Exp_Attr is
 
    function Find_Inherited_TSS
      (Typ : Entity_Id;
-      Nam : Name_Id) return Entity_Id
+      Nam : TSS_Name_Type) return Entity_Id
    is
-      P_Type : Entity_Id := Typ;
-      Proc   : Entity_Id;
+      Btyp : Entity_Id := Typ;
+      Proc : Entity_Id;
 
    begin
-      Proc :=  TSS (Base_Type (Typ), Nam);
+      loop
+         Btyp := Base_Type (Btyp);
+         Proc :=  TSS (Btyp, Nam);
 
-      --  Check first if there is a TSS given for the type itself.
+         exit when Present (Proc)
+           or else not Is_Derived_Type (Btyp);
 
-      if Present (Proc) then
-         return Proc;
-      end if;
+         --  If Typ is a derived type, it may inherit attributes from
+         --  some ancestor.
 
-      --  If Typ is a derived type, it may inherit attributes from some
-      --  ancestor which is not the ultimate underlying one.
+         Btyp := Etype (Btyp);
+      end loop;
 
-      if Is_Derived_Type (P_Type) then
+      if No (Proc) then
 
-         while Is_Derived_Type (P_Type) loop
-            Proc :=  TSS (Base_Type (Etype (Typ)), Nam);
+         --  If nothing else, use the TSS of the root type
 
-            if Present (Proc) then
-               return Proc;
-            else
-               P_Type := Base_Type (Etype (P_Type));
-            end if;
-         end loop;
+         Proc := TSS (Base_Type (Underlying_Type (Typ)), Nam);
       end if;
 
-      --  If nothing else, use the TSS of the root type.
+      return Proc;
 
-      return TSS (Base_Type (Underlying_Type (Typ)), Nam);
    end Find_Inherited_TSS;
 
+   ----------------------------
+   -- Find_Stream_Subprogram --
+   ----------------------------
+
+   function Find_Stream_Subprogram
+     (Typ : Entity_Id;
+      Nam : TSS_Name_Type) return Entity_Id is
+   begin
+      if Is_Tagged_Type (Typ)
+        and then Is_Derived_Type (Typ)
+      then
+         return Find_Prim_Op (Typ, Nam);
+      else
+         return Find_Inherited_TSS (Typ, Nam);
+      end if;
+   end Find_Stream_Subprogram;
+
    -----------------------
    -- Get_Index_Subtype --
    -----------------------