diff options
Diffstat (limited to 'gcc/ada/sem_util.adb')
-rw-r--r-- | gcc/ada/sem_util.adb | 2131 |
1 files changed, 1388 insertions, 743 deletions
diff --git a/gcc/ada/sem_util.adb b/gcc/ada/sem_util.adb index 1cf5c69..01a4e2b 100644 --- a/gcc/ada/sem_util.adb +++ b/gcc/ada/sem_util.adb @@ -6,7 +6,7 @@ -- -- -- B o d y -- -- -- --- Copyright (C) 1992-2020, Free Software Foundation, Inc. -- +-- Copyright (C) 1992-2021, 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- -- @@ -23,53 +23,56 @@ -- -- ------------------------------------------------------------------------------ -with Casing; use Casing; -with Checks; use Checks; -with Debug; use Debug; -with Elists; use Elists; -with Errout; use Errout; -with Erroutc; use Erroutc; -with Exp_Ch3; use Exp_Ch3; -with Exp_Ch11; use Exp_Ch11; -with Exp_Util; use Exp_Util; -with Fname; use Fname; -with Freeze; use Freeze; -with Itypes; use Itypes; -with Lib; use Lib; -with Lib.Xref; use Lib.Xref; -with Namet.Sp; use Namet.Sp; -with Nlists; use Nlists; -with Nmake; use Nmake; -with Output; use Output; -with Restrict; use Restrict; -with Rident; use Rident; -with Rtsfind; use Rtsfind; -with Sem; use Sem; -with Sem_Aux; use Sem_Aux; -with Sem_Attr; use Sem_Attr; -with Sem_Cat; use Sem_Cat; -with Sem_Ch6; use Sem_Ch6; -with Sem_Ch8; use Sem_Ch8; -with Sem_Ch13; use Sem_Ch13; -with Sem_Disp; use Sem_Disp; -with Sem_Elab; use Sem_Elab; -with Sem_Eval; use Sem_Eval; -with Sem_Prag; use Sem_Prag; -with Sem_Res; use Sem_Res; -with Sem_Warn; use Sem_Warn; -with Sem_Type; use Sem_Type; -with Sinfo; use Sinfo; -with Sinput; use Sinput; -with Stand; use Stand; +with Casing; use Casing; +with Checks; use Checks; +with Debug; use Debug; +with Einfo.Utils; use Einfo.Utils; +with Elists; use Elists; +with Errout; use Errout; +with Erroutc; use Erroutc; +with Exp_Ch3; use Exp_Ch3; +with Exp_Ch11; use Exp_Ch11; +with Exp_Util; use Exp_Util; +with Fname; use Fname; +with Freeze; use Freeze; +with Itypes; use Itypes; +with Lib; use Lib; +with Lib.Xref; use Lib.Xref; +with Namet.Sp; use Namet.Sp; +with Nlists; use Nlists; +with Nmake; use Nmake; +with Output; use Output; +with Restrict; use Restrict; +with Rident; use Rident; +with Rtsfind; use Rtsfind; +with Sem; use Sem; +with Sem_Aux; use Sem_Aux; +with Sem_Attr; use Sem_Attr; +with Sem_Cat; use Sem_Cat; +with Sem_Ch6; use Sem_Ch6; +with Sem_Ch8; use Sem_Ch8; +with Sem_Ch13; use Sem_Ch13; +with Sem_Disp; use Sem_Disp; +with Sem_Elab; use Sem_Elab; +with Sem_Eval; use Sem_Eval; +with Sem_Prag; use Sem_Prag; +with Sem_Res; use Sem_Res; +with Sem_Warn; use Sem_Warn; +with Sem_Type; use Sem_Type; +with Sinfo; use Sinfo; +with Sinfo.Nodes; use Sinfo.Nodes; +with Sinfo.Utils; use Sinfo.Utils; +with Sinput; use Sinput; +with Stand; use Stand; with Style; -with Stringt; use Stringt; -with Targparm; use Targparm; -with Tbuild; use Tbuild; -with Ttypes; use Ttypes; -with Uname; use Uname; +with Stringt; use Stringt; +with Targparm; use Targparm; +with Tbuild; use Tbuild; +with Ttypes; use Ttypes; +with Uname; use Uname; with GNAT.Heap_Sort_G; -with GNAT.HTable; use GNAT.HTable; +with GNAT.HTable; use GNAT.HTable; package body Sem_Util is @@ -146,7 +149,7 @@ package body Sem_Util is -- have a default. function Is_Preelaborable_Function (Id : Entity_Id) return Boolean; - -- Ada 2020: Determine whether the specified function is suitable as the + -- Ada 2022: Determine whether the specified function is suitable as the -- name of a call in a preelaborable construct (RM 10.2.1(7/5)). type Null_Status_Kind is @@ -174,9 +177,9 @@ package body Sem_Util is -- "subp:file:line:col", corresponding to the source location of the -- body of the subprogram. - ------------------------------ - -- Abstract_Interface_List -- - ------------------------------ + ----------------------------- + -- Abstract_Interface_List -- + ----------------------------- function Abstract_Interface_List (Typ : Entity_Id) return List_Id is Nod : Node_Id; @@ -257,7 +260,8 @@ package body Sem_Util is function Accessibility_Level (Expr : Node_Id; Level : Accessibility_Level_Kind; - In_Return_Context : Boolean := False) return Node_Id + In_Return_Context : Boolean := False; + Allow_Alt_Model : Boolean := True) return Node_Id is Loc : constant Source_Ptr := Sloc (Expr); @@ -269,25 +273,27 @@ package body Sem_Util is -- Construct an integer literal representing an accessibility level -- with its type set to Natural. - function Innermost_Master_Scope_Depth - (N : Node_Id) return Uint; + function Innermost_Master_Scope_Depth (N : Node_Id) return Uint; -- Returns the scope depth of the given node's innermost -- enclosing dynamic scope (effectively the accessibility -- level of the innermost enclosing master). - function Function_Call_Or_Allocator_Level - (N : Node_Id) return Node_Id; + function Function_Call_Or_Allocator_Level (N : Node_Id) return Node_Id; -- Centralized processing of subprogram calls which may appear in -- prefix notation. + function Typ_Access_Level (Typ : Entity_Id) return Uint + is (Type_Access_Level (Typ, Allow_Alt_Model)); + -- Renaming of Type_Access_Level with Allow_Alt_Model specified to avoid + -- passing the parameter specifically in every call. + ---------------------------------- -- Innermost_Master_Scope_Depth -- ---------------------------------- - function Innermost_Master_Scope_Depth - (N : Node_Id) return Uint - is + function Innermost_Master_Scope_Depth (N : Node_Id) return Uint is Encl_Scop : Entity_Id; + Ent : Entity_Id; Node_Par : Node_Id := Parent (N); Master_Lvl_Modifier : Int := 0; @@ -301,12 +307,10 @@ package body Sem_Util is -- among other things. These cases are detected properly ??? while Present (Node_Par) loop + Ent := Defining_Entity_Or_Empty (Node_Par); - if Present (Defining_Entity - (Node_Par, Empty_On_Errors => True)) - then - Encl_Scop := Nearest_Dynamic_Scope - (Defining_Entity (Node_Par)); + if Present (Ent) then + Encl_Scop := Nearest_Dynamic_Scope (Ent); -- Ignore transient scopes made during expansion @@ -377,7 +381,7 @@ package body Sem_Util is (Subprogram_Access_Level (Entity (Name (N)))); else return Make_Level_Literal - (Type_Access_Level (Etype (Prefix (Name (N))))); + (Typ_Access_Level (Etype (Prefix (Name (N))))); end if; -- We ignore coextensions as they cannot be implemented under the @@ -394,19 +398,40 @@ package body Sem_Util is -- Named access types have a designated level if Is_Named_Access_Type (Etype (N)) then - return Make_Level_Literal (Type_Access_Level (Etype (N))); + return Make_Level_Literal (Typ_Access_Level (Etype (N))); -- Otherwise, the level is dictated by RM 3.10.2 (10.7/3) else + -- Check No_Dynamic_Accessibility_Checks restriction override for + -- alternative accessibility model. + + if Allow_Alt_Model + and then No_Dynamic_Accessibility_Checks_Enabled (N) + and then Is_Anonymous_Access_Type (Etype (N)) + then + -- In the alternative model the level is that of the + -- designated type. + + if Debug_Flag_Underscore_B then + return Make_Level_Literal (Typ_Access_Level (Etype (N))); + + -- Otherwise the level is that of the subprogram + + else + return Make_Level_Literal + (Subprogram_Access_Level (Entity (Name (N)))); + end if; + end if; + if Nkind (N) = N_Function_Call then -- Dynamic checks are generated when we are within a return -- value or we are in a function call within an anonymous -- access discriminant constraint of a return object (signified -- by In_Return_Context) on the side of the callee. - -- So, in this case, return library accessibility level to null - -- out the check on the side of the caller. + -- So, in this case, return accessibility level of the + -- enclosing subprogram. if In_Return_Value (N) or else In_Return_Context @@ -416,6 +441,17 @@ package body Sem_Util is end if; end if; + -- When the call is being dereferenced the level is that of the + -- enclosing master of the dereferenced call. + + if Nkind (Parent (N)) in N_Explicit_Dereference + | N_Indexed_Component + | N_Selected_Component + then + return Make_Level_Literal + (Innermost_Master_Scope_Depth (Expr)); + end if; + -- Find any relevant enclosing parent nodes that designate an -- object being initialized. @@ -436,7 +472,7 @@ package body Sem_Util is and then Is_Named_Access_Type (Etype (Par)) then return Make_Level_Literal - (Type_Access_Level (Etype (Par))); + (Typ_Access_Level (Etype (Par))); end if; -- Jump out when we hit an object declaration or the right-hand @@ -553,7 +589,7 @@ package body Sem_Util is if Is_Named_Access_Type (Etype (Pre)) then return Make_Level_Literal - (Type_Access_Level (Etype (Pre))); + (Typ_Access_Level (Etype (Pre))); -- Anonymous access types @@ -618,8 +654,34 @@ package body Sem_Util is (Scope_Depth (Standard_Standard)); end if; - return - New_Occurrence_Of (Get_Dynamic_Accessibility (E), Loc); + -- No_Dynamic_Accessibility_Checks restriction override for + -- alternative accessibility model. + + if Allow_Alt_Model + and then No_Dynamic_Accessibility_Checks_Enabled (E) + then + -- In the alternative model the level is that of the + -- designated type entity's context. + + if Debug_Flag_Underscore_B then + return Make_Level_Literal (Typ_Access_Level (Etype (E))); + + -- Otherwise the level depends on the entity's context + + elsif Is_Formal (E) then + return Make_Level_Literal + (Subprogram_Access_Level + (Enclosing_Subprogram (E))); + else + return Make_Level_Literal + (Scope_Depth (Enclosing_Dynamic_Scope (E))); + end if; + end if; + + -- Return the dynamic level in the normal case + + return New_Occurrence_Of + (Get_Dynamic_Accessibility (E), Loc); -- Initialization procedures have a special extra accessitility -- parameter associated with the level at which the object @@ -637,8 +699,19 @@ package body Sem_Util is -- according to RM 3.10.2 (21). elsif Is_Type (E) then - return Make_Level_Literal - (Type_Access_Level (E) + 1); + -- When restriction No_Dynamic_Accessibility_Checks is active + -- along with -gnatd_b. + + if Allow_Alt_Model + and then No_Dynamic_Accessibility_Checks_Enabled (E) + and then Debug_Flag_Underscore_B + then + return Make_Level_Literal (Typ_Access_Level (E)); + end if; + + -- Normal path + + return Make_Level_Literal (Typ_Access_Level (E) + 1); -- Move up the renamed entity if it came from source since -- expansion may have created a dummy renaming under certain @@ -653,7 +726,7 @@ package body Sem_Util is elsif Is_Named_Access_Type (Etype (E)) then return Make_Level_Literal - (Type_Access_Level (Etype (E))); + (Typ_Access_Level (Etype (E))); -- When E is a component of the current instance of a -- protected type, we assume the level to be deeper than that of @@ -666,6 +739,15 @@ package body Sem_Util is return Make_Level_Literal (Scope_Depth (Enclosing_Dynamic_Scope (E)) + 1); + -- Check if E is an expansion-generated renaming of an iterator + -- by examining Related_Expression. If so, determine the + -- accessibility level based on the original expression. + + elsif Ekind (E) in E_Constant | E_Variable + and then Present (Related_Expression (E)) + then + return Accessibility_Level (Related_Expression (E)); + -- Normal object - get the level of the enclosing scope else @@ -695,7 +777,7 @@ package body Sem_Util is elsif Is_Named_Access_Type (Etype (Pre)) then return Make_Level_Literal - (Type_Access_Level (Etype (Pre))); + (Typ_Access_Level (Etype (Pre))); -- The current expression is a named access type, so there is no -- reason to look at the prefix. Instead obtain the level of E's @@ -703,21 +785,44 @@ package body Sem_Util is elsif Is_Named_Access_Type (Etype (E)) then return Make_Level_Literal - (Type_Access_Level (Etype (E))); + (Typ_Access_Level (Etype (E))); - -- A non-discriminant selected component where the component + -- A nondiscriminant selected component where the component -- is an anonymous access type means that its associated -- level is that of the containing type - see RM 3.10.2 (16). + -- Note that when restriction No_Dynamic_Accessibility_Checks is + -- in effect we treat discriminant components as regular + -- components. + elsif Nkind (E) = N_Selected_Component and then Ekind (Etype (E)) = E_Anonymous_Access_Type and then Ekind (Etype (Pre)) /= E_Anonymous_Access_Type - and then not (Nkind (Selector_Name (E)) in N_Has_Entity - and then Ekind (Entity (Selector_Name (E))) - = E_Discriminant) + and then (not (Nkind (Selector_Name (E)) in N_Has_Entity + and then Ekind (Entity (Selector_Name (E))) + = E_Discriminant) + + -- The alternative accessibility models both treat + -- discriminants as regular components. + + or else (No_Dynamic_Accessibility_Checks_Enabled (E) + and then Allow_Alt_Model)) then + -- When restriction No_Dynamic_Accessibility_Checks is active + -- and -gnatd_b set, the level is that of the designated type. + + if Allow_Alt_Model + and then No_Dynamic_Accessibility_Checks_Enabled (E) + and then Debug_Flag_Underscore_B + then + return Make_Level_Literal + (Typ_Access_Level (Etype (E))); + end if; + + -- Otherwise proceed normally + return Make_Level_Literal - (Type_Access_Level (Etype (Prefix (E)))); + (Typ_Access_Level (Etype (Prefix (E)))); -- Similar to the previous case - arrays featuring components of -- anonymous access components get their corresponding level from @@ -729,8 +834,21 @@ package body Sem_Util is and then Ekind (Component_Type (Base_Type (Etype (Pre)))) = E_Anonymous_Access_Type then + -- When restriction No_Dynamic_Accessibility_Checks is active + -- and -gnatd_b set, the level is that of the designated type. + + if Allow_Alt_Model + and then No_Dynamic_Accessibility_Checks_Enabled (E) + and then Debug_Flag_Underscore_B + then + return Make_Level_Literal + (Typ_Access_Level (Etype (E))); + end if; + + -- Otherwise proceed normally + return Make_Level_Literal - (Type_Access_Level (Etype (Prefix (E)))); + (Typ_Access_Level (Etype (Prefix (E)))); -- The accessibility calculation routine that handles function -- calls (Function_Call_Level) assumes, in the case the @@ -778,7 +896,7 @@ package body Sem_Util is when N_Qualified_Expression => if Is_Named_Access_Type (Etype (E)) then return Make_Level_Literal - (Type_Access_Level (Etype (E))); + (Typ_Access_Level (Etype (E))); else return Accessibility_Level (Expression (E)); end if; @@ -797,7 +915,7 @@ package body Sem_Util is -- its type. if Is_Named_Access_Type (Etype (Pre)) then - return Make_Level_Literal (Type_Access_Level (Etype (Pre))); + return Make_Level_Literal (Typ_Access_Level (Etype (Pre))); -- Otherwise, recurse deeper @@ -824,7 +942,7 @@ package body Sem_Util is elsif Is_Named_Access_Type (Etype (E)) then return Make_Level_Literal - (Type_Access_Level (Etype (E))); + (Typ_Access_Level (Etype (E))); -- In section RM 3.10.2 (10/4) the accessibility rules for -- aggregates and value conversions are outlined. Are these @@ -840,7 +958,7 @@ package body Sem_Util is -- expression's entity. when others => - return Make_Level_Literal (Type_Access_Level (Etype (E))); + return Make_Level_Literal (Typ_Access_Level (Etype (E))); end case; end Accessibility_Level; @@ -1000,11 +1118,7 @@ package body Sem_Util is and then Is_Entity_Name (Name (Expr)) and then Is_RTE (Entity (Name (Expr)), RE_To_Address) then - Expr := First (Parameter_Associations (Expr)); - - if Nkind (Expr) = N_Parameter_Association then - Expr := Explicit_Actual_Parameter (Expr); - end if; + Expr := First_Actual (Expr); -- We finally have the real expression @@ -1406,14 +1520,14 @@ package body Sem_Util is ----------------------------------------- procedure Apply_Compile_Time_Constraint_Error - (N : Node_Id; - Msg : String; - Reason : RT_Exception_Code; - Ent : Entity_Id := Empty; - Typ : Entity_Id := Empty; - Loc : Source_Ptr := No_Location; - Rep : Boolean := True; - Warn : Boolean := False) + (N : Node_Id; + Msg : String; + Reason : RT_Exception_Code; + Ent : Entity_Id := Empty; + Typ : Entity_Id := Empty; + Loc : Source_Ptr := No_Location; + Warn : Boolean := False; + Emit_Message : Boolean := True) is Stat : constant Boolean := Is_Static_Expression (N); R_Stat : constant Node_Id := @@ -1427,17 +1541,9 @@ package body Sem_Util is Rtyp := Typ; end if; - Discard_Node - (Compile_Time_Constraint_Error (N, Msg, Ent, Loc, Warn => Warn)); - - -- In GNATprove mode, do not replace the node with an exception raised. - -- In such a case, either the call to Compile_Time_Constraint_Error - -- issues an error which stops analysis, or it issues a warning in - -- a few cases where a suitable check flag is set for GNATprove to - -- generate a check message. - - if not Rep or GNATprove_Mode then - return; + if Emit_Message then + Discard_Node + (Compile_Time_Constraint_Error (N, Msg, Ent, Loc, Warn => Warn)); end if; -- Now we replace the node by an N_Raise_Constraint_Error node @@ -1676,6 +1782,7 @@ package body Sem_Util is Subt : Entity_Id; Disc_Type : Entity_Id; Obj : Node_Id; + Index : Node_Id; begin Loc := Sloc (N); @@ -1706,6 +1813,8 @@ package body Sem_Util is if Is_Array_Type (T) then Constraints := New_List; + Index := First_Index (T); + for J in 1 .. Number_Dimensions (T) loop -- Build an array subtype declaration with the nominal subtype and @@ -1713,13 +1822,24 @@ package body Sem_Util is -- local declarations for the subprogram, for analysis before any -- reference to the formal in the body. - Lo := - Make_Attribute_Reference (Loc, - Prefix => - Duplicate_Subexpr_No_Checks (Obj, Name_Req => True), - Attribute_Name => Name_First, - Expressions => New_List ( - Make_Integer_Literal (Loc, J))); + -- If this is for an index with a fixed lower bound, then use + -- the fixed lower bound as the lower bound of the actual + -- subtype's corresponding index. + + if not Is_Constrained (T) + and then Is_Fixed_Lower_Bound_Index_Subtype (Etype (Index)) + then + Lo := New_Copy_Tree (Type_Low_Bound (Etype (Index))); + + else + Lo := + Make_Attribute_Reference (Loc, + Prefix => + Duplicate_Subexpr_No_Checks (Obj, Name_Req => True), + Attribute_Name => Name_First, + Expressions => New_List ( + Make_Integer_Literal (Loc, J))); + end if; Hi := Make_Attribute_Reference (Loc, @@ -1730,6 +1850,8 @@ package body Sem_Util is Make_Integer_Literal (Loc, J))); Append (Make_Range (Loc, Lo, Hi), Constraints); + + Next_Index (Index); end loop; -- If the type has unknown discriminants there is no constrained @@ -2008,7 +2130,7 @@ package body Sem_Util is -- the original constraint from its component declaration. Sel := Entity (Selector_Name (N)); - if Nkind (Parent (Sel)) /= N_Component_Declaration then + if Parent_Kind (Sel) /= N_Component_Declaration then return Empty; end if; end if; @@ -2900,6 +3022,32 @@ package body Sem_Util is ----------------------------------- function Cannot_Raise_Constraint_Error (Expr : Node_Id) return Boolean is + + function List_Cannot_Raise_CE (L : List_Id) return Boolean; + -- Returns True if none of the list members cannot possibly raise + -- Constraint_Error. + + -------------------------- + -- List_Cannot_Raise_CE -- + -------------------------- + + function List_Cannot_Raise_CE (L : List_Id) return Boolean is + N : Node_Id; + begin + N := First (L); + while Present (N) loop + if Cannot_Raise_Constraint_Error (N) then + Next (N); + else + return False; + end if; + end loop; + + return True; + end List_Cannot_Raise_CE; + + -- Start of processing for Cannot_Raise_Constraint_Error + begin if Compile_Time_Known_Value (Expr) then return True; @@ -2918,8 +3066,14 @@ package body Sem_Util is when N_Expanded_Name => return True; + when N_Indexed_Component => + return not Do_Range_Check (Expr) + and then Cannot_Raise_Constraint_Error (Prefix (Expr)) + and then List_Cannot_Raise_CE (Expressions (Expr)); + when N_Selected_Component => - return not Do_Discriminant_Check (Expr); + return not Do_Discriminant_Check (Expr) + and then Cannot_Raise_Constraint_Error (Prefix (Expr)); when N_Attribute_Reference => if Do_Overflow_Check (Expr) then @@ -2929,27 +3083,12 @@ package body Sem_Util is return True; else - declare - N : Node_Id; - - begin - N := First (Expressions (Expr)); - while Present (N) loop - if Cannot_Raise_Constraint_Error (N) then - Next (N); - else - return False; - end if; - end loop; - - return True; - end; + return List_Cannot_Raise_CE (Expressions (Expr)); end if; when N_Type_Conversion => if Do_Overflow_Check (Expr) or else Do_Length_Check (Expr) - or else Do_Tag_Check (Expr) then return False; else @@ -4683,10 +4822,6 @@ package body Sem_Util is -- and post-state. Prag is a [refined] postcondition or a contract-cases -- pragma. Result_Seen is set when the pragma mentions attribute 'Result - function Has_In_Out_Parameter (Subp_Id : Entity_Id) return Boolean; - -- Determine whether subprogram Subp_Id contains at least one IN OUT - -- formal parameter. - ------------------------------------------- -- Check_Result_And_Post_State_In_Pragma -- ------------------------------------------- @@ -5075,28 +5210,6 @@ package body Sem_Util is end if; end Check_Result_And_Post_State_In_Pragma; - -------------------------- - -- Has_In_Out_Parameter -- - -------------------------- - - function Has_In_Out_Parameter (Subp_Id : Entity_Id) return Boolean is - Formal : Entity_Id; - - begin - -- Traverse the formals looking for an IN OUT parameter - - Formal := First_Formal (Subp_Id); - while Present (Formal) loop - if Ekind (Formal) = E_In_Out_Parameter then - return True; - end if; - - Next_Formal (Formal); - end loop; - - return False; - end Has_In_Out_Parameter; - -- Local variables Items : constant Node_Id := Contract (Subp_Id); @@ -5176,10 +5289,10 @@ package body Sem_Util is null; -- Regardless of whether the function has postconditions or contract - -- cases, or whether they mention attribute 'Result, an IN OUT formal + -- cases, or whether they mention attribute 'Result, an [IN] OUT formal -- parameter is always treated as a result. - elsif Has_In_Out_Parameter (Spec_Id) then + elsif Has_Out_Or_In_Out_Parameter (Spec_Id) then null; -- The function has both a postcondition and contract cases and they do @@ -5596,6 +5709,13 @@ package body Sem_Util is if Ekind (State_Id) = E_Constant then null; + -- Overlays do not contribute to package state + + elsif Ekind (State_Id) = E_Variable + and then Present (Ultimate_Overlaid_Entity (State_Id)) + then + null; + -- Generate an error message of the form: -- body of package ... has unused hidden states @@ -6355,8 +6475,8 @@ package body Sem_Util is Is_Type_In_Pkg := Is_Package_Or_Generic_Package (B_Scope) and then - Nkind (Parent (Declaration_Node (First_Subtype (T)))) /= - N_Package_Body; + Parent_Kind (Declaration_Node (First_Subtype (T))) /= + N_Package_Body; while Present (Id) loop @@ -6374,8 +6494,8 @@ package body Sem_Util is and then (Is_Type_In_Pkg or else Is_Derived_Type (B_Type) or else Is_Primitive (Id)) - and then Nkind (Parent (Parent (Id))) - not in N_Formal_Subprogram_Declaration + and then Parent_Kind (Parent (Id)) + not in N_Formal_Subprogram_Declaration then Is_Prim := False; @@ -6446,7 +6566,7 @@ package body Sem_Util is -- appear in the target-specific extension to System. if No (Id) - and then B_Scope = RTU_Entity (System) + and then Is_RTU (B_Scope, System) and then Present_System_Aux then B_Scope := System_Aux_Id; @@ -6484,7 +6604,6 @@ package body Sem_Util is Remove (Op_List, Node (Second)); else - pragma Assert (False); raise Program_Error; end if; end if; @@ -6662,6 +6781,116 @@ package body Sem_Util is return N; end Compile_Time_Constraint_Error; + ---------------------------- + -- Compute_Returns_By_Ref -- + ---------------------------- + + procedure Compute_Returns_By_Ref (Func : Entity_Id) is + Typ : constant Entity_Id := Etype (Func); + Utyp : constant Entity_Id := Underlying_Type (Typ); + + begin + if Is_Limited_View (Typ) then + Set_Returns_By_Ref (Func); + + elsif Present (Utyp) and then CW_Or_Has_Controlled_Part (Utyp) then + Set_Returns_By_Ref (Func); + end if; + end Compute_Returns_By_Ref; + + -------------------------------- + -- Collect_Types_In_Hierarchy -- + -------------------------------- + + function Collect_Types_In_Hierarchy + (Typ : Entity_Id; + Examine_Components : Boolean := False) return Elist_Id + is + Results : Elist_Id; + + procedure Process_Type (Typ : Entity_Id); + -- Collect type Typ if it satisfies function Predicate. Do so for its + -- parent type, base type, progenitor types, and any component types. + + ------------------ + -- Process_Type -- + ------------------ + + procedure Process_Type (Typ : Entity_Id) is + Comp : Entity_Id; + Iface_Elmt : Elmt_Id; + + begin + if not Is_Type (Typ) or else Error_Posted (Typ) then + return; + end if; + + -- Collect the current type if it satisfies the predicate + + if Predicate (Typ) then + Append_Elmt (Typ, Results); + end if; + + -- Process component types + + if Examine_Components then + + -- Examine components and discriminants + + if Is_Concurrent_Type (Typ) + or else Is_Incomplete_Or_Private_Type (Typ) + or else Is_Record_Type (Typ) + or else Has_Discriminants (Typ) + then + Comp := First_Component_Or_Discriminant (Typ); + + while Present (Comp) loop + Process_Type (Etype (Comp)); + + Next_Component_Or_Discriminant (Comp); + end loop; + + -- Examine array components + + elsif Ekind (Typ) = E_Array_Type then + Process_Type (Component_Type (Typ)); + end if; + end if; + + -- Examine parent type + + if Etype (Typ) /= Typ then + Process_Type (Etype (Typ)); + end if; + + -- Examine base type + + if Base_Type (Typ) /= Typ then + Process_Type (Base_Type (Typ)); + end if; + + -- Examine interfaces + + if Is_Record_Type (Typ) + and then Present (Interfaces (Typ)) + then + Iface_Elmt := First_Elmt (Interfaces (Typ)); + while Present (Iface_Elmt) loop + Process_Type (Node (Iface_Elmt)); + + Next_Elmt (Iface_Elmt); + end loop; + end if; + end Process_Type; + + -- Start of processing for Collect_Types_In_Hierarchy + + begin + Results := New_Elmt_List; + Process_Type (Typ); + return Results; + end Collect_Types_In_Hierarchy; + ----------------------- -- Conditional_Delay -- ----------------------- @@ -6873,19 +7102,30 @@ package body Sem_Util is ----------------------------- function Current_Entity_In_Scope (N : Name_Id) return Entity_Id is - E : Entity_Id; CS : constant Entity_Id := Current_Scope; - Transient_Case : constant Boolean := Scope_Is_Transient; + E : Entity_Id; begin E := Get_Name_Entity_Id (N); - while Present (E) - and then Scope (E) /= CS - and then (not Transient_Case or else Scope (E) /= Scope (CS)) - loop - E := Homonym (E); - end loop; + + if No (E) then + null; + + elsif Scope_Is_Transient then + while Present (E) loop + exit when Scope (E) = CS or else Scope (E) = Scope (CS); + + E := Homonym (E); + end loop; + + else + while Present (E) loop + exit when Scope (E) = CS; + + E := Homonym (E); + end loop; + end if; return E; end Current_Entity_In_Scope; @@ -6959,15 +7199,36 @@ package body Sem_Util is end Current_Subprogram; ------------------------------- + -- CW_Or_Has_Controlled_Part -- + ------------------------------- + + function CW_Or_Has_Controlled_Part (T : Entity_Id) return Boolean is + begin + return Is_Class_Wide_Type (T) or else Needs_Finalization (T); + end CW_Or_Has_Controlled_Part; + + ------------------------------- -- Deepest_Type_Access_Level -- ------------------------------- - function Deepest_Type_Access_Level (Typ : Entity_Id) return Uint is + function Deepest_Type_Access_Level + (Typ : Entity_Id; + Allow_Alt_Model : Boolean := True) return Uint + is begin if Ekind (Typ) = E_Anonymous_Access_Type and then not Is_Local_Anonymous_Access (Typ) and then Nkind (Associated_Node_For_Itype (Typ)) = N_Object_Declaration then + -- No_Dynamic_Accessibility_Checks override for alternative + -- accessibility model. + + if Allow_Alt_Model + and then No_Dynamic_Accessibility_Checks_Enabled (Typ) + then + return Type_Access_Level (Typ, Allow_Alt_Model); + end if; + -- Typ is the type of an Ada 2012 stand-alone object of an anonymous -- access type. @@ -6983,7 +7244,7 @@ package body Sem_Util is return UI_From_Int (Int'Last); else - return Type_Access_Level (Typ); + return Type_Access_Level (Typ, Allow_Alt_Model); end if; end Deepest_Type_Access_Level; @@ -6991,10 +7252,23 @@ package body Sem_Util is -- Defining_Entity -- --------------------- - function Defining_Entity - (N : Node_Id; - Empty_On_Errors : Boolean := False) return Entity_Id - is + function Defining_Entity (N : Node_Id) return Entity_Id is + Ent : constant Entity_Id := Defining_Entity_Or_Empty (N); + + begin + if Present (Ent) then + return Ent; + + else + raise Program_Error; + end if; + end Defining_Entity; + + ------------------------------ + -- Defining_Entity_Or_Empty -- + ------------------------------ + + function Defining_Entity_Or_Empty (N : Node_Id) return Entity_Id is begin case Nkind (N) is when N_Abstract_Subprogram_Declaration @@ -7093,13 +7367,9 @@ package body Sem_Util is return Entity (Identifier (N)); when others => - if Empty_On_Errors then - return Empty; - end if; - - raise Program_Error; + return Empty; end case; - end Defining_Entity; + end Defining_Entity_Or_Empty; -------------------------- -- Denotes_Discriminant -- @@ -7139,8 +7409,8 @@ package body Sem_Util is ------------------------- function Denotes_Same_Object (A1, A2 : Node_Id) return Boolean is - function Is_Renaming (N : Node_Id) return Boolean; - -- Return true if N names a renaming entity + function Is_Object_Renaming (N : Node_Id) return Boolean; + -- Return true if N names an object renaming entity function Is_Valid_Renaming (N : Node_Id) return Boolean; -- For renamings, return False if the prefix of any dereference within @@ -7148,185 +7418,144 @@ package body Sem_Util is -- renamed object_name contains references to variables or calls on -- nonstatic functions; otherwise return True (RM 6.4.1(6.10/3)) - ----------------- - -- Is_Renaming -- - ----------------- + ------------------------ + -- Is_Object_Renaming -- + ------------------------ - function Is_Renaming (N : Node_Id) return Boolean is + function Is_Object_Renaming (N : Node_Id) return Boolean is begin - if not Is_Entity_Name (N) then - return False; - end if; - - case Ekind (Entity (N)) is - when E_Variable | E_Constant => - return Present (Renamed_Object (Entity (N))); - - when E_Exception - | E_Function - | E_Generic_Function - | E_Generic_Package - | E_Generic_Procedure - | E_Operator - | E_Package - | E_Procedure - => - return Present (Renamed_Entity (Entity (N))); - - when others => - return False; - end case; - end Is_Renaming; + return Is_Entity_Name (N) + and then Ekind (Entity (N)) in E_Variable | E_Constant + and then Present (Renamed_Object (Entity (N))); + end Is_Object_Renaming; ----------------------- -- Is_Valid_Renaming -- ----------------------- function Is_Valid_Renaming (N : Node_Id) return Boolean is - function Check_Renaming (N : Node_Id) return Boolean; - -- Recursive function used to traverse all the prefixes of N - - -------------------- - -- Check_Renaming -- - -------------------- + begin + if Is_Object_Renaming (N) + and then not Is_Valid_Renaming (Renamed_Entity (Entity (N))) + then + return False; + end if; - function Check_Renaming (N : Node_Id) return Boolean is - begin - if Is_Renaming (N) - and then not Check_Renaming (Renamed_Entity (Entity (N))) - then - return False; - end if; + -- Check if any expression within the renamed object_name contains no + -- references to variables nor calls on nonstatic functions. - if Nkind (N) = N_Indexed_Component then - declare - Indx : Node_Id; + if Nkind (N) = N_Indexed_Component then + declare + Indx : Node_Id; - begin - Indx := First (Expressions (N)); - while Present (Indx) loop - if not Is_OK_Static_Expression (Indx) then - return False; - end if; + begin + Indx := First (Expressions (N)); + while Present (Indx) loop + if not Is_OK_Static_Expression (Indx) then + return False; + end if; - Next_Index (Indx); - end loop; - end; - end if; + Next_Index (Indx); + end loop; + end; - if Has_Prefix (N) then - declare - P : constant Node_Id := Prefix (N); + elsif Nkind (N) = N_Slice then + declare + Rng : constant Node_Id := Discrete_Range (N); + begin + -- Bounds specified as a range - begin - if Nkind (N) = N_Explicit_Dereference - and then Is_Variable (P) - then + if Nkind (Rng) = N_Range then + if not Is_OK_Static_Range (Rng) then return False; + end if; - elsif Is_Entity_Name (P) - and then Ekind (Entity (P)) = E_Function - then - return False; + -- Bounds specified as a constrained subtype indication - elsif Nkind (P) = N_Function_Call then + elsif Nkind (Rng) = N_Subtype_Indication then + if not Is_OK_Static_Range + (Range_Expression (Constraint (Rng))) + then return False; end if; - -- Recursion to continue traversing the prefix of the - -- renaming expression + -- Bounds specified as a subtype name - return Check_Renaming (P); - end; - end if; + elsif not Is_OK_Static_Expression (Rng) then + return False; + end if; + end; + end if; - return True; - end Check_Renaming; + if Has_Prefix (N) then + declare + P : constant Node_Id := Prefix (N); - -- Start of processing for Is_Valid_Renaming + begin + if Nkind (N) = N_Explicit_Dereference + and then Is_Variable (P) + then + return False; - begin - return Check_Renaming (N); - end Is_Valid_Renaming; + elsif Is_Entity_Name (P) + and then Ekind (Entity (P)) = E_Function + then + return False; - -- Local variables + elsif Nkind (P) = N_Function_Call then + return False; + end if; - Obj1 : Node_Id := A1; - Obj2 : Node_Id := A2; + -- Recursion to continue traversing the prefix of the + -- renaming expression + + return Is_Valid_Renaming (P); + end; + end if; + + return True; + end Is_Valid_Renaming; -- Start of processing for Denotes_Same_Object begin - -- Both names statically denote the same stand-alone object or parameter - -- (RM 6.4.1(6.5/3)) + -- Both names statically denote the same stand-alone object or + -- parameter (RM 6.4.1(6.6/3)). - if Is_Entity_Name (Obj1) - and then Is_Entity_Name (Obj2) - and then Entity (Obj1) = Entity (Obj2) + if Is_Entity_Name (A1) + and then Is_Entity_Name (A2) + and then Entity (A1) = Entity (A2) then return True; - end if; - - -- For renamings, the prefix of any dereference within the renamed - -- object_name is not a variable, and any expression within the - -- renamed object_name contains no references to variables nor - -- calls on nonstatic functions (RM 6.4.1(6.10/3)). - - if Is_Renaming (Obj1) then - if Is_Valid_Renaming (Obj1) then - Obj1 := Renamed_Entity (Entity (Obj1)); - else - return False; - end if; - end if; - - if Is_Renaming (Obj2) then - if Is_Valid_Renaming (Obj2) then - Obj2 := Renamed_Entity (Entity (Obj2)); - else - return False; - end if; - end if; - - -- No match if not same node kind (such cases are handled by - -- Denotes_Same_Prefix) - - if Nkind (Obj1) /= Nkind (Obj2) then - return False; - - -- After handling valid renamings, one of the two names statically - -- denoted a renaming declaration whose renamed object_name is known - -- to denote the same object as the other (RM 6.4.1(6.10/3)) - - elsif Is_Entity_Name (Obj1) then - if Is_Entity_Name (Obj2) then - return Entity (Obj1) = Entity (Obj2); - else - return False; - end if; -- Both names are selected_components, their prefixes are known to -- denote the same object, and their selector_names denote the same - -- component (RM 6.4.1(6.6/3)). + -- component (RM 6.4.1(6.7/3)). - elsif Nkind (Obj1) = N_Selected_Component then - return Denotes_Same_Object (Prefix (Obj1), Prefix (Obj2)) + elsif Nkind (A1) = N_Selected_Component + and then Nkind (A2) = N_Selected_Component + then + return Denotes_Same_Object (Prefix (A1), Prefix (A2)) and then - Entity (Selector_Name (Obj1)) = Entity (Selector_Name (Obj2)); + Entity (Selector_Name (A1)) = Entity (Selector_Name (A2)); -- Both names are dereferences and the dereferenced names are known to - -- denote the same object (RM 6.4.1(6.7/3)) + -- denote the same object (RM 6.4.1(6.8/3)). - elsif Nkind (Obj1) = N_Explicit_Dereference then - return Denotes_Same_Object (Prefix (Obj1), Prefix (Obj2)); + elsif Nkind (A1) = N_Explicit_Dereference + and then Nkind (A2) = N_Explicit_Dereference + then + return Denotes_Same_Object (Prefix (A1), Prefix (A2)); -- Both names are indexed_components, their prefixes are known to denote -- the same object, and each of the pairs of corresponding index values -- are either both static expressions with the same static value or both - -- names that are known to denote the same object (RM 6.4.1(6.8/3)) + -- names that are known to denote the same object (RM 6.4.1(6.9/3)). - elsif Nkind (Obj1) = N_Indexed_Component then - if not Denotes_Same_Object (Prefix (Obj1), Prefix (Obj2)) then + elsif Nkind (A1) = N_Indexed_Component + and then Nkind (A2) = N_Indexed_Component + then + if not Denotes_Same_Object (Prefix (A1), Prefix (A2)) then return False; else declare @@ -7334,8 +7563,8 @@ package body Sem_Util is Indx2 : Node_Id; begin - Indx1 := First (Expressions (Obj1)); - Indx2 := First (Expressions (Obj2)); + Indx1 := First (Expressions (A1)); + Indx2 := First (Expressions (A2)); while Present (Indx1) loop -- Indexes must denote the same static value or same object @@ -7362,33 +7591,49 @@ package body Sem_Util is -- Both names are slices, their prefixes are known to denote the same -- object, and the two slices have statically matching index constraints - -- (RM 6.4.1(6.9/3)) + -- (RM 6.4.1(6.10/3)). - elsif Nkind (Obj1) = N_Slice - and then Denotes_Same_Object (Prefix (Obj1), Prefix (Obj2)) + elsif Nkind (A1) = N_Slice + and then Nkind (A2) = N_Slice then - declare - Lo1, Lo2, Hi1, Hi2 : Node_Id; - - begin - Get_Index_Bounds (Etype (Obj1), Lo1, Hi1); - Get_Index_Bounds (Etype (Obj2), Lo2, Hi2); + if not Denotes_Same_Object (Prefix (A1), Prefix (A2)) then + return False; + else + declare + Lo1, Lo2, Hi1, Hi2 : Node_Id; - -- Check whether bounds are statically identical. There is no - -- attempt to detect partial overlap of slices. + begin + Get_Index_Bounds (Discrete_Range (A1), Lo1, Hi1); + Get_Index_Bounds (Discrete_Range (A2), Lo2, Hi2); + + -- Check whether bounds are statically identical. There is no + -- attempt to detect partial overlap of slices. + + return Is_OK_Static_Expression (Lo1) + and then Is_OK_Static_Expression (Lo2) + and then Is_OK_Static_Expression (Hi1) + and then Is_OK_Static_Expression (Hi2) + and then Expr_Value (Lo1) = Expr_Value (Lo2) + and then Expr_Value (Hi1) = Expr_Value (Hi2); + end; + end if; - return Denotes_Same_Object (Lo1, Lo2) - and then - Denotes_Same_Object (Hi1, Hi2); - end; + -- One of the two names statically denotes a renaming declaration whose + -- renamed object_name is known to denote the same object as the other; + -- the prefix of any dereference within the renamed object_name is not a + -- variable, and any expression within the renamed object_name contains + -- no references to variables nor calls on nonstatic functions (RM + -- 6.4.1(6.11/3)). - -- In the recursion, literals appear as indexes + elsif Is_Object_Renaming (A1) + and then Is_Valid_Renaming (A1) + then + return Denotes_Same_Object (Renamed_Entity (Entity (A1)), A2); - elsif Nkind (Obj1) = N_Integer_Literal - and then - Nkind (Obj2) = N_Integer_Literal + elsif Is_Object_Renaming (A2) + and then Is_Valid_Renaming (A2) then - return Intval (Obj1) = Intval (Obj2); + return Denotes_Same_Object (A1, Renamed_Entity (Entity (A2))); else return False; @@ -7793,11 +8038,7 @@ package body Sem_Util is Current_Node := Parent (Current_Node); end loop; - if Nkind (Current_Node) /= N_Compilation_Unit then - return Empty; - else - return Current_Node; - end if; + return Current_Node; end Enclosing_Comp_Unit_Node; -------------------------- @@ -8462,7 +8703,7 @@ package body Sem_Util is -- will be detected. Any_Type insures that no cascaded errors will occur else - Set_Ekind (Def_Id, E_Void); + Mutate_Ekind (Def_Id, E_Void); Set_Etype (Def_Id, Any_Type); end if; @@ -9280,6 +9521,10 @@ package body Sem_Util is Ent : out Entity_Id; Off : out Boolean) is + pragma Assert + (Nkind (N) = N_Attribute_Definition_Clause + and then Chars (N) = Name_Address); + Expr : Node_Id; begin @@ -9299,61 +9544,68 @@ package body Sem_Util is Ent := Empty; Off := False; - if Nkind (N) = N_Attribute_Definition_Clause - and then Chars (N) = Name_Address - then - Expr := Expression (N); + Expr := Expression (N); - -- This loop checks the form of the expression for Y'Address, - -- using recursion to deal with intermediate constants. + -- This loop checks the form of the expression for Y'Address, using + -- recursion to deal with intermediate constants. - loop - -- Check for Y'Address + loop + -- Check for Y'Address - if Nkind (Expr) = N_Attribute_Reference - and then Attribute_Name (Expr) = Name_Address - then - Expr := Prefix (Expr); - exit; + if Nkind (Expr) = N_Attribute_Reference + and then Attribute_Name (Expr) = Name_Address + then + Expr := Prefix (Expr); + exit; - -- Check for Const where Const is a constant entity + -- Check for Const where Const is a constant entity - elsif Is_Entity_Name (Expr) - and then Ekind (Entity (Expr)) = E_Constant - then - Expr := Constant_Value (Entity (Expr)); + elsif Is_Entity_Name (Expr) + and then Ekind (Entity (Expr)) = E_Constant + then + Expr := Constant_Value (Entity (Expr)); - -- Anything else does not need checking + -- Anything else does not need checking - else - return; - end if; - end loop; + else + return; + end if; + end loop; - -- This loop checks the form of the prefix for an entity, using - -- recursion to deal with intermediate components. + -- This loop checks the form of the prefix for an entity, using + -- recursion to deal with intermediate components. - loop - -- Check for Y where Y is an entity + loop + -- Check for Y where Y is an entity - if Is_Entity_Name (Expr) then - Ent := Entity (Expr); - return; + if Is_Entity_Name (Expr) then + Ent := Entity (Expr); - -- Check for components + -- If expansion is disabled, then we might see an entity of a + -- protected component or of a discriminant of a concurrent unit. + -- Ignore such entities, because further warnings for overlays + -- expect this routine to only collect entities of entire objects. - elsif Nkind (Expr) in N_Selected_Component | N_Indexed_Component - then - Expr := Prefix (Expr); - Off := True; + if Ekind (Ent) in E_Component | E_Discriminant then + pragma Assert + (not Expander_Active + and then Is_Concurrent_Type (Scope (Ent))); + Ent := Empty; + end if; + return; - -- Anything else does not need checking + -- Check for components - else - return; - end if; - end loop; - end if; + elsif Nkind (Expr) in N_Selected_Component | N_Indexed_Component then + Expr := Prefix (Expr); + Off := True; + + -- Anything else does not need checking + + else + return; + end if; + end loop; end Find_Overlaid_Entity; ------------------------- @@ -9899,6 +10151,18 @@ package body Sem_Util is Discrim_Value : Node_Id; Discrim_Value_Subtype : Node_Id; Discrim_Value_Status : Discriminant_Value_Status := Bad; + + function OK_Scope_For_Discrim_Value_Error_Messages return Boolean is + (Scope (Original_Record_Component + (Entity (First (Choices (Assoc))))) = Typ); + -- Used to avoid generating error messages having a source position + -- which refers to somewhere (e.g., a discriminant value in a derived + -- tagged type declaration) unrelated to the offending construct. This + -- is required for correctness - clients of Gather_Components such as + -- Sem_Ch3.Create_Constrained_Components depend on this function + -- returning True while processing semantically correct examples; + -- generating an error message in this case would be wrong. + begin Report_Errors := False; @@ -10043,7 +10307,7 @@ package body Sem_Util is then Discrim_Value_Status := Static_Expr; else - if Ada_Version >= Ada_2020 then + if Ada_Version >= Ada_2022 then if Original_Node (Discrim_Value) /= Discrim_Value and then Nkind (Discrim_Value) = N_Type_Conversion and then Etype (Original_Node (Discrim_Value)) @@ -10082,15 +10346,13 @@ package body Sem_Util is -- components are being gathered for an aggregate, in which case -- the caller must check Report_Errors. -- - -- In Ada 2020 the above rules are relaxed. A nonstatic governing + -- In Ada 2022 the above rules are relaxed. A nonstatic governing -- discriminant is OK as long as it has a static subtype and -- every value of that subtype (and there must be at least one) -- selects the same variant. - if Scope (Original_Record_Component - ((Entity (First (Choices (Assoc)))))) = Typ - then - if Ada_Version >= Ada_2020 then + if OK_Scope_For_Discrim_Value_Error_Messages then + if Ada_Version >= Ada_2022 then Error_Msg_FE ("value for discriminant & must be static or " & "discriminant's nominal subtype must be static " & @@ -10208,10 +10470,12 @@ package body Sem_Util is (Subset => Discrim_Value_Subtype_Intervals, Of_Set => Variant_Intervals) then - Error_Msg_NE - ("no single variant is associated with all values of " & - "the subtype of discriminant value &", - Discrim_Value, Discrim); + if OK_Scope_For_Discrim_Value_Error_Messages then + Error_Msg_NE + ("no single variant is associated with all values of " & + "the subtype of discriminant value &", + Discrim_Value, Discrim); + end if; Report_Errors := True; return; end if; @@ -10651,22 +10915,26 @@ package body Sem_Util is when E_Class_Wide_Type => return Get_Fullest_View (Root_Type (E), Include_PAT); - when E_Class_Wide_Subtype => + when E_Class_Wide_Subtype => if Present (Equivalent_Type (E)) then return Get_Fullest_View (Equivalent_Type (E), Include_PAT); elsif Present (Cloned_Subtype (E)) then return Get_Fullest_View (Cloned_Subtype (E), Include_PAT); end if; - when E_Protected_Type | E_Protected_Subtype - | E_Task_Type | E_Task_Subtype => + when E_Protected_Subtype + | E_Protected_Type + | E_Task_Subtype + | E_Task_Type + => if Present (Corresponding_Record_Type (E)) then return Get_Fullest_View (Corresponding_Record_Type (E), Include_PAT); end if; when E_Access_Protected_Subprogram_Type - | E_Anonymous_Access_Protected_Subprogram_Type => + | E_Anonymous_Access_Protected_Subprogram_Type + => if Present (Equivalent_Type (E)) then return Get_Fullest_View (Equivalent_Type (E), Include_PAT); end if; @@ -10822,6 +11090,23 @@ package body Sem_Util is end if; end Get_Index_Bounds; + function Get_Index_Bounds + (N : Node_Id; + Use_Full_View : Boolean := False) return Range_Nodes is + Result : Range_Nodes; + begin + Get_Index_Bounds (N, Result.First, Result.Last, Use_Full_View); + return Result; + end Get_Index_Bounds; + + function Get_Index_Bounds + (N : Node_Id; + Use_Full_View : Boolean := False) return Range_Values is + Nodes : constant Range_Nodes := Get_Index_Bounds (N, Use_Full_View); + begin + return (Expr_Value (Nodes.First), Expr_Value (Nodes.Last)); + end Get_Index_Bounds; + ----------------------------- -- Get_Interfacing_Aspects -- ----------------------------- @@ -11401,12 +11686,13 @@ package body Sem_Util is -- Has_Access_Values -- ----------------------- - function Has_Access_Values (T : Entity_Id) return Boolean is + function Has_Access_Values (T : Entity_Id) return Boolean + is Typ : constant Entity_Id := Underlying_Type (T); begin -- Case of a private type which is not completed yet. This can only - -- happen in the case of a generic format type appearing directly, or + -- happen in the case of a generic formal type appearing directly, or -- as a component of the type to which this function is being applied -- at the top level. Return False in this case, since we certainly do -- not know that the type contains access types. @@ -11548,7 +11834,7 @@ package body Sem_Util is if Default = Known_Compatible or else (Etype (Obj) = Etype (Expr) - and then (Unknown_Alignment (Obj) + and then (not Known_Alignment (Obj) or else Alignment (Obj) = Alignment (Etype (Obj)))) then @@ -11651,22 +11937,23 @@ package body Sem_Util is Set_Result (Known_Incompatible); end if; - -- See if Expr is an object with known alignment + -- See if Expr is an object with known alignment elsif Is_Entity_Name (Expr) and then Known_Alignment (Entity (Expr)) then + Offs := Uint_0; ExpA := Alignment (Entity (Expr)); - -- Otherwise, we can use the alignment of the type of - -- Expr given that we already checked for - -- discombobulating rep clauses for the cases of indexed - -- and selected components above. + -- Otherwise, we can use the alignment of the type of Expr + -- given that we already checked for discombobulating rep + -- clauses for the cases of indexed and selected components + -- above. elsif Known_Alignment (Etype (Expr)) then ExpA := Alignment (Etype (Expr)); - -- Otherwise the alignment is unknown + -- Otherwise the alignment is unknown else Set_Result (Default); @@ -11678,28 +11965,28 @@ package body Sem_Util is Set_Result (Known_Incompatible); end if; - -- If Expr is not a piece of a larger object, see if size - -- is given. If so, check that it is not too small for the - -- required alignment. + -- If Expr is a component or an entire object with a known + -- alignment, then we are fine. Otherwise, if its size is + -- known, it must be big enough for the required alignment. if Offs /= No_Uint then null; - -- See if Expr is an object with known size + -- See if Expr is an object with known size elsif Is_Entity_Name (Expr) and then Known_Static_Esize (Entity (Expr)) then SizA := Esize (Entity (Expr)); - -- Otherwise, we check the object size of the Expr type + -- Otherwise, we check the object size of the Expr type elsif Known_Static_Esize (Etype (Expr)) then SizA := Esize (Etype (Expr)); end if; -- If we got a size, see if it is a multiple of the Obj - -- alignment, if not, then the alignment cannot be + -- alignment; if not, then the alignment cannot be -- acceptable, since the size is always a multiple of the -- alignment. @@ -11737,25 +12024,24 @@ package body Sem_Util is -- where we do not know the alignment of Obj. if Known_Alignment (Entity (Expr)) - and then UI_To_Int (Alignment (Entity (Expr))) < - Ttypes.Maximum_Alignment + and then Alignment (Entity (Expr)) < Ttypes.Maximum_Alignment then Set_Result (Unknown); - -- Now check size of Expr object. Any size that is not an - -- even multiple of Maximum_Alignment is also worrisome - -- since it may cause the alignment of the object to be less - -- than the alignment of the type. + -- Now check size of Expr object. Any size that is not an even + -- multiple of Maximum_Alignment is also worrisome since it + -- may cause the alignment of the object to be less than the + -- alignment of the type. elsif Known_Static_Esize (Entity (Expr)) and then - (UI_To_Int (Esize (Entity (Expr))) mod - (Ttypes.Maximum_Alignment * Ttypes.System_Storage_Unit)) + Esize (Entity (Expr)) mod + (Ttypes.Maximum_Alignment * Ttypes.System_Storage_Unit) /= 0 then Set_Result (Unknown); - -- Otherwise same type is decisive + -- Otherwise same type is decisive else Set_Result (Known_Compatible); @@ -11793,7 +12079,7 @@ package body Sem_Util is -- do it when there is an address clause since we can do more if the -- alignment is known. - if Unknown_Alignment (Obj) then + if not Known_Alignment (Obj) and then Known_Alignment (Etype (Obj)) then Set_Alignment (Obj, Alignment (Etype (Obj))); end if; @@ -11827,7 +12113,6 @@ package body Sem_Util is function Has_Defaulted_Discriminants (Typ : Entity_Id) return Boolean is begin return Has_Discriminants (Typ) - and then Present (First_Discriminant (Typ)) and then Present (Discriminant_Default_Value (First_Discriminant (Typ))); end Has_Defaulted_Discriminants; @@ -12444,6 +12729,84 @@ package body Sem_Util is return False; end Has_Fully_Default_Initializing_DIC_Pragma; + --------------------------------- + -- Has_Inferable_Discriminants -- + --------------------------------- + + function Has_Inferable_Discriminants (N : Node_Id) return Boolean is + + function Prefix_Is_Formal_Parameter (N : Node_Id) return Boolean; + -- Determines whether the left-most prefix of a selected component is a + -- formal parameter in a subprogram. Assumes N is a selected component. + + -------------------------------- + -- Prefix_Is_Formal_Parameter -- + -------------------------------- + + function Prefix_Is_Formal_Parameter (N : Node_Id) return Boolean is + Sel_Comp : Node_Id; + + begin + -- Move to the left-most prefix by climbing up the tree + + Sel_Comp := N; + while Present (Parent (Sel_Comp)) + and then Nkind (Parent (Sel_Comp)) = N_Selected_Component + loop + Sel_Comp := Parent (Sel_Comp); + end loop; + + return Is_Formal (Entity (Prefix (Sel_Comp))); + end Prefix_Is_Formal_Parameter; + + -- Start of processing for Has_Inferable_Discriminants + + begin + -- For selected components, the subtype of the selector must be a + -- constrained Unchecked_Union. If the component is subject to a + -- per-object constraint, then the enclosing object must have inferable + -- discriminants. + + if Nkind (N) = N_Selected_Component then + if Has_Per_Object_Constraint (Entity (Selector_Name (N))) then + + -- A small hack. If we have a per-object constrained selected + -- component of a formal parameter, return True since we do not + -- know the actual parameter association yet. + + if Prefix_Is_Formal_Parameter (N) then + return True; + + -- Otherwise, check the enclosing object and the selector + + else + return Has_Inferable_Discriminants (Prefix (N)) + and then Has_Inferable_Discriminants (Selector_Name (N)); + end if; + + -- The call to Has_Inferable_Discriminants will determine whether + -- the selector has a constrained Unchecked_Union nominal type. + + else + return Has_Inferable_Discriminants (Selector_Name (N)); + end if; + + -- A qualified expression has inferable discriminants if its subtype + -- mark is a constrained Unchecked_Union subtype. + + elsif Nkind (N) = N_Qualified_Expression then + return Is_Unchecked_Union (Etype (Subtype_Mark (N))) + and then Is_Constrained (Etype (Subtype_Mark (N))); + + -- For all other names, it is sufficient to have a constrained + -- Unchecked_Union nominal subtype. + + else + return Is_Unchecked_Union (Base_Type (Etype (N))) + and then Is_Constrained (Etype (N)); + end if; + end Has_Inferable_Discriminants; + -------------------- -- Has_Infinities -- -------------------- @@ -12944,6 +13307,44 @@ package body Sem_Util is and then Nkind (Node (First_Elmt (Constits))) = N_Null; end Has_Null_Refinement; + ------------------------------------------ + -- Has_Nonstatic_Class_Wide_Pre_Or_Post -- + ------------------------------------------ + + function Is_Prim_Of_Abst_Type_With_Nonstatic_CW_Pre_Post + (Subp : Entity_Id) return Boolean + is + Disp_Type : constant Entity_Id := Find_Dispatching_Type (Subp); + Prag : Node_Id; + Pragma_Arg : Node_Id; + + begin + if Present (Disp_Type) + and then Is_Abstract_Type (Disp_Type) + and then Present (Contract (Subp)) + then + Prag := Pre_Post_Conditions (Contract (Subp)); + + while Present (Prag) loop + if Pragma_Name (Prag) in Name_Precondition | Name_Postcondition + and then Class_Present (Prag) + then + Pragma_Arg := + Nlists.First + (Pragma_Argument_Associations (Prag)); + + if not Is_Static_Expression (Expression (Pragma_Arg)) then + return True; + end if; + end if; + + Prag := Next_Pragma (Prag); + end loop; + end if; + + return False; + end Is_Prim_Of_Abst_Type_With_Nonstatic_CW_Pre_Post; + ------------------------------- -- Has_Overriding_Initialize -- ------------------------------- @@ -13706,7 +14107,7 @@ package body Sem_Util is elsif Is_Record_Type (Typ) then Comp := First_Component (Typ); while Present (Comp) loop - if Is_Volatile_Object (Comp) then + if Is_Volatile_Object_Ref (Comp) then return True; end if; @@ -14080,7 +14481,9 @@ package body Sem_Util is -- In_Pre_Post_Condition -- --------------------------- - function In_Pre_Post_Condition (N : Node_Id) return Boolean is + function In_Pre_Post_Condition + (N : Node_Id; Class_Wide_Only : Boolean := False) return Boolean + is Par : Node_Id; Prag : Node_Id := Empty; Prag_Id : Pragma_Id; @@ -14106,13 +14509,24 @@ package body Sem_Util is if Present (Prag) then Prag_Id := Get_Pragma_Id (Prag); - return - Prag_Id = Pragma_Post - or else Prag_Id = Pragma_Post_Class - or else Prag_Id = Pragma_Postcondition - or else Prag_Id = Pragma_Pre - or else Prag_Id = Pragma_Pre_Class - or else Prag_Id = Pragma_Precondition; + if Class_Wide_Only then + return + Prag_Id = Pragma_Post_Class + or else Prag_Id = Pragma_Pre_Class + or else (Class_Present (Prag) + and then (Prag_Id = Pragma_Post + or else Prag_Id = Pragma_Postcondition + or else Prag_Id = Pragma_Pre + or else Prag_Id = Pragma_Precondition)); + else + return + Prag_Id = Pragma_Post + or else Prag_Id = Pragma_Post_Class + or else Prag_Id = Pragma_Postcondition + or else Prag_Id = Pragma_Pre + or else Prag_Id = Pragma_Pre_Class + or else Prag_Id = Pragma_Precondition; + end if; -- Otherwise the node is not enclosed by a pre/postcondition pragma @@ -14337,6 +14751,17 @@ package body Sem_Util is when N_Function_Call => if not In_Function_Call then In_Function_Call := True; + + -- When the function return type has implicit dereference + -- specified we know it cannot directly contribute to the + -- return value. + + if Present (Etype (Par)) + and then Has_Implicit_Dereference + (Get_Full_View (Etype (Par))) + then + return False; + end if; else return False; end if; @@ -14424,6 +14849,8 @@ package body Sem_Util is -------------------------------- function Incomplete_Or_Partial_View (Id : Entity_Id) return Entity_Id is + S : constant Entity_Id := Scope (Id); + function Inspect_Decls (Decls : List_Id; Taft : Boolean := False) return Entity_Id; @@ -14492,7 +14919,13 @@ package body Sem_Util is begin -- Deferred constant or incomplete type case - Prev := Current_Entity_In_Scope (Id); + Prev := Current_Entity (Id); + + while Present (Prev) loop + exit when Scope (Prev) = S; + + Prev := Homonym (Prev); + end loop; if Present (Prev) and then (Is_Incomplete_Type (Prev) or else Ekind (Prev) = E_Constant) @@ -14504,18 +14937,11 @@ package body Sem_Util is -- Private or Taft amendment type case - declare - Pkg : constant Entity_Id := Scope (Id); - Pkg_Decl : Node_Id := Pkg; - - begin - if Present (Pkg) - and then Is_Package_Or_Generic_Package (Pkg) - then - while Nkind (Pkg_Decl) /= N_Package_Specification loop - Pkg_Decl := Parent (Pkg_Decl); - end loop; + if Present (S) and then Is_Package_Or_Generic_Package (S) then + declare + Pkg_Decl : constant Node_Id := Package_Specification (S); + begin -- It is knows that Typ has a private view, look for it in the -- visible declarations of the enclosing scope. A special case -- of this is when the two views have been exchanged - the full @@ -14536,11 +14962,11 @@ package body Sem_Util is -- Taft amendment type. The incomplete view should be located in -- the private declarations of the enclosing scope. - elsif In_Package_Body (Pkg) then + elsif In_Package_Body (S) then return Inspect_Decls (Private_Declarations (Pkg_Decl), True); end if; - end if; - end; + end; + end if; -- The type has no incomplete or private view @@ -14616,6 +15042,12 @@ package body Sem_Util is return No_Uint; end if; + -- Do not attempt to compute offsets within multi-dimensional arrays + + if Present (Next_Index (Ind)) then + return No_Uint; + end if; + if Nkind (Ind) = N_Subtype_Indication then Ind := Constraint (Ind); @@ -14632,7 +15064,7 @@ package body Sem_Util is -- Return the scaled offset - return Off * (Expr_Value (Exp) - Expr_Value (Low_Bound ((Ind)))); + return Off * (Expr_Value (Exp) - Expr_Value (Low_Bound (Ind))); end Indexed_Component_Bit_Offset; ----------------------------- @@ -14867,8 +15299,6 @@ package body Sem_Util is Get_Next_Interp (I, It); end loop; - End_Interp_List; - else -- Prefix is unambiguous: mark the original prefix (which might -- Come_From_Source) as a reference, since the new (relocated) one @@ -15198,8 +15628,9 @@ package body Sem_Util is function Is_Access_Variable (E : Entity_Id) return Boolean is begin - return Is_Access_Object_Type (E) - and then not Is_Access_Constant (E); + return Is_Access_Type (E) + and then not Is_Access_Constant (E) + and then Ekind (Directly_Designated_Type (E)) /= E_Subprogram_Type; end Is_Access_Variable; ----------------------------- @@ -15251,7 +15682,9 @@ package body Sem_Util is when N_Parameter_Association => return N = Explicit_Actual_Parameter (Parent (N)); - when N_Subprogram_Call => + when N_Entry_Call_Statement + | N_Subprogram_Call + => return Is_List_Member (N) and then List_Containing (N) = Parameter_Associations (Parent (N)); @@ -15312,6 +15745,15 @@ package body Sem_Util is -- statement is aliased if its type is immutably limited. or else (Is_Return_Object (E) + and then Is_Limited_View (Etype (E))) + + -- The current instance of a limited type is aliased, so + -- we want to allow uses of T'Access in the init proc for + -- a limited type T. However, we don't want to mark the formal + -- parameter as being aliased since that could impact callers. + + or else (Is_Formal (E) + and then Chars (E) = Name_uInit and then Is_Limited_View (Etype (E))); elsif Nkind (Obj) = N_Selected_Component then @@ -15328,7 +15770,7 @@ package body Sem_Util is return Is_Tagged_Type (Etype (Obj)) and then Is_Aliased_View (Expression (Obj)); - -- Ada 202x AI12-0228 + -- Ada 2022 AI12-0228 elsif Nkind (Obj) = N_Qualified_Expression and then Ada_Version >= Ada_2012 @@ -15698,18 +16140,32 @@ package body Sem_Util is Aspect_Spec_1, Aspect_Spec_2 : Node_Id) return Boolean is function Names_Match (Nm1, Nm2 : Node_Id) return Boolean; + + ----------------- + -- Names_Match -- + ----------------- + function Names_Match (Nm1, Nm2 : Node_Id) return Boolean is begin if Nkind (Nm1) /= Nkind (Nm2) then return False; + -- This may be too restrictive given that visibility + -- may allow an identifier in one case and an expanded + -- name in the other. end if; case Nkind (Nm1) is when N_Identifier => return Name_Equals (Chars (Nm1), Chars (Nm2)); + when N_Expanded_Name => - return Names_Match (Prefix (Nm1), Prefix (Nm2)) - and then Names_Match (Selector_Name (Nm1), - Selector_Name (Nm2)); + -- An inherited operation has the same name as its + -- ancestor, but they may have different scopes. + -- This may be too permissive for Iterator_Element, which + -- is intended to be identical in parent and derived type. + + return Names_Match (Selector_Name (Nm1), + Selector_Name (Nm2)); + when N_Empty => return True; -- needed for Aggregate aspect checking @@ -15737,8 +16193,7 @@ package body Sem_Util is when Aspect_Default_Iterator | Aspect_Iterator_Element | Aspect_Constant_Indexing - | Aspect_Variable_Indexing - | Aspect_Implicit_Dereference => + | Aspect_Variable_Indexing => declare Item_1 : constant Node_Id := Aspect_Rep_Item (Aspect_Spec_1); Item_2 : constant Node_Id := Aspect_Rep_Item (Aspect_Spec_2); @@ -15754,6 +16209,13 @@ package body Sem_Util is Expression (Item_2)); end; + -- A confirming aspect for Implicit_Derenfence on a derived type + -- has already been checked in Analyze_Aspect_Implicit_Dereference, + -- including the presence of renamed discriminants. + + when Aspect_Implicit_Dereference => + return True; + -- one of a kind when Aspect_Aggregate => declare @@ -15810,11 +16272,9 @@ package body Sem_Util is function Is_Concurrent_Interface (T : Entity_Id) return Boolean is begin - return Is_Interface (T) - and then - (Is_Protected_Interface (T) - or else Is_Synchronized_Interface (T) - or else Is_Task_Interface (T)); + return Is_Protected_Interface (T) + or else Is_Synchronized_Interface (T) + or else Is_Task_Interface (T); end Is_Concurrent_Interface; ----------------------- @@ -16894,8 +17354,8 @@ package body Sem_Util is Nkind (E) = N_Function_Call and then not Configurable_Run_Time_Mode and then Nkind (Original_Node (E)) = N_Attribute_Reference - and then (Entity (Name (E)) = RTE (RE_Get_Ceiling) - or else Entity (Name (E)) = RTE (RO_PE_Get_Ceiling)); + and then (Is_RTE (Entity (Name (E)), RE_Get_Ceiling) + or else Is_RTE (Entity (Name (E)), RO_PE_Get_Ceiling)); end Is_Expanded_Priority_Attribute; ---------------------------- @@ -17050,7 +17510,8 @@ package body Sem_Util is function Is_Full_Access_Object (N : Node_Id) return Boolean is begin - return Is_Atomic_Object (N) or else Is_Volatile_Full_Access_Object (N); + return Is_Atomic_Object (N) + or else Is_Volatile_Full_Access_Object_Ref (N); end Is_Full_Access_Object; ------------------------------- @@ -17139,9 +17600,7 @@ package body Sem_Util is -- Record types elsif Is_Record_Type (Typ) then - if Has_Discriminants (Typ) - and then - Present (Discriminant_Default_Value (First_Discriminant (Typ))) + if Has_Defaulted_Discriminants (Typ) and then Is_Fully_Initialized_Variant (Typ) then return True; @@ -17685,7 +18144,9 @@ package body Sem_Util is Ent : constant Entity_Id := Entity (Expr); Sub : constant Entity_Id := Enclosing_Subprogram (Ent); begin - if Ekind (Ent) not in E_Variable | E_In_Out_Parameter then + if Ekind (Ent) + not in E_Variable | E_In_Out_Parameter | E_Out_Parameter + then return False; else return Present (Sub) and then Sub = Current_Subprogram; @@ -18174,10 +18635,10 @@ package body Sem_Util is when N_Function_Call => - -- Ada 2020 (AI12-0175): Calls to certain functions that are + -- Ada 2022 (AI12-0175): Calls to certain functions that are -- essentially unchecked conversions are preelaborable. - if Ada_Version >= Ada_2020 + if Ada_Version >= Ada_2022 and then Nkind (Expr) = N_Function_Call and then Is_Entity_Name (Name (Expr)) and then Is_Preelaborable_Function (Entity (Name (Expr))) @@ -18292,18 +18753,143 @@ package body Sem_Util is return False; end Is_Nontrivial_DIC_Procedure; + ----------------------- + -- Is_Null_Extension -- + ----------------------- + + function Is_Null_Extension + (T : Entity_Id; Ignore_Privacy : Boolean := False) return Boolean + is + Type_Decl : Node_Id; + Type_Def : Node_Id; + begin + if Ignore_Privacy then + Type_Decl := Parent (Underlying_Type (Base_Type (T))); + else + Type_Decl := Parent (Base_Type (T)); + if Nkind (Type_Decl) /= N_Full_Type_Declaration then + return False; + end if; + end if; + pragma Assert (Nkind (Type_Decl) = N_Full_Type_Declaration); + Type_Def := Type_Definition (Type_Decl); + if Present (Discriminant_Specifications (Type_Decl)) + or else Nkind (Type_Def) /= N_Derived_Type_Definition + or else not Is_Tagged_Type (T) + or else No (Record_Extension_Part (Type_Def)) + then + return False; + end if; + + return Is_Null_Record_Definition (Record_Extension_Part (Type_Def)); + end Is_Null_Extension; + + -------------------------- + -- Is_Null_Extension_Of -- + -------------------------- + + function Is_Null_Extension_Of + (Descendant, Ancestor : Entity_Id) return Boolean + is + Ancestor_Type : constant Entity_Id + := Underlying_Type (Base_Type (Ancestor)); + Descendant_Type : Entity_Id := Underlying_Type (Base_Type (Descendant)); + begin + pragma Assert (Descendant_Type /= Ancestor_Type); + while Descendant_Type /= Ancestor_Type loop + if not Is_Null_Extension + (Descendant_Type, Ignore_Privacy => True) + then + return False; + end if; + Descendant_Type := Etype (Subtype_Indication + (Type_Definition (Parent (Descendant_Type)))); + Descendant_Type := Underlying_Type (Base_Type (Descendant_Type)); + end loop; + return True; + end Is_Null_Extension_Of; + + ------------------------------- + -- Is_Null_Record_Definition -- + ------------------------------- + + function Is_Null_Record_Definition (Record_Def : Node_Id) return Boolean is + Item : Node_Id; + begin + -- Testing Null_Present is just an optimization, not required. + + if Null_Present (Record_Def) then + return True; + elsif Present (Variant_Part (Component_List (Record_Def))) then + return False; + elsif not Present (Component_List (Record_Def)) then + return True; + end if; + + Item := First (Component_Items (Component_List (Record_Def))); + + while Present (Item) loop + if Nkind (Item) = N_Component_Declaration + and then Is_Internal_Name (Chars (Defining_Identifier (Item))) + then + null; + elsif Nkind (Item) = N_Pragma then + null; + else + return False; + end if; + Item := Next (Item); + end loop; + + return True; + end Is_Null_Record_Definition; + ------------------------- -- Is_Null_Record_Type -- ------------------------- - function Is_Null_Record_Type (T : Entity_Id) return Boolean is - Decl : constant Node_Id := Parent (T); + function Is_Null_Record_Type + (T : Entity_Id; Ignore_Privacy : Boolean := False) return Boolean + is + Decl : Node_Id; + Type_Def : Node_Id; begin - return Nkind (Decl) = N_Full_Type_Declaration - and then Nkind (Type_Definition (Decl)) = N_Record_Definition - and then - (No (Component_List (Type_Definition (Decl))) - or else Null_Present (Component_List (Type_Definition (Decl)))); + if not Is_Record_Type (T) then + return False; + end if; + + if Ignore_Privacy then + Decl := Parent (Underlying_Type (Base_Type (T))); + else + Decl := Parent (Base_Type (T)); + if Nkind (Decl) /= N_Full_Type_Declaration then + return False; + end if; + end if; + pragma Assert (Nkind (Decl) = N_Full_Type_Declaration); + Type_Def := Type_Definition (Decl); + + if Has_Discriminants (Defining_Identifier (Decl)) then + return False; + end if; + + case Nkind (Type_Def) is + when N_Record_Definition => + return Is_Null_Record_Definition (Type_Def); + when N_Derived_Type_Definition => + if not Is_Null_Record_Type + (Etype (Subtype_Indication (Type_Def)), + Ignore_Privacy => Ignore_Privacy) + then + return False; + elsif not Is_Tagged_Type (T) then + return True; + else + return Is_Null_Extension (T, Ignore_Privacy => Ignore_Privacy); + end if; + when others => + return False; + end case; end Is_Null_Record_Type; --------------------- @@ -18317,7 +18903,9 @@ package body Sem_Util is -- This is because the parser always checks that prefixes of attributes -- are named. - return not (Is_Entity_Name (Prefix) and then Is_Type (Entity (Prefix))); + return not (Is_Entity_Name (Prefix) + and then Is_Type (Entity (Prefix)) + and then not Is_Current_Instance (Prefix)); end Is_Object_Image; ------------------------- @@ -18409,7 +18997,7 @@ package body Sem_Util is and then Is_Object_Reference (Expression (N)); else - -- AI12-0226: In Ada 202x a value conversion of an object is + -- AI12-0226: In Ada 2022 a value conversion of an object is -- an object. return Is_Object_Reference (Expression (N)); @@ -18557,8 +19145,9 @@ package body Sem_Util is ---------------------------- function Is_OK_Volatile_Context - (Context : Node_Id; - Obj_Ref : Node_Id) return Boolean + (Context : Node_Id; + Obj_Ref : Node_Id; + Check_Actuals : Boolean) return Boolean is function Is_Protected_Operation_Call (Nod : Node_Id) return Boolean; -- Determine whether an arbitrary node denotes a call to a protected @@ -18633,21 +19222,14 @@ package body Sem_Util is ------------------------------ function Within_Volatile_Function (Id : Entity_Id) return Boolean is - Func_Id : Entity_Id; + pragma Assert (Ekind (Id) = E_Return_Statement); - begin - -- Traverse the scope stack looking for a [generic] function + Func_Id : constant Entity_Id := Return_Applies_To (Id); - Func_Id := Id; - while Present (Func_Id) and then Func_Id /= Standard_Standard loop - if Ekind (Func_Id) in E_Function | E_Generic_Function then - return Is_Volatile_Function (Func_Id); - end if; - - Func_Id := Scope (Func_Id); - end loop; + begin + pragma Assert (Ekind (Func_Id) in E_Function | E_Generic_Function); - return False; + return Is_Volatile_Function (Func_Id); end Within_Volatile_Function; -- Local variables @@ -18657,9 +19239,26 @@ package body Sem_Util is -- Start of processing for Is_OK_Volatile_Context begin + -- Ignore context restriction when doing preanalysis, e.g. on a copy of + -- an expression function, because this copy is not fully decorated and + -- it is not possible to reliably decide the legality of the context. + -- Any violations will be reported anyway when doing the full analysis. + + if not Full_Analysis then + return True; + end if; + + -- For actual parameters within explicit parameter associations switch + -- the context to the corresponding subprogram call. + + if Nkind (Context) = N_Parameter_Association then + return Is_OK_Volatile_Context (Context => Parent (Context), + Obj_Ref => Obj_Ref, + Check_Actuals => Check_Actuals); + -- The volatile object appears on either side of an assignment - if Nkind (Context) = N_Assignment_Statement then + elsif Nkind (Context) = N_Assignment_Statement then return True; -- The volatile object is part of the initialization expression of @@ -18677,7 +19276,7 @@ package body Sem_Util is -- function is volatile. if Is_Return_Object (Obj_Id) then - return Within_Volatile_Function (Obj_Id); + return Within_Volatile_Function (Scope (Obj_Id)); -- Otherwise this is a normal object initialization @@ -18728,8 +19327,9 @@ package body Sem_Util is N_Slice and then Prefix (Context) = Obj_Ref and then Is_OK_Volatile_Context - (Context => Parent (Context), - Obj_Ref => Context) + (Context => Parent (Context), + Obj_Ref => Context, + Check_Actuals => Check_Actuals) then return True; @@ -18761,8 +19361,9 @@ package body Sem_Util is | N_Unchecked_Type_Conversion and then Expression (Context) = Obj_Ref and then Is_OK_Volatile_Context - (Context => Parent (Context), - Obj_Ref => Context) + (Context => Parent (Context), + Obj_Ref => Context, + Check_Actuals => Check_Actuals) then return True; @@ -18777,17 +19378,43 @@ package body Sem_Util is elsif Within_Check (Context) then return True; - -- Assume that references to effectively volatile objects that appear - -- as actual parameters in a subprogram call are always legal. A full - -- legality check is done when the actuals are resolved (see routine - -- Resolve_Actuals). + -- References to effectively volatile objects that appear as actual + -- parameters in subprogram calls can be examined only after call itself + -- has been resolved. Before that, assume such references to be legal. - elsif Within_Subprogram_Call (Context) then - return True; + elsif Nkind (Context) in N_Subprogram_Call | N_Entry_Call_Statement then + if Check_Actuals then + declare + Call : Node_Id; + Formal : Entity_Id; + Subp : constant Entity_Id := Get_Called_Entity (Context); + begin + Find_Actual (Obj_Ref, Formal, Call); + pragma Assert (Call = Context); + + -- An effectively volatile object may act as an actual when the + -- corresponding formal is of a non-scalar effectively volatile + -- type (SPARK RM 7.1.3(10)). + + if not Is_Scalar_Type (Etype (Formal)) + and then Is_Effectively_Volatile_For_Reading (Etype (Formal)) + then + return True; - -- Otherwise the context is not suitable for an effectively volatile - -- object. + -- An effectively volatile object may act as an actual in a + -- call to an instance of Unchecked_Conversion. (SPARK RM + -- 7.1.3(10)). + elsif Is_Unchecked_Conversion_Instance (Subp) then + return True; + + else + return False; + end if; + end; + else + return True; + end if; else return False; end if; @@ -18860,7 +19487,7 @@ package body Sem_Util is elsif Is_Tagged_Type (Typ) then return True; - -- Case of non-discriminated record + -- Case of nondiscriminated record else declare @@ -19103,8 +19730,8 @@ package body Sem_Util is and then Aggregate_Type /= Any_Composite then if Is_Array_Type (Aggregate_Type) then - if Ada_Version >= Ada_2020 then - -- For Ada_2020, this predicate returns True for + if Ada_Version >= Ada_2022 then + -- For Ada 2022, this predicate returns True for -- any "repeatedly evaluated" expression. return True; end if; @@ -19517,10 +20144,10 @@ package body Sem_Util is elsif Nkind (N) = N_Null then return True; - -- Ada 2020 (AI12-0175): Calls to certain functions that are essentially + -- Ada 2022 (AI12-0175): Calls to certain functions that are essentially -- unchecked conversions are preelaborable. - elsif Ada_Version >= Ada_2020 + elsif Ada_Version >= Ada_2022 and then Nkind (N) = N_Function_Call and then Is_Entity_Name (Name (N)) and then Is_Preelaborable_Function (Entity (Name (N))) @@ -19749,7 +20376,8 @@ package body Sem_Util is function Is_Renamed_Entry (Proc_Nam : Entity_Id) return Boolean is Orig_Node : Node_Id := Empty; - Subp_Decl : Node_Id := Parent (Parent (Proc_Nam)); + Subp_Decl : Node_Id := + (if No (Parent (Proc_Nam)) then Empty else Parent (Parent (Proc_Nam))); function Is_Entry (Nam : Node_Id) return Boolean; -- Determine whether Nam is an entry. Traverse selectors if there are @@ -20022,11 +20650,11 @@ package body Sem_Util is function Is_Static_Function (Subp : Entity_Id) return Boolean is begin - -- Always return False for pre Ada 2020 to e.g. ignore the Static - -- aspect in package Interfaces for Ada_Version < 2020 and also + -- Always return False for pre Ada 2022 to e.g. ignore the Static + -- aspect in package Interfaces for Ada_Version < 2022 and also -- for efficiency. - return Ada_Version >= Ada_2020 + return Ada_Version >= Ada_2022 and then Has_Aspect (Subp, Aspect_Static) and then (No (Find_Value_Of_Aspect (Subp, Aspect_Static)) @@ -20782,11 +21410,11 @@ package body Sem_Util is and then Scope (Scope (Scope (Root))) = Standard_Standard; end Is_Visibly_Controlled; - -------------------------------------- - -- Is_Volatile_Full_Access_Object -- - -------------------------------------- + ---------------------------------------- + -- Is_Volatile_Full_Access_Object_Ref -- + ---------------------------------------- - function Is_Volatile_Full_Access_Object (N : Node_Id) return Boolean is + function Is_Volatile_Full_Access_Object_Ref (N : Node_Id) return Boolean is function Is_VFA_Object_Entity (Id : Entity_Id) return Boolean; -- Determine whether arbitrary entity Id denotes an object that is -- Volatile_Full_Access. @@ -20804,7 +21432,7 @@ package body Sem_Util is Is_Volatile_Full_Access (Etype (Id))); end Is_VFA_Object_Entity; - -- Start of processing for Is_Volatile_Full_Access_Object + -- Start of processing for Is_Volatile_Full_Access_Object_Ref begin if Is_Entity_Name (N) then @@ -20819,7 +21447,7 @@ package body Sem_Util is else return False; end if; - end Is_Volatile_Full_Access_Object; + end Is_Volatile_Full_Access_Object_Ref; -------------------------- -- Is_Volatile_Function -- @@ -20829,9 +21457,11 @@ package body Sem_Util is begin pragma Assert (Ekind (Func_Id) in E_Function | E_Generic_Function); - -- A function declared within a protected type is volatile + -- A protected function is volatile - if Is_Protected_Type (Scope (Func_Id)) then + if Nkind (Parent (Unit_Declaration_Node (Func_Id))) = + N_Protected_Definition + then return True; -- An instance of Ada.Unchecked_Conversion is a volatile function if @@ -20851,11 +21481,11 @@ package body Sem_Util is end if; end Is_Volatile_Function; - ------------------------ - -- Is_Volatile_Object -- - ------------------------ + ---------------------------- + -- Is_Volatile_Object_Ref -- + ---------------------------- - function Is_Volatile_Object (N : Node_Id) return Boolean is + function Is_Volatile_Object_Ref (N : Node_Id) return Boolean is function Is_Volatile_Object_Entity (Id : Entity_Id) return Boolean; -- Determine whether arbitrary entity Id denotes an object that is -- Volatile. @@ -20901,7 +21531,7 @@ package body Sem_Util is then return True; - elsif Is_Volatile_Object (P) then + elsif Is_Volatile_Object_Ref (P) then return True; else @@ -20909,7 +21539,7 @@ package body Sem_Util is end if; end Prefix_Has_Volatile_Components; - -- Start of processing for Is_Volatile_Object + -- Start of processing for Is_Volatile_Object_Ref begin if Is_Entity_Name (N) then @@ -20928,7 +21558,7 @@ package body Sem_Util is else return False; end if; - end Is_Volatile_Object; + end Is_Volatile_Object_Ref; ----------------------------- -- Iterate_Call_Parameters -- @@ -22727,9 +23357,6 @@ package body Sem_Util is -- This routine performs low-level tree manipulations and needs access -- to the internals of the tree. - use Atree.Unchecked_Access; - use Atree_Private_Part; - EWA_Level : Nat := 0; -- This counter keeps track of how many N_Expression_With_Actions nodes -- are encountered during a depth-first traversal of the subtree. These @@ -23271,6 +23898,25 @@ package body Sem_Util is function Copy_Node_With_Replacement (N : Node_Id) return Node_Id is Result : Node_Id; + function Transform (U : Union_Id) return Union_Id; + -- Copies one field, replacing N with Result + + --------------- + -- Transform -- + --------------- + + function Transform (U : Union_Id) return Union_Id is + begin + return Copy_Field_With_Replacement + (Field => U, + Old_Par => N, + New_Par => Result); + end Transform; + + procedure Walk is new Walk_Sinfo_Fields_Pairwise (Transform); + + -- Start of processing for Copy_Node_With_Replacement + begin -- Assume that the node must be returned unchanged @@ -23281,35 +23927,7 @@ package body Sem_Util is Result := New_Copy (N); - Set_Field1 (Result, - Copy_Field_With_Replacement - (Field => Field1 (Result), - Old_Par => N, - New_Par => Result)); - - Set_Field2 (Result, - Copy_Field_With_Replacement - (Field => Field2 (Result), - Old_Par => N, - New_Par => Result)); - - Set_Field3 (Result, - Copy_Field_With_Replacement - (Field => Field3 (Result), - Old_Par => N, - New_Par => Result)); - - Set_Field4 (Result, - Copy_Field_With_Replacement - (Field => Field4 (Result), - Old_Par => N, - New_Par => Result)); - - Set_Field5 (Result, - Copy_Field_With_Replacement - (Field => Field5 (Result), - Old_Par => N, - New_Par => Result)); + Walk (Result, Result); -- Update the Comes_From_Source and Sloc attributes of the node -- in case the caller has supplied new values. @@ -23449,7 +24067,7 @@ package body Sem_Util is -- A new source location defaults the Comes_From_Source attribute if New_Sloc /= No_Location then - Set_Comes_From_Source (N, Default_Node.Comes_From_Source); + Set_Comes_From_Source (N, Get_Comes_From_Source_Default); Set_Sloc (N, New_Sloc); end if; end Update_CFS_Sloc; @@ -24056,25 +24674,37 @@ package body Sem_Util is EWA_Inner_Scope_Level := EWA_Inner_Scope_Level + 1; end if; - Visit_Field - (Field => Field1 (N), - Par_Nod => N); + -- If the node is a block, we need to process all declarations + -- in the block and make new entities for each. - Visit_Field - (Field => Field2 (N), - Par_Nod => N); + if Nkind (N) = N_Block_Statement and then Present (Declarations (N)) + then + declare + Decl : Node_Id := First (Declarations (N)); - Visit_Field - (Field => Field3 (N), - Par_Nod => N); + begin + while Present (Decl) loop + if Nkind (Decl) = N_Object_Declaration then + Add_New_Entity (Defining_Identifier (Decl), + New_Copy (Defining_Identifier (Decl))); + end if; - Visit_Field - (Field => Field4 (N), - Par_Nod => N); + Next (Decl); + end loop; + end; + end if; - Visit_Field - (Field => Field5 (N), - Par_Nod => N); + declare + procedure Action (U : Union_Id); + procedure Action (U : Union_Id) is + begin + Visit_Field (Field => U, Par_Nod => N); + end Action; + + procedure Walk is new Walk_Sinfo_Fields (Action); + begin + Walk (N); + end; if EWA_Level > 0 and then Nkind (N) in N_Block_Statement @@ -24284,10 +24914,10 @@ package body Sem_Util is (Chars (Related_Id), Suffix, Suffix_Index, Prefix)); begin - Set_Ekind (N, Kind); - Set_Is_Internal (N, True); - Append_Entity (N, Scope_Id); - Set_Public_Status (N); + Mutate_Ekind (N, Kind); + Set_Is_Internal (N, True); + Append_Entity (N, Scope_Id); + Set_Public_Status (N); if Kind in Type_Kind then Init_Size_Align (N); @@ -24309,7 +24939,7 @@ package body Sem_Util is N : constant Entity_Id := Make_Temporary (Sloc_Value, Id_Char); begin - Set_Ekind (N, Kind); + Mutate_Ekind (N, Kind); Set_Is_Internal (N, True); Append_Entity (N, Scope_Id); @@ -24941,7 +25571,7 @@ package body Sem_Util is Domain : constant Node_Id := Name (Parent (Ent)); begin - -- TBD : in the full version of the construct, the + -- ??? In the full version of the construct, the -- domain of iteration can be given by an expression. if Is_Entity_Name (Domain) then @@ -26008,14 +26638,16 @@ package body Sem_Util is Partial_DIC_Proc := Partial_DIC_Procedure (From_Typ); -- The setting of the attributes is intentionally conservative. This - -- prevents accidental clobbering of enabled attributes. + -- prevents accidental clobbering of enabled attributes. We need to + -- call Base_Type twice, because it is sometimes not set to an actual + -- base type. if Has_Inherited_DIC (From_Typ) then - Set_Has_Inherited_DIC (Typ); + Set_Has_Inherited_DIC (Base_Type (Base_Type (Typ))); end if; if Has_Own_DIC (From_Typ) then - Set_Has_Own_DIC (Typ); + Set_Has_Own_DIC (Base_Type (Base_Type (Typ))); end if; if Present (DIC_Proc) and then No (DIC_Procedure (Typ)) then @@ -26056,7 +26688,9 @@ package body Sem_Util is Part_IP := Partial_Invariant_Procedure (From_Typ); -- The setting of the attributes is intentionally conservative. This - -- prevents accidental clobbering of enabled attributes. + -- prevents accidental clobbering of enabled attributes. We need to + -- call Base_Type twice, because it is sometimes not set to an actual + -- base type. if Has_Inheritable_Invariants (From_Typ) then Set_Has_Inheritable_Invariants (Typ); @@ -26067,7 +26701,7 @@ package body Sem_Util is end if; if Has_Own_Invariants (From_Typ) then - Set_Has_Own_Invariants (Base_Type (Typ)); + Set_Has_Own_Invariants (Base_Type (Base_Type (Typ))); end if; if Present (Full_IP) and then No (Invariant_Procedure (Typ)) then @@ -26371,6 +27005,8 @@ package body Sem_Util is -- generated before the next instruction. function Requires_Transient_Scope (Id : Entity_Id) return Boolean is + pragma Assert (if Present (Id) then Ekind (Id) in E_Void | Type_Kind); + function Caller_Known_Size_Record (Typ : Entity_Id) return Boolean; -- This is called for untagged records and protected types, with -- nondefaulted discriminants. Returns True if the size of function @@ -26451,8 +27087,8 @@ package body Sem_Util is -- Do not set Has_Controlled_Component on a class-wide equivalent -- type. See Make_CW_Equivalent_Type. - if Present (Typ) - and then not Is_Frozen (Typ) + if not Is_Frozen (Typ) + and then Is_Base_Type (Typ) and then (Is_Record_Type (Typ) or else Is_Concurrent_Type (Typ) or else Is_Incomplete_Or_Private_Type (Typ)) @@ -26568,19 +27204,20 @@ package body Sem_Util is -- Start of processing for Requires_Transient_Scope begin - Ensure_Minimum_Decoration (Id); - -- This is a private type which is not completed yet. This can only -- happen in a default expression (of a formal parameter or of a -- record component). Do not expand transient scope in this case. if No (Typ) then return False; + end if; + + Ensure_Minimum_Decoration (Id); -- Do not expand transient scope for non-existent procedure return or -- string literal types. - elsif Typ = Standard_Void_Type + if Typ = Standard_Void_Type or else Ekind (Typ) = E_String_Literal_Subtype then return False; @@ -26721,7 +27358,7 @@ package body Sem_Util is is begin -- The only entities for which we track constant values are variables - -- which are not renamings, constants and formal parameters, so check + -- that are not renamings, constants and formal parameters, so check -- if we have this case. -- Note: it may seem odd to track constant values for constants, but in @@ -26792,7 +27429,7 @@ package body Sem_Util is -- or an exception handler). We skip this if Cond is True, since the -- capturing of values from conditional tests handles this ok. - if Cond then + if Cond or else No (N) then return True; end if; @@ -27163,66 +27800,6 @@ package body Sem_Util is return False; end Scope_Within_Or_Same; - -------------------- - -- Set_Convention -- - -------------------- - - procedure Set_Convention (E : Entity_Id; Val : Snames.Convention_Id) is - begin - Basic_Set_Convention (E, Val); - - if Is_Type (E) - and then Is_Access_Subprogram_Type (Base_Type (E)) - and then Has_Foreign_Convention (E) - then - Set_Can_Use_Internal_Rep (E, False); - end if; - - -- If E is an object, including a component, and the type of E is an - -- anonymous access type with no convention set, then also set the - -- convention of the anonymous access type. We do not do this for - -- anonymous protected types, since protected types always have the - -- default convention. - - if Present (Etype (E)) - and then (Is_Object (E) - - -- Allow E_Void (happens for pragma Convention appearing - -- in the middle of a record applying to a component) - - or else Ekind (E) = E_Void) - then - declare - Typ : constant Entity_Id := Etype (E); - - begin - if Ekind (Typ) in E_Anonymous_Access_Type - | E_Anonymous_Access_Subprogram_Type - and then not Has_Convention_Pragma (Typ) - then - Basic_Set_Convention (Typ, Val); - Set_Has_Convention_Pragma (Typ); - - -- And for the access subprogram type, deal similarly with the - -- designated E_Subprogram_Type, which is always internal. - - if Ekind (Typ) = E_Anonymous_Access_Subprogram_Type then - declare - Dtype : constant Entity_Id := Designated_Type (Typ); - begin - if Ekind (Dtype) = E_Subprogram_Type - and then not Has_Convention_Pragma (Dtype) - then - Basic_Set_Convention (Dtype, Val); - Set_Has_Convention_Pragma (Dtype); - end if; - end; - end if; - end if; - end; - end if; - end Set_Convention; - ------------------------ -- Set_Current_Entity -- ------------------------ @@ -27789,7 +28366,7 @@ package body Sem_Util is Set_Is_Unsigned_Type (T1, Is_Unsigned_Type (T2)); end if; - Set_Alignment (T1, Alignment (T2)); + Copy_Alignment (To => T1, From => T2); end Set_Size_Info; ------------------------------ @@ -28587,12 +29164,15 @@ package body Sem_Util is -- Type_Access_Level -- ----------------------- - function Type_Access_Level (Typ : Entity_Id) return Uint is - Btyp : Entity_Id; + function Type_Access_Level + (Typ : Entity_Id; + Allow_Alt_Model : Boolean := True; + Assoc_Ent : Entity_Id := Empty) return Uint + is + Btyp : Entity_Id := Base_Type (Typ); + Def_Ent : Entity_Id; begin - Btyp := Base_Type (Typ); - -- Ada 2005 (AI-230): For most cases of anonymous access types, we -- simply use the level where the type is declared. This is true for -- stand-alone object declarations, and for anonymous access types @@ -28603,13 +29183,62 @@ package body Sem_Util is if Is_Access_Type (Btyp) then if Ekind (Btyp) = E_Anonymous_Access_Type then + -- No_Dynamic_Accessibility_Checks restriction override for + -- alternative accessibility model. + + if Allow_Alt_Model + and then No_Dynamic_Accessibility_Checks_Enabled (Btyp) + then + -- In the -gnatd_b model, the level of an anonymous access + -- type is always that of the designated type. + + if Debug_Flag_Underscore_B then + return Type_Access_Level + (Designated_Type (Btyp), Allow_Alt_Model); + end if; + + -- When an anonymous access type's Assoc_Ent is specifiedi, + -- calculate the result based on the general accessibility + -- level routine. + + -- We would like to use Associated_Node_For_Itype here instead, + -- but in some cases it is not fine grained enough ??? + + if Present (Assoc_Ent) then + return Static_Accessibility_Level + (Assoc_Ent, Object_Decl_Level); + end if; + + -- Otherwise take the context of the anonymous access type into + -- account. + + -- Obtain the defining entity for the internally generated + -- anonymous access type. + + Def_Ent := Defining_Entity_Or_Empty + (Associated_Node_For_Itype (Typ)); + + if Present (Def_Ent) then + -- When the type comes from an anonymous access parameter, + -- the level is that of the subprogram declaration. + + if Ekind (Def_Ent) in Subprogram_Kind then + return Scope_Depth (Def_Ent); + + -- When the type is an access discriminant, the level is + -- that of the type. + + elsif Ekind (Def_Ent) = E_Discriminant then + return Scope_Depth (Scope (Def_Ent)); + end if; + end if; -- If the type is a nonlocal anonymous access type (such as for -- an access parameter) we treat it as being declared at the -- library level to ensure that names such as X.all'access don't -- fail static accessibility checks. - if not Is_Local_Anonymous_Access (Typ) then + elsif not Is_Local_Anonymous_Access (Typ) then return Scope_Depth (Standard_Standard); -- If this is a return object, the accessibility level is that of @@ -28643,7 +29272,7 @@ package body Sem_Util is -- Treat the return object's type as having the level of the -- function's result subtype (as per RM05-6.5(5.3/2)). - return Type_Access_Level (Etype (Scop)); + return Type_Access_Level (Etype (Scop), Allow_Alt_Model); end; end if; end if; @@ -28754,6 +29383,39 @@ package body Sem_Util is end if; end Type_Without_Stream_Operation; + ------------------------------ + -- Ultimate_Overlaid_Entity -- + ------------------------------ + + function Ultimate_Overlaid_Entity (E : Entity_Id) return Entity_Id is + Address : Node_Id; + Alias : Entity_Id := E; + Offset : Boolean; + + begin + -- Currently this routine is only called for stand-alone objects that + -- have been analysed, since the analysis of the Address aspect is often + -- delayed. + + pragma Assert (Ekind (E) in E_Constant | E_Variable); + + loop + Address := Address_Clause (Alias); + if Present (Address) then + Find_Overlaid_Entity (Address, Alias, Offset); + if Present (Alias) then + null; + else + return Empty; + end if; + elsif Alias = E then + return Empty; + else + return Alias; + end if; + end loop; + end Ultimate_Overlaid_Entity; + --------------------- -- Ultimate_Prefix -- --------------------- @@ -29186,9 +29848,7 @@ package body Sem_Util is 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 + if Is_Universal_Numeric_Type (Etype (Opnd)) then return Etype (Opnd); else return Empty; @@ -29197,9 +29857,7 @@ package body Sem_Util is else Get_First_Interp (Opnd, Index, It); while Present (It.Typ) loop - if It.Typ = Universal_Integer - or else It.Typ = Universal_Real - then + if Is_Universal_Numeric_Type (It.Typ) then return It.Typ; end if; @@ -29255,42 +29913,55 @@ package body Sem_Util is -------------------- function Validated_View (Typ : Entity_Id) return Entity_Id is - Continue : Boolean; - Val_Typ : Entity_Id; - begin - Continue := True; - Val_Typ := Base_Type (Typ); + -- Scalar types can be always validated. In fast, switiching to the base + -- type would drop the range constraints and force validation to use a + -- larger type than necessary. + + if Is_Scalar_Type (Typ) then + return Typ; + + -- Array types can be validated even when they are derived, because + -- validation only requires their bounds and component types to be + -- accessible. In fact, switching to the parent type would pollute + -- expansion of attribute Valid_Scalars with unnecessary conversion + -- that might not be eliminated by the frontend. + + elsif Is_Array_Type (Typ) then + return Typ; + + -- For other types, in particular for record subtypes, we switch to the + -- base type. + + elsif not Is_Base_Type (Typ) then + return Validated_View (Base_Type (Typ)); -- Obtain the full view of the input type by stripping away concurrency, -- derivations, and privacy. - while Continue loop - Continue := False; - - if Is_Concurrent_Type (Val_Typ) then - if Present (Corresponding_Record_Type (Val_Typ)) then - Continue := True; - Val_Typ := Corresponding_Record_Type (Val_Typ); - end if; + elsif Is_Concurrent_Type (Typ) then + if Present (Corresponding_Record_Type (Typ)) then + return Corresponding_Record_Type (Typ); + else + return Typ; + end if; - elsif Is_Derived_Type (Val_Typ) then - Continue := True; - Val_Typ := Etype (Val_Typ); + elsif Is_Derived_Type (Typ) then + return Validated_View (Etype (Typ)); - elsif Is_Private_Type (Val_Typ) then - if Present (Underlying_Full_View (Val_Typ)) then - Continue := True; - Val_Typ := Underlying_Full_View (Val_Typ); + elsif Is_Private_Type (Typ) then + if Present (Underlying_Full_View (Typ)) then + return Validated_View (Underlying_Full_View (Typ)); - elsif Present (Full_View (Val_Typ)) then - Continue := True; - Val_Typ := Full_View (Val_Typ); - end if; + elsif Present (Full_View (Typ)) then + return Validated_View (Full_View (Typ)); + else + return Typ; end if; - end loop; - return Val_Typ; + else + return Typ; + end if; end Validated_View; ----------------------- @@ -29381,36 +30052,6 @@ package body Sem_Util is return Scope_Within_Or_Same (Scope (E), S); end Within_Scope; - ---------------------------- - -- Within_Subprogram_Call -- - ---------------------------- - - function Within_Subprogram_Call (N : Node_Id) return Boolean is - Par : Node_Id; - - begin - -- Climb the parent chain looking for a function or procedure call - - Par := N; - while Present (Par) loop - if Nkind (Par) in N_Entry_Call_Statement - | N_Function_Call - | N_Procedure_Call_Statement - then - return True; - - -- Prevent the search from going too far - - elsif Is_Body_Or_Package_Declaration (Par) then - exit; - end if; - - Par := Parent (Par); - end loop; - - return False; - end Within_Subprogram_Call; - ---------------- -- Wrong_Type -- ---------------- @@ -29939,7 +30580,7 @@ package body Sem_Util is procedure Normalize_Interval_List (List : in out Discrete_Interval_List; Last : out Nat); - -- Perform sorting and merging as required by Check_Consistency. + -- Perform sorting and merging as required by Check_Consistency ------------------------- -- Aggregate_Intervals -- @@ -29954,6 +30595,10 @@ package body Sem_Util is -- Count the number of intervals given in the aggregate N; the others -- choice (if present) is not taken into account. + ------------------------------ + -- Unmerged_Intervals_Count -- + ------------------------------ + function Unmerged_Intervals_Count return Nat is Count : Nat := 0; Choice : Node_Id; @@ -30054,7 +30699,7 @@ package body Sem_Util is (Discrete_Choices : List_Id) return Discrete_Interval_List is function Unmerged_Choice_Count return Nat; - -- The number of intervals before adjacent intervals are merged. + -- The number of intervals before adjacent intervals are merged --------------------------- -- Unmerged_Choice_Count -- @@ -30732,7 +31377,7 @@ package body Sem_Util is -- type case correctly, so we avoid that problem by -- returning True here. return True; - elsif Ada_Version < Ada_2020 then + elsif Ada_Version < Ada_2022 then return False; elsif not Is_Conditionally_Evaluated (Expr) then return False; @@ -31143,9 +31788,9 @@ package body Sem_Util is (Loc, Access_Type_Id, Type_Definition => Access_Type_Def); begin - Set_Ekind (Temp_Id, E_Variable); + Mutate_Ekind (Temp_Id, E_Variable); Set_Etype (Temp_Id, Access_Type_Id); - Set_Ekind (Access_Type_Id, E_Access_Type); + Mutate_Ekind (Access_Type_Id, E_Access_Type); if Append_Decls_In_Reverse_Order then Append_Item (Temp_Decl, Is_Eval_Stmt => False); |