diff options
Diffstat (limited to 'gcc/ada/sem_util.adb')
-rw-r--r-- | gcc/ada/sem_util.adb | 1214 |
1 files changed, 1040 insertions, 174 deletions
diff --git a/gcc/ada/sem_util.adb b/gcc/ada/sem_util.adb index 45c02c5..e5cb289 100644 --- a/gcc/ada/sem_util.adb +++ b/gcc/ada/sem_util.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- -- @@ -26,10 +26,13 @@ with Atree; use Atree; with Casing; use Casing; +with Checks; use Checks; with Debug; use Debug; with Errout; use Errout; with Elists; use Elists; +with Exp_Tss; use Exp_Tss; with Exp_Util; use Exp_Util; +with Fname; use Fname; with Freeze; use Freeze; with Lib; use Lib; with Lib.Xref; use Lib.Xref; @@ -63,21 +66,30 @@ package body Sem_Util is ----------------------- function Build_Component_Subtype - (C : List_Id; - Loc : Source_Ptr; - T : Entity_Id) - return Node_Id; + (C : List_Id; + Loc : Source_Ptr; + T : Entity_Id) return Node_Id; -- This function builds the subtype for Build_Actual_Subtype_Of_Component -- and Build_Discriminal_Subtype_Of_Component. C is a list of constraints, -- Loc is the source location, T is the original subtype. + function Is_Fully_Initialized_Variant (Typ : Entity_Id) return Boolean; + -- Subsidiary to Is_Fully_Initialized_Type. For an unconstrained type + -- with discriminants whose default values are static, examine only the + -- components in the selected variant to determine whether all of them + -- have a default. + + function Has_Null_Extension (T : Entity_Id) return Boolean; + -- T is a derived tagged type. Check whether the type extension is null. + -- If the parent type is fully initialized, T can be treated as such. + -------------------------------- -- Add_Access_Type_To_Process -- -------------------------------- - procedure Add_Access_Type_To_Process (E : Entity_Id; A : Entity_Id) - is + procedure Add_Access_Type_To_Process (E : Entity_Id; A : Entity_Id) is L : Elist_Id; + begin Ensure_Freeze_Node (E); L := Access_Types_To_Process (Freeze_Node (E)); @@ -110,7 +122,8 @@ package body Sem_Util is Ent : Entity_Id := Empty; Typ : Entity_Id := Empty; Loc : Source_Ptr := No_Location; - Rep : Boolean := True) + Rep : Boolean := True; + Warn : Boolean := False) is Stat : constant Boolean := Is_Static_Expression (N); Rtyp : Entity_Id; @@ -122,7 +135,7 @@ package body Sem_Util is Rtyp := Typ; end if; - if No (Compile_Time_Constraint_Error (N, Msg, Ent, Loc)) + if No (Compile_Time_Constraint_Error (N, Msg, Ent, Loc, Warn => Warn)) or else not Rep then return; @@ -152,9 +165,8 @@ package body Sem_Util is -------------------------- function Build_Actual_Subtype - (T : Entity_Id; - N : Node_Or_Entity_Id) - return Node_Id + (T : Entity_Id; + N : Node_Or_Entity_Id) return Node_Id is Obj : Node_Id; @@ -181,7 +193,7 @@ package body Sem_Util is -- Build an array subtype declaration with the nominal -- subtype and the bounds of the actual. Add the declaration - -- in front of the local declarations for the subprogram,for + -- in front of the local declarations for the subprogram, for -- analysis before any reference to the formal in the body. Lo := @@ -204,7 +216,8 @@ package body Sem_Util is end loop; -- If the type has unknown discriminants there is no constrained - -- subtype to build. + -- subtype to build. This is never called for a formal or for a + -- lhs, so returning the type is ok ??? elsif Has_Unknown_Discriminants (T) then return T; @@ -258,9 +271,8 @@ package body Sem_Util is --------------------------------------- function Build_Actual_Subtype_Of_Component - (T : Entity_Id; - N : Node_Id) - return Node_Id + (T : Entity_Id; + N : Node_Id) return Node_Id is Loc : constant Source_Ptr := Sloc (N); P : constant Node_Id := Prefix (N); @@ -286,7 +298,7 @@ package body Sem_Util is ----------------------------------- function Build_Actual_Array_Constraint return List_Id is - Constraints : List_Id := New_List; + Constraints : constant List_Id := New_List; Indx : Node_Id; Hi : Node_Id; Lo : Node_Id; @@ -340,7 +352,7 @@ package body Sem_Util is ------------------------------------ function Build_Actual_Record_Constraint return List_Id is - Constraints : List_Id := New_List; + Constraints : constant List_Id := New_List; D : Elmt_Id; D_Val : Node_Id; @@ -367,7 +379,10 @@ package body Sem_Util is -- Start of processing for Build_Actual_Subtype_Of_Component begin - if Nkind (N) = N_Explicit_Dereference then + if In_Default_Expression then + return Empty; + + elsif Nkind (N) = N_Explicit_Dereference then if Is_Composite_Type (T) and then not Is_Constrained (T) and then not (Is_Class_Wide_Type (T) @@ -397,7 +412,6 @@ package body Sem_Util is end if; if Ekind (Deaccessed_T) = E_Array_Subtype then - Id := First_Index (Deaccessed_T); Indx_Type := Underlying_Type (Etype (Id)); @@ -436,7 +450,6 @@ package body Sem_Util is -- If none of the above, the actual and nominal subtypes are the same. return Empty; - end Build_Actual_Subtype_Of_Component; ----------------------------- @@ -444,10 +457,9 @@ package body Sem_Util is ----------------------------- function Build_Component_Subtype - (C : List_Id; - Loc : Source_Ptr; - T : Entity_Id) - return Node_Id + (C : List_Id; + Loc : Source_Ptr; + T : Entity_Id) return Node_Id is Subt : Entity_Id; Decl : Node_Id; @@ -477,8 +489,7 @@ package body Sem_Util is -------------------------------------------- function Build_Discriminal_Subtype_Of_Component - (T : Entity_Id) - return Node_Id + (T : Entity_Id) return Node_Id is Loc : constant Source_Ptr := Sloc (T); D : Elmt_Id; @@ -498,7 +509,7 @@ package body Sem_Util is ---------------------------------------- function Build_Discriminal_Array_Constraint return List_Id is - Constraints : List_Id := New_List; + Constraints : constant List_Id := New_List; Indx : Node_Id; Hi : Node_Id; Lo : Node_Id; @@ -537,14 +548,13 @@ package body Sem_Util is ----------------------------------------- function Build_Discriminal_Record_Constraint return List_Id is - Constraints : List_Id := New_List; - D : Elmt_Id; - D_Val : Node_Id; + Constraints : constant List_Id := New_List; + D : Elmt_Id; + D_Val : Node_Id; begin D := First_Elmt (Discriminant_Constraint (T)); while Present (D) loop - if Denotes_Discriminant (Node (D)) then D_Val := New_Occurrence_Of (Discriminal (Entity (Node (D))), Loc); @@ -564,11 +574,9 @@ package body Sem_Util is begin if Ekind (T) = E_Array_Subtype then - Id := First_Index (T); while Present (Id) loop - if Denotes_Discriminant (Type_Low_Bound (Etype (Id))) or else Denotes_Discriminant (Type_High_Bound (Etype (Id))) then @@ -585,7 +593,6 @@ package body Sem_Util is then D := First_Elmt (Discriminant_Constraint (T)); while Present (D) loop - if Denotes_Discriminant (Node (D)) then return Build_Component_Subtype (Build_Discriminal_Record_Constraint, Loc, T); @@ -598,7 +605,6 @@ package body Sem_Util is -- If none of the above, the actual and nominal subtypes are the same. return Empty; - end Build_Discriminal_Subtype_Of_Component; ------------------------------ @@ -672,6 +678,7 @@ package body Sem_Util is -- assign a value to the variable in the binder main. Set_Is_True_Constant (Elab_Ent, False); + Set_Current_Value (Elab_Ent, Empty); -- We do not want any further qualification of the name (if we did -- not do this, we would pick up the name of the generic package @@ -708,9 +715,7 @@ package body Sem_Util is return not Do_Discriminant_Check (Expr); when N_Attribute_Reference => - if Do_Overflow_Check (Expr) - or else Do_Access_Check (Expr) - then + if Do_Overflow_Check (Expr) then return False; elsif No (Expressions (Expr)) then @@ -812,15 +817,41 @@ package body Sem_Util is procedure Check_Fully_Declared (T : Entity_Id; N : Node_Id) is begin if Ekind (T) = E_Incomplete_Type then - Error_Msg_NE - ("premature usage of incomplete}", N, First_Subtype (T)); + + -- If the type is available through a limited_with_clause, + -- verify that its full view has been analyzed. + + if From_With_Type (T) + and then Present (Non_Limited_View (T)) + and then Ekind (Non_Limited_View (T)) /= E_Incomplete_Type + then + -- The non-limited view is fully declared + null; + + else + Error_Msg_NE + ("premature usage of incomplete}", N, First_Subtype (T)); + end if; elsif Has_Private_Component (T) and then not Is_Generic_Type (Root_Type (T)) and then not In_Default_Expression then - Error_Msg_NE - ("premature usage of incomplete}", N, First_Subtype (T)); + + -- Special case: if T is the anonymous type created for a single + -- task or protected object, use the name of the source object. + + if Is_Concurrent_Type (T) + and then not Comes_From_Source (T) + and then Nkind (N) = N_Object_Declaration + then + Error_Msg_NE ("type of& has incomplete component", N, + Defining_Identifier (N)); + + else + Error_Msg_NE + ("premature usage of incomplete}", N, First_Subtype (T)); + end if; end if; end Check_Fully_Declared; @@ -847,7 +878,7 @@ package body Sem_Util is while Present (S) and then S /= Standard_Standard loop if Is_Protected_Type (S) then if Restricted_Profile then - Insert_Before (N, + Insert_Before_And_Analyze (N, Make_Raise_Program_Error (Loc, Reason => PE_Potentially_Blocking_Operation)); Error_Msg_N ("potentially blocking operation, " & @@ -1006,9 +1037,7 @@ package body Sem_Util is B_Scope := System_Aux_Id; Id := First_Entity (System_Aux_Id); end if; - end loop; - end if; return Op_List; @@ -1022,12 +1051,12 @@ package body Sem_Util is (N : Node_Id; Msg : String; Ent : Entity_Id := Empty; - Loc : Source_Ptr := No_Location) - return Node_Id + Loc : Source_Ptr := No_Location; + Warn : Boolean := False) return Node_Id is Msgc : String (1 .. Msg'Length + 2); Msgl : Natural; - Warn : Boolean; + Wmsg : Boolean; P : Node_Id; Msgs : Boolean; Eloc : Source_Ptr; @@ -1056,28 +1085,26 @@ package body Sem_Util is -- Message is a warning, even in Ada 95 case if Msg (Msg'Length) = '?' then - Warn := True; + Wmsg := True; -- In Ada 83, all messages are warnings. In the private part and -- the body of an instance, constraint_checks are only warnings. + -- We also make this a warning if the Warn parameter is set. - elsif Ada_83 and then Comes_From_Source (N) then - + elsif Warn or else (Ada_83 and then Comes_From_Source (N)) then Msgl := Msgl + 1; Msgc (Msgl) := '?'; - Warn := True; + Wmsg := True; elsif In_Instance_Not_Visible then - Msgl := Msgl + 1; Msgc (Msgl) := '?'; - Warn := True; - Warn_On_Instance := True; + Wmsg := True; -- Otherwise we have a real error message (Ada 95 static case) else - Warn := False; + Wmsg := False; end if; -- Should we generate a warning? The answer is not quite yes. The @@ -1118,7 +1145,7 @@ package body Sem_Util is Error_Msg_NEL (Msgc (1 .. Msgl), N, Etype (N), Eloc); end if; - if Warn then + if Wmsg then if Inside_Init_Proc then Error_Msg_NEL ("\& will be raised for objects of this type!?", @@ -1217,16 +1244,8 @@ package body Sem_Util is Scop : constant Entity_Id := Current_Scope; begin - if Ekind (Scop) = E_Function - or else - Ekind (Scop) = E_Procedure - or else - Ekind (Scop) = E_Generic_Function - or else - Ekind (Scop) = E_Generic_Procedure - then + if Is_Subprogram (Scop) or else Is_Generic_Subprogram (Scop) then return Scop; - else return Enclosing_Subprogram (Scop); end if; @@ -1343,11 +1362,35 @@ package body Sem_Util is -- Denotes_Discriminant -- -------------------------- - function Denotes_Discriminant (N : Node_Id) return Boolean is + function Denotes_Discriminant + (N : Node_Id; + Check_Protected : Boolean := False) return Boolean + is + E : Entity_Id; begin - return Is_Entity_Name (N) - and then Present (Entity (N)) - and then Ekind (Entity (N)) = E_Discriminant; + if not Is_Entity_Name (N) + or else No (Entity (N)) + then + return False; + else + E := Entity (N); + end if; + + -- If we are checking for a protected type, the discriminant may have + -- been rewritten as the corresponding discriminal of the original type + -- or of the corresponding concurrent record, depending on whether we + -- are in the spec or body of the protected type. + + return Ekind (E) = E_Discriminant + or else + (Check_Protected + and then Ekind (E) = E_In_Parameter + and then Present (Discriminal_Link (E)) + and then + (Is_Protected_Type (Scope (Discriminal_Link (E))) + or else + Is_Concurrent_Record_Type (Scope (Discriminal_Link (E))))); + end Denotes_Discriminant; ----------------------------- @@ -1369,11 +1412,10 @@ package body Sem_Util is function Designate_Same_Unit (Name1 : Node_Id; - Name2 : Node_Id) - return Boolean + Name2 : Node_Id) return Boolean is - K1 : Node_Kind := Nkind (Name1); - K2 : Node_Kind := Nkind (Name2); + K1 : constant Node_Kind := Nkind (Name1); + K2 : constant Node_Kind := Nkind (Name2); function Prefix_Node (N : Node_Id) return Node_Id; -- Returns the parent unit name node of a defining program unit name @@ -1384,6 +1426,10 @@ package body Sem_Util is -- name or the selector node if N is a selected component or an -- expanded name. + ----------------- + -- Prefix_Node -- + ----------------- + function Prefix_Node (N : Node_Id) return Node_Id is begin if Nkind (N) = N_Defining_Program_Unit_Name then @@ -1394,6 +1440,10 @@ package body Sem_Util is end if; end Prefix_Node; + ----------------- + -- Select_Node -- + ----------------- + function Select_Node (N : Node_Id) return Node_Id is begin if Nkind (N) = N_Defining_Program_Unit_Name then @@ -1439,8 +1489,7 @@ package body Sem_Util is ---------------------------- function Enclosing_Generic_Body - (E : Entity_Id) - return Node_Id + (E : Entity_Id) return Node_Id is P : Node_Id; Decl : Node_Id; @@ -1631,6 +1680,7 @@ package body Sem_Util is declare Prev : Entity_Id; Prev_Vis : Entity_Id; + Decl : constant Node_Id := Parent (E); begin -- If E is an implicit declaration, it cannot be the first @@ -1638,33 +1688,51 @@ package body Sem_Util is Prev := First_Entity (Current_Scope); - while Next_Entity (Prev) /= E loop + while Present (Prev) + and then Next_Entity (Prev) /= E + loop Next_Entity (Prev); end loop; - Set_Next_Entity (Prev, Next_Entity (E)); + if No (Prev) then - if No (Next_Entity (Prev)) then - Set_Last_Entity (Current_Scope, Prev); - end if; + -- If E is not on the entity chain of the current scope, + -- it is an implicit declaration in the generic formal + -- part of a generic subprogram. When analyzing the body, + -- the generic formals are visible but not on the entity + -- chain of the subprogram. The new entity will become + -- the visible one in the body. + + pragma Assert + (Nkind (Parent (Decl)) = N_Generic_Subprogram_Declaration); + null; - if E = Current_Entity (E) then - Prev_Vis := Empty; else - Prev_Vis := Current_Entity (E); - while Homonym (Prev_Vis) /= E loop - Prev_Vis := Homonym (Prev_Vis); - end loop; - end if; + Set_Next_Entity (Prev, Next_Entity (E)); + + if No (Next_Entity (Prev)) then + Set_Last_Entity (Current_Scope, Prev); + end if; + + if E = Current_Entity (E) then + Prev_Vis := Empty; + + else + Prev_Vis := Current_Entity (E); + while Homonym (Prev_Vis) /= E loop + Prev_Vis := Homonym (Prev_Vis); + end loop; + end if; - if Present (Prev_Vis) then + if Present (Prev_Vis) then - -- Skip E in the visibility chain + -- Skip E in the visibility chain - Set_Homonym (Prev_Vis, Homonym (E)); + Set_Homonym (Prev_Vis, Homonym (E)); - else - Set_Name_Entity_Id (Chars (E), Homonym (E)); + else + Set_Name_Entity_Id (Chars (E), Homonym (E)); + end if; end if; end; @@ -1829,8 +1897,8 @@ package body Sem_Util is -- Warn if new entity hides an old one if Warn_On_Hiding - and then Length_Of_Name (Chars (C)) /= 1 and then Present (C) + and then Length_Of_Name (Chars (C)) /= 1 and then Comes_From_Source (C) and then Comes_From_Source (Def_Id) and then In_Extended_Main_Source_Unit (Def_Id) @@ -1838,17 +1906,60 @@ package body Sem_Util is Error_Msg_Sloc := Sloc (C); Error_Msg_N ("declaration hides &#?", Def_Id); end if; - end Enter_Name; + -------------------------- + -- Explain_Limited_Type -- + -------------------------- + + procedure Explain_Limited_Type (T : Entity_Id; N : Node_Id) is + C : Entity_Id; + + begin + -- For array, component type must be limited + + if Is_Array_Type (T) then + Error_Msg_Node_2 := T; + Error_Msg_NE + ("component type& of type& is limited", N, Component_Type (T)); + Explain_Limited_Type (Component_Type (T), N); + + elsif Is_Record_Type (T) then + + -- No need for extra messages if explicit limited record + + if Is_Limited_Record (Base_Type (T)) then + return; + end if; + + -- Otherwise find a limited component + + C := First_Component (T); + while Present (C) loop + if Is_Limited_Type (Etype (C)) then + Error_Msg_Node_2 := T; + Error_Msg_NE ("\component& of type& has limited type", N, C); + Explain_Limited_Type (Etype (C), N); + return; + end if; + + Next_Component (C); + end loop; + + -- It's odd if the loop falls through, but this is only an extra + -- error message, so we just let it go and ignore the situation. + + return; + end if; + end Explain_Limited_Type; + ------------------------------------- -- Find_Corresponding_Discriminant -- ------------------------------------- function Find_Corresponding_Discriminant - (Id : Node_Id; - Typ : Entity_Id) - return Entity_Id + (Id : Node_Id; + Typ : Entity_Id) return Entity_Id is Par_Disc : Entity_Id; Old_Disc : Entity_Id; @@ -1878,6 +1989,84 @@ package body Sem_Util is raise Program_Error; end Find_Corresponding_Discriminant; + ----------------------------- + -- Find_Static_Alternative -- + ----------------------------- + + function Find_Static_Alternative (N : Node_Id) return Node_Id is + Expr : constant Node_Id := Expression (N); + Val : constant Uint := Expr_Value (Expr); + Alt : Node_Id; + Choice : Node_Id; + + begin + Alt := First (Alternatives (N)); + + Search : loop + if Nkind (Alt) /= N_Pragma then + Choice := First (Discrete_Choices (Alt)); + + while Present (Choice) loop + + -- Others choice, always matches + + if Nkind (Choice) = N_Others_Choice then + exit Search; + + -- Range, check if value is in the range + + elsif Nkind (Choice) = N_Range then + exit Search when + Val >= Expr_Value (Low_Bound (Choice)) + and then + Val <= Expr_Value (High_Bound (Choice)); + + -- Choice is a subtype name. Note that we know it must + -- be a static subtype, since otherwise it would have + -- been diagnosed as illegal. + + elsif Is_Entity_Name (Choice) + and then Is_Type (Entity (Choice)) + then + exit Search when Is_In_Range (Expr, Etype (Choice)); + + -- Choice is a subtype indication + + elsif Nkind (Choice) = N_Subtype_Indication then + declare + C : constant Node_Id := Constraint (Choice); + R : constant Node_Id := Range_Expression (C); + + begin + exit Search when + Val >= Expr_Value (Low_Bound (R)) + and then + Val <= Expr_Value (High_Bound (R)); + end; + + -- Choice is a simple expression + + else + exit Search when Val = Expr_Value (Choice); + end if; + + Next (Choice); + end loop; + end if; + + Next (Alt); + pragma Assert (Present (Alt)); + end loop Search; + + -- The above loop *must* terminate by finding a match, since + -- we know the case statement is valid, and the value of the + -- expression is known at compile time. When we fall out of + -- the loop, Alt points to the alternative that we know will + -- be selected at run time. + + return Alt; + end Find_Static_Alternative; + ------------------ -- First_Actual -- ------------------ @@ -1904,12 +2093,16 @@ package body Sem_Util is ------------------------- function Full_Qualified_Name (E : Entity_Id) return String_Id is - Res : String_Id; + pragma Warnings (Off, Res); function Internal_Full_Qualified_Name (E : Entity_Id) return String_Id; -- Compute recursively the qualified name without NUL at the end. + ---------------------------------- + -- Internal_Full_Qualified_Name -- + ---------------------------------- + function Internal_Full_Qualified_Name (E : Entity_Id) return String_Id is Ent : Entity_Id := E; Parent_Name : String_Id := No_String; @@ -1953,6 +2146,8 @@ package body Sem_Util is return End_String; end Internal_Full_Qualified_Name; + -- Start of processing for Full_Qualified_Name + begin Res := Internal_Full_Qualified_Name (E); Store_String_Char (Get_Char_Code (ASCII.nul)); @@ -2033,32 +2228,48 @@ package body Sem_Util is if No (Next (Assoc)) then if not Is_Constrained (Typ) and then Is_Derived_Type (Typ) - and then Present (Girder_Constraint (Typ)) + and then Present (Stored_Constraint (Typ)) then -- If the type is a tagged type with inherited discriminants, - -- use the girder constraint on the parent in order to find + -- use the stored constraint on the parent in order to find -- the values of discriminants that are otherwise hidden by an -- explicit constraint. Renamed discriminants are handled in -- the code above. + -- If several parent discriminants are renamed by a single + -- discriminant of the derived type, the call to obtain the + -- Corresponding_Discriminant field only retrieves the last + -- of them. We recover the constraint on the others from the + -- Stored_Constraint as well. + declare D : Entity_Id; C : Elmt_Id; begin D := First_Discriminant (Etype (Typ)); - C := First_Elmt (Girder_Constraint (Typ)); + C := First_Elmt (Stored_Constraint (Typ)); while Present (D) and then Present (C) loop if Chars (Discrim_Name) = Chars (D) then - Assoc := - Make_Component_Association (Sloc (Typ), - New_List - (New_Occurrence_Of (D, Sloc (Typ))), - Duplicate_Subexpr_No_Checks (Node (C))); + if Is_Entity_Name (Node (C)) + and then Entity (Node (C)) = Entity (Discrim) + then + -- D is renamed by Discrim, whose value is + -- given in Assoc. + + null; + + else + Assoc := + Make_Component_Association (Sloc (Typ), + New_List + (New_Occurrence_Of (D, Sloc (Typ))), + Duplicate_Subexpr_No_Checks (Node (C))); + end if; exit Find_Constraint; end if; @@ -2082,8 +2293,10 @@ package body Sem_Util is Discrim_Value := Expression (Assoc); if not Is_OK_Static_Expression (Discrim_Value) then - Error_Msg_NE - ("value for discriminant & must be static", Discrim_Value, Discrim); + Error_Msg_FE + ("value for discriminant & must be static!", + Discrim_Value, Discrim); + Why_Not_Static (Discrim_Value); Report_Errors := True; return; end if; @@ -2189,6 +2402,14 @@ package body Sem_Util is if In_Default_Expression then return Typ; + elsif Is_Private_Type (Typ) + and then not Has_Discriminants (Typ) + then + -- If the type has no discriminants, there is no subtype to + -- build, even if the underlying type is discriminated. + + return Typ; + -- Else build the actual subtype else @@ -2276,7 +2497,6 @@ package body Sem_Util is return Make_String_Literal (Sloc (E), Strval => String_From_Name_Buffer); - end Get_Default_External_Name; --------------------------- @@ -2284,10 +2504,9 @@ package body Sem_Util is --------------------------- function Get_Enum_Lit_From_Pos - (T : Entity_Id; - Pos : Uint; - Loc : Source_Ptr) - return Node_Id + (T : Entity_Id; + Pos : Uint; + Loc : Source_Ptr) return Node_Id is Lit : Node_Id; P : constant Nat := UI_To_Int (Pos); @@ -2456,6 +2675,43 @@ package body Sem_Util is and then Includes_Infinities (Scalar_Range (E)); end Has_Infinities; + ------------------------ + -- Has_Null_Extension -- + ------------------------ + + function Has_Null_Extension (T : Entity_Id) return Boolean is + B : constant Entity_Id := Base_Type (T); + Comps : Node_Id; + Ext : Node_Id; + + begin + if Nkind (Parent (B)) = N_Full_Type_Declaration + and then Present (Record_Extension_Part (Type_Definition (Parent (B)))) + then + Ext := Record_Extension_Part (Type_Definition (Parent (B))); + + if Present (Ext) then + if Null_Present (Ext) then + return True; + else + Comps := Component_List (Ext); + + -- The null component list is rewritten during analysis to + -- include the parent component. Any other component indicates + -- that the extension was not originally null. + + return Null_Present (Comps) + or else No (Next (First (Component_Items (Comps)))); + end if; + else + return False; + end if; + + else + return False; + end if; + end Has_Null_Extension; + --------------------------- -- Has_Private_Component -- --------------------------- @@ -2667,6 +2923,29 @@ package body Sem_Util is return False; end In_Instance_Visible_Part; + ---------------------- + -- In_Packiage_Body -- + ---------------------- + + function In_Package_Body return Boolean is + S : Entity_Id := Current_Scope; + + begin + while Present (S) + and then S /= Standard_Standard + loop + if Ekind (S) = E_Package + and then In_Package_Body (S) + then + return True; + else + S := Scope (S); + end if; + end loop; + + return False; + end In_Package_Body; + -------------------------------------- -- In_Subprogram_Or_Concurrent_Unit -- -------------------------------------- @@ -2684,8 +2963,7 @@ package body Sem_Util is if K in Subprogram_Kind or else K in Concurrent_Kind - or else K = E_Generic_Procedure - or else K = E_Generic_Function + or else K in Generic_Subprogram_Kind then return True; @@ -2695,7 +2973,6 @@ package body Sem_Util is E := Scope (E); end loop; - end In_Subprogram_Or_Concurrent_Unit; --------------------- @@ -2711,6 +2988,45 @@ package body Sem_Util is and then not In_Private_Part (Scope_Id); end In_Visible_Part; + --------------------------------- + -- Insert_Explicit_Dereference -- + --------------------------------- + + procedure Insert_Explicit_Dereference (N : Node_Id) is + New_Prefix : constant Node_Id := Relocate_Node (N); + I : Interp_Index; + It : Interp; + T : Entity_Id; + + begin + Save_Interps (N, New_Prefix); + Rewrite (N, + Make_Explicit_Dereference (Sloc (N), Prefix => New_Prefix)); + + Set_Etype (N, Designated_Type (Etype (New_Prefix))); + + if Is_Overloaded (New_Prefix) then + + -- The deference is also overloaded, and its interpretations are the + -- designated types of the interpretations of the original node. + + Set_Etype (N, Any_Type); + Get_First_Interp (New_Prefix, I, It); + + while Present (It.Nam) loop + T := It.Typ; + + if Is_Access_Type (T) then + Add_One_Interp (N, Designated_Type (T), Designated_Type (T)); + end if; + + Get_Next_Interp (I, It); + end loop; + + End_Interp_List; + end if; + end Insert_Explicit_Dereference; + ------------------- -- Is_AAMP_Float -- ------------------- @@ -2795,7 +3111,7 @@ package body Sem_Util is or else Nkind (Obj) = N_Type_Conversion then return Is_Tagged_Type (Etype (Obj)) - or else Is_Aliased_View (Expression (Obj)); + and then Is_Aliased_View (Expression (Obj)); elsif Nkind (Obj) = N_Explicit_Dereference then return Nkind (Original_Node (Obj)) /= N_Function_Call; @@ -2873,8 +3189,7 @@ package body Sem_Util is ---------------------------------------------- function Is_Dependent_Component_Of_Mutable_Object - (Object : Node_Id) - return Boolean + (Object : Node_Id) return Boolean is P : Node_Id; Prefix_Type : Entity_Id; @@ -3009,6 +3324,25 @@ package body Sem_Util is return False; end Is_Dependent_Component_Of_Mutable_Object; + --------------------- + -- Is_Dereferenced -- + --------------------- + + function Is_Dereferenced (N : Node_Id) return Boolean is + P : constant Node_Id := Parent (N); + + begin + return + (Nkind (P) = N_Selected_Component + or else + Nkind (P) = N_Explicit_Dereference + or else + Nkind (P) = N_Indexed_Component + or else + Nkind (P) = N_Slice) + and then Prefix (P) = N; + end Is_Dereferenced; + -------------- -- Is_False -- -------------- @@ -3106,7 +3440,56 @@ package body Sem_Util is return False; + -- Record types + elsif Is_Record_Type (Typ) then + if Has_Discriminants (Typ) + and then + Present (Discriminant_Default_Value (First_Discriminant (Typ))) + and then Is_Fully_Initialized_Variant (Typ) + then + return True; + end if; + + -- Controlled records are considered to be fully initialized if + -- there is a user defined Initialize routine. This may not be + -- entirely correct, but as the spec notes, we are guessing here + -- what is best from the point of view of issuing warnings. + + if Is_Controlled (Typ) then + declare + Utyp : constant Entity_Id := Underlying_Type (Typ); + + begin + if Present (Utyp) then + declare + Init : constant Entity_Id := + (Find_Prim_Op + (Underlying_Type (Typ), Name_Initialize)); + + begin + if Present (Init) + and then Comes_From_Source (Init) + and then not + Is_Predefined_File_Name + (File_Name (Get_Source_File_Index (Sloc (Init)))) + then + return True; + + elsif Has_Null_Extension (Typ) + and then + Is_Fully_Initialized_Type + (Etype (Base_Type (Typ))) + then + return True; + end if; + end; + end if; + end; + end if; + + -- Otherwise see if all record components are initialized + declare Ent : Entity_Id; @@ -3114,7 +3497,10 @@ package body Sem_Util is Ent := First_Entity (Typ); while Present (Ent) loop - if Ekind (Ent) = E_Component + if Chars (Ent) = Name_uController then + null; + + elsif Ekind (Ent) = E_Component and then (No (Parent (Ent)) or else No (Expression (Parent (Ent)))) and then not Is_Fully_Initialized_Type (Etype (Ent)) @@ -3151,6 +3537,95 @@ package body Sem_Util is end if; end Is_Fully_Initialized_Type; + ---------------------------------- + -- Is_Fully_Initialized_Variant -- + ---------------------------------- + + function Is_Fully_Initialized_Variant (Typ : Entity_Id) return Boolean is + Loc : constant Source_Ptr := Sloc (Typ); + Comp_Elmt : Elmt_Id; + Comp_Id : Node_Id; + Comp_List : Node_Id; + Discr : Entity_Id; + Discr_Val : Node_Id; + Constraints : List_Id := New_List; + Components : Elist_Id := New_Elmt_List; + Report_Errors : Boolean; + + begin + if Serious_Errors_Detected > 0 then + return False; + end if; + + if Is_Record_Type (Typ) + and then Nkind (Parent (Typ)) = N_Full_Type_Declaration + and then Nkind (Type_Definition (Parent (Typ))) = N_Record_Definition + then + Comp_List := Component_List (Type_Definition (Parent (Typ))); + Discr := First_Discriminant (Typ); + + while Present (Discr) loop + if Nkind (Parent (Discr)) = N_Discriminant_Specification then + Discr_Val := Expression (Parent (Discr)); + if not Is_OK_Static_Expression (Discr_Val) then + return False; + else + Append_To (Constraints, + Make_Component_Association (Loc, + Choices => New_List (New_Occurrence_Of (Discr, Loc)), + Expression => New_Copy (Discr_Val))); + + end if; + else + return False; + end if; + + Next_Discriminant (Discr); + end loop; + + Gather_Components + (Typ => Typ, + Comp_List => Comp_List, + Governed_By => Constraints, + Into => Components, + Report_Errors => Report_Errors); + + -- Check that each component present is fully initialized. + + Comp_Elmt := First_Elmt (Components); + + while Present (Comp_Elmt) loop + Comp_Id := Node (Comp_Elmt); + + if Ekind (Comp_Id) = E_Component + and then (No (Parent (Comp_Id)) + or else No (Expression (Parent (Comp_Id)))) + and then not Is_Fully_Initialized_Type (Etype (Comp_Id)) + then + return False; + end if; + + Next_Elmt (Comp_Elmt); + end loop; + + return True; + + elsif Is_Private_Type (Typ) then + declare + U : constant Entity_Id := Underlying_Type (Typ); + + begin + if No (U) then + return False; + else + return Is_Fully_Initialized_Variant (U); + end if; + end; + else + return False; + end if; + end Is_Fully_Initialized_Variant; + ---------------------------- -- Is_Inherited_Operation -- ---------------------------- @@ -3173,6 +3648,17 @@ package body Sem_Util is function Is_Library_Level_Entity (E : Entity_Id) return Boolean is begin + -- The following is a small optimization, and it also handles + -- properly discriminals, which in task bodies might appear in + -- expressions before the corresponding procedure has been + -- created, and which therefore do not have an assigned scope. + + if Ekind (E) in Formal_Kind then + return False; + end if; + + -- Normal test is simply that the enclosing dynamic scope is Standard + return Enclosing_Dynamic_Scope (E) = Standard_Standard; end Is_Library_Level_Entity; @@ -3204,6 +3690,60 @@ package body Sem_Util is end if; end Is_Local_Variable_Reference; + --------------- + -- Is_Lvalue -- + --------------- + + function Is_Lvalue (N : Node_Id) return Boolean is + P : constant Node_Id := Parent (N); + + begin + case Nkind (P) is + + -- Test left side of assignment + + when N_Assignment_Statement => + return N = Name (P); + + -- Test prefix of component or attribute + + when N_Attribute_Reference | + N_Expanded_Name | + N_Explicit_Dereference | + N_Indexed_Component | + N_Reference | + N_Selected_Component | + N_Slice => + return N = Prefix (P); + + -- Test subprogram parameter (we really should check the + -- parameter mode, but it is not worth the trouble) + + when N_Function_Call | + N_Procedure_Call_Statement | + N_Accept_Statement | + N_Parameter_Association => + return True; + + -- Test for appearing in a conversion that itself appears + -- in an lvalue context, since this should be an lvalue. + + when N_Type_Conversion => + return Is_Lvalue (P); + + -- Test for appearence in object renaming declaration + + when N_Object_Renaming_Declaration => + return True; + + -- All other references are definitely not Lvalues + + when others => + return False; + + end case; + end Is_Lvalue; + ------------------------- -- Is_Object_Reference -- ------------------------- @@ -3218,12 +3758,12 @@ package body Sem_Util is when N_Indexed_Component | N_Slice => return Is_Object_Reference (Prefix (N)); - -- In Ada95, a function call is a constant object. + -- In Ada95, a function call is a constant object when N_Function_Call => return True; - -- A reference to the stream attribute Input is a function call. + -- A reference to the stream attribute Input is a function call when N_Attribute_Reference => return Attribute_Name (N) = Name_Input; @@ -3315,7 +3855,7 @@ package body Sem_Util is -- If this node is rewritten, then test the original form, if that is -- OK, then we consider the rewritten node OK (for example, if the -- original node is a conversion, then Is_Variable will not be true - -- but we still want to allow the conversion if it converts a variable. + -- but we still want to allow the conversion if it converts a variable). elsif Original_Node (AV) /= AV then return Is_OK_Variable_For_Out_Formal (Original_Node (AV)); @@ -3484,16 +4024,16 @@ package body Sem_Util is ----------------------------------------- function Is_Remote_Access_To_Class_Wide_Type - (E : Entity_Id) - return Boolean + (E : Entity_Id) return Boolean is D : Entity_Id; function Comes_From_Limited_Private_Type_Declaration (E : Entity_Id) return Boolean; - -- Check if the original declaration is a limited private one and - -- if all the derivations have been using private extensions. + -- Check that the type is declared by a limited type declaration, + -- or else is derived from a Remote_Type ancestor through private + -- extensions. ------------------------------------------------- -- Comes_From_Limited_Private_Type_Declaration -- @@ -3511,7 +4051,12 @@ package body Sem_Util is end if; if Nkind (N) = N_Private_Extension_Declaration then - return Comes_From_Limited_Private_Type_Declaration (Etype (E)); + return + Comes_From_Limited_Private_Type_Declaration (Etype (E)) + or else + (Is_Remote_Types (Etype (E)) + and then Is_Limited_Record (Etype (E)) + and then Has_Private_Declaration (Etype (E))); end if; return False; @@ -3542,8 +4087,7 @@ package body Sem_Util is ----------------------------------------- function Is_Remote_Access_To_Subprogram_Type - (E : Entity_Id) - return Boolean + (E : Entity_Id) return Boolean is begin return (Ekind (E) = E_Access_Subprogram_Type @@ -3713,6 +4257,10 @@ package body Sem_Util is -- must test for the case of a reference of a constant access -- type, which can never be a variable. + --------------------------- + -- In_Protected_Function -- + --------------------------- + function In_Protected_Function (E : Entity_Id) return Boolean is Prot : constant Entity_Id := Scope (E); S : Entity_Id; @@ -3738,6 +4286,10 @@ package body Sem_Util is end if; end In_Protected_Function; + ------------------------ + -- Is_Variable_Prefix -- + ------------------------ + function Is_Variable_Prefix (P : Node_Id) return Boolean is begin if Is_Access_Type (Etype (P)) then @@ -3801,13 +4353,18 @@ package body Sem_Util is return Is_Variable_Prefix (Prefix (Orig_Node)) and then Is_Variable (Selector_Name (Orig_Node)); - -- For an explicit dereference, we must check whether the type - -- is ACCESS CONSTANT, since if it is, then it is not a variable. + -- For an explicit dereference, the type of the prefix cannot + -- be an access to constant or an access to subprogram. when N_Explicit_Dereference => - return Is_Access_Type (Etype (Prefix (Orig_Node))) - and then not - Is_Access_Constant (Root_Type (Etype (Prefix (Orig_Node)))); + declare + Typ : constant Entity_Id := Etype (Prefix (Orig_Node)); + + begin + return Is_Access_Type (Typ) + and then not Is_Access_Constant (Root_Type (Typ)) + and then Ekind (Typ) /= E_Access_Subprogram_Type; + end; -- The type conversion is the case where we do not deal with the -- context dependent special case of an actual parameter. Thus @@ -3853,19 +4410,38 @@ package body Sem_Util is function Is_Volatile_Prefix (N : Node_Id) return Boolean; -- If prefix is an implicit dereference, examine designated type. + ------------------------ + -- Is_Volatile_Prefix -- + ------------------------ + function Is_Volatile_Prefix (N : Node_Id) return Boolean is + Typ : constant Entity_Id := Etype (N); + begin - if Is_Access_Type (Etype (N)) then - return Has_Volatile_Components (Designated_Type (Etype (N))); + if Is_Access_Type (Typ) then + declare + Dtyp : constant Entity_Id := Designated_Type (Typ); + + begin + return Is_Volatile (Dtyp) + or else Has_Volatile_Components (Dtyp); + end; + else return Object_Has_Volatile_Components (N); end if; end Is_Volatile_Prefix; + ------------------------------------ + -- Object_Has_Volatile_Components -- + ------------------------------------ + function Object_Has_Volatile_Components (N : Node_Id) return Boolean is + Typ : constant Entity_Id := Etype (N); + begin - if Is_Volatile (Etype (N)) - or else Has_Volatile_Components (Etype (N)) + if Is_Volatile (Typ) + or else Has_Volatile_Components (Typ) then return True; @@ -3903,6 +4479,80 @@ package body Sem_Util is end if; end Is_Volatile_Object; + ------------------------- + -- Kill_Current_Values -- + ------------------------- + + procedure Kill_Current_Values is + S : Entity_Id; + + procedure Kill_Current_Values_For_Entity_Chain (E : Entity_Id); + -- Clear current value for entity E and all entities chained to E + + ------------------------------------------- + -- Kill_Current_Values_For_Entity_Chain -- + ------------------------------------------- + + procedure Kill_Current_Values_For_Entity_Chain (E : Entity_Id) is + Ent : Entity_Id; + + begin + Ent := E; + while Present (Ent) loop + if Is_Object (Ent) then + Set_Current_Value (Ent, Empty); + + if not Can_Never_Be_Null (Ent) then + Set_Is_Known_Non_Null (Ent, False); + end if; + end if; + + Next_Entity (Ent); + end loop; + end Kill_Current_Values_For_Entity_Chain; + + -- Start of processing for Kill_Current_Values + + begin + -- Kill all saved checks, a special case of killing saved values + + Kill_All_Checks; + + -- Loop through relevant scopes, which includes the current scope and + -- any parent scopes if the current scope is a block or a package. + + S := Current_Scope; + Scope_Loop : loop + + -- Clear current values of all entities in current scope + + Kill_Current_Values_For_Entity_Chain (First_Entity (S)); + + -- If scope is a package, also clear current values of all + -- private entities in the scope. + + if Ekind (S) = E_Package + or else + Ekind (S) = E_Generic_Package + or else + Is_Concurrent_Type (S) + then + Kill_Current_Values_For_Entity_Chain (First_Private_Entity (S)); + end if; + + -- If this is a block or nested package, deal with parent + + if Ekind (S) = E_Block + or else (Ekind (S) = E_Package + and then not Is_Library_Level_Entity (S)) + then + S := Scope (S); + else + exit Scope_Loop; + end if; + end loop Scope_Loop; + end Kill_Current_Values; + -------------------------- -- Kill_Size_Check_Code -- -------------------------- @@ -3928,8 +4578,7 @@ package body Sem_Util is Related_Id : Entity_Id; Suffix : Character; Suffix_Index : Nat := 0; - Prefix : Character := ' ') - return Entity_Id + Prefix : Character := ' ') return Entity_Id is N : constant Entity_Id := Make_Defining_Identifier (Sloc_Value, @@ -3957,8 +4606,7 @@ package body Sem_Util is (Kind : Entity_Kind; Scope_Id : Entity_Id; Sloc_Value : Source_Ptr; - Id_Char : Character) - return Entity_Id + Id_Char : Character) return Entity_Id is N : constant Entity_Id := Make_Defining_Identifier (Sloc_Value, New_Internal_Name (Id_Char)); @@ -4059,10 +4707,14 @@ package body Sem_Util is function Reporting return Boolean; -- Determines if an error is to be reported. To report an error, we -- need Report to be True, and also we do not report errors caused - -- by calls to Init_Proc's that occur within other Init_Proc's. Such + -- by calls to init procs that occur within other init procs. Such -- errors must always be cascaded errors, since if all the types are -- declared correctly, the compiler will certainly build decent calls! + ----------- + -- Chain -- + ----------- + procedure Chain (A : Node_Id) is begin if No (Last) then @@ -4079,6 +4731,10 @@ package body Sem_Util is Set_Next_Named_Actual (Last, Empty); end Chain; + --------------- + -- Reporting -- + --------------- + function Reporting return Boolean is begin if not Report then @@ -4087,7 +4743,7 @@ package body Sem_Util is elsif not Within_Init_Proc then return True; - elsif Chars (Entity (Name (N))) = Name_uInit_Proc then + elsif Is_Init_Proc (Entity (Name (N))) then return False; else @@ -4139,7 +4795,11 @@ package body Sem_Util is -- Too many actuals: will not work. if Reporting then - Error_Msg_N ("too many arguments in call", N); + if Is_Entity_Name (Name (N)) then + Error_Msg_N ("too many arguments in call to&", Name (N)); + else + Error_Msg_N ("too many arguments in call", N); + end if; end if; Success := False; @@ -4205,7 +4865,8 @@ package body Sem_Util is or else No (Default_Value (Formal)) then if Reporting then - if Comes_From_Source (S) + if (Comes_From_Source (S) + or else Sloc (S) = Standard_Location) and then Is_Overloadable (S) then Error_Msg_Name_1 := Chars (S); @@ -4213,6 +4874,19 @@ package body Sem_Util is Error_Msg_NE ("missing argument for parameter & " & "in call to % declared #", N, Formal); + + elsif Is_Overloadable (S) then + Error_Msg_Name_1 := Chars (S); + + -- Point to type derivation that + -- generated the operation. + + Error_Msg_Sloc := Sloc (Parent (S)); + + Error_Msg_NE + ("missing argument for parameter & " & + "in call to % (inherited) #", N, Formal); + else Error_Msg_NE ("missing argument for parameter &", N, Formal); @@ -4249,7 +4923,8 @@ package body Sem_Util is and then Actual /= Last and then No (Next_Named_Actual (Actual)) then - Error_Msg_N ("Unmatched actual in call", Actual); + Error_Msg_N ("unmatched actual & in call", + Selector_Name (Actual)); exit; end if; @@ -4272,12 +4947,28 @@ package body Sem_Util is procedure Set_Ref (E : Entity_Id; N : Node_Id); -- Internal routine to note modification on entity E by node N + -- Has no effect if entity E does not represent an object. + + ------------- + -- Set_Ref -- + ------------- procedure Set_Ref (E : Entity_Id; N : Node_Id) is begin - Set_Not_Source_Assigned (E, False); - Set_Is_True_Constant (E, False); - Generate_Reference (E, N, 'm'); + if Is_Object (E) then + if Comes_From_Source (N) then + Set_Never_Set_In_Source (E, False); + end if; + + Set_Is_True_Constant (E, False); + Set_Current_Value (E, Empty); + Generate_Reference (E, N, 'm'); + Kill_Checks (E); + + if not Can_Never_Be_Null (E) then + Set_Is_Known_Non_Null (E, False); + end if; + end if; end Set_Ref; -- Start of processing for Note_Possible_Modification @@ -4290,21 +4981,32 @@ package body Sem_Util is -- Test for node rewritten as dereference (e.g. accept parameter) if Nkind (Exp) = N_Explicit_Dereference - and then Is_Entity_Name (Original_Node (Exp)) + and then not Comes_From_Source (Exp) then - Set_Ref (Entity (Original_Node (Exp)), Original_Node (Exp)); - return; + Exp := Original_Node (Exp); + end if; - elsif Is_Entity_Name (Exp) then + -- Now look for entity being referenced + + if Is_Entity_Name (Exp) then Ent := Entity (Exp); if (Ekind (Ent) = E_Variable or else Ekind (Ent) = E_Constant) and then Present (Renamed_Object (Ent)) then + Set_Never_Set_In_Source (Ent, False); + Set_Is_True_Constant (Ent, False); + Set_Current_Value (Ent, Empty); + + if not Can_Never_Be_Null (Ent) then + Set_Is_Known_Non_Null (Ent, False); + end if; + Exp := Renamed_Object (Ent); else Set_Ref (Ent, Exp); + Kill_Checks (Ent); return; end if; @@ -4404,7 +5106,9 @@ package body Sem_Util is return Type_Access_Level (Etype (Prefix (Obj))); end if; - elsif Nkind (Obj) = N_Type_Conversion then + elsif Nkind (Obj) = N_Type_Conversion + or else Nkind (Obj) = N_Unchecked_Type_Conversion + then return Object_Access_Level (Expression (Obj)); -- Function results are objects, so we get either the access level @@ -4443,8 +5147,7 @@ package body Sem_Util is function Trace_Components (T : Entity_Id; - Check : Boolean) - return Entity_Id; + Check : Boolean) return Entity_Id; -- Recursive function that does the work, and checks against circular -- definition for each subcomponent type. @@ -4666,7 +5369,9 @@ package body Sem_Util is -- and generate an l-type cross-reference entry for the label if Label_Ref then - Style.Check_Identifier (Endl, Ent); + if Style_Check then + Style.Check_Identifier (Endl, Ent); + end if; Generate_Reference (Ent, Endl, 'l', Set_Ref => False); end if; @@ -4727,6 +5432,34 @@ package body Sem_Util is return Token_Node; end Real_Convert; + --------------------- + -- Rep_To_Pos_Flag -- + --------------------- + + function Rep_To_Pos_Flag (E : Entity_Id; Loc : Source_Ptr) return Node_Id is + begin + if Range_Checks_Suppressed (E) then + return New_Occurrence_Of (Standard_False, Loc); + else + return New_Occurrence_Of (Standard_True, Loc); + end if; + end Rep_To_Pos_Flag; + + -------------------- + -- Require_Entity -- + -------------------- + + procedure Require_Entity (N : Node_Id) is + begin + if Is_Entity_Name (N) and then No (Entity (N)) then + if Total_Errors_Detected /= 0 then + Set_Entity (N, Any_Id); + else + raise Program_Error; + end if; + end if; + end Require_Entity; + ------------------------------ -- Requires_Transient_Scope -- ------------------------------ @@ -4790,16 +5523,18 @@ package body Sem_Util is procedure Reset_Analyzed_Flags (N : Node_Id) is function Clear_Analyzed - (N : Node_Id) - return Traverse_Result; + (N : Node_Id) return Traverse_Result; -- Function used to reset Analyzed flags in tree. Note that we do -- not reset Analyzed flags in entities, since there is no need to -- renalalyze entities, and indeed, it is wrong to do so, since it -- can result in generating auxiliary stuff more than once. + -------------------- + -- Clear_Analyzed -- + -------------------- + function Clear_Analyzed - (N : Node_Id) - return Traverse_Result + (N : Node_Id) return Traverse_Result is begin if not Has_Extension (N) then @@ -4813,6 +5548,7 @@ package body Sem_Util is new Traverse_Func (Clear_Analyzed); Discard : Traverse_Result; + pragma Warnings (Off, Discard); -- Start of processing for Reset_Analyzed_Flags @@ -4820,6 +5556,94 @@ package body Sem_Util is Discard := Reset_Analyzed (N); end Reset_Analyzed_Flags; + --------------------------- + -- Safe_To_Capture_Value -- + --------------------------- + + function Safe_To_Capture_Value + (N : Node_Id; + Ent : Entity_Id) return Boolean + is + begin + -- The only entities for which we track constant values are variables, + -- out parameters and in out parameters, so check if we have this case. + + if Ekind (Ent) /= E_Variable + and then + Ekind (Ent) /= E_Out_Parameter + and then + Ekind (Ent) /= E_In_Out_Parameter + then + return False; + end if; + + -- Skip volatile and aliased variables, since funny things might + -- be going on in these cases which we cannot necessarily track. + + if Treat_As_Volatile (Ent) or else Is_Aliased (Ent) then + return False; + end if; + + -- OK, all above conditions are met. We also require that the scope + -- of the reference be the same as the scope of the entity, not + -- counting packages and blocks. + + declare + E_Scope : constant Entity_Id := Scope (Ent); + R_Scope : Entity_Id; + + begin + R_Scope := Current_Scope; + while R_Scope /= Standard_Standard loop + exit when R_Scope = E_Scope; + + if Ekind (R_Scope) /= E_Package + and then + Ekind (R_Scope) /= E_Block + then + return False; + else + R_Scope := Scope (R_Scope); + end if; + end loop; + end; + + -- We also require that the reference does not appear in a context + -- where it is not sure to be executed (i.e. a conditional context + -- or an exception handler). + + declare + P : Node_Id; + + begin + P := Parent (N); + while Present (P) loop + if Nkind (P) = N_If_Statement + or else + Nkind (P) = N_Case_Statement + or else + Nkind (P) = N_Exception_Handler + or else + Nkind (P) = N_Selective_Accept + or else + Nkind (P) = N_Conditional_Entry_Call + or else + Nkind (P) = N_Timed_Entry_Call + or else + Nkind (P) = N_Asynchronous_Select + then + return False; + else + P := Parent (P); + end if; + end loop; + end; + + -- OK, looks safe to set value + + return True; + end Safe_To_Capture_Value; + --------------- -- Same_Name -- --------------- @@ -4966,10 +5790,8 @@ package body Sem_Util is while not Comes_From_Source (Val_Actual) and then Nkind (Val_Actual) in N_Entity and then (Ekind (Val_Actual) = E_Enumeration_Literal - or else Ekind (Val_Actual) = E_Function - or else Ekind (Val_Actual) = E_Generic_Function - or else Ekind (Val_Actual) = E_Procedure - or else Ekind (Val_Actual) = E_Generic_Procedure) + or else Is_Subprogram (Val_Actual) + or else Is_Generic_Subprogram (Val_Actual)) and then Present (Alias (Val_Actual)) loop Val_Actual := Alias (Val_Actual); @@ -4982,7 +5804,6 @@ package body Sem_Util is if Chars (Nod) = Chars (Val_Actual) then Style.Check_Identifier (Nod, Val_Actual); end if; - end if; Set_Entity (N, Val); @@ -5064,7 +5885,6 @@ package body Sem_Util is then Set_Is_Unsigned_Type (T1, Is_Unsigned_Type (T2)); end if; - Set_Alignment (T1, Alignment (T2)); end Set_Size_Info; @@ -5094,7 +5914,8 @@ package body Sem_Util is return No_Uint; else - Error_Msg_N ("static integer expression required here", N); + Flag_Non_Static_Expr + ("static integer expression required here", N); return No_Uint; end if; end Static_Integer; @@ -5249,6 +6070,7 @@ package body Sem_Util is and then Nkind (N) /= N_Package_Instantiation and then Nkind (N) /= N_Package_Renaming_Declaration and then Nkind (N) /= N_Procedure_Instantiation + and then Nkind (N) /= N_Protected_Body and then Nkind (N) /= N_Subprogram_Declaration and then Nkind (N) /= N_Subprogram_Body and then Nkind (N) /= N_Subprogram_Body_Stub @@ -5264,6 +6086,47 @@ package body Sem_Util is return N; end Unit_Declaration_Node; + ------------------------------ + -- Universal_Interpretation -- + ------------------------------ + + function Universal_Interpretation (Opnd : Node_Id) return Entity_Id is + Index : Interp_Index; + It : Interp; + + begin + -- The argument may be a formal parameter of an operator or subprogram + -- with multiple interpretations, or else an expression for an actual. + + if Nkind (Opnd) = N_Defining_Identifier + or else not Is_Overloaded (Opnd) + then + if Etype (Opnd) = Universal_Integer + or else Etype (Opnd) = Universal_Real + then + return Etype (Opnd); + else + return Empty; + end if; + + else + Get_First_Interp (Opnd, Index, It); + + while Present (It.Typ) loop + + if It.Typ = Universal_Integer + or else It.Typ = Universal_Real + then + return It.Typ; + end if; + + Get_Next_Interp (Index, It); + end loop; + + return Empty; + end if; + end Universal_Interpretation; + ---------------------- -- Within_Init_Proc -- ---------------------- @@ -5281,7 +6144,7 @@ package body Sem_Util is end if; end loop; - return Chars (S) = Name_uInit_Proc; + return Is_Init_Proc (S); end Within_Init_Proc; ---------------- @@ -5368,6 +6231,9 @@ package body Sem_Util is elsif In_Instance then if Etype (Etype (Expr)) = Etype (Expected_Type) + and then + (Has_Private_Declaration (Expected_Type) + or else Has_Private_Declaration (Etype (Expr))) and then No (Parent (Expected_Type)) then return; |