]> gcc.gnu.org Git - gcc.git/blobdiff - gcc/ada/sem_ch9.adb
ada: Cleanup related to lock-free protected subprograms
[gcc.git] / gcc / ada / sem_ch9.adb
index df438aca0780670f5778ded81f421288e4e77f58..6506358a02b778d0a2bf59cfe733e9e166beb4cb 100644 (file)
@@ -6,7 +6,7 @@
 --                                                                          --
 --                                 B o d y                                  --
 --                                                                          --
---          Copyright (C) 1992-2020, Free Software Foundation, Inc.         --
+--          Copyright (C) 1992-2022, 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- --
 --                                                                          --
 ------------------------------------------------------------------------------
 
-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 Errout;    use Errout;
-with Exp_Ch9;   use Exp_Ch9;
-with Elists;    use Elists;
-with Freeze;    use Freeze;
-with Layout;    use Layout;
-with Lib;       use Lib;
-with Lib.Xref;  use Lib.Xref;
-with Namet;     use Namet;
-with Nlists;    use Nlists;
-with Nmake;     use Nmake;
-with Opt;       use Opt;
-with Restrict;  use Restrict;
-with Rident;    use Rident;
-with Rtsfind;   use Rtsfind;
-with Sem;       use Sem;
-with Sem_Aux;   use Sem_Aux;
-with Sem_Ch3;   use Sem_Ch3;
-with Sem_Ch5;   use Sem_Ch5;
-with Sem_Ch6;   use Sem_Ch6;
-with Sem_Ch8;   use Sem_Ch8;
-with Sem_Ch13;  use Sem_Ch13;
-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_Type;  use Sem_Type;
-with Sem_Util;  use Sem_Util;
-with Sem_Warn;  use Sem_Warn;
-with Snames;    use Snames;
-with Stand;     use Stand;
-with Sinfo;     use Sinfo;
+with Aspects;        use Aspects;
+with Atree;          use Atree;
+with Checks;         use Checks;
+with Contracts;      use Contracts;
+with Einfo;          use Einfo;
+with Einfo.Entities; use Einfo.Entities;
+with Einfo.Utils;    use Einfo.Utils;
+with Errout;         use Errout;
+with Exp_Ch9;        use Exp_Ch9;
+with Elists;         use Elists;
+with Freeze;         use Freeze;
+with Layout;         use Layout;
+with Lib;            use Lib;
+with Lib.Xref;       use Lib.Xref;
+with Namet;          use Namet;
+with Nlists;         use Nlists;
+with Nmake;          use Nmake;
+with Opt;            use Opt;
+with Restrict;       use Restrict;
+with Rident;         use Rident;
+with Rtsfind;        use Rtsfind;
+with Sem;            use Sem;
+with Sem_Aux;        use Sem_Aux;
+with Sem_Ch3;        use Sem_Ch3;
+with Sem_Ch5;        use Sem_Ch5;
+with Sem_Ch6;        use Sem_Ch6;
+with Sem_Ch8;        use Sem_Ch8;
+with Sem_Ch13;       use Sem_Ch13;
+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_Type;       use Sem_Type;
+with Sem_Util;       use Sem_Util;
+with Sem_Warn;       use Sem_Warn;
+with Snames;         use Snames;
+with Stand;          use Stand;
+with Sinfo;          use Sinfo;
+with Sinfo.Nodes;    use Sinfo.Nodes;
+with Sinfo.Utils;    use Sinfo.Utils;
 with Style;
-with Tbuild;    use Tbuild;
-with Uintp;     use Uintp;
+with Targparm;       use Targparm;
+with Tbuild;         use Tbuild;
+with Uintp;          use Uintp;
 
 package body Sem_Ch9 is
 
@@ -133,16 +137,8 @@ package body Sem_Ch9 is
       --  when Lock_Free_Given is True.
 
    begin
-      pragma Assert (Nkind_In (N, N_Protected_Type_Declaration,
-                                  N_Protected_Body));
-
-      --  The lock-free implementation is currently enabled through a debug
-      --  flag. When Lock_Free_Given is True, an aspect Lock_Free forces the
-      --  lock-free implementation. In that case, the debug flag is not needed.
-
-      if not Lock_Free_Given and then not Debug_Flag_9 then
-         return False;
-      end if;
+      pragma Assert
+        (Nkind (N) in N_Protected_Type_Declaration | N_Protected_Body);
 
       --  Get the number of errors detected by the compiler so far
 
@@ -182,8 +178,6 @@ package body Sem_Ch9 is
                elsif Nkind (Decl) = N_Subprogram_Declaration
                  and then
                    Nkind (Specification (Decl)) = N_Procedure_Specification
-                 and then
-                   Present (Parameter_Specifications (Specification (Decl)))
                then
                   declare
                      Par_Specs : constant List_Id   :=
@@ -211,6 +205,27 @@ package body Sem_Ch9 is
                         Next (Par);
                      end loop;
                   end;
+
+               elsif Nkind (Decl) = N_Subprogram_Declaration
+                 and then
+                   Nkind (Specification (Decl)) = N_Function_Specification
+                 and then
+                   Nkind (Result_Definition (Specification (Decl)))
+                     in N_Has_Entity
+                 and then
+                   Needs_Secondary_Stack
+                     (Entity (Result_Definition (Specification (Decl))))
+               then
+                  if Lock_Free_Given then
+                     --  Message text is imprecise; "unconstrained" is
+                     --  similar to "needs secondary stack" but not identical.
+                     Error_Msg_N
+                       ("unconstrained function result subtype not allowed "
+                        & "when Lock_Free given",
+                        Decl);
+                  else
+                     return False;
+                  end if;
                end if;
 
                --  Examine private declarations after visible declarations
