-------------------------------------------------------------------------------
-- (C) Altran Praxis Limited
-------------------------------------------------------------------------------
--
-- The SPARK toolset is free software; you can redistribute it and/or modify it
-- under terms of the GNU General Public License as published by the Free
-- Software Foundation; either version 3, or (at your option) any later
-- version. The SPARK toolset is distributed in the hope that it will be
-- useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
-- Public License for more details. You should have received a copy of the GNU
-- General Public License distributed with the SPARK toolset; see file
-- COPYING3. If not, go to http://www.gnu.org/licenses for a complete copy of
-- the license.
--
--=============================================================================

with SLI;

separate (Sem)
procedure Wf_Global_Definition
  (Node          : in     STree.SyntaxNode;
   Scope         : in     Dictionary.Scopes;
   Subprog_Sym   : in     Dictionary.Symbol;
   First_Seen    : in     Boolean;
   Sem_Err_Found :    out Boolean)
is
   Abstraction    : Dictionary.Abstractions;
   Doing_Function : Boolean;

   ----------------------------------------------------------------------

   -- Handle Special case for stream variables here:
   -- Error occurs if the subprogram references a global which is a mode IN refinement
   -- constituent whose abstract subject is unmoded.  This condition is illegal for
   -- a function subprogram (because it would conceal the stream side-efefct in the
   -- abstract view).  For a procedure, we are protected because derives refinement
   -- checks will always reveal the error; however, we can improve error reporting
   -- by putting something out here as well
   procedure Check_Stream_Variable_Refinement
     (Subprog_Sym   : in     Dictionary.Symbol;
      Err_Pos       : in     LexTokenManager.Token_Position;
      Sem_Err_Found : in out Boolean)
   --# global in     CommandLineData.Content;
   --#        in     Dictionary.Dict;
   --#        in     LexTokenManager.State;
   --#        in out ErrorHandler.Error_Context;
   --#        in out SPARK_IO.File_Sys;
   --# derives ErrorHandler.Error_Context,
   --#         SPARK_IO.File_Sys          from CommandLineData.Content,
   --#                                         Dictionary.Dict,
   --#                                         ErrorHandler.Error_Context,
   --#                                         Err_Pos,
   --#                                         LexTokenManager.State,
   --#                                         SPARK_IO.File_Sys,
   --#                                         Subprog_Sym &
   --#         Sem_Err_Found              from *,
   --#                                         Dictionary.Dict,
   --#                                         Subprog_Sym;
   is
      Refined_Global    : Dictionary.Symbol;
      Abstract_Global   : Dictionary.Symbol;
      Refined_Glob_List : Dictionary.Iterator;

      function Is_Local_Constituent (Sym         : Dictionary.Symbol;
                                     Subprog_Sym : Dictionary.Symbol) return Boolean
      --# global in Dictionary.Dict;
      is
      begin
         return Dictionary.IsConstituent (Sym)
           and then Dictionary.IsPackage (Dictionary.GetOwner (Sym))
           and then Dictionary.Packages_Are_Equal
           (Left_Symbol  => Dictionary.GetEnclosingPackage (Dictionary.GetScope (Subprog_Sym)),
            Right_Symbol => Dictionary.GetOwner (Sym));
      end Is_Local_Constituent;

   begin -- Check_Stream_Variable_Refinement
      Refined_Glob_List := Dictionary.FirstGlobalVariable (Dictionary.IsRefined, Subprog_Sym);
      while not Dictionary.IsNullIterator (Refined_Glob_List) loop
         Refined_Global := Dictionary.CurrentSymbol (Refined_Glob_List);
         if Is_Local_Constituent (Sym         => Refined_Global,
                                  Subprog_Sym => Subprog_Sym) then
            Abstract_Global := Dictionary.GetSubject (Refined_Global);
            if Dictionary.GetOwnVariableOrConstituentMode (Refined_Global) = Dictionary.InMode
              and then
              -- Abstract has no mode
              Dictionary.GetOwnVariableOrConstituentMode (Abstract_Global) = Dictionary.DefaultMode
              and then
              -- Abstract is not protected
              not (Dictionary.IsOwnVariable (Abstract_Global) and then Dictionary.GetOwnVariableProtected (Abstract_Global)) then
               -- an error condition may exist
               --# accept Flow, 41, "Expected stable expression";
               if Dictionary.IsAdaFunction (Subprog_Sym) then
                  --# end accept;
                  -- an error condition does exist
                  ErrorHandler.Semantic_Error2
                    (Err_Num   => 721,
                     Reference => ErrorHandler.No_Reference,
                     Position  => Err_Pos,
                     Id_Str1   => Dictionary.GetSimpleName (Refined_Global),
                     Id_Str2   => Dictionary.GetSimpleName (Abstract_Global));
                  Sem_Err_Found := True;
               else -- must be procedure

                  --  extra checks here - for there to be an error the
                  --  abstract own variable must be have global mode
                  --  IN and the refinement constituent as well
                  if Dictionary.GetGlobalMode (Dictionary.IsAbstract, Subprog_Sym, Abstract_Global) = Dictionary.InMode
                    and then Dictionary.GetGlobalMode (Dictionary.IsRefined, Subprog_Sym, Refined_Global) = Dictionary.InMode then
                     ErrorHandler.Semantic_Error2
                       (Err_Num   => 722,
                        Reference => ErrorHandler.No_Reference,
                        Position  => Err_Pos,
                        Id_Str1   => Dictionary.GetSimpleName (Refined_Global),
                        Id_Str2   => Dictionary.GetSimpleName (Abstract_Global));
                     Sem_Err_Found := True;
                  end if;
               end if;
            end if;
         end if;
         Refined_Glob_List := Dictionary.NextSymbol (Refined_Glob_List);
      end loop;
   end Check_Stream_Variable_Refinement;

   ----------------------------------------------------------------------

   function Type_Two_Error_Position (Node : STree.SyntaxNode) return LexTokenManager.Token_Position
   --# global in STree.Table;
   --# pre Syntax_Node_Type (Node, STree.Table) = SP_Symbols.moded_global_definition;
   is
      Temp_Node : STree.SyntaxNode;
   begin
      Temp_Node := Child_Node (Current_Node => Child_Node (Current_Node => Node));
      -- ASSUME Temp_Node = global_definition_rep OR global_variable_clause
      if Syntax_Node_Type (Node => Temp_Node) = SP_Symbols.global_definition_rep then
         -- ASSUME Temp_Node = global_definition_rep
         Temp_Node := Next_Sibling (Current_Node => Temp_Node);
      elsif Syntax_Node_Type (Node => Temp_Node) /= SP_Symbols.global_variable_clause then
         Temp_Node := STree.NullNode;
         SystemErrors.Fatal_Error
           (Sys_Err => SystemErrors.Invalid_Syntax_Tree,
            Msg     => "Expect Temp_Node = global_definition_rep OR global_variable_clause in Type_Two_Error_Position");
      end if;
      -- ASSUME Temp_Node = global_variable_clause
      SystemErrors.RT_Assert
        (C       => Syntax_Node_Type (Node => Temp_Node) = SP_Symbols.global_variable_clause,
         Sys_Err => SystemErrors.Invalid_Syntax_Tree,
         Msg     => "Expect Temp_Node = global_variable_clause in Type_Two_Error_Position");
      Temp_Node := Child_Node (Current_Node => Next_Sibling (Current_Node => Child_Node (Current_Node => Temp_Node)));
      -- ASSUME Temp_Node = global_variable_list OR global_variable
      if Syntax_Node_Type (Node => Temp_Node) = SP_Symbols.global_variable_list then
         -- ASSUME Temp_Node = global_variable_list
         Temp_Node := Next_Sibling (Current_Node => Temp_Node);
      elsif Syntax_Node_Type (Node => Temp_Node) /= SP_Symbols.global_variable then
         Temp_Node := STree.NullNode;
         SystemErrors.Fatal_Error
           (Sys_Err => SystemErrors.Invalid_Syntax_Tree,
            Msg     => "Expect Temp_Node = global_variable_list OR global_variable in Type_Two_Error_Position");
      end if;
      -- Temp_Node is right-most global variable
      -- ASSUME Temp_Node = global_variable
      SystemErrors.RT_Assert
        (C       => Syntax_Node_Type (Node => Temp_Node) = SP_Symbols.global_variable,
         Sys_Err => SystemErrors.Invalid_Syntax_Tree,
         Msg     => "Expect Temp_Node = global_variable in Type_Two_Error_Position");
      return Node_Position (Node => Temp_Node);
   end Type_Two_Error_Position;

   ----------------------------------------------------------------------

   procedure Check_On_Global_Refinement_2
     (Subprog_Sym   : in     Dictionary.Symbol;
      Err_Pos       : in     LexTokenManager.Token_Position;
      Sem_Err_Found : in out Boolean)
   --# global in     CommandLineData.Content;
   --#        in     Dictionary.Dict;
   --#        in     LexTokenManager.State;
   --#        in out ErrorHandler.Error_Context;
   --#        in out SPARK_IO.File_Sys;
   --# derives ErrorHandler.Error_Context,
   --#         SPARK_IO.File_Sys          from CommandLineData.Content,
   --#                                         Dictionary.Dict,
   --#                                         ErrorHandler.Error_Context,
   --#                                         Err_Pos,
   --#                                         LexTokenManager.State,
   --#                                         SPARK_IO.File_Sys,
   --#                                         Subprog_Sym &
   --#         Sem_Err_Found              from *,
   --#                                         Dictionary.Dict,
   --#                                         Subprog_Sym;
   is
      A_Glo_Var       : Dictionary.Symbol;
      First_Glob_List : Dictionary.Iterator;

      -- lifted out from loop in enclosing procedure below
      procedure Look_For_Refinement_Constituent
        (Subprog_Sym   : in     Dictionary.Symbol;
         A_Glo_Var     : in     Dictionary.Symbol;
         Err_Pos       : in     LexTokenManager.Token_Position;
         Sem_Err_Found : in out Boolean)
      --# global in     CommandLineData.Content;
      --#        in     Dictionary.Dict;
      --#        in     LexTokenManager.State;
      --#        in out ErrorHandler.Error_Context;
      --#        in out SPARK_IO.File_Sys;
      --# derives ErrorHandler.Error_Context,
      --#         SPARK_IO.File_Sys          from A_Glo_Var,
      --#                                         CommandLineData.Content,
      --#                                         Dictionary.Dict,
      --#                                         ErrorHandler.Error_Context,
      --#                                         Err_Pos,
      --#                                         LexTokenManager.State,
      --#                                         SPARK_IO.File_Sys,
      --#                                         Subprog_Sym &
      --#         Sem_Err_Found              from *,
      --#                                         A_Glo_Var,
      --#                                         Dictionary.Dict,
      --#                                         Subprog_Sym;
      is
         Found            : Boolean;
         Second_Glob_List : Dictionary.Iterator;
      begin
         Found            := False;
         Second_Glob_List := Dictionary.FirstGlobalVariable (Dictionary.IsRefined, Subprog_Sym);
         loop
            exit when Dictionary.IsNullIterator (Second_Glob_List);
            Found := Dictionary.IsRefinement (A_Glo_Var, Dictionary.CurrentSymbol (Second_Glob_List));
            exit when Found;
            Second_Glob_List := Dictionary.NextSymbol (Second_Glob_List);
         end loop;
         if not Found then
            ErrorHandler.Semantic_Error_Sym
              (Err_Num   => 86,
               Reference => ErrorHandler.No_Reference,
               Position  => Err_Pos,
               Sym       => A_Glo_Var,
               Scope     => Dictionary.GetScope (Subprog_Sym));
            Sem_Err_Found := True;
         end if;
      end Look_For_Refinement_Constituent;

      -- new procedure similar to above but for unrefined global items
      procedure Look_For_Self
        (Subprog_Sym   : in     Dictionary.Symbol;
         A_Glo_Var     : in     Dictionary.Symbol;
         Err_Pos       : in     LexTokenManager.Token_Position;
         Sem_Err_Found : in out Boolean)
      --# global in     CommandLineData.Content;
      --#        in     Dictionary.Dict;
      --#        in     LexTokenManager.State;
      --#        in out ErrorHandler.Error_Context;
      --#        in out SPARK_IO.File_Sys;
      --# derives ErrorHandler.Error_Context,
      --#         SPARK_IO.File_Sys          from A_Glo_Var,
      --#                                         CommandLineData.Content,
      --#                                         Dictionary.Dict,
      --#                                         ErrorHandler.Error_Context,
      --#                                         Err_Pos,
      --#                                         LexTokenManager.State,
      --#                                         SPARK_IO.File_Sys,
      --#                                         Subprog_Sym &
      --#         Sem_Err_Found              from *,
      --#                                         A_Glo_Var,
      --#                                         Dictionary.Dict,
      --#                                         Subprog_Sym;
      is
         Found            : Boolean;
         Second_Glob_List : Dictionary.Iterator;
      begin
         Found            := False;
         Second_Glob_List := Dictionary.FirstGlobalVariable (Dictionary.IsRefined, Subprog_Sym);
         loop
            exit when Dictionary.IsNullIterator (Second_Glob_List);
            Found := A_Glo_Var = Dictionary.CurrentSymbol (Second_Glob_List);
            exit when Found;
            Second_Glob_List := Dictionary.NextSymbol (Second_Glob_List);
         end loop;
         if not Found and then not Dictionary.Is_Null_Variable (A_Glo_Var) then -- no refinement of "null" needed
            ErrorHandler.Semantic_Error_Sym
              (Err_Num   => 723,
               Reference => ErrorHandler.No_Reference,
               Position  => Err_Pos,
               Sym       => A_Glo_Var,
               Scope     => Dictionary.GetScope (Subprog_Sym));
            Sem_Err_Found := True;
         end if;
      end Look_For_Self;

      function Constituent_Required (The_Global, Subprogram : Dictionary.Symbol) return Boolean
      --# global in Dictionary.Dict;
      is
         Result : Boolean := False;
         Region : Dictionary.Symbol;
      begin
         -- We expect a refinement sonstituent of The_Global if:
         --   The_Global is an abstract own variable  and
         --      (its owner is the package in which Subprogram is declared or
         --       the Subprogram is declared in a protected type and the owner
         --       of The_Global is the package in which the protected type is declared)
         if Dictionary.IsRefinedOwnVariable (The_Global) then
            Result :=
              Is_Enclosing_Package (Outer_Pack => Dictionary.GetOwner (The_Global),
                                    Scope      => Dictionary.GetScope (Subprogram));
            if not Result then
               Region := Dictionary.GetRegion (Dictionary.GetScope (Subprogram));
               if Dictionary.IsProtectedType (Region) then
                  Result :=
                    Is_Enclosing_Package (Outer_Pack => Dictionary.GetOwner (The_Global),
                                          Scope      => Dictionary.GetScope (Region));
               end if;
            end if;
         end if;
         return Result;
      end Constituent_Required;

   begin -- Check_On_Global_Refinement_2
      First_Glob_List := Dictionary.FirstGlobalVariable (Dictionary.IsAbstract, Subprog_Sym);
      while not Dictionary.IsNullIterator (First_Glob_List) loop
         A_Glo_Var := Dictionary.CurrentSymbol (First_Glob_List);
         if Constituent_Required (The_Global => A_Glo_Var,
                                  Subprogram => Subprog_Sym) then
            Look_For_Refinement_Constituent
              (Subprog_Sym   => Subprog_Sym,
               A_Glo_Var     => A_Glo_Var,
               Err_Pos       => Err_Pos,
               Sem_Err_Found => Sem_Err_Found);
         else
            Look_For_Self (Subprog_Sym   => Subprog_Sym,
                           A_Glo_Var     => A_Glo_Var,
                           Err_Pos       => Err_Pos,
                           Sem_Err_Found => Sem_Err_Found);
         end if;
         First_Glob_List := Dictionary.NextSymbol (First_Glob_List);
      end loop;
   end Check_On_Global_Refinement_2;

   ----------------------------------------------------------------------

   procedure Wf_Moded_Global_Definition
     (Node           : in     STree.SyntaxNode;
      Scope          : in     Dictionary.Scopes;
      Subprog_Sym    : in     Dictionary.Symbol;
      First_Seen     : in     Boolean;
      Abstraction    : in     Dictionary.Abstractions;
      Doing_Function : in     Boolean;
      Sem_Err_Found  : in out Boolean)
   --# global in     CommandLineData.Content;
   --#        in     ContextManager.Ops.Unit_Stack;
   --#        in     LexTokenManager.State;
   --#        in out Dictionary.Dict;
   --#        in out ErrorHandler.Error_Context;
   --#        in out SPARK_IO.File_Sys;
   --#        in out STree.Table;
   --# derives Dictionary.Dict,
   --#         STree.Table                from Abstraction,
   --#                                         CommandLineData.Content,
   --#                                         ContextManager.Ops.Unit_Stack,
   --#                                         Dictionary.Dict,
   --#                                         LexTokenManager.State,
   --#                                         Node,
   --#                                         Scope,
   --#                                         STree.Table,
   --#                                         Subprog_Sym &
   --#         ErrorHandler.Error_Context,
   --#         SPARK_IO.File_Sys          from Abstraction,
   --#                                         CommandLineData.Content,
   --#                                         ContextManager.Ops.Unit_Stack,
   --#                                         Dictionary.Dict,
   --#                                         Doing_Function,
   --#                                         ErrorHandler.Error_Context,
   --#                                         First_Seen,
   --#                                         LexTokenManager.State,
   --#                                         Node,
   --#                                         Scope,
   --#                                         SPARK_IO.File_Sys,
   --#                                         STree.Table,
   --#                                         Subprog_Sym &
   --#         Sem_Err_Found              from *,
   --#                                         Abstraction,
   --#                                         CommandLineData.Content,
   --#                                         ContextManager.Ops.Unit_Stack,
   --#                                         Dictionary.Dict,
   --#                                         Doing_Function,
   --#                                         First_Seen,
   --#                                         LexTokenManager.State,
   --#                                         Node,
   --#                                         Scope,
   --#                                         STree.Table,
   --#                                         Subprog_Sym;
   --# pre Syntax_Node_Type (Node, STree.Table) = SP_Symbols.moded_global_definition;
   --# post STree.Table = STree.Table~;
   is
      It                         : STree.Iterator;
      Next_Node, Dependency_Node : STree.SyntaxNode;
      Mode                       : Dictionary.Modes;

      function Get_Mode (Node : STree.SyntaxNode) return Dictionary.Modes
      --# global in STree.Table;
      --# pre Syntax_Node_Type (Node, STree.Table) = SP_Symbols.global_variable_clause;
      is
         Mode_Node : STree.SyntaxNode;
         Result    : Dictionary.Modes;
      begin
         Mode_Node := Child_Node (Current_Node => Child_Node (Current_Node => Node));
         -- ASSUME Mode_Node = in_mode OR inout_mode OR out_mode OR NULL
         if Mode_Node = STree.NullNode then
            -- ASSUME Mode_Node = NULL
            Result := Dictionary.DefaultMode;
         else
            -- ASSUME Mode_Node = in_mode OR inout_mode OR out_mode
            case Syntax_Node_Type (Node => Mode_Node) is
               when SP_Symbols.in_mode =>
                  -- ASSUME Mode_Node = in_mode
                  Result := Dictionary.InMode;
               when SP_Symbols.inout_mode =>
                  -- ASSUME Mode_Node = inout_mode
                  Result := Dictionary.InOutMode;
               when SP_Symbols.out_mode =>
                  -- ASSUME Mode_Node = out_mode
                  Result := Dictionary.OutMode;
               when others =>
                  Result := Dictionary.DefaultMode; -- cannot occur
                  SystemErrors.Fatal_Error
                    (Sys_Err => SystemErrors.Invalid_Syntax_Tree,
                     Msg     => "Expect Mode_Node = in_mode OR inout_mode OR out_mode OR NULL in Get_Mode");
            end case;
         end if;
         return Result;
      end Get_Mode;

      --------------------------------------------------

      procedure Process_Global_List
        (Node          : in     STree.SyntaxNode;
         Mode          : in     Dictionary.Modes;
         Scope         : in     Dictionary.Scopes;
         Subprog_Sym   : in     Dictionary.Symbol;
         First_Seen    : in     Boolean;
         Abstraction   : in     Dictionary.Abstractions;
         Sem_Err_Found : in out Boolean)
      --# global in     CommandLineData.Content;
      --#        in     ContextManager.Ops.Unit_Stack;
      --#        in     LexTokenManager.State;
      --#        in out Dictionary.Dict;
      --#        in out ErrorHandler.Error_Context;
      --#        in out SPARK_IO.File_Sys;
      --#        in out STree.Table;
      --# derives Dictionary.Dict,
      --#         STree.Table                from Abstraction,
      --#                                         CommandLineData.Content,
      --#                                         ContextManager.Ops.Unit_Stack,
      --#                                         Dictionary.Dict,
      --#                                         LexTokenManager.State,
      --#                                         Mode,
      --#                                         Node,
      --#                                         Scope,
      --#                                         STree.Table,
      --#                                         Subprog_Sym &
      --#         ErrorHandler.Error_Context,
      --#         SPARK_IO.File_Sys          from Abstraction,
      --#                                         CommandLineData.Content,
      --#                                         ContextManager.Ops.Unit_Stack,
      --#                                         Dictionary.Dict,
      --#                                         ErrorHandler.Error_Context,
      --#                                         First_Seen,
      --#                                         LexTokenManager.State,
      --#                                         Mode,
      --#                                         Node,
      --#                                         Scope,
      --#                                         SPARK_IO.File_Sys,
      --#                                         STree.Table,
      --#                                         Subprog_Sym &
      --#         Sem_Err_Found              from *,
      --#                                         Abstraction,
      --#                                         CommandLineData.Content,
      --#                                         ContextManager.Ops.Unit_Stack,
      --#                                         Dictionary.Dict,
      --#                                         First_Seen,
      --#                                         LexTokenManager.State,
      --#                                         Mode,
      --#                                         Node,
      --#                                         Scope,
      --#                                         STree.Table,
      --#                                         Subprog_Sym;
      --# pre Syntax_Node_Type (Node, STree.Table) = SP_Symbols.global_variable_list;
      --# post STree.Table = STree.Table~;
      is
         It        : STree.Iterator;
         Next_Node : STree.SyntaxNode;

         ----------------------------------------------------------------------

         procedure Process_One_Global
           (Node          : in     STree.SyntaxNode;
            Mode          : in     Dictionary.Modes;
            Scope         : in     Dictionary.Scopes;
            Subprog_Sym   : in     Dictionary.Symbol;
            First_Seen    : in     Boolean;
            Abstraction   : in     Dictionary.Abstractions;
            Sem_Err_Found : in out Boolean)
         --# global in     CommandLineData.Content;
         --#        in     ContextManager.Ops.Unit_Stack;
         --#        in     LexTokenManager.State;
         --#        in out Dictionary.Dict;
         --#        in out ErrorHandler.Error_Context;
         --#        in out SPARK_IO.File_Sys;
         --#        in out STree.Table;
         --# derives Dictionary.Dict,
         --#         STree.Table                from Abstraction,
         --#                                         CommandLineData.Content,
         --#                                         ContextManager.Ops.Unit_Stack,
         --#                                         Dictionary.Dict,
         --#                                         LexTokenManager.State,
         --#                                         Mode,
         --#                                         Node,
         --#                                         Scope,
         --#                                         STree.Table,
         --#                                         Subprog_Sym &
         --#         ErrorHandler.Error_Context from *,
         --#                                         Abstraction,
         --#                                         CommandLineData.Content,
         --#                                         Dictionary.Dict,
         --#                                         First_Seen,
         --#                                         LexTokenManager.State,
         --#                                         Mode,
         --#                                         Node,
         --#                                         Scope,
         --#                                         SPARK_IO.File_Sys,
         --#                                         STree.Table,
         --#                                         Subprog_Sym &
         --#         Sem_Err_Found              from *,
         --#                                         Abstraction,
         --#                                         CommandLineData.Content,
         --#                                         Dictionary.Dict,
         --#                                         First_Seen,
         --#                                         LexTokenManager.State,
         --#                                         Mode,
         --#                                         Node,
         --#                                         Scope,
         --#                                         STree.Table,
         --#                                         Subprog_Sym &
         --#         SPARK_IO.File_Sys          from *,
         --#                                         Abstraction,
         --#                                         CommandLineData.Content,
         --#                                         ContextManager.Ops.Unit_Stack,
         --#                                         Dictionary.Dict,
         --#                                         ErrorHandler.Error_Context,
         --#                                         First_Seen,
         --#                                         LexTokenManager.State,
         --#                                         Mode,
         --#                                         Node,
         --#                                         Scope,
         --#                                         STree.Table,
         --#                                         Subprog_Sym;
         --# pre Syntax_Node_Type (Node, STree.Table) = SP_Symbols.global_variable;
         --# post STree.Table = STree.Table~;
         is
            Dotted               : Boolean;
            Sym                  : Dictionary.Symbol;
            Global_Variable_Sym  : Dictionary.Symbol;
            Param_Mode           : Dictionary.Modes;
            Entire_Variable_Node : STree.SyntaxNode;

            ----------------------------------------------------------------------

            procedure Global_Not_Refined
              (Global_Sym    : in out Dictionary.Symbol;
               Error_Pos     : in     LexTokenManager.Token_Position;
               Subprog_Sym   : in     Dictionary.Symbol;
               Sem_Err_Found : in out Boolean)
            --# global in     CommandLineData.Content;
            --#        in     Dictionary.Dict;
            --#        in     LexTokenManager.State;
            --#        in out ErrorHandler.Error_Context;
            --#        in out SPARK_IO.File_Sys;
            --# derives ErrorHandler.Error_Context,
            --#         SPARK_IO.File_Sys          from CommandLineData.Content,
            --#                                         Dictionary.Dict,
            --#                                         ErrorHandler.Error_Context,
            --#                                         Error_Pos,
            --#                                         Global_Sym,
            --#                                         LexTokenManager.State,
            --#                                         SPARK_IO.File_Sys,
            --#                                         Subprog_Sym &
            --#         Global_Sym,
            --#         Sem_Err_Found              from *,
            --#                                         Dictionary.Dict,
            --#                                         Global_Sym,
            --#                                         Subprog_Sym;
            is
            begin
               if Dictionary.IsRefinedOwnVariable (Global_Sym)
                 and then Is_Enclosing_Package
                 (Outer_Pack => Dictionary.GetOwner (Global_Sym),
                  Scope      => Dictionary.Set_Visibility (The_Visibility => Dictionary.Local,
                                                           The_Unit       => Subprog_Sym)) then
                  ErrorHandler.Semantic_Error
                    (Err_Num   => 314,
                     Reference => ErrorHandler.No_Reference,
                     Position  => Error_Pos,
                     Id_Str    => Dictionary.GetSimpleName (Global_Sym));
                  Global_Sym    := Dictionary.NullSymbol;
                  Sem_Err_Found := True;
               end if;
            end Global_Not_Refined;

            ----------------------------------------------------------------------

            procedure Check_Stream_Mode_Consistency
              (Global_Sym    : in out Dictionary.Symbol;
               Mode          : in     Dictionary.Modes;
               Error_Pos     : in     LexTokenManager.Token_Position;
               Subprog_Sym   : in     Dictionary.Symbol;
               Sem_Err_Found : in out Boolean)
            --# global in     CommandLineData.Content;
            --#        in     Dictionary.Dict;
            --#        in     LexTokenManager.State;
            --#        in out ErrorHandler.Error_Context;
            --#        in out SPARK_IO.File_Sys;
            --# derives ErrorHandler.Error_Context,
            --#         SPARK_IO.File_Sys          from CommandLineData.Content,
            --#                                         Dictionary.Dict,
            --#                                         ErrorHandler.Error_Context,
            --#                                         Error_Pos,
            --#                                         Global_Sym,
            --#                                         LexTokenManager.State,
            --#                                         Mode,
            --#                                         SPARK_IO.File_Sys,
            --#                                         Subprog_Sym &
            --#         Global_Sym,
            --#         Sem_Err_Found              from *,
            --#                                         Dictionary.Dict,
            --#                                         Global_Sym,
            --#                                         Mode,
            --#                                         Subprog_Sym;
            is
               Possible_Stream_Mode : Dictionary.Modes;
            begin
               Possible_Stream_Mode := Dictionary.GetOwnVariableOrConstituentMode (Global_Sym);
               -- Possible_Stream_Mode contains DefaultMode unless the global is a stream
               -- variable or a stream constituent in which case it will be either InMode
               -- or OutMode (it can never be InOutMode because of earlier wffs).

               -- checks are only required if the mode is something other than DefaultMode
               if Possible_Stream_Mode /= Dictionary.DefaultMode then
                  if Dictionary.IsFunction (Subprog_Sym) then
                     -- required check is that global has default mode or mode in
                     if Possible_Stream_Mode = Dictionary.OutMode then
                        ErrorHandler.Semantic_Error
                          (Err_Num   => 709,
                           Reference => ErrorHandler.No_Reference,
                           Position  => Error_Pos,
                           Id_Str    => Dictionary.GetSimpleName (Global_Sym));
                        Global_Sym    := Dictionary.NullSymbol;
                        Sem_Err_Found := True;
                     end if;

                  else -- handle procedure

                     --  required check is that a moded own variable must have
                     --  the same mode as the global mode if one is given.
                     --  Also, global mode in out cannot be used if the own
                     --  variable is moded.
                     if Mode = Dictionary.InMode and then Possible_Stream_Mode /= Mode then
                        ErrorHandler.Semantic_Error
                          (Err_Num   => 711,
                           Reference => ErrorHandler.No_Reference,
                           Position  => Error_Pos,
                           Id_Str    => Dictionary.GetSimpleName (Global_Sym));
                        Global_Sym    := Dictionary.NullSymbol;
                        Sem_Err_Found := True;
                     elsif Mode = Dictionary.OutMode and then Possible_Stream_Mode /= Mode then
                        ErrorHandler.Semantic_Error
                          (Err_Num   => 710,
                           Reference => ErrorHandler.No_Reference,
                           Position  => Error_Pos,
                           Id_Str    => Dictionary.GetSimpleName (Global_Sym));
                        Global_Sym    := Dictionary.NullSymbol;
                        Sem_Err_Found := True;
                     elsif Mode = Dictionary.InOutMode then
                        ErrorHandler.Semantic_Error
                          (Err_Num   => 712,
                           Reference => ErrorHandler.No_Reference,
                           Position  => Error_Pos,
                           Id_Str    => Dictionary.GetSimpleName (Global_Sym));
                        Global_Sym    := Dictionary.NullSymbol;
                        Sem_Err_Found := True;
                     end if;
                  end if;
               end if;
            end Check_Stream_Mode_Consistency;

            ----------------------------------------------------------------------

            procedure Unique_Global
              (Global_Sym    : in out Dictionary.Symbol;
               Dotted        : in     Boolean;
               Error_Pos     : in     LexTokenManager.Token_Position;
               Subprog_Sym   : in     Dictionary.Symbol;
               Abstraction   : in     Dictionary.Abstractions;
               Sem_Err_Found : in out Boolean)
            --# global in     CommandLineData.Content;
            --#        in     Dictionary.Dict;
            --#        in     LexTokenManager.State;
            --#        in out ErrorHandler.Error_Context;
            --#        in out SPARK_IO.File_Sys;
            --# derives ErrorHandler.Error_Context,
            --#         SPARK_IO.File_Sys          from Abstraction,
            --#                                         CommandLineData.Content,
            --#                                         Dictionary.Dict,
            --#                                         Dotted,
            --#                                         ErrorHandler.Error_Context,
            --#                                         Error_Pos,
            --#                                         Global_Sym,
            --#                                         LexTokenManager.State,
            --#                                         SPARK_IO.File_Sys,
            --#                                         Subprog_Sym &
            --#         Global_Sym,
            --#         Sem_Err_Found              from *,
            --#                                         Abstraction,
            --#                                         Dictionary.Dict,
            --#                                         Dotted,
            --#                                         Global_Sym,
            --#                                         LexTokenManager.State,
            --#                                         Subprog_Sym;
            is
               It         : Dictionary.Iterator;
               Global_Str : LexTokenManager.Lex_String;
            begin
               Global_Str := Dictionary.GetSimpleName (Global_Sym);
               if not Dotted and then Dictionary.Is_Subprogram (Subprog_Sym) then -- task types have no parameters so skip search
                  It := Dictionary.FirstSubprogramParameter (Subprog_Sym);
                  while It /= Dictionary.NullIterator loop
                     if LexTokenManager.Lex_String_Case_Insensitive_Compare
                       (Lex_Str1 => Global_Str,
                        Lex_Str2 => Dictionary.GetSimpleName (Dictionary.CurrentSymbol (It))) =
                       LexTokenManager.Str_Eq then
                        ErrorHandler.Semantic_Error
                          (Err_Num   => 158,
                           Reference => ErrorHandler.No_Reference,
                           Position  => Error_Pos,
                           Id_Str    => Global_Str);
                        Global_Sym    := Dictionary.NullSymbol;
                        Sem_Err_Found := True;
                        exit;
                     end if;
                     It := Dictionary.NextSymbol (It);
                  end loop;
               end if;

               if not Dictionary.Is_Null_Symbol (Global_Sym) then
                  It := Dictionary.FirstGlobalVariable (Abstraction, Subprog_Sym);
                  while It /= Dictionary.NullIterator loop
                     if Global_Sym = Dictionary.CurrentSymbol (It) then
                        ErrorHandler.Semantic_Error
                          (Err_Num   => 157,
                           Reference => ErrorHandler.No_Reference,
                           Position  => Error_Pos,
                           Id_Str    => Global_Str);
                        Global_Sym    := Dictionary.NullSymbol;
                        Sem_Err_Found := True;
                        exit;
                     end if;
                     It := Dictionary.NextSymbol (It);
                  end loop;
               end if;
            end Unique_Global;

            -----------------------------------------------------------------------

            procedure Check_Import_Init
              (Import_Node_Pos         : in     LexTokenManager.Token_Position;
               Import_Sym, Subprog_Sym : in     Dictionary.Symbol;
               Sem_Err_Found           : in out Boolean)
            --# global in     CommandLineData.Content;
            --#        in     Dictionary.Dict;
            --#        in     LexTokenManager.State;
            --#        in out ErrorHandler.Error_Context;
            --#        in out SPARK_IO.File_Sys;
            --# derives ErrorHandler.Error_Context,
            --#         SPARK_IO.File_Sys          from CommandLineData.Content,
            --#                                         Dictionary.Dict,
            --#                                         ErrorHandler.Error_Context,
            --#                                         Import_Node_Pos,
            --#                                         Import_Sym,
            --#                                         LexTokenManager.State,
            --#                                         SPARK_IO.File_Sys,
            --#                                         Subprog_Sym &
            --#         Sem_Err_Found              from *,
            --#                                         Dictionary.Dict,
            --#                                         Import_Sym,
            --#                                         Subprog_Sym;
            is
            begin
               if Dictionary.IsMainProgram (Subprog_Sym)
                 and then Dictionary.IsFunction (Subprog_Sym)
                 and then not Dictionary.OwnVariableIsInitialized (Import_Sym)
                 and then Dictionary.GetOwnVariableOrConstituentMode (Import_Sym) = Dictionary.DefaultMode then
                  Sem_Err_Found := True;
                  ErrorHandler.Semantic_Error
                    (Err_Num   => 167,
                     Reference => ErrorHandler.No_Reference,
                     Position  => Import_Node_Pos,
                     Id_Str    => Dictionary.GetSimpleName (Import_Sym));
               end if;
            end Check_Import_Init;

            ----------------------------------------------------------------------

            procedure Check_On_Global_Refinement_1
              (Subprog_Sym   : in     Dictionary.Symbol;
               Var_Sym       : in     Dictionary.Symbol;
               Err_Pos       : in     LexTokenManager.Token_Position;
               Sem_Err_Found : in out Boolean)
            --# global in     CommandLineData.Content;
            --#        in     Dictionary.Dict;
            --#        in     LexTokenManager.State;
            --#        in out ErrorHandler.Error_Context;
            --#        in out SPARK_IO.File_Sys;
            --# derives ErrorHandler.Error_Context,
            --#         SPARK_IO.File_Sys          from CommandLineData.Content,
            --#                                         Dictionary.Dict,
            --#                                         ErrorHandler.Error_Context,
            --#                                         Err_Pos,
            --#                                         LexTokenManager.State,
            --#                                         SPARK_IO.File_Sys,
            --#                                         Subprog_Sym,
            --#                                         Var_Sym &
            --#         Sem_Err_Found              from *,
            --#                                         Dictionary.Dict,
            --#                                         Subprog_Sym,
            --#                                         Var_Sym;
            is
               Subject_Sym : Dictionary.Symbol;
               Found       : Boolean;
               It          : Dictionary.Iterator;

               -- GAA duplicated code from SEM-DEPENDENCY_RELATION-CHECK_DERIVES_CONSISTENCY.ADB
               function Valid_Refinement (Constituent, Subprogram : Dictionary.Symbol) return Boolean
               --# global in Dictionary.Dict;
               is
                  Owner, Region, Enclosing_Region : Dictionary.Symbol;
                  Result                          : Boolean := False;
               begin
                  if Dictionary.IsConstituent (Constituent) then
                     -- We regard Constituent as a Valid_Refinement if:
                     --   It is a refinement constituent of Subject AND
                     --      (Subject is owned by the region in which the Subprogram is declared OR
                     --       Subject is owned by the region in which the protected type in which the
                     --          Subprogram is declared)
                     Owner  := Dictionary.GetOwner (Dictionary.GetSubject (Constituent));
                     Region := Dictionary.GetRegion (Dictionary.GetScope (Subprogram));
                     Result := Owner = Region;
                     if not Result and then Dictionary.IsProtectedType (Region) then
                        Enclosing_Region := Dictionary.GetRegion (Dictionary.GetScope (Region));
                        Result           := Owner = Enclosing_Region;
                     end if;
                  end if;
                  return Result;
               end Valid_Refinement;

            begin -- Check_On_Global_Refinement_1

               -- look for refinement subject in first global anno
               Subject_Sym := Dictionary.GetSubject (Var_Sym);
               -- if subject not from this package then use own var itself
               if not Valid_Refinement (Constituent => Var_Sym,
                                        Subprogram  => Subprog_Sym) then
                  Subject_Sym := Var_Sym;
               end if;

               Found := False;
               It    := Dictionary.FirstGlobalVariable (Dictionary.IsAbstract, Subprog_Sym);
               loop
                  exit when Dictionary.IsNullIterator (It);
                  Found := Subject_Sym = Dictionary.CurrentSymbol (It);
                  exit when Found;
                  It := Dictionary.NextSymbol (It);
               end loop;
               if not Found then
                  ErrorHandler.Semantic_Error_Sym
                    (Err_Num   => 85,
                     Reference => ErrorHandler.No_Reference,
                     Position  => Err_Pos,
                     Sym       => Var_Sym,
                     Scope     => Dictionary.GetScope (Subprog_Sym));
                  Sem_Err_Found := True;
               end if;
            end Check_On_Global_Refinement_1;

            ----------------------------------------------------------------------

            procedure Check_Main_Program_Global
              (Node    : in     STree.SyntaxNode;
               Scope   : in     Dictionary.Scopes;
               Var_Sym :    out Dictionary.Symbol;
               Dotted  :    out Boolean)
            --# global in     CommandLineData.Content;
            --#        in     Dictionary.Dict;
            --#        in     LexTokenManager.State;
            --#        in out ErrorHandler.Error_Context;
            --#        in out SPARK_IO.File_Sys;
            --#        in out STree.Table;
            --# derives Dotted,
            --#         STree.Table,
            --#         Var_Sym                    from CommandLineData.Content,
            --#                                         Dictionary.Dict,
            --#                                         LexTokenManager.State,
            --#                                         Node,
            --#                                         Scope,
            --#                                         STree.Table &
            --#         ErrorHandler.Error_Context,
            --#         SPARK_IO.File_Sys          from CommandLineData.Content,
            --#                                         Dictionary.Dict,
            --#                                         ErrorHandler.Error_Context,
            --#                                         LexTokenManager.State,
            --#                                         Node,
            --#                                         Scope,
            --#                                         SPARK_IO.File_Sys,
            --#                                         STree.Table;
            --# pre Syntax_Node_Type (Node, STree.Table) = SP_Symbols.entire_variable;
            --# post STree.Table = STree.Table~;
            is
               Id_Node, Next_Id_Node : STree.SyntaxNode;
               P_Id_Str, Id_Str      : LexTokenManager.Lex_String;
               P_Sym                 : Dictionary.Symbol;
            begin
               Id_Node := Last_Child_Of (Start_Node => Node);
               -- ASSUME Id_Node = identifier
               if Syntax_Node_Type (Node => Id_Node) = SP_Symbols.identifier then
                  -- ASSUME Id_Node = identifier
                  Id_Str  := Node_Lex_String (Node => Id_Node);
                  Var_Sym :=
                    Dictionary.LookupItem
                    (Name              => Id_Str,
                     Scope             => Scope,
                     Context           => Dictionary.ProofContext,
                     Full_Package_Name => False);
               else
                  Id_Str  := LexTokenManager.Null_String;
                  Var_Sym := Dictionary.NullSymbol;
                  SystemErrors.Fatal_Error
                    (Sys_Err => SystemErrors.Invalid_Syntax_Tree,
                     Msg     => "Expect Id_Node = identifier in Check_Main_Program_Global");
               end if;
               P_Id_Str := LexTokenManager.Null_String;
               loop
                  --# assert STree.Table = STree.Table~ and
                  --#   Syntax_Node_Type (Id_Node, STree.Table) = SP_Symbols.identifier;
                  -- introduced for multiple prefixes
                  if Dictionary.Is_Null_Symbol (Var_Sym) then
                     ErrorHandler.Semantic_Error2
                       (Err_Num   => 144,
                        Reference => ErrorHandler.No_Reference,
                        Position  => Node_Position (Node => Node),
                        Id_Str1   => Id_Str,
                        Id_Str2   => P_Id_Str);
                     exit;
                  end if;

                  Next_Id_Node := Next_Sibling (Current_Node => Parent_Node (Current_Node => Id_Node));
                  -- ASSUME Next_Id_Node = identifier OR NULL
                  SystemErrors.RT_Assert
                    (C       => Next_Id_Node = STree.NullNode
                       or else Syntax_Node_Type (Node => Next_Id_Node) = SP_Symbols.identifier,
                     Sys_Err => SystemErrors.Invalid_Syntax_Tree,
                     Msg     => "Expect Next_Id_Node = identifier OR NULL in Check_Main_Program_Global");

                  if Dictionary.IsOwnVariable (Var_Sym) then
                     -- entire variable check
                     -- at this point Sym is a variable, final check that there is no dotted
                     -- part to the right of it as there would be if a record field was there
                     if Next_Id_Node /= STree.NullNode then
                        ErrorHandler.Semantic_Error
                          (Err_Num   => 156,
                           Reference => ErrorHandler.No_Reference,
                           Position  => Node_Position (Node => Node),
                           Id_Str    => LexTokenManager.Null_String);
                        Var_Sym := Dictionary.NullSymbol;
                     end if;
                     exit;
                  end if;

                  if not Dictionary.IsPackage (Var_Sym) then
                     ErrorHandler.Semantic_Error
                       (Err_Num   => 174,
                        Reference => ErrorHandler.No_Reference,
                        Position  => Node_Position (Node => Id_Node),
                        Id_Str    => Id_Str);
                     Var_Sym := Dictionary.NullSymbol;
                     exit;
                  end if;

                  if Next_Id_Node = STree.NullNode then
                     -- package without a selected component
                     ErrorHandler.Semantic_Error
                       (Err_Num   => 174,
                        Reference => ErrorHandler.No_Reference,
                        Position  => Node_Position (Node => Id_Node),
                        Id_Str    => Id_Str);
                     Var_Sym := Dictionary.NullSymbol;
                     exit;
                  end if;
                  STree.Set_Node_Lex_String (Sym  => Var_Sym,
                                             Node => Id_Node);
                  P_Id_Str := Id_Str;
                  Id_Node  := Next_Id_Node;
                  Id_Str   := Node_Lex_String (Node => Id_Node);
                  P_Sym    := Var_Sym;
                  Var_Sym  :=
                    Dictionary.LookupSelectedItem
                    (Prefix   => P_Sym,
                     Selector => Id_Str,
                     Scope    => Dictionary.Set_Visibility (The_Visibility => Dictionary.Visible,
                                                            The_Unit       => Var_Sym),
                     Context  => Dictionary.ProofContext);
                  if Dictionary.Is_Null_Symbol (Var_Sym) then
                     -- need also to search current scope for inherited child packages
                     Var_Sym :=
                       Dictionary.LookupSelectedItem
                       (Prefix   => P_Sym,
                        Selector => Id_Str,
                        Scope    => Scope,
                        Context  => Dictionary.ProofContext);
                  end if;
               end loop;

               Dotted :=
                 LexTokenManager.Lex_String_Case_Insensitive_Compare
                 (Lex_Str1 => P_Id_Str,
                  Lex_Str2 => LexTokenManager.Null_String) /=
                 LexTokenManager.Str_Eq
                 and then not Dictionary.Is_Null_Symbol (Var_Sym);
            end Check_Main_Program_Global;

         begin -- Process_One_Global
            Entire_Variable_Node := Child_Node (Current_Node => Node);
            -- ASSUME Entire_Variable_Node = entire_variable
            SystemErrors.RT_Assert
              (C       => Syntax_Node_Type (Node => Entire_Variable_Node) = SP_Symbols.entire_variable,
               Sys_Err => SystemErrors.Invalid_Syntax_Tree,
               Msg     => "Expect Entire_Variable_Node = entire_variable in Process_One_Global");
            if Dictionary.IsMainProgram (Subprog_Sym) then
               Check_Main_Program_Global
                 (Node    => Entire_Variable_Node,
                  Scope   => Dictionary.Set_Visibility (The_Visibility => Dictionary.Local,
                                                        The_Unit       => Subprog_Sym),
                  Var_Sym => Sym,
                  Dotted  => Dotted);
            else
               Wf_Entire_Variable
                 (Node       => Entire_Variable_Node,
                  Scope      => Scope,
                  Error_Hint => In_Global_List,
                  Var_Sym    => Sym,
                  Dotted     => Dotted);
            end if;

            --# assert STree.Table = STree.Table~ and
            --#   Syntax_Node_Type (Node, STree.Table) = SP_Symbols.global_variable and
            --#   Syntax_Node_Type (Entire_Variable_Node, STree.Table) = SP_Symbols.entire_variable;
            if Dictionary.Is_Null_Symbol (Sym) then
               Sem_Err_Found := True;
            end if;

            if CommandLineData.Ravenscar_Selected
              and then not (Dictionary.Is_Subprogram (Subprog_Sym)
                              and then Dictionary.Subprograms_Are_Equal
                              (Left_Symbol  => Subprog_Sym,
                               Right_Symbol => Dictionary.GetThePartition))
              and then Dictionary.IsOwnVariable (Sym)
              and then Dictionary.GetOwnVariableIsInterruptStream (Sym) then
               -- An interrupt stream variable is being used outside the partition
               -- wide flow annotation.
               ErrorHandler.Semantic_Error_Sym
                 (Err_Num   => 955,
                  Reference => ErrorHandler.No_Reference,
                  Position  => Node_Position (Node => Node),
                  Sym       => Sym,
                  Scope     => Scope);
               Sym := Dictionary.NullSymbol;
            end if;

            --# assert STree.Table = STree.Table~ and
            --#   Syntax_Node_Type (Node, STree.Table) = SP_Symbols.global_variable and
            --#   Syntax_Node_Type (Entire_Variable_Node, STree.Table) = SP_Symbols.entire_variable;
            if not Dictionary.Is_Null_Symbol (Sym)
              and then (Dictionary.IsMainProgram (Subprog_Sym) or else Dictionary.IsTaskType (Subprog_Sym)) then
               -- check to ensure that global is initialized
               if CommandLineData.Content.Language_Profile /= CommandLineData.SPARK83
                 and then not Dictionary.GetHasDerivesAnnotation (Subprog_Sym)
                 and then (Mode = Dictionary.InMode or else Mode = Dictionary.InOutMode)
                 and then not Dictionary.OwnVariableIsInitialized (Sym)
                 and then Dictionary.GetOwnVariableOrConstituentMode (Sym) = Dictionary.DefaultMode then
                  ErrorHandler.Semantic_Error
                    (Err_Num   => 167,
                     Reference => ErrorHandler.No_Reference,
                     Position  => Node_Position (Node => Node),
                     Id_Str    => Dictionary.GetSimpleName (Sym));
               end if;
            end if;

            --# assert STree.Table = STree.Table~ and
            --#   Syntax_Node_Type (Node, STree.Table) = SP_Symbols.global_variable and
            --#   Syntax_Node_Type (Entire_Variable_Node, STree.Table) = SP_Symbols.entire_variable;
            if not Dictionary.Is_Null_Symbol (Sym) then
               Global_Not_Refined
                 (Global_Sym    => Sym,
                  Error_Pos     => Node_Position (Node => Entire_Variable_Node),
                  Subprog_Sym   => Subprog_Sym,
                  Sem_Err_Found => Sem_Err_Found);
            end if;

            --# assert STree.Table = STree.Table~ and
            --#   Syntax_Node_Type (Node, STree.Table) = SP_Symbols.global_variable and
            --#   Syntax_Node_Type (Entire_Variable_Node, STree.Table) = SP_Symbols.entire_variable;
            if not Dictionary.Is_Null_Symbol (Sym) then
               Unique_Global
                 (Global_Sym    => Sym,
                  Dotted        => Dotted,
                  Error_Pos     => Node_Position (Node => Entire_Variable_Node),
                  Subprog_Sym   => Subprog_Sym,
                  Abstraction   => Abstraction,
                  Sem_Err_Found => Sem_Err_Found);
            end if;

            --# assert STree.Table = STree.Table~ and
            --#   Syntax_Node_Type (Node, STree.Table) = SP_Symbols.global_variable and
            --#   Syntax_Node_Type (Entire_Variable_Node, STree.Table) = SP_Symbols.entire_variable;
            if not Dictionary.Is_Null_Symbol (Sym) then
               Check_Stream_Mode_Consistency
                 (Global_Sym    => Sym,
                  Mode          => Mode,
                  Error_Pos     => Node_Position (Node => Entire_Variable_Node),
                  Subprog_Sym   => Subprog_Sym,
                  Sem_Err_Found => Sem_Err_Found);
            end if;

            --# assert STree.Table = STree.Table~ and
            --#   Syntax_Node_Type (Node, STree.Table) = SP_Symbols.global_variable and
            --#   Syntax_Node_Type (Entire_Variable_Node, STree.Table) = SP_Symbols.entire_variable;
            if not Dictionary.Is_Null_Symbol (Sym)
              and then Dictionary.IsOwnVariable (Sym)
              and then Dictionary.IsVirtualElement (Sym) then
               if Dictionary.IsOrIsInProtectedScope (Scope)
                 and then Dictionary.Types_Are_Equal
                 (Left_Symbol        => Dictionary.GetEnclosingProtectedRegion (Scope),
                  Right_Symbol       => Dictionary.GetRootType (Dictionary.GetType (Dictionary.GetVirtualElementOwner (Sym))),
                  Full_Range_Subtype => False) then
                  -- Mark the virtual element as having been seen by its "owning"
                  -- protected type.
                  Dictionary.SetVirtualElementSeenByOwner (Sym);
               else
                  -- This is an access to a protected virtual element outside
                  -- it's protected type.
                  ErrorHandler.Semantic_Error_Sym2
                    (Err_Num   => 946,
                     Reference => ErrorHandler.No_Reference,
                     Position  => Node_Position (Node => Node),
                     Sym       => Sym,
                     Sym2      => Dictionary.GetRootType (Dictionary.GetType (Dictionary.GetVirtualElementOwner (Sym))),
                     Scope     => Scope);
               end if;
            end if;

            --# assert STree.Table = STree.Table~ and
            --#   Syntax_Node_Type (Node, STree.Table) = SP_Symbols.global_variable and
            --#   Syntax_Node_Type (Entire_Variable_Node, STree.Table) = SP_Symbols.entire_variable;
            if not Dictionary.Is_Null_Symbol (Sym) then
               if not First_Seen then
                  Check_On_Global_Refinement_1
                    (Subprog_Sym   => Subprog_Sym,
                     Var_Sym       => Sym,
                     Err_Pos       => Node_Position (Node => Entire_Variable_Node),
                     Sem_Err_Found => Sem_Err_Found);
               end if;

               Check_Import_Init
                 (Import_Node_Pos => Node_Position (Node => Node),
                  Import_Sym      => Sym,
                  Subprog_Sym     => Subprog_Sym,
                  Sem_Err_Found   => Sem_Err_Found);

               -- check that mode on a global of an embedded procedure is compatible with
               -- parameters mode if the global is refering to a parameter of an enclosing
               -- procedure
               if Dictionary.IsSubprogramParameter (Sym) then
                  Param_Mode := Dictionary.GetSubprogramParameterMode (Sym);
                  if Param_Mode = Dictionary.InMode or else Param_Mode = Dictionary.DefaultMode then
                     if Mode /= Dictionary.InMode and then Mode /= Dictionary.DefaultMode then
                        ErrorHandler.Semantic_Error
                          (Err_Num   => 508,
                           Reference => ErrorHandler.No_Reference,
                           Position  => Node_Position (Node => Node),
                           Id_Str    => LexTokenManager.Null_String);

                     end if;
                  end if;
               end if;

               Dictionary.AddGlobalVariable
                 (Abstraction         => Abstraction,
                  Subprogram          => Subprog_Sym,
                  Variable            => Sym,
                  Mode                => Mode,
                  PrefixNeeded        => Dotted,
                  Comp_Unit           => ContextManager.Ops.Current_Unit,
                  VariableReference   => Dictionary.Location'(Start_Position => Node_Position (Node => Node),
                                                              End_Position   => Node_Position (Node => Node)),
                  Global_Variable_Sym => Global_Variable_Sym);
               STree.Add_Node_Symbol (Node => Node,
                                      Sym  => Global_Variable_Sym);
               -- Mark the global variable as being referenced by a thread if the
               -- owner of this global variable is a thread (i.e. task, main program or
               -- interrupt handler) and the variable is not protected. This data is
               -- required by the main program shared variable checks.
               if Dictionary.IsThread (Subprog_Sym)
                 and then Dictionary.IsOwnVariable (Sym)
                 and then not Dictionary.GetOwnVariableProtected (Sym) then
                  Dictionary.SetUsesUnprotectedVariables (Subprog_Sym);
               end if;
            end if;
         end Process_One_Global;

      begin -- Process_Global_List
         It := Find_First_Node (Node_Kind    => SP_Symbols.global_variable,
                                From_Root    => Node,
                                In_Direction => STree.Down);
         while not STree.IsNull (It) loop
            Next_Node := Get_Node (It => It);
            --# assert STree.Table = STree.Table~ and
            --#   Syntax_Node_Type (Next_Node, STree.Table) = SP_Symbols.global_variable and
            --#   Next_Node = Get_Node (It);
            Process_One_Global
              (Node          => Next_Node,
               Mode          => Mode,
               Scope         => Scope,
               Subprog_Sym   => Subprog_Sym,
               First_Seen    => First_Seen,
               Abstraction   => Abstraction,
               Sem_Err_Found => Sem_Err_Found);
            It := STree.NextNode (It);
         end loop;
      end Process_Global_List;

   begin -- Wf_Moded_Global_Definition
      Dependency_Node := Next_Sibling (Current_Node => Node);
      -- ASSUME Dependency_Node = function_constraint OR procedure_constraint OR declare_annotation OR
      --                          dependency_relation OR not_overriding_subprogram_body OR NULL
      if Dependency_Node = STree.NullNode
        or else Syntax_Node_Type (Node => Dependency_Node) = SP_Symbols.function_constraint
        or else Syntax_Node_Type (Node => Dependency_Node) = SP_Symbols.procedure_constraint
        or else Syntax_Node_Type (Node => Dependency_Node) = SP_Symbols.declare_annotation
        or else Syntax_Node_Type (Node => Dependency_Node) = SP_Symbols.not_overriding_subprogram_body then
         Dependency_Node := STree.NullNode;
      elsif Syntax_Node_Type (Node => Dependency_Node) /= SP_Symbols.dependency_relation then
         SystemErrors.Fatal_Error
           (Sys_Err => SystemErrors.Invalid_Syntax_Tree,
            Msg     => "Expect Dependency_Node = function_constraint OR procedure_constraint OR declare_annotation OR " &
              "dependency_relation OR not_overriding_subprogram_body OR NULL in Wf_Moded_Global_Definition");
      end if;
      -- ASSUME Dependency_Node = dependency_relation OR NULL

      It := Find_First_Node (Node_Kind    => SP_Symbols.global_variable_clause,
                             From_Root    => Node,
                             In_Direction => STree.Down);
      while not STree.IsNull (It) loop
         Next_Node := Get_Node (It => It);
         --# assert STree.Table = STree.Table~ and
         --#   Syntax_Node_Type (Next_Node, STree.Table) = SP_Symbols.global_variable_clause and
         --#   Next_Node = Get_Node (It);
         Mode := Get_Mode (Node => Next_Node);

         -- Globals are required to have modes if:
         -- 1. Performing data-flow analysis (unless lang=83)
         -- 2. Performing auto-flow analysis if there is no derives anno

         --# accept Flow, 41, "Expected stable expression";
         if CommandLineData.Content.Language_Profile /= CommandLineData.SPARK83 then
            --# end accept;

            if (CommandLineData.Content.Flow_Option = CommandLineData.Data_Flow
                  and then not Doing_Function
                  and then Mode = Dictionary.DefaultMode)
              or else (CommandLineData.Content.Flow_Option = CommandLineData.Auto_Flow
                         and then not Doing_Function
                         and then Mode = Dictionary.DefaultMode
                         and then Dependency_Node = STree.NullNode) then
               Sem_Err_Found := True;
               ErrorHandler.Semantic_Error
                 (Err_Num   => 500,
                  Reference => ErrorHandler.No_Reference,
                  Position  => Node_Position (Node => Next_Node),
                  Id_Str    => LexTokenManager.Null_String);
            end if;
         end if;

         if Doing_Function and then (Mode = Dictionary.OutMode or else Mode = Dictionary.InOutMode) then
            Sem_Err_Found := True;
            ErrorHandler.Semantic_Error
              (Err_Num   => 169,
               Reference => ErrorHandler.No_Reference,
               Position  => Node_Position (Node => Next_Node),
               Id_Str    => LexTokenManager.Null_String);
         end if;

         Next_Node := Next_Sibling (Current_Node => Child_Node (Current_Node => Next_Node));
         -- ASSUME Next_Node = global_variable_list
         SystemErrors.RT_Assert
           (C       => Syntax_Node_Type (Node => Next_Node) = SP_Symbols.global_variable_list,
            Sys_Err => SystemErrors.Invalid_Syntax_Tree,
            Msg     => "Expect Next_Node = global_variable_list in Wf_Moded_Global_Definition");
         Process_Global_List
           (Node          => Next_Node,
            Mode          => Mode,
            Scope         => Scope,
            Subprog_Sym   => Subprog_Sym,
            First_Seen    => First_Seen,
            Abstraction   => Abstraction,
            Sem_Err_Found => Sem_Err_Found);
         It := STree.NextNode (It);
      end loop;
   end Wf_Moded_Global_Definition;

