diff options
Diffstat (limited to 'gcc/ada/exp_attr.adb')
-rw-r--r-- | gcc/ada/exp_attr.adb | 584 |
1 files changed, 444 insertions, 140 deletions
diff --git a/gcc/ada/exp_attr.adb b/gcc/ada/exp_attr.adb index bf65d883720..7a5d7737f02 100644 --- a/gcc/ada/exp_attr.adb +++ b/gcc/ada/exp_attr.adb @@ -6,7 +6,7 @@ -- -- -- B o d y -- -- -- --- Copyright (C) 1992-2002 Free Software Foundation, Inc. -- +-- Copyright (C) 1992-2003 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- -- @@ -81,26 +81,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 @@ -116,7 +122,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 @@ -242,6 +260,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); @@ -251,7 +270,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 @@ -272,7 +291,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 @@ -284,7 +303,6 @@ package body Exp_Attr is Parameter_Associations => Args))); Analyze_And_Resolve (N, Typ); - end Expand_Fpt_Attribute; ---------------------------- @@ -300,8 +318,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; ----------------------------- @@ -319,9 +338,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; ----------------------------- @@ -338,9 +359,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; ---------------------------------- @@ -365,16 +388,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 @@ -382,6 +454,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, @@ -644,6 +717,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 -- --------------- @@ -884,10 +1010,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; @@ -981,9 +1107,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, @@ -1025,16 +1154,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 @@ -1335,6 +1459,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. @@ -1453,6 +1590,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; @@ -1610,7 +1752,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; @@ -1659,7 +1801,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); @@ -1724,20 +1866,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 @@ -1793,6 +1935,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; @@ -1929,7 +2076,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)))))), @@ -2006,7 +2154,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))))))))); @@ -2117,7 +2266,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; @@ -2135,7 +2283,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; @@ -2188,7 +2336,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); @@ -2236,12 +2384,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 @@ -2273,10 +2421,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 @@ -2301,13 +2450,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); @@ -2369,25 +2517,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); @@ -2498,7 +2675,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; @@ -2553,7 +2730,7 @@ package body Exp_Attr is Rewrite (N, Make_Assignment_Statement (Loc, - Name => Lhs, + Name => Lhs, Expression => Rhs)); Set_Assignment_OK (Lhs); Analyze (N); @@ -2598,7 +2775,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 @@ -2717,8 +2894,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 @@ -2785,10 +2962,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_Class_Wide_Type (Ptyp) then + 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. + + elsif Is_Class_Wide_Type (Ptyp) then New_Node := Make_Function_Call (Loc, Name => New_Reference_To @@ -2918,9 +3105,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))))); @@ -3011,25 +3201,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); @@ -3231,12 +3450,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; @@ -3252,15 +3502,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 @@ -3279,7 +3539,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, @@ -3291,6 +3552,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. @@ -3299,10 +3565,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 @@ -3354,7 +3644,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))), @@ -3471,6 +3761,7 @@ package body Exp_Attr is end if; Analyze_And_Resolve (N, Standard_Boolean); + Validity_Checks_On := Save_Validity_Checks_On; end Valid; ----------- @@ -3605,7 +3896,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; @@ -3665,7 +3956,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 @@ -3722,7 +4013,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 @@ -3730,7 +4022,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 => @@ -3775,7 +4066,9 @@ package body Exp_Attr is Attribute_Signed_Zeros | Attribute_Small | Attribute_Storage_Unit | + Attribute_Target_Name | Attribute_Type_Class | + Attribute_Unconstrained_Array | Attribute_Universal_Literal_String | Attribute_Wchar_T_Size | Attribute_Word_Size => @@ -3793,6 +4086,9 @@ package body Exp_Attr is end case; + exception + when RE_Not_Available => + return; end Expand_N_Attribute_Reference; ---------------------- @@ -3825,7 +4121,8 @@ 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 => @@ -3841,46 +4138,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. - -- If Typ is a derived tagged type, the corresponding primitive - -- operation has been created explicitly. + Btyp := Etype (Btyp); + end loop; - if Is_Derived_Type (P_Type) then - if Is_Tagged_Type (P_Type) then - return Find_Prim_Op (P_Type, Nam); - else - while Is_Derived_Type (P_Type) loop - Proc := TSS (Base_Type (Etype (Typ)), Nam); + if No (Proc) then - if Present (Proc) then - return Proc; - else - P_Type := Base_Type (Etype (P_Type)); - end if; - end loop; - end if; + -- If nothing else, use the TSS of the root type + + 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 -- ----------------------- |