@@ -250,11 +265,6 @@ package body Sem_Ch9 is
             function Satisfies_Lock_Free_Requirements
               (Sub_Body : Node_Id) return Boolean
             is
-               Is_Procedure : constant Boolean    :=
-                                Ekind (Corresponding_Spec (Sub_Body)) =
-                                  E_Procedure;
-               --  Indicates if Sub_Body is a procedure body
-
                Comp : Entity_Id := Empty;
                --  Track the current component which the body references
 
@@ -334,222 +344,220 @@ package body Sem_Ch9 is
                --  Start of processing for Check_Node
 
                begin
-                  if Is_Procedure then
-                     --  Allocators restricted
-
-                     if Kind = N_Allocator then
-                        if Lock_Free_Given then
-                           Error_Msg_N ("allocator not allowed", N);
-                           return Skip;
-                        end if;
+                  --  Allocators restricted
 
-                        return Abandon;
+                  if Kind = N_Allocator then
+                     if Lock_Free_Given then
+                        Error_Msg_N ("allocator not allowed", N);
+                        return Skip;
+                     end if;
 
-                     --  Aspects Address, Export and Import restricted
+                     return Abandon;
 
-                     elsif Kind = N_Aspect_Specification then
-                        declare
-                           Asp_Name : constant Name_Id   :=
-                                        Chars (Identifier (N));
-                           Asp_Id   : constant Aspect_Id :=
-                                        Get_Aspect_Id (Asp_Name);
+                  --  Aspects Address, Export and Import restricted
 
-                        begin
-                           if Asp_Id = Aspect_Address or else
-                              Asp_Id = Aspect_Export  or else
-                              Asp_Id = Aspect_Import
-                           then
-                              Error_Msg_Name_1 := Asp_Name;
+                  elsif Kind = N_Aspect_Specification then
+                     declare
+                        Asp_Name : constant Name_Id   :=
+                                     Chars (Identifier (N));
+                        Asp_Id   : constant Aspect_Id :=
+                                     Get_Aspect_Id (Asp_Name);
 
-                              if Lock_Free_Given then
-                                 Error_Msg_N ("aspect% not allowed", N);
-                                 return Skip;
-                              end if;
+                     begin
+                        if Asp_Id = Aspect_Address or else
+                           Asp_Id = Aspect_Export  or else
+                           Asp_Id = Aspect_Import
+                        then
+                           Error_Msg_Name_1 := Asp_Name;
 
-                              return Abandon;
+                           if Lock_Free_Given then
+                              Error_Msg_N ("aspect% not allowed", N);
+                              return Skip;
                            end if;
-                        end;
 
-                     --  Address attribute definition clause restricted
+                           return Abandon;
+                        end if;
+                     end;
 
-                     elsif Kind = N_Attribute_Definition_Clause
-                       and then Get_Attribute_Id (Chars (N)) =
-                                  Attribute_Address
-                     then
-                        Error_Msg_Name_1 := Chars (N);
+                  --  Address attribute definition clause restricted
 
-                        if Lock_Free_Given then
-                           if From_Aspect_Specification (N) then
-                              Error_Msg_N ("aspect% not allowed", N);
-                           else
-                              Error_Msg_N ("% clause not allowed", N);
-                           end if;
+                  elsif Kind = N_Attribute_Definition_Clause
+                    and then Get_Attribute_Id (Chars (N)) =
+                               Attribute_Address
+                  then
+                     Error_Msg_Name_1 := Chars (N);
 
-                           return Skip;
+                     if Lock_Free_Given then
+                        if From_Aspect_Specification (N) then
+                           Error_Msg_N ("aspect% not allowed", N);
+                        else
+                           Error_Msg_N ("% clause not allowed", N);
                         end if;
 
-                        return Abandon;
+                        return Skip;
+                     end if;
 
-                     --  Non-static Attribute references that don't denote a
-                     --  static function restricted.
+                     return Abandon;
 
-                     elsif Kind = N_Attribute_Reference
-                       and then not Is_OK_Static_Expression (N)
-                       and then not Is_Static_Function (N)
-                     then
-                        if Lock_Free_Given then
-                           Error_Msg_N
-                             ("non-static attribute reference not allowed", N);
-                           return Skip;
-                        end if;
+                  --  Non-static Attribute references that don't denote a
+                  --  static function restricted.
 
-                        return Abandon;
+                  elsif Kind = N_Attribute_Reference
+                    and then not Is_OK_Static_Expression (N)
+                    and then not Is_Static_Function (N)
+                  then
+                     if Lock_Free_Given then
+                        Error_Msg_N
+                          ("non-static attribute reference not allowed", N);
+                        return Skip;
+                     end if;
 
-                     --  Delay statements restricted
+                     return Abandon;
 
-                     elsif Kind in N_Delay_Statement then
-                        if Lock_Free_Given then
-                           Error_Msg_N ("delay not allowed", N);
-                           return Skip;
-                        end if;
+                  --  Delay statements restricted
 
-                        return Abandon;
+                  elsif Kind in N_Delay_Statement then
+                     if Lock_Free_Given then
+                        Error_Msg_N ("delay not allowed", N);
+                        return Skip;
+                     end if;
 
-                     --  Dereferences of access values restricted
+                     return Abandon;
 
-                     elsif Kind = N_Explicit_Dereference
-                       or else (Kind = N_Selected_Component
-                                 and then Is_Access_Type (Etype (Prefix (N))))
-                     then
-                        if Lock_Free_Given then
-                           Error_Msg_N
-                             ("dereference of access value not allowed", N);
-                           return Skip;
-                        end if;
+                  --  Dereferences of access values restricted
 