begin -- Wf_Global_Definition
   Sem_Err_Found  := False;
   Doing_Function := Dictionary.IsFunction (Subprog_Sym);

   if First_Seen then
      Abstraction := Dictionary.IsAbstract;
   else
      Abstraction := Dictionary.IsRefined;
   end if;

   Dictionary.AddGlobalAnnotation
     (Abstraction => Abstraction,
      Subprogram  => Subprog_Sym,
      Comp_Unit   => ContextManager.Ops.Current_Unit,
      Annotation  => Dictionary.Location'(Start_Position => Node_Position (Node => Node),
                                          End_Position   => Node_Position (Node => Node)));

   Wf_Moded_Global_Definition
     (Node           => Node,
      Scope          => Scope,
      Subprog_Sym    => Subprog_Sym,
      First_Seen     => First_Seen,
      Abstraction    => Abstraction,
      Doing_Function => Doing_Function,
      Sem_Err_Found  => Sem_Err_Found);

   if not First_Seen then
      Check_On_Global_Refinement_2
        (Subprog_Sym   => Subprog_Sym,
         Err_Pos       => Type_Two_Error_Position (Node => Node),
         Sem_Err_Found => Sem_Err_Found);
      Check_Stream_Variable_Refinement
        (Subprog_Sym   => Subprog_Sym,
         Err_Pos       => Type_Two_Error_Position (Node => Node),
         Sem_Err_Found => Sem_Err_Found);
   end if;

   if ErrorHandler.Generate_SLI then
      SLI.Generate_Xref_Global
        (Comp_Unit   => ContextManager.Ops.Current_Unit,
         Parse_Tree  => Node,
         Scope       => Scope,
         Subprog_Sym => Subprog_Sym);
   end if;
end Wf_Global_Definition;
