diff options
author | Ian Lance Taylor <iant@golang.org> | 2021-09-13 10:37:49 -0700 |
---|---|---|
committer | Ian Lance Taylor <iant@golang.org> | 2021-09-13 10:37:49 -0700 |
commit | e252b51ccde010cbd2a146485d8045103cd99533 (patch) | |
tree | e060f101cdc32bf5e520de8e5275db9d4236b74c /gcc/ada/sem_ch6.adb | |
parent | f10c7c4596dda99d2ee872c995ae4aeda65adbdf (diff) | |
parent | 104c05c5284b7822d770ee51a7d91946c7e56d50 (diff) | |
download | gcc-e252b51ccde010cbd2a146485d8045103cd99533.zip gcc-e252b51ccde010cbd2a146485d8045103cd99533.tar.gz gcc-e252b51ccde010cbd2a146485d8045103cd99533.tar.bz2 |
Merge from trunk revision 104c05c5284b7822d770ee51a7d91946c7e56d50.
Diffstat (limited to 'gcc/ada/sem_ch6.adb')
-rw-r--r-- | gcc/ada/sem_ch6.adb | 635 |
1 files changed, 396 insertions, 239 deletions
diff --git a/gcc/ada/sem_ch6.adb b/gcc/ada/sem_ch6.adb index 7bab772..304dc19 100644 --- a/gcc/ada/sem_ch6.adb +++ b/gcc/ada/sem_ch6.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,70 +23,73 @@ -- -- ------------------------------------------------------------------------------ -with Aspects; use Aspects; -with Atree; use Atree; -with Checks; use Checks; -with Contracts; use Contracts; -with Debug; use Debug; -with Einfo; use Einfo; -with Elists; use Elists; -with Errout; use Errout; -with Expander; use Expander; -with Exp_Ch3; use Exp_Ch3; -with Exp_Ch6; use Exp_Ch6; -with Exp_Ch7; use Exp_Ch7; -with Exp_Ch9; use Exp_Ch9; -with Exp_Dbug; use Exp_Dbug; -with Exp_Tss; use Exp_Tss; -with Exp_Util; use Exp_Util; -with Freeze; use Freeze; -with Ghost; use Ghost; -with Inline; use Inline; -with Itypes; use Itypes; -with Lib.Xref; use Lib.Xref; -with Layout; use Layout; -with Namet; use Namet; -with Lib; use Lib; -with Nlists; use Nlists; -with Nmake; use Nmake; -with Opt; use Opt; -with Output; use Output; -with Restrict; use Restrict; -with Rtsfind; use Rtsfind; -with Sem; use Sem; -with Sem_Aux; use Sem_Aux; -with Sem_Cat; use Sem_Cat; -with Sem_Ch3; use Sem_Ch3; -with Sem_Ch4; use Sem_Ch4; -with Sem_Ch5; use Sem_Ch5; -with Sem_Ch8; use Sem_Ch8; -with Sem_Ch9; use Sem_Ch9; -with Sem_Ch10; use Sem_Ch10; -with Sem_Ch12; use Sem_Ch12; -with Sem_Ch13; use Sem_Ch13; -with Sem_Dim; use Sem_Dim; -with Sem_Disp; use Sem_Disp; -with Sem_Dist; use Sem_Dist; -with Sem_Elim; use Sem_Elim; -with Sem_Eval; use Sem_Eval; -with Sem_Mech; use Sem_Mech; -with Sem_Prag; use Sem_Prag; -with Sem_Res; use Sem_Res; -with Sem_Util; use Sem_Util; -with Sem_Type; use Sem_Type; -with Sem_Warn; use Sem_Warn; -with Sinput; use Sinput; -with Stand; use Stand; -with Sinfo; use Sinfo; -with Sinfo.CN; use Sinfo.CN; -with Snames; use Snames; -with Stringt; use Stringt; +with Aspects; use Aspects; +with Atree; use Atree; +with Checks; use Checks; +with Contracts; use Contracts; +with Debug; use Debug; +with Einfo; use Einfo; +with Einfo.Entities; use Einfo.Entities; +with Einfo.Utils; use Einfo.Utils; +with Elists; use Elists; +with Errout; use Errout; +with Expander; use Expander; +with Exp_Ch3; use Exp_Ch3; +with Exp_Ch6; use Exp_Ch6; +with Exp_Ch9; use Exp_Ch9; +with Exp_Dbug; use Exp_Dbug; +with Exp_Tss; use Exp_Tss; +with Exp_Util; use Exp_Util; +with Freeze; use Freeze; +with Ghost; use Ghost; +with Inline; use Inline; +with Itypes; use Itypes; +with Lib.Xref; use Lib.Xref; +with Layout; use Layout; +with Namet; use Namet; +with Lib; use Lib; +with Nlists; use Nlists; +with Nmake; use Nmake; +with Opt; use Opt; +with Output; use Output; +with Restrict; use Restrict; +with Rtsfind; use Rtsfind; +with Sem; use Sem; +with Sem_Aux; use Sem_Aux; +with Sem_Cat; use Sem_Cat; +with Sem_Ch3; use Sem_Ch3; +with Sem_Ch4; use Sem_Ch4; +with Sem_Ch5; use Sem_Ch5; +with Sem_Ch8; use Sem_Ch8; +with Sem_Ch9; use Sem_Ch9; +with Sem_Ch10; use Sem_Ch10; +with Sem_Ch12; use Sem_Ch12; +with Sem_Ch13; use Sem_Ch13; +with Sem_Dim; use Sem_Dim; +with Sem_Disp; use Sem_Disp; +with Sem_Dist; use Sem_Dist; +with Sem_Elim; use Sem_Elim; +with Sem_Eval; use Sem_Eval; +with Sem_Mech; use Sem_Mech; +with Sem_Prag; use Sem_Prag; +with Sem_Res; use Sem_Res; +with Sem_Util; use Sem_Util; +with Sem_Type; use Sem_Type; +with Sem_Warn; use Sem_Warn; +with Sinput; use Sinput; +with Stand; use Stand; +with Sinfo; use Sinfo; +with Sinfo.Nodes; use Sinfo.Nodes; +with Sinfo.Utils; use Sinfo.Utils; +with Sinfo.CN; use Sinfo.CN; +with Snames; use Snames; +with Stringt; use Stringt; with Style; -with Stylesw; use Stylesw; -with Tbuild; use Tbuild; -with Uintp; use Uintp; -with Urealp; use Urealp; -with Validsw; use Validsw; +with Stylesw; use Stylesw; +with Tbuild; use Tbuild; +with Uintp; use Uintp; +with Urealp; use Urealp; +with Validsw; use Validsw; package body Sem_Ch6 is @@ -128,9 +131,6 @@ package body Sem_Ch6 is -- Does all the real work of Analyze_Subprogram_Body. This is split out so -- that we can use RETURN but not skip the debug output at the end. - function Can_Override_Operator (Subp : Entity_Id) return Boolean; - -- Returns true if Subp can override a predefined operator. - procedure Check_Conformance (New_Id : Entity_Id; Old_Id : Entity_Id; @@ -298,8 +298,9 @@ package body Sem_Ch6 is Asp : Node_Id; New_Body : Node_Id; New_Spec : Node_Id; - Orig_N : Node_Id; + Orig_N : Node_Id := Empty; Ret : Node_Id; + Typ : Entity_Id := Empty; Def_Id : Entity_Id := Empty; Prev : Entity_Id; @@ -333,6 +334,8 @@ package body Sem_Ch6 is Def_Id := Analyze_Subprogram_Specification (Spec); Prev := Find_Corresponding_Spec (N); + Typ := Etype (Def_Id); + -- The previous entity may be an expression function as well, in -- which case the redeclaration is illegal. @@ -406,7 +409,7 @@ package body Sem_Ch6 is if not Inside_A_Generic then Freeze_Expr_Types (Def_Id => Def_Id, - Typ => Etype (Def_Id), + Typ => Typ, Expr => Expr, N => N); end if; @@ -496,6 +499,8 @@ package body Sem_Ch6 is Def_Id := Defining_Entity (N); Set_Is_Inlined (Def_Id); + Typ := Etype (Def_Id); + -- Establish the linkages between the spec and the body. These are -- used when the expression function acts as the prefix of attribute -- 'Access in order to freeze the original expression which has been @@ -517,107 +522,99 @@ package body Sem_Ch6 is Set_Has_Completion (Def_Id, not Is_Ignored_Ghost_Entity (Def_Id)); Push_Scope (Def_Id); Install_Formals (Def_Id); - Preanalyze_Spec_Expression (Expr, Etype (Def_Id)); + Preanalyze_Spec_Expression (Expr, Typ); + End_Scope; + else + Push_Scope (Def_Id); + Install_Formals (Def_Id); + Preanalyze_Formal_Expression (Expr, Typ); + Check_Limited_Return (Orig_N, Expr, Typ); End_Scope; end if; + -- If this is a wrapper created in an instance for a formal + -- subprogram, insert body after declaration, to be analyzed when the + -- enclosing instance is analyzed. + + if GNATprove_Mode + and then Is_Generic_Actual_Subprogram (Def_Id) + then + Insert_After (N, New_Body); + -- To prevent premature freeze action, insert the new body at the end -- of the current declarations, or at the end of the package spec. -- However, resolve usage names now, to prevent spurious visibility -- on later entities. Note that the function can now be called in - -- the current declarative part, which will appear to be prior to - -- the presence of the body in the code. There are nevertheless no - -- order of elaboration issues because all name resolution has taken - -- place at the point of declaration. - - declare - Decls : List_Id := List_Containing (N); - Expr : constant Node_Id := Expression (Ret); - Par : constant Node_Id := Parent (Decls); - Typ : constant Entity_Id := Etype (Def_Id); - - begin - -- If this is a wrapper created for in an instance for a formal - -- subprogram, insert body after declaration, to be analyzed when - -- the enclosing instance is analyzed. + -- the current declarative part, which will appear to be prior to the + -- presence of the body in the code. There are nevertheless no order + -- of elaboration issues because all name resolution has taken place + -- at the point of declaration. - if GNATprove_Mode - and then Is_Generic_Actual_Subprogram (Def_Id) - then - Insert_After (N, New_Body); + else + declare + Decls : List_Id := List_Containing (N); + Par : constant Node_Id := Parent (Decls); - else + begin if Nkind (Par) = N_Package_Specification and then Decls = Visible_Declarations (Par) - and then Present (Private_Declarations (Par)) and then not Is_Empty_List (Private_Declarations (Par)) then Decls := Private_Declarations (Par); end if; Insert_After (Last (Decls), New_Body); + end; + end if; - -- Preanalyze the expression if not already done above - - if not Inside_A_Generic then - Push_Scope (Def_Id); - Install_Formals (Def_Id); - Preanalyze_Formal_Expression (Expr, Typ); - Check_Limited_Return (Original_Node (N), Expr, Typ); - End_Scope; - end if; - - -- In the case of an expression function marked with the - -- aspect Static, we need to check the requirement that the - -- function's expression is a potentially static expression. - -- This is done by making a full copy of the expression tree - -- and performing a special preanalysis on that tree with - -- the global flag Checking_Potentially_Static_Expression - -- enabled. If the resulting expression is static, then it's - -- OK, but if not, that means the expression violates the - -- requirements of the Ada 202x RM in 4.9(3.2/5-3.4/5) and - -- we flag an error. - - if Is_Static_Function (Def_Id) then - if not Is_Static_Expression (Expr) then - declare - Exp_Copy : constant Node_Id := New_Copy_Tree (Expr); - begin - Set_Checking_Potentially_Static_Expression (True); + -- In the case of an expression function marked with the aspect + -- Static, we need to check the requirement that the function's + -- expression is a potentially static expression. This is done + -- by making a full copy of the expression tree and performing + -- a special preanalysis on that tree with the global flag + -- Checking_Potentially_Static_Expression enabled. If the + -- resulting expression is static, then it's OK, but if not, that + -- means the expression violates the requirements of the Ada 2022 + -- RM in 4.9(3.2/5-3.4/5) and we flag an error. - Preanalyze_Formal_Expression (Exp_Copy, Typ); + if Is_Static_Function (Def_Id) then + if not Is_Static_Expression (Expr) then + declare + Exp_Copy : constant Node_Id := New_Copy_Tree (Expr); + begin + Set_Checking_Potentially_Static_Expression (True); - if not Is_Static_Expression (Exp_Copy) then - Error_Msg_N - ("static expression function requires " - & "potentially static expression", Expr); - end if; + Preanalyze_Formal_Expression (Exp_Copy, Typ); - Set_Checking_Potentially_Static_Expression (False); - end; + if not Is_Static_Expression (Exp_Copy) then + Error_Msg_N + ("static expression function requires " + & "potentially static expression", Expr); end if; - -- We also make an additional copy of the expression and - -- replace the expression of the expression function with - -- this copy, because the currently present expression is - -- now associated with the body created for the static - -- expression function, which will later be analyzed and - -- possibly rewritten, and we need to have the separate - -- unanalyzed copy available for use with later static - -- calls. + Set_Checking_Potentially_Static_Expression (False); + end; + end if; - Set_Expression - (Original_Node (Subprogram_Spec (Def_Id)), - New_Copy_Tree (Expr)); + -- We also make an additional copy of the expression and + -- replace the expression of the expression function with + -- this copy, because the currently present expression is + -- now associated with the body created for the static + -- expression function, which will later be analyzed and + -- possibly rewritten, and we need to have the separate + -- unanalyzed copy available for use with later static + -- calls. - -- Mark static expression functions as inlined, to ensure - -- that even calls with nonstatic actuals will be inlined. + Set_Expression + (Original_Node (Subprogram_Spec (Def_Id)), + New_Copy_Tree (Expr)); - Set_Has_Pragma_Inline (Def_Id); - Set_Is_Inlined (Def_Id); - end if; - end if; - end; + -- Mark static expression functions as inlined, to ensure + -- that even calls with nonstatic actuals will be inlined. + + Set_Has_Pragma_Inline (Def_Id); + Set_Is_Inlined (Def_Id); + end if; end if; -- Check incorrect use of dynamically tagged expression. This doesn't @@ -626,13 +623,12 @@ package body Sem_Ch6 is -- nodes that don't come from source. if Present (Def_Id) - and then Nkind (Def_Id) in N_Has_Etype - and then Is_Tagged_Type (Etype (Def_Id)) + and then Is_Tagged_Type (Typ) then Check_Dynamically_Tagged_Expression (Expr => Expr, - Typ => Etype (Def_Id), - Related_Nod => Original_Node (N)); + Typ => Typ, + Related_Nod => Orig_N); end if; -- We must enforce checks for unreferenced formals in our newly @@ -642,9 +638,9 @@ package body Sem_Ch6 is if Present (Parameter_Specifications (New_Spec)) then declare Form_New_Def : Entity_Id; - Form_New_Spec : Entity_Id; + Form_New_Spec : Node_Id; Form_Old_Def : Entity_Id; - Form_Old_Spec : Entity_Id; + Form_Old_Spec : Node_Id; begin Form_New_Spec := First (Parameter_Specifications (New_Spec)); @@ -740,7 +736,7 @@ package body Sem_Ch6 is -- Function result subtype procedure Check_No_Return_Expression (Return_Expr : Node_Id); - -- Ada 2020: Check that the return expression in a No_Return function + -- Ada 2022: Check that the return expression in a No_Return function -- meets the conditions specified by RM 6.5.1(5.1/5). procedure Check_Return_Construct_Accessibility (Return_Stmt : Node_Id); @@ -1446,13 +1442,13 @@ package body Sem_Ch6 is Check_Return_Construct_Accessibility (N); - -- Ada 2020 (AI12-0269): Any return statement that applies to a + -- Ada 2022 (AI12-0269): Any return statement that applies to a -- nonreturning function shall be a simple_return_statement with -- an expression that is a raise_expression, or else a call on a -- nonreturning function, or else a parenthesized expression of -- one of these. - if Ada_Version >= Ada_2020 + if Ada_Version >= Ada_2022 and then No_Return (Scope_Id) and then Comes_From_Source (N) then @@ -1531,14 +1527,12 @@ package body Sem_Ch6 is -- Check RM 6.5 (5.9/3) if Has_Aliased then - if Ada_Version < Ada_2012 then - - -- Shouldn't this test Warn_On_Ada_2012_Compatibility ??? - -- Can it really happen (extended return???) - + if Ada_Version < Ada_2012 + and then Warn_On_Ada_2012_Compatibility + then Error_Msg_N ("ALIASED only allowed for limited return objects " - & "in Ada 2012??", N); + & "in Ada 2012?y?", N); elsif not Is_Limited_View (R_Type) then Error_Msg_N @@ -1546,10 +1540,10 @@ package body Sem_Ch6 is end if; end if; - -- Ada 2020 (AI12-0269): Any return statement that applies to a + -- Ada 2022 (AI12-0269): Any return statement that applies to a -- nonreturning function shall be a simple_return_statement. - if Ada_Version >= Ada_2020 + if Ada_Version >= Ada_2022 and then No_Return (Scope_Id) and then Comes_From_Source (N) then @@ -1670,9 +1664,9 @@ package body Sem_Ch6 is Related_Nod => N); end if; - -- ??? A real run-time accessibility check is needed in cases - -- involving dereferences of access parameters. For now we just - -- check the static cases. + -- Perform static accessibility checks for cases involving + -- dereferences of access parameters. Runtime accessibility checks + -- get generated elsewhere. if (Ada_Version < Ada_2005 or else Debug_Flag_Dot_L) and then Is_Limited_View (Etype (Scope_Id)) @@ -1770,13 +1764,13 @@ package body Sem_Ch6 is if Kind = E_Generic_Procedure and then Nkind (Spec) /= N_Procedure_Specification then - Error_Msg_N ("invalid body for generic procedure ", Body_Id); + Error_Msg_N ("invalid body for generic procedure", Body_Id); return; elsif Kind = E_Generic_Function and then Nkind (Spec) /= N_Function_Specification then - Error_Msg_N ("invalid body for generic function ", Body_Id); + Error_Msg_N ("invalid body for generic function", Body_Id); return; end if; @@ -1792,7 +1786,7 @@ package body Sem_Ch6 is end if; if Nkind (N) = N_Subprogram_Body_Stub then - Set_Ekind (Defining_Entity (Specification (N)), Kind); + Mutate_Ekind (Defining_Entity (Specification (N)), Kind); else Set_Corresponding_Spec (N, Gen_Id); end if; @@ -1843,8 +1837,13 @@ package body Sem_Ch6 is -- Visible generic entity is callable within its own body - Set_Ekind (Gen_Id, Ekind (Body_Id)); - Set_Ekind (Body_Id, E_Subprogram_Body); + Mutate_Ekind (Gen_Id, Ekind (Body_Id)); + Reinit_Field_To_Zero (Body_Id, F_Has_Out_Or_In_Out_Parameter, + Old_Ekind => + (E_Function | E_Procedure | + E_Generic_Function | E_Generic_Procedure => True, + others => False)); + Mutate_Ekind (Body_Id, E_Subprogram_Body); Set_Convention (Body_Id, Convention (Gen_Id)); Set_Is_Obsolescent (Body_Id, Is_Obsolescent (Gen_Id)); Set_Scope (Body_Id, Scope (Gen_Id)); @@ -1855,8 +1854,8 @@ package body Sem_Ch6 is -- No body to analyze, so restore state of generic unit - Set_Ekind (Gen_Id, Kind); - Set_Ekind (Body_Id, Kind); + Mutate_Ekind (Gen_Id, Kind); + Mutate_Ekind (Body_Id, Kind); if Present (First_Ent) then Set_First_Entity (Gen_Id, First_Ent); @@ -1920,7 +1919,9 @@ package body Sem_Ch6 is -- Outside of its body, unit is generic again - Set_Ekind (Gen_Id, Kind); + Reinit_Field_To_Zero (Gen_Id, F_Has_Nested_Subprogram, + Old_Ekind => (E_Function | E_Procedure => True, others => False)); + Mutate_Ekind (Gen_Id, Kind); Generate_Reference (Gen_Id, Body_Id, 'b', Set_Ref => False); if Style_Check then @@ -2015,7 +2016,7 @@ package body Sem_Ch6 is if Present (Prev) and then Is_Generic_Subprogram (Prev) then Insert_Before (N, Null_Body); - Set_Ekind (Defining_Entity (N), Ekind (Prev)); + Mutate_Ekind (Defining_Entity (N), Ekind (Prev)); Rewrite (N, Make_Null_Statement (Loc)); Analyze_Generic_Subprogram_Body (Null_Body, Prev); @@ -2328,7 +2329,7 @@ package body Sem_Ch6 is if Present (Actuals) then Analyze_Call_And_Resolve; else - Error_Msg_N ("missing explicit dereference in call ", N); + Error_Msg_N ("missing explicit dereference in call", N); end if; -- If not an access to subprogram, then the prefix must resolve to the @@ -2605,6 +2606,18 @@ package body Sem_Ch6 is Analyze_Dimension (N); end Analyze_Return_Statement; + ----------------------------------- + -- Analyze_Return_When_Statement -- + ----------------------------------- + + procedure Analyze_Return_When_Statement (N : Node_Id) is + begin + -- Verify the condition is a Boolean expression + + Analyze_And_Resolve (Condition (N), Any_Boolean); + Check_Unset_Reference (Condition (N)); + end Analyze_Return_When_Statement; + ------------------------------------- -- Analyze_Simple_Return_Statement -- ------------------------------------- @@ -3416,15 +3429,13 @@ package body Sem_Ch6 is Prag := Empty; end if; - if Present (Prag) then + if Present (Prag) and then Is_List_Member (N) then if Present (Spec_Id) then - if Is_List_Member (N) - and then Is_List_Member (Unit_Declaration_Node (Spec_Id)) + if Is_List_Member (Unit_Declaration_Node (Spec_Id)) and then In_Same_List (N, Unit_Declaration_Node (Spec_Id)) then Analyze (Prag); end if; - else -- Create a subprogram declaration, to make treatment uniform. -- Make the sloc of the subprogram name that of the entity in @@ -3443,7 +3454,12 @@ package body Sem_Ch6 is -- Link the body and the generated spec Set_Corresponding_Body (Decl, Body_Id); - Set_Corresponding_Spec (N, Subp); + + if Nkind (N) = N_Subprogram_Body_Stub then + Set_Corresponding_Spec_Of_Stub (N, Subp); + else + Set_Corresponding_Spec (N, Subp); + end if; Set_Defining_Unit_Name (Specification (Decl), Subp); @@ -3818,7 +3834,8 @@ package body Sem_Ch6 is Result : Elist_Id := No_Elist; function Mask_Type_Refs (Node : Node_Id) return Traverse_Result; - -- Mask all types referenced in the subtree rooted at Node + -- Mask all types referenced in the subtree rooted at Node as + -- formally frozen. -------------------- -- Mask_Type_Refs -- @@ -3826,7 +3843,8 @@ package body Sem_Ch6 is function Mask_Type_Refs (Node : Node_Id) return Traverse_Result is procedure Mask_Type (Typ : Entity_Id); - -- ??? what does this do? + -- Mask a given type as formally frozen when outside the current + -- scope, or else freeze the type. --------------- -- Mask_Type -- @@ -4061,7 +4079,7 @@ package body Sem_Ch6 is and then Operator_Matches_Spec (Spec_Id, Spec_Id) then Error_Msg_NE - ("subprogram& overrides predefined operator ", + ("subprogram& overrides predefined operator", Body_Spec, Spec_Id); -- Overriding indicators aren't allowed for protected subprogram @@ -4568,6 +4586,17 @@ package body Sem_Ch6 is then Conformant := True; + -- Finally, a body generated for an expression function copies + -- the profile of the function and no check is needed either. + -- If the body is the completion of a previous function + -- declared elsewhere, the conformance check is required. + + elsif Nkind (N) = N_Subprogram_Body + and then Was_Expression_Function (N) + and then Sloc (Spec_Id) = Sloc (Body_Id) + then + Conformant := True; + else Check_Conformance (Body_Id, Spec_Id, @@ -4601,7 +4630,19 @@ package body Sem_Ch6 is Reference_Body_Formals (Spec_Id, Body_Id); end if; - Set_Ekind (Body_Id, E_Subprogram_Body); + Reinit_Field_To_Zero (Body_Id, F_Has_Out_Or_In_Out_Parameter); + Reinit_Field_To_Zero (Body_Id, F_Needs_No_Actuals, + Old_Ekind => (E_Function | E_Procedure => True, others => False)); + Reinit_Field_To_Zero (Body_Id, F_Is_Predicate_Function, + Old_Ekind => (E_Function | E_Procedure => True, others => False)); + Reinit_Field_To_Zero (Body_Id, F_Protected_Subprogram, + Old_Ekind => (E_Function | E_Procedure => True, others => False)); + + if Ekind (Body_Id) = E_Procedure then + Reinit_Field_To_Zero (Body_Id, F_Receiving_Entry); + end if; + + Mutate_Ekind (Body_Id, E_Subprogram_Body); if Nkind (N) = N_Subprogram_Body_Stub then Set_Corresponding_Spec_Of_Stub (N, Spec_Id); @@ -5644,17 +5685,6 @@ package body Sem_Ch6 is end; end if; - -- What is the following code for, it used to be - - -- ??? Set_Suppress_Elaboration_Checks - -- ??? (Designator, Elaboration_Checks_Suppressed (Designator)); - - -- The following seems equivalent, but a bit dubious - - if Elaboration_Checks_Suppressed (Designator) then - Set_Kill_Elaboration_Checks (Designator); - end if; - -- For a compilation unit, set body required. This flag will only be -- reset if a valid Import or Interface pragma is processed later on. @@ -5766,10 +5796,10 @@ package body Sem_Ch6 is end if; if Nkind (N) = N_Function_Specification then - Set_Ekind (Designator, E_Function); + Mutate_Ekind (Designator, E_Function); Set_Mechanism (Designator, Default_Mechanism); else - Set_Ekind (Designator, E_Procedure); + Mutate_Ekind (Designator, E_Procedure); Set_Etype (Designator, Standard_Void_Type); end if; @@ -6255,7 +6285,9 @@ package body Sem_Ch6 is -- Null exclusion must match - if not Null_Exclusions_Match (Old_Formal, New_Formal) then + if not Relaxed_RM_Semantics + and then not Null_Exclusions_Match (Old_Formal, New_Formal) + then Conformance_Error ("\null exclusion for& does not match", New_Formal); @@ -6727,18 +6759,7 @@ package body Sem_Ch6 is -- may not be known yet (for private types). if not Has_Delayed_Freeze (Designator) and then Expander_Active then - declare - Typ : constant Entity_Id := Etype (Designator); - Utyp : constant Entity_Id := Underlying_Type (Typ); - - begin - if Is_Limited_View (Typ) then - Set_Returns_By_Ref (Designator); - - elsif Present (Utyp) and then CW_Or_Has_Controlled_Part (Utyp) then - Set_Returns_By_Ref (Designator); - end if; - end; + Compute_Returns_By_Ref (Designator); end if; end Check_Delayed_Subprogram; @@ -6990,16 +7011,14 @@ package body Sem_Ch6 is -- A limited interface that is not immutably limited is OK if Is_Limited_Interface (R_Type) - and then - not (Is_Task_Interface (R_Type) - or else Is_Protected_Interface (R_Type) - or else Is_Synchronized_Interface (R_Type)) + and then not Is_Concurrent_Interface (R_Type) then null; elsif Is_Limited_Type (R_Type) and then not Is_Interface (R_Type) - and then Comes_From_Source (N) + and then not (Nkind (N) = N_Simple_Return_Statement + and then Comes_From_Extended_Return_Statement (N)) and then not In_Instance_Body and then not OK_For_Limited_Init_In_05 (R_Type, Expr) then @@ -7261,10 +7280,14 @@ package body Sem_Ch6 is then Set_Overridden_Operation (Subp, Alias (Overridden_Subp)); Inherit_Subprogram_Contract (Subp, Alias (Overridden_Subp)); + Set_Is_Ada_2022_Only (Subp, + Is_Ada_2022_Only (Alias (Overridden_Subp))); else Set_Overridden_Operation (Subp, Overridden_Subp); Inherit_Subprogram_Contract (Subp, Overridden_Subp); + Set_Is_Ada_2022_Only (Subp, + Is_Ada_2022_Only (Overridden_Subp)); end if; end if; end if; @@ -7293,7 +7316,7 @@ package body Sem_Ch6 is -- predefined signature, because we know already that there is no -- explicit overridden operation. - elsif Nkind (Subp) = N_Defining_Operator_Symbol then + elsif Chars (Subp) in Any_Operator_Name then if Must_Not_Override (Spec) then -- If this is not a primitive or a protected subprogram, then @@ -7307,7 +7330,7 @@ package body Sem_Ch6 is elsif Can_Override_Operator (Subp) then Error_Msg_NE - ("subprogram& overrides predefined operator ", Spec, Subp); + ("subprogram& overrides predefined operator", Spec, Subp); end if; elsif Must_Override (Spec) then @@ -8285,7 +8308,12 @@ package body Sem_Ch6 is Typ : Entity_Id; begin - if Nkind (Subp) /= N_Defining_Operator_Symbol then + -- Return False if not an operator. We test the name rather than testing + -- that the Nkind is N_Defining_Operator_Symbol, because there are cases + -- where an operator entity can be an N_Defining_Identifier (such as for + -- function instantiations). + + if Chars (Subp) not in Any_Operator_Name then return False; else @@ -8775,7 +8803,7 @@ package body Sem_Ch6 is return Empty; end if; - Set_Ekind (EF, E_In_Parameter); + Mutate_Ekind (EF, E_In_Parameter); Set_Actual_Subtype (EF, Typ); Set_Etype (EF, Typ); Set_Scope (EF, Scope); @@ -8874,7 +8902,7 @@ package body Sem_Ch6 is end if; if not Has_Discriminants (Formal_Type) - and then Ekind (Formal_Type) in Private_Kind + and then Is_Private_Type (Formal_Type) and then Present (Underlying_Type (Formal_Type)) then Formal_Type := Underlying_Type (Formal_Type); @@ -9021,7 +9049,7 @@ package body Sem_Ch6 is if Needs_BIP_Task_Actuals (E) then Discard := Add_Extra_Formal - (E, RTE (RE_Master_Id), + (E, Standard_Integer, E, BIP_Formal_Suffix (BIP_Task_Master)); Set_Has_Master_Entity (E); @@ -10713,8 +10741,8 @@ package body Sem_Ch6 is exit; end if; - Next_Entity (P_Formal); - Next_Entity (N_Formal); + Next_Formal (P_Formal); + Next_Formal (N_Formal); end loop; -- Found a matching primitive operation belonging to the @@ -10991,9 +11019,11 @@ package body Sem_Ch6 is (Is_Primitive : out Boolean; Is_Overriding : Boolean := False) is - Formal : Entity_Id; - F_Typ : Entity_Id; - B_Typ : Entity_Id; + procedure Add_Or_Replace_Untagged_Primitive (Typ : Entity_Id); + -- Either add the new subprogram to the list of primitives for + -- untagged type Typ, or if it overrides a primitive of Typ, then + -- replace the overridden primitive in Typ's primitives list with + -- the new subprogram. function Visible_Part_Type (T : Entity_Id) return Boolean; -- Returns true if T is declared in the visible part of the current @@ -11008,6 +11038,63 @@ package body Sem_Ch6 is -- in a private part, then it must override a function declared in -- the visible part. + --------------------------------------- + -- Add_Or_Replace_Untagged_Primitive -- + --------------------------------------- + + procedure Add_Or_Replace_Untagged_Primitive (Typ : Entity_Id) is + Replaced_Overridden_Subp : Boolean := False; + + begin + pragma Assert (not Is_Tagged_Type (Typ)); + + -- Anonymous access types don't have a primitives list. Normally + -- such types wouldn't make it here, but the case of anonymous + -- access-to-subprogram types can. + + if not Is_Anonymous_Access_Type (Typ) then + + -- If S overrides a subprogram that's a primitive of + -- the formal's type, then replace the overridden + -- subprogram with the new subprogram in the type's + -- list of primitives. + + if Is_Overriding then + pragma Assert (Present (Overridden_Subp) + and then Overridden_Subp = E); -- Added for now + + declare + Prim_Ops : constant Elist_Id := + Primitive_Operations (Typ); + Elmt : Elmt_Id; + begin + if Present (Prim_Ops) then + Elmt := First_Elmt (Prim_Ops); + + while Present (Elmt) + and then Node (Elmt) /= Overridden_Subp + loop + Next_Elmt (Elmt); + end loop; + + if Present (Elmt) then + Replace_Elmt (Elmt, S); + Replaced_Overridden_Subp := True; + end if; + end if; + end; + end if; + + -- If the new subprogram did not override an operation + -- of the formal's type, then add it to the primitives + -- list of the type. + + if not Replaced_Overridden_Subp then + Append_Unique_Elmt (S, Primitive_Operations (Typ)); + end if; + end if; + end Add_Or_Replace_Untagged_Primitive; + ------------------------------ -- Check_Private_Overriding -- ------------------------------ @@ -11163,7 +11250,7 @@ package body Sem_Ch6 is -- If the entity is a private type, then it must be declared in a -- visible part. - if Ekind (T) in Private_Kind then + if Is_Private_Type (T) then return True; elsif Is_Type (T) and then Has_Private_Declaration (T) then @@ -11180,13 +11267,29 @@ package body Sem_Ch6 is end if; end Visible_Part_Type; + -- Local variables + + Formal : Entity_Id; + F_Typ : Entity_Id; + B_Typ : Entity_Id; + -- Start of processing for Check_For_Primitive_Subprogram begin Is_Primitive := False; if not Comes_From_Source (S) then - null; + + -- Add an inherited primitive for an untagged derived type to + -- Derived_Type's list of primitives. Tagged primitives are dealt + -- with in Check_Dispatching_Operation. + + if Present (Derived_Type) + and then Extensions_Allowed + and then not Is_Tagged_Type (Derived_Type) + then + Append_Unique_Elmt (S, Primitive_Operations (Derived_Type)); + end if; -- If subprogram is at library level, it is not primitive operation @@ -11215,8 +11318,18 @@ package body Sem_Ch6 is Is_Primitive := True; Set_Has_Primitive_Operations (B_Typ); Set_Is_Primitive (S); - Check_Private_Overriding (B_Typ); + -- Add a primitive for an untagged type to B_Typ's list + -- of primitives. Tagged primitives are dealt with in + -- Check_Dispatching_Operation. + + if Extensions_Allowed + and then not Is_Tagged_Type (B_Typ) + then + Add_Or_Replace_Untagged_Primitive (B_Typ); + end if; + + Check_Private_Overriding (B_Typ); -- The Ghost policy in effect at the point of declaration -- or a tagged type and a primitive operation must match -- (SPARK RM 6.9(16)). @@ -11248,6 +11361,17 @@ package body Sem_Ch6 is Is_Primitive := True; Set_Is_Primitive (S); Set_Has_Primitive_Operations (B_Typ); + + -- Add a primitive for an untagged type to B_Typ's list + -- of primitives. Tagged primitives are dealt with in + -- Check_Dispatching_Operation. + + if Extensions_Allowed + and then not Is_Tagged_Type (B_Typ) + then + Add_Or_Replace_Untagged_Primitive (B_Typ); + end if; + Check_Private_Overriding (B_Typ); -- The Ghost policy in effect at the point of declaration @@ -11681,7 +11805,7 @@ package body Sem_Ch6 is if Inside_Freezing_Actions = 0 and then Is_Package_Or_Generic_Package (Current_Scope) and then In_Private_Part (Current_Scope) - and then Nkind (Parent (E)) = N_Private_Extension_Declaration + and then Parent_Kind (E) = N_Private_Extension_Declaration and then Nkind (Parent (S)) = N_Full_Type_Declaration and then Full_View (Defining_Identifier (Parent (E))) = Defining_Identifier (Parent (S)) @@ -11878,10 +12002,13 @@ package body Sem_Ch6 is if Present (Alias (S)) then Set_Overridden_Operation (E, Alias (S)); Inherit_Subprogram_Contract (E, Alias (S)); + Set_Is_Ada_2022_Only (E, + Is_Ada_2022_Only (Alias (S))); else Set_Overridden_Operation (E, S); Inherit_Subprogram_Contract (E, S); + Set_Is_Ada_2022_Only (E, Is_Ada_2022_Only (S)); end if; -- When a dispatching operation overrides an inherited @@ -12048,6 +12175,8 @@ package body Sem_Ch6 is then Set_Overridden_Operation (S, Alias (E)); Inherit_Subprogram_Contract (S, Alias (E)); + Set_Is_Ada_2022_Only (S, + Is_Ada_2022_Only (Alias (E))); -- Normal case of setting entity as overridden @@ -12059,8 +12188,22 @@ package body Sem_Ch6 is -- must check whether the target is an init_proc. elsif not Is_Init_Proc (S) then - Set_Overridden_Operation (S, E); - Inherit_Subprogram_Contract (S, E); + + -- LSP wrappers must override the ultimate alias of their + -- wrapped dispatching primitive E; required to traverse + -- the chain of ancestor primitives (c.f. Map_Primitives) + -- They don't inherit contracts. + + if Is_Wrapper (S) + and then Present (LSP_Subprogram (S)) + then + Set_Overridden_Operation (S, Ultimate_Alias (E)); + else + Set_Overridden_Operation (S, E); + Inherit_Subprogram_Contract (S, E); + end if; + + Set_Is_Ada_2022_Only (S, Is_Ada_2022_Only (E)); end if; Check_Overriding_Indicator (S, E, Is_Primitive => True); @@ -12087,8 +12230,22 @@ package body Sem_Ch6 is Is_Predefined_Dispatching_Operation (Alias (E))) then if Present (Alias (E)) then - Set_Overridden_Operation (S, Alias (E)); - Inherit_Subprogram_Contract (S, Alias (E)); + + -- LSP wrappers must override the ultimate alias of + -- their wrapped dispatching primitive E; required to + -- traverse the chain of ancestor primitives (see + -- Map_Primitives). They don't inherit contracts. + + if Is_Wrapper (S) + and then Present (LSP_Subprogram (S)) + then + Set_Overridden_Operation (S, Ultimate_Alias (E)); + else + Set_Overridden_Operation (S, Alias (E)); + Inherit_Subprogram_Contract (S, Alias (E)); + end if; + + Set_Is_Ada_2022_Only (S, Is_Ada_2022_Only (Alias (E))); end if; end if; @@ -12963,30 +13120,30 @@ package body Sem_Ch6 is end if; if In_Present (Spec) then - Set_Ekind (Formal_Id, E_In_Out_Parameter); + Mutate_Ekind (Formal_Id, E_In_Out_Parameter); else - Set_Ekind (Formal_Id, E_Out_Parameter); + Mutate_Ekind (Formal_Id, E_Out_Parameter); end if; -- But not in earlier versions of Ada else Error_Msg_N ("functions can only have IN parameters", Spec); - Set_Ekind (Formal_Id, E_In_Parameter); + Mutate_Ekind (Formal_Id, E_In_Parameter); end if; elsif In_Present (Spec) then - Set_Ekind (Formal_Id, E_In_Out_Parameter); + Mutate_Ekind (Formal_Id, E_In_Out_Parameter); else - Set_Ekind (Formal_Id, E_Out_Parameter); + Mutate_Ekind (Formal_Id, E_Out_Parameter); Set_Never_Set_In_Source (Formal_Id, True); Set_Is_True_Constant (Formal_Id, False); Set_Current_Value (Formal_Id, Empty); end if; else - Set_Ekind (Formal_Id, E_In_Parameter); + Mutate_Ekind (Formal_Id, E_In_Parameter); end if; -- Set Is_Known_Non_Null for access parameters since the language |