-                        return Abandon;
+                  elsif Kind = N_Explicit_Dereference
+                    or else (Kind = N_Selected_Component
+                              and then Is_Access_Type (Etype (Prefix (N))))
+                  then
+                     if Lock_Free_Given then
+                        Error_Msg_N
+                          ("dereference of access value not allowed", N);
+                        return Skip;
+                     end if;
 
-                     --  Non-static function calls restricted
+                     return Abandon;
 
-                     elsif Kind = N_Function_Call
-                       and then not Is_OK_Static_Expression (N)
-                     then
-                        if Lock_Free_Given then
-                           Error_Msg_N
-                             ("non-static function call not allowed", N);
-                           return Skip;
-                        end if;
+                  --  Non-static function calls restricted
 
-                        return Abandon;
+                  elsif Kind = N_Function_Call
+                    and then not Is_OK_Static_Expression (N)
+                  then
+                     if Lock_Free_Given then
+                        Error_Msg_N
+                          ("non-static function call not allowed", N);
+                        return Skip;
+                     end if;
 
-                     --  Goto statements restricted
+                     return Abandon;
 
-                     elsif Kind = N_Goto_Statement then
-                        if Lock_Free_Given then
-                           Error_Msg_N ("goto statement not allowed", N);
-                           return Skip;
-                        end if;
+                  --  Goto statements restricted
 
-                        return Abandon;
+                  elsif Kind = N_Goto_Statement then
+                     if Lock_Free_Given then
+                        Error_Msg_N ("goto statement not allowed", N);
+                        return Skip;
+                     end if;
 
-                     --  References
+                     return Abandon;
 
-                     elsif Kind = N_Identifier
-                       and then Present (Entity (N))
-                     then
-                        declare
-                           Id     : constant Entity_Id := Entity (N);
-                           Sub_Id : constant Entity_Id :=
-                                      Corresponding_Spec (Sub_Body);
+                  --  References
 
-                        begin
-                           --  Prohibit references to non-constant entities
-                           --  outside the protected subprogram scope.
-
-                           if Ekind (Id) in Assignable_Kind
-                             and then not
-                               Scope_Within_Or_Same (Scope (Id), Sub_Id)
-                             and then not
-                               Scope_Within_Or_Same
-                                 (Scope (Id),
-                                  Protected_Body_Subprogram (Sub_Id))
-                           then
-                              if Lock_Free_Given then
-                                 Error_Msg_NE
-                                   ("reference to global variable& not " &
-                                    "allowed", N, Id);
-                                 return Skip;
-                              end if;
+                  elsif Kind = N_Identifier
+                    and then Present (Entity (N))
+                  then
+                     declare
+                        Id     : constant Entity_Id := Entity (N);
+                        Sub_Id : constant Entity_Id :=
+                                   Corresponding_Spec (Sub_Body);
 
-                              return Abandon;
+                     begin
+                        --  Prohibit references to non-constant entities
+                        --  outside the protected subprogram scope.
+
+                        if Is_Assignable (Id)
+                          and then not
+                            Scope_Within_Or_Same (Scope (Id), Sub_Id)
+                          and then not
+                            Scope_Within_Or_Same
+                              (Scope (Id),
+                               Protected_Body_Subprogram (Sub_Id))
+                        then
+                           if Lock_Free_Given then
+                              Error_Msg_NE
+                                ("reference to global variable& not allowed",
+                                 N, Id);
+                              return Skip;
                            end if;
-                        end;
 
-                     --  Loop statements restricted
-
-                     elsif Kind = N_Loop_Statement then
-                        if Lock_Free_Given then
-                           Error_Msg_N ("loop not allowed", N);
-                           return Skip;
+                           return Abandon;
                         end if;
+                     end;
 
-                        return Abandon;
+                  --  Loop statements restricted
 
-                     --  Pragmas Export and Import restricted
+                  elsif Kind = N_Loop_Statement then
+                     if Lock_Free_Given then
+                        Error_Msg_N ("loop not allowed", N);
+                        return Skip;
+                     end if;
 
-                     elsif Kind = N_Pragma then
-                        declare
-                           Prag_Name : constant Name_Id   :=
-                             Pragma_Name (N);
-                           Prag_Id   : constant Pragma_Id :=
-                             Get_Pragma_Id (Prag_Name);
+                     return Abandon;
 
-                        begin
-                           if Prag_Id = Pragma_Export
-                             or else Prag_Id = Pragma_Import
-                           then
-                              Error_Msg_Name_1 := Prag_Name;
+                  --  Pragmas Export and Import restricted
 
-                              if Lock_Free_Given then
-                                 if From_Aspect_Specification (N) then
-                                    Error_Msg_N ("aspect% not allowed", N);
-                                 else
-                                    Error_Msg_N ("pragma% not allowed", N);
-                                 end if;
+                  elsif Kind = N_Pragma then
+                     declare
+                        Prag_Name : constant Name_Id   :=
+                          Pragma_Name (N);
+                        Prag_Id   : constant Pragma_Id :=
+                          Get_Pragma_Id (Prag_Name);
+
+                     begin
+                        if Prag_Id = Pragma_Export
+                          or else Prag_Id = Pragma_Import
+                        then
+                           Error_Msg_Name_1 := Prag_Name;
 
-                                 return Skip;
+                           if Lock_Free_Given then
+                              if From_Aspect_Specification (N) then
+                                 Error_Msg_N ("aspect% not allowed", N);
+                              else
+                                 Error_Msg_N ("pragma% not allowed", N);
                               end if;
 
-                              return Abandon;
+                              return Skip;
                            end if;
-                        end;
 
-                     --  Procedure call statements restricted
-
-                     elsif Kind = N_Procedure_Call_Statement then
-                        if Lock_Free_Given then
-                           Error_Msg_N ("procedure call not allowed", N);
-                           return Skip;
+                           return Abandon;
                         end if;
+                     end;
 
-                        return Abandon;
+                  --  Procedure call statements restricted
 
-                     --  Quantified expression restricted. Note that we have
-                     --  to check the original node as well, since at this
-                     --  stage, it may have been rewritten.
+                  elsif Kind = N_Procedure_Call_Statement then
+                     if Lock_Free_Given then
+                        Error_Msg_N ("procedure call not allowed", N);
+                        return Skip;
+                     end if;
 
-                     elsif Kind = N_Quantified_Expression
-                       or else
-                         Nkind (Original_Node (N)) = N_Quantified_Expression
-                     then
-                        if Lock_Free_Given then
-                           Error_Msg_N
-                             ("quantified expression not allowed", N);
-                           return Skip;
-                        end if;
+                     return Abandon;
 
-                        return Abandon;
+                  --  Quantified expression restricted. Note that we have
+                  --  to check the original node as well, since at this
+                  --  stage, it may have been rewritten.
+
+                  elsif Kind = N_Quantified_Expression
+                    or else
+                      Nkind (Original_Node (N)) = N_Quantified_Expression
+                  then
+                     if Lock_Free_Given then
+                        Error_Msg_N
+                          ("quantified expression not allowed", N);
+                        return Skip;
                      end if;
+
+                     return Abandon;
                   end if;
 
                   --  A protected subprogram (function or procedure) may
@@ -569,7 +577,7 @@ package body Sem_Ch9 is
                         if Ekind (Id) = E_Component then
                            Comp_Id := Id;
 
-                        elsif Ekind_In (Id, E_Constant, E_Variable)
+                        elsif Ekind (Id) in E_Constant | E_Variable
                           and then Present (Prival_Link (Id))
                         then
                            Comp_Id := Prival_Link (Id);
@@ -640,6 +648,35 @@ package body Sem_Ch9 is
             --  Start of processing for Satisfies_Lock_Free_Requirements
 
             begin
+               if not Support_Atomic_Primitives_On_Target then
+                  if Lock_Free_Given then
+                     Error_Msg_N
+                       ("Lock_Free aspect requires target support for "
+                          & "atomic primitives", N);
+                  end if;
+                  return False;
+               end if;
+
+               --  Deal with case where Ceiling_Locking locking policy is
+               --  in effect.
+
+               if Locking_Policy = 'C' then
+                  if Lock_Free_Given then
+                     --  Explicit Lock_Free aspect spec overrides
+                     --  Ceiling_Locking so we generate a warning.
+
+                     Error_Msg_N
+                       ("Lock_Free aspect specification overrides "
+                          & "Ceiling_Locking locking policy??", N);
+                  else
+                     --  If Ceiling_Locking locking policy is in effect, then
+                     --  Lock_Free can be explicitly specified but it is
+                     --  never the default.
+
+                     return False;
+                  end if;
+               end if;
+
                --  Get the number of errors detected by the compiler so far
 
                if Lock_Free_Given then
@@ -706,7 +743,6 @@ package body Sem_Ch9 is
 
    begin
       Tasking_Used := True;
-      Check_SPARK_05_Restriction ("abort statement is not allowed", N);
 
       T_Name := First (Names (N));
       while Present (T_Name) loop
@@ -777,7 +813,6 @@ package body Sem_Ch9 is
 
    begin
       Tasking_Used := True;
-      Check_SPARK_05_Restriction ("accept statement is not allowed", N);
 
       --  Entry name is initialized to Any_Id. It should get reset to the
       --  matching entry entity. An error is signalled if it is not reset.
@@ -792,13 +827,13 @@ package body Sem_Ch9 is
          if Kind /= E_Block and then Kind /= E_Loop
            and then not Is_Entry (Task_Nam)
          then
-            Error_Msg_N ("enclosing body of accept must be a task", N);
+            Error_Msg_N ("enclosing body of ACCEPT must be a task", N);
             return;
          end if;
       end loop;
 
       if Ekind (Etype (Task_Nam)) /= E_Task_Type then
-         Error_Msg_N ("invalid context for accept statement",  N);
+         Error_Msg_N ("invalid context for ACCEPT statement",  N);
          return;
       end if;
 
@@ -846,7 +881,7 @@ package body Sem_Ch9 is
       end loop;
 
       if Entry_Nam = Any_Id then
-         Error_Msg_N ("no entry declaration matches accept statement",  N);
+         Error_Msg_N ("no entry declaration matches ACCEPT statement",  N);
          return;
       else
          Set_Entity (Nam, Entry_Nam);
@@ -884,7 +919,7 @@ package body Sem_Ch9 is
 
          if Entry_Nam = Scope_Stack.Table (J).Entity then
             Error_Msg_N
-              ("duplicate accept statement for same entry (RM 9.5.2 (15))", N);
+              ("duplicate ACCEPT statement for same entry (RM 9.5.2 (15))", N);
 
             --  Do not continue analysis of accept statement, to prevent
             --  cascaded errors.
@@ -906,8 +941,8 @@ package body Sem_Ch9 is
 
                when N_Asynchronous_Select =>
                   Error_Msg_N
-                    ("accept statements are not allowed within an "
-                     & "asynchronous select inner to the enclosing task body",
+                    ("ACCEPT statement not allowed within an "
+                     & "asynchronous SELECT inner to the enclosing task body",
                      N);
                   exit;
 
@@ -917,12 +952,12 @@ package body Sem_Ch9 is
          end loop;
       end;
 
-      if Ekind (E) = E_Entry_Family then
+      if Ekind (Entry_Nam) = E_Entry_Family then
          if No (Index) then
             Error_Msg_N ("missing entry index in accept for entry family", N);
          else
-            Analyze_And_Resolve (Index, Entry_Index_Type (E));
-            Apply_Range_Check (Index, Entry_Index_Type (E));
+            Analyze_And_Resolve (Index, Entry_Index_Type (Entry_Nam));
+            Apply_Scalar_Range_Check (Index, Entry_Index_Type (Entry_Nam));
          end if;
 
       elsif Present (Index) then
@@ -1019,7 +1054,6 @@ package body Sem_Ch9 is
 
    begin
       Tasking_Used := True;
-      Check_SPARK_05_Restriction ("select statement is not allowed", N);
       Check_Restriction (Max_Asynchronous_Select_Nesting, N);
       Check_Restriction (No_Select_Statements, N);
 
@@ -1065,7 +1099,6 @@ package body Sem_Ch9 is
 
    begin
       Tasking_Used := True;
-      Check_SPARK_05_Restriction ("select statement is not allowed", N);
       Check_Restriction (No_Select_Statements, N);
 
       --  Ada 2005 (AI-345): The trigger may be a dispatching call
@@ -1117,7 +1150,7 @@ package body Sem_Ch9 is
          Analyze_List (Pragmas_Before (N));
       end if;
 
-      if Nkind_In (Parent (N), N_Selective_Accept, N_Timed_Entry_Call) then
+      if Nkind (Parent (N)) in N_Selective_Accept | N_Timed_Entry_Call then
          Expr := Expression (Delay_Statement (N));
 
          --  Defer full analysis until the statement is expanded, to insure
@@ -1163,7 +1196,6 @@ package body Sem_Ch9 is
 
    begin
       Tasking_Used := True;
-      Check_SPARK_05_Restriction ("delay statement is not allowed", N);
       Check_Restriction (No_Relative_Delay, N);
       Check_Restriction (No_Delay, N);
       Check_Potentially_Blocking_Operation (N);
@@ -1189,7 +1221,6 @@ package body Sem_Ch9 is
 
    begin
       Tasking_Used := True;
-      Check_SPARK_05_Restriction ("delay statement is not allowed", N);
       Check_Restriction (No_Delay, N);
       Check_Potentially_Blocking_Operation (N);
       Analyze_And_Resolve (E);
@@ -1234,9 +1265,9 @@ package body Sem_Ch9 is
       Analyze (Formals);
 
       if Present (Entry_Index_Specification (Formals)) then
-         Set_Ekind (Id, E_Entry_Family);
+         Mutate_Ekind (Id, E_Entry_Family);
       else
-         Set_Ekind (Id, E_Entry);
+         Mutate_Ekind (Id, E_Entry);
       end if;
 
       Set_Etype          (Id, Standard_Void_Type);
@@ -1258,7 +1289,7 @@ package body Sem_Ch9 is
       E := First_Entity (P_Type);
       while Present (E) loop
          if Chars (E) = Chars (Id)
-           and then (Ekind (E) = Ekind (Id))
+           and then Ekind (E) = Ekind (Id)
            and then Type_Conformant (Id, E)
          then
             Entry_Name := E;
@@ -1303,7 +1334,7 @@ package body Sem_Ch9 is
                         Set_Analyzed (Def, False);
 
                         --  Keep the original subtree to ensure a properly
-                        --  formed tree (e.g. for ASIS use).
+                        --  formed tree.
 
                         Rewrite
                           (Discrete_Subtype_Definition (Index_Spec), Def);
@@ -1505,7 +1536,6 @@ package body Sem_Ch9 is
 
    begin
       Tasking_Used := True;
-      Check_SPARK_05_Restriction ("entry call is not allowed", N);
 
       if Present (Pragmas_Before (N)) then
          Analyze_List (Pragmas_Before (N));
@@ -1529,7 +1559,7 @@ package body Sem_Ch9 is
 
       if Nkind (Call) = N_Explicit_Dereference then
          Error_Msg_N
-           ("entry call or dispatching primitive of interface required ", N);
+           ("entry call or dispatching primitive of interface required", N);
       end if;
 
       if Is_Non_Empty_List (Statements (N)) then
@@ -1554,13 +1584,13 @@ package body Sem_Ch9 is
       --  Case of no discrete subtype definition
 
       if No (D_Sdef) then
-         Set_Ekind (Def_Id, E_Entry);
+         Mutate_Ekind (Def_Id, E_Entry);
 
       --  Processing for discrete subtype definition present
 
       else
          Enter_Name (Def_Id);
-         Set_Ekind (Def_Id, E_Entry_Family);
+         Mutate_Ekind (Def_Id, E_Entry_Family);
          Analyze (D_Sdef);
          Make_Index (D_Sdef, N, Def_Id);
 
@@ -1725,11 +1755,11 @@ package body Sem_Ch9 is
          Make_Index (Def, N);
       end if;
 
-      Set_Ekind (Loop_Id, E_Loop);
+      Mutate_Ekind (Loop_Id, E_Loop);
       Set_Scope (Loop_Id, Current_Scope);
       Push_Scope (Loop_Id);
       Enter_Name (Iden);
-      Set_Ekind (Iden, E_Entry_Index_Parameter);
+      Mutate_Ekind (Iden, E_Entry_Index_Parameter);
       Set_Etype (Iden, Etype (Def));
    end Analyze_Entry_Index_Specification;
 
@@ -1811,7 +1841,7 @@ package body Sem_Ch9 is
       Freeze_Previous_Contracts (N);
 
       Tasking_Used := True;
-      Set_Ekind (Body_Id, E_Protected_Body);
+      Mutate_Ekind (Body_Id, E_Protected_Body);
       Set_Etype (Body_Id, Standard_Void_Type);
       Spec_Id := Find_Concurrent_Spec (Body_Id);
 
@@ -1956,12 +1986,9 @@ package body Sem_Ch9 is
 
    begin
       Tasking_Used := True;
-      Check_SPARK_05_Restriction ("protected definition is not allowed", N);
       Analyze_Declarations (Visible_Declarations (N));
 
-      if Present (Private_Declarations (N))
-        and then not Is_Empty_List (Private_Declarations (N))
-      then
+      if not Is_Empty_List (Private_Declarations (N)) then
          Last_Id := Last_Entity (Prot_Typ);
          Analyze_Declarations (Private_Declarations (N));
 
@@ -1974,7 +2001,7 @@ package body Sem_Ch9 is
 
       Item_Id := First_Entity (Prot_Typ);
       while Present (Item_Id) loop
-         if Ekind_In (Item_Id, E_Function, E_Procedure) then
+         if Ekind (Item_Id) in E_Function | E_Procedure then
             Set_Convention (Item_Id, Convention_Protected);
          else
             Propagate_Concurrent_Flags (Prot_Typ, Etype (Item_Id));
@@ -2028,13 +2055,19 @@ package body Sem_Ch9 is
          Set_Completion_Referenced (T);
       end if;
 
-      Set_Ekind              (T, E_Protected_Type);
+      Mutate_Ekind           (T, E_Protected_Type);
       Set_Is_First_Subtype   (T);
-      Init_Size_Align        (T);
+      Reinit_Size_Align      (T);
       Set_Etype              (T, T);
       Set_Has_Delayed_Freeze (T);
       Set_Stored_Constraint  (T, No_Elist);
 
+      --  Initialize type's primitive operations list, for possible use when
+      --  the extension of prefixed call notation for untagged types is enabled
+      --  (such as by use of -gnatX).
+
+      Set_Direct_Primitive_Operations (T, New_Elmt_List);
+
       --  Mark this type as a protected type for the sake of restrictions,
       --  unless the protected type is declared in a private part of a package
       --  of the runtime. With this exception, the Suspension_Object from
@@ -2142,8 +2175,8 @@ package body Sem_Ch9 is
       E := First_Entity (Current_Scope);
       while Present (E) loop
          if Ekind (E) = E_Void then
-            Set_Ekind (E, E_Component);
-            Init_Component_Location (E);
+            Mutate_Ekind (E, E_Component);
+            Reinit_Component_Location (E);
          end if;
 
          Next_Entity (E);
@@ -2258,6 +2291,11 @@ package body Sem_Ch9 is
 
          Propagate_Invariant_Attributes (T, From_Typ => Def_Id);
 
+         --  Propagate predicate-related attributes from the private type to
+         --  the protected type.
+
+         Propagate_Predicate_Attributes (T, From_Typ => Def_Id);
+
          --  Create corresponding record now, because some private dependents
          --  may be subtypes of the partial view.
 
@@ -2288,6 +2326,64 @@ package body Sem_Ch9 is
    ---------------------
 
    procedure Analyze_Requeue (N : Node_Id) is
+
+      procedure Check_Wrong_Attribute_In_Postconditions
+        (Entry_Id   : Entity_Id;
+         Error_Node : Node_Id);
+      --  Check that the requeue target Entry_Id does not have an specific or
+      --  class-wide postcondition that references an Old or Index attribute.
+
+      ---------------------------------------------
+      -- Check_Wrong_Attribute_In_Postconditions --
+      ---------------------------------------------
+
+      procedure Check_Wrong_Attribute_In_Postconditions
+        (Entry_Id   : Entity_Id;
+         Error_Node : Node_Id)
+      is
+         function Check_Node (N : Node_Id) return Traverse_Result;
+         --  Check that N is not a reference to attribute Index or Old; report
+         --  an error otherwise.
+
+         ----------------
+         -- Check_Node --
+         ----------------
+
+         function Check_Node (N : Node_Id) return Traverse_Result is
+         begin
+            if Nkind (N) = N_Attribute_Reference
+              and then Attribute_Name (N) in Name_Index
+                                           | Name_Old
+            then
+               Error_Msg_Name_1 := Attribute_Name (N);
+               Error_Msg_N
+                 ("target of requeue must not have references to attribute % "
+                  & "in postcondition",
+                  Error_Node);
+            end if;
+
+            return OK;
+         end Check_Node;
+
+         procedure Check_Attr_Refs is new Traverse_Proc (Check_Node);
+
+         --  Local variables
+
+         Prag : Node_Id;
+      begin
+         Prag := Pre_Post_Conditions (Contract (Entry_Id));
+
+         while Present (Prag) loop
+            if Pragma_Name (Prag) = Name_Postcondition then
+               Check_Attr_Refs (First (Pragma_Argument_Associations (Prag)));
+            end if;
+
+            Prag := Next_Pragma (Prag);
+         end loop;
+      end Check_Wrong_Attribute_In_Postconditions;
+
+      --  Local variables
+
       Count       : Natural := 0;
       Entry_Name  : Node_Id := Name (N);
       Entry_Id    : Entity_Id;
@@ -2300,6 +2396,8 @@ package body Sem_Ch9 is
       Outer_Ent   : Entity_Id;
       Synch_Type  : Entity_Id := Empty;
 
+   --  Start of processing for Analyze_Requeue
+
    begin
       --  Preserve relevant elaboration-related attributes of the context which
       --  are no longer available or very expensive to recompute once analysis,
@@ -2312,7 +2410,6 @@ package body Sem_Ch9 is
          Warnings => True);
 
       Tasking_Used := True;
-      Check_SPARK_05_Restriction ("requeue statement is not allowed", N);
       Check_Restriction (No_Requeue_Statements, N);
       Check_Unreachable_Code (N);
 
@@ -2321,7 +2418,7 @@ package body Sem_Ch9 is
          Enclosing := Scope_Stack.Table (J).Entity;
          exit when Is_Entry (Enclosing);
 
-         if not Ekind_In (Enclosing, E_Block, E_Loop) then
+         if Ekind (Enclosing) not in E_Block | E_Loop then
             Error_Msg_N ("requeue must appear within accept or entry body", N);
             return;
          end if;
@@ -2364,7 +2461,8 @@ package body Sem_Ch9 is
          --  entry body) unless it is a parameter of the innermost enclosing
          --  accept statement (or entry body).
 
-         if Object_Access_Level (Target_Obj) >= Scope_Depth (Outer_Ent)
+         if Static_Accessibility_Level (Target_Obj, Zero_On_Dynamic_Level)
+              >= Scope_Depth (Outer_Ent)
            and then
              (not Is_Entity_Name (Target_Obj)
                or else not Is_Formal (Entity (Target_Obj))
@@ -2554,7 +2652,7 @@ package body Sem_Ch9 is
                   --  perform an unconditional goto so that any further
                   --  references will not occur anyway.
 
-                  if Ekind_In (Ent, E_Out_Parameter, E_In_Out_Parameter) then
+                  if Ekind (Ent) in E_Out_Parameter | E_In_Out_Parameter then
                      Set_Never_Set_In_Source (Ent, False);
                      Set_Is_True_Constant    (Ent, False);
                   end if;
@@ -2583,6 +2681,18 @@ package body Sem_Ch9 is
            ("target protected object of requeue must be a variable", N);
       end if;
 
+      --  Ada 2022 (AI12-0143): The requeue target shall not have an
+      --  applicable specific or class-wide postcondition which includes
+      --  an Old or Index attribute reference.
+
+      if Ekind (Entry_Id) = E_Entry_Family
+        and then Present (Contract (Entry_Id))
+      then
+         Check_Wrong_Attribute_In_Postconditions
+           (Entry_Id   => Entry_Id,
+            Error_Node => Entry_Name);
+      end if;
+
       --  A requeue statement is treated as a call for purposes of ABE checks
       --  and diagnostics. Annotate the tree by creating a call marker in case
       --  the requeue statement is transformed by expansion.
@@ -2606,7 +2716,6 @@ package body Sem_Ch9 is
 
    begin
       Tasking_Used := True;
-      Check_SPARK_05_Restriction ("select statement is not allowed", N);
       Check_Restriction (No_Select_Statements, N);
 
       --  Loop to analyze alternatives
@@ -2623,7 +2732,7 @@ package body Sem_Ch9 is
                    (Nkind (Delay_Statement (Alt)) = N_Delay_Relative_Statement)
                then
                   Error_Msg_N
-                    ("delay_until and delay_relative alternatives ", Alt);
+                    ("delay_until and delay_relative alternatives", Alt);
                   Error_Msg_N
                     ("\cannot appear in the same selective_wait", Alt);
                end if;
@@ -2675,7 +2784,7 @@ package body Sem_Ch9 is
                               if Entity (EDN1) = Ent then
                                  Error_Msg_Sloc := Sloc (Stm1);
                                  Error_Msg_N
-                                   ("accept duplicates one on line#??", Stm);
+                                   ("ACCEPT duplicates one on line#??", Stm);
                                  exit;
                               end if;
                            end if;
@@ -2695,16 +2804,16 @@ package body Sem_Ch9 is
       Check_Potentially_Blocking_Operation (N);
 
       if Terminate_Present and Delay_Present then
-         Error_Msg_N ("at most one of terminate or delay alternative", N);
+         Error_Msg_N ("at most one of TERMINATE or DELAY alternative", N);
 
       elsif not Accept_Present then
          Error_Msg_N
-           ("select must contain at least one accept alternative", N);
+           ("SELECT must contain at least one ACCEPT alternative", N);
       end if;
 
       if Present (Else_Statements (N)) then
          if Terminate_Present or Delay_Present then
-            Error_Msg_N ("else part not allowed with other alternatives", N);
+            Error_Msg_N ("ELSE part not allowed with other alternatives", N);
          end if;
 
          Analyze_Statements (Else_Statements (N));
@@ -2775,12 +2884,12 @@ package body Sem_Ch9 is
       --  its own body.
 
       Enter_Name (Typ);
-      Set_Ekind            (Typ, E_Protected_Type);
+      Mutate_Ekind         (Typ, E_Protected_Type);
       Set_Etype            (Typ, Typ);
       Set_Anonymous_Object (Typ, Obj_Id);
 
       Enter_Name (Obj_Id);
-      Set_Ekind                  (Obj_Id, E_Variable);
+      Mutate_Ekind               (Obj_Id, E_Variable);
       Set_Etype                  (Obj_Id, Typ);
       Set_SPARK_Pragma           (Obj_Id, SPARK_Mode_Pragma);
       Set_SPARK_Pragma_Inherited (Obj_Id);
@@ -2861,12 +2970,12 @@ package body Sem_Ch9 is
       --  in its own body.
 
       Enter_Name (Typ);
-      Set_Ekind            (Typ, E_Task_Type);
+      Mutate_Ekind         (Typ, E_Task_Type);
       Set_Etype            (Typ, Typ);
       Set_Anonymous_Object (Typ, Obj_Id);
 
       Enter_Name (Obj_Id);
-      Set_Ekind                  (Obj_Id, E_Variable);
+      Mutate_Ekind               (Obj_Id, E_Variable);
       Set_Etype                  (Obj_Id, Typ);
       Set_SPARK_Pragma           (Obj_Id, SPARK_Mode_Pragma);
       Set_SPARK_Pragma_Inherited (Obj_Id);
@@ -2922,7 +3031,7 @@ package body Sem_Ch9 is
 
       Tasking_Used := True;
       Set_Scope (Body_Id, Current_Scope);
-      Set_Ekind (Body_Id, E_Task_Body);
+      Mutate_Ekind (Body_Id, E_Task_Body);
       Set_Etype (Body_Id, Standard_Void_Type);
       Spec_Id := Find_Concurrent_Spec (Body_Id);
 
@@ -2993,6 +3102,24 @@ package body Sem_Ch9 is
          else
             Set_First_Private_Entity (Spec_Id, First_Entity (Spec_Id));
          end if;
+
+         --  The entity list of the current scope now includes entities in
+         --  the spec as well as the body. Their declarations will become
+         --  part of the statement sequence of the task body procedure that
+         --  is built during expansion. Indicate that aspect specifications
+         --  for these entities need not be rechecked. The guards on
+         --  Check_Aspect_At_End_Of_Declarations are not sufficient to
+         --  suppress these checks, because the declarations come from source.
+
+         declare
+            Priv : Entity_Id := First_Private_Entity (Spec_Id);
+
+         begin
+            while Present (Priv) loop
+               Set_Has_Delayed_Aspects (Priv, False);
+               Next_Entity (Priv);
+            end loop;
+         end;
       end if;
 
       --  Mark all handlers as not suitable for local raise optimization,
@@ -3050,7 +3177,6 @@ package body Sem_Ch9 is
 
    begin
       Tasking_Used := True;
-      Check_SPARK_05_Restriction ("task definition is not allowed", N);
 
       if Present (Visible_Declarations (N)) then
          Analyze_Declarations (Visible_Declarations (N));
@@ -3122,19 +3248,25 @@ package body Sem_Ch9 is
             Set_Completion_Referenced (T);
 
          else
-            Set_Ekind (T, E_Task_Type);
+            Mutate_Ekind (T, E_Task_Type);
             Set_Corresponding_Record_Type (T, Empty);
          end if;
       end if;
 
-      Set_Ekind              (T, E_Task_Type);
+      Mutate_Ekind           (T, E_Task_Type);
       Set_Is_First_Subtype   (T, True);
       Set_Has_Task           (T, True);
-      Init_Size_Align        (T);
+      Reinit_Size_Align      (T);
       Set_Etype              (T, T);
       Set_Has_Delayed_Freeze (T, True);
       Set_Stored_Constraint  (T, No_Elist);
 
+      --  Initialize type's primitive operations list, for possible use when
+      --  the extension of prefixed call notation for untagged types is enabled
+      --  (such as by use of -gnatX).
+
+      Set_Direct_Primitive_Operations (T, New_Elmt_List);
+
       --  Set the SPARK_Mode from the current context (may be overwritten later
       --  with an explicit pragma).
 
@@ -3239,6 +3371,11 @@ package body Sem_Ch9 is
 
          Propagate_Invariant_Attributes (T, From_Typ => Def_Id);
 
+         --  Propagate predicate-related attributes from the private type to
+         --  task type.
+
+         Propagate_Predicate_Attributes (T, From_Typ => Def_Id);
+
          --  Create corresponding record now, because some private dependents
          --  may be subtypes of the partial view.
 
@@ -3292,7 +3429,6 @@ package body Sem_Ch9 is
 
    begin
       Tasking_Used := True;
-      Check_SPARK_05_Restriction ("select statement is not allowed", N);
       Check_Restriction (No_Select_Statements, N);
 
       --  Ada 2005 (AI-345): The trigger may be a dispatching call
@@ -3454,7 +3590,7 @@ package body Sem_Ch9 is
 
    begin
       pragma Assert
-        (Nkind_In (N, N_Protected_Type_Declaration, N_Task_Type_Declaration));
+        (Nkind (N) in N_Protected_Type_Declaration | N_Task_Type_Declaration);
 
       if Present (Interface_List (N)) then
          Set_Is_Tagged_Type (T);
@@ -3462,7 +3598,7 @@ package body Sem_Ch9 is
          --  The primitive operations of a tagged synchronized type are placed
          --  on the Corresponding_Record for proper dispatching, but are
          --  attached to the synchronized type itself when expansion is
-         --  disabled, for ASIS use.
+         --  disabled.
 
          Set_Direct_Primitive_Operations (T, New_Elmt_List);
 
@@ -3516,6 +3652,14 @@ package body Sem_Ch9 is
 
             Next (Iface);
          end loop;
+
+         --  Check consistency of any nonoverridable aspects that are
+         --  inherited from multiple sources.
+
+         Check_Inherited_Nonoverridable_Aspects
+           (Inheritor      => N,
+            Interface_List => Interface_List (N),
+            Parent_Type    => Empty);
       end if;
 
       if not Has_Private_Declaration (T) then
@@ -3652,7 +3796,7 @@ package body Sem_Ch9 is
 
          elsif Nkind (Trigger) = N_Explicit_Dereference then
             Error_Msg_N
-              ("entry call or dispatching primitive of interface required ",
+              ("entry call or dispatching primitive of interface required",
                 Trigger);
          end if;
       end if;
This page took 0.070672 seconds and 5 git commands to generate.