-------------------------------------------------------------------------------
-- (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.
--
--=============================================================================

-- This procedure checks the following :
--
-- 1. The parameter associations defined by a procedure call form a bijective
--    function from formal to actual parameters.
-- 2. Every actual parameter corresponding to an exported formal parameter is
--    an entire variable (Section 6.4 Rule 1).
-- 3. Every actual parameter of mode in out or out is the name of a variable.
--    (LRM 6.4.1).
-- 4. Every actual parameter of mode in out or out is not
--       -  a formal parameter of mode in (LRM 6.2), or
--       -  a loop parameter (LRM 5.5), or
-- 5. If a variable V named in the global definition of a procedure P
--    is exported, then neither V nor any of its subcomponents can occur
--    as an actual parameter of P (LRM 6.4 Rule 1), or
-- 6. If a variable V occurs in the global definition of a procedure
--    P, then neither V nor any of its subcomponents can occur as an
--    actual parameter of P where the corresponding formal parameter is
--    an exported variable (LRM 6.4 Rule 2), or
-- 7. If an entire variable V or a subcomponent of V occurs as an
--    actual parameter in a procedure call statement, and the
--    corresponding formal parameter is an exported variable, then
--    neither V or an overlapping subcomponent of V can occur as another
--    actual parameter in that statement. Two components are considered
--    to be overlapping if they are elements of the same array or are
--    the same component of a record (for example V.F and V.F) including
--    subcomponents of the component (for example V.F and V.F.P). Note
--    array elements are always considered to be overlapping and so, for
--    example, V.A(I).P and V.A(J).Q are considered as overlapping
--    (LRM 6.4 Rule 3).
-- 8. The types of Formal and Actual parameters are compatible.
-- 9. The procedure is callable at the point of call.
--10. Globals imported or exported by a procedure are visible at the point of
--    call.
--11. Procedure calls resulting in direct update of non-enclosing package
--    own variable generate a warning.
--12. After substitution of actuals-for-formals, the resulting information
--    flow relation is checked against the selected information flow policy.
--------------------------------------------------------------------------------

separate (Sem.CompUnit.WalkStatements)
procedure Wf_Proc_Call
  (Node           : in     STree.SyntaxNode;
   Scope          : in     Dictionary.Scopes;
   Table          : in out RefList.HashTable;
   Component_Data : in out ComponentManager.ComponentData)
is
   Proc_Sym                                    : Dictionary.Symbol;
   Arg_List_Node, Name_Node                    : STree.SyntaxNode;
   Dotted, Valid                               : Boolean;
   Actual_Parameter_List, Formal_Position_List : SimpleLists.SimpleList;
   Abstraction                                 : Dictionary.Abstractions := Dictionary.IsAbstract;
   -- ineffective, but removes spurious flowerrs

   subtype Param_Index is Integer range 1 .. ExaminerConstants.MaxProcCallParams;

   -- A Param_Info stores the sequence of items referenced in an actual parameter.  For an IN
   -- parameter it will be just the variables for that appear in the general expression
   -- that makes up the actual.  For OUT and IN OUT cases, we normally would expect a singleton
   -- element in the sequence because the actual must be a variable (note in this context that a
   -- record field is still a single variable because each field has its own symbol).  For all the
   -- above cases, the Seq field contains the only useful data and the Entire_Array_Sym is null.
   -- The special case occurs whn the actual parameter is an array element such as A(I).  Here the
   -- Seq field will contain both A and I (in a non-deterministic order); however, we need to know that
   -- the parameter is an array element so we can correct the flow analysis in BuilIORelation.  In this
   -- case, the Entire_Array_Sym will be set to A.
   type Param_Info is record
      Seq              : Natural;
      Entire_Array_Sym : Dictionary.Symbol;
   end record;
   type Param_Tables is array (Param_Index) of Param_Info;
   Param_Table : Param_Tables;

   -- The following variable gets set to the type that an actual parameter
   -- must be in a call to an inherited operation
   Tagged_Parameter_Sym : Dictionary.Symbol;
   -- and this is the type of the formal of the inherited operation
   Root_Parameter_Sym : Dictionary.Symbol;
   -- we need global access to the Prefix_Symbol (which gets set by Do_Dotted_Name)
   -- so that we can deal with "self substitutions" in PO calls.
   Prefix_Symbol : Dictionary.Symbol;

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

   function Tagged_Substitution_Required (Formal, Actual_Type, Root_Parameter_Sym : Dictionary.Symbol) return Boolean
   --# global in Dictionary.Dict;
   is
   begin
      return Dictionary.Types_Are_Equal
        (Left_Symbol        => Dictionary.GetType (Formal),
         Right_Symbol       => Root_Parameter_Sym,
         Full_Range_Subtype => False)
        and then Dictionary.IsAnExtensionOf (Root_Parameter_Sym, Actual_Type);
   end Tagged_Substitution_Required;

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

   procedure Add_Seq
     (Param_No         : in     Positive;
      Refs             : in     SeqAlgebra.Seq;
      Entire_Array_Sym : in     Dictionary.Symbol;
      Param_Table      : in out Param_Tables)
   -- see comment on type Param_Info for explanation of parameter Entire_Array_Sym
   --# derives Param_Table from *,
   --#                          Entire_Array_Sym,
   --#                          Param_No,
   --#                          Refs;
   is
   begin
      if Param_No > Param_Index'Last then
         SystemErrors.Fatal_Error (Sys_Err => SystemErrors.Too_Many_Params_In_Procedure_Call,
                                   Msg     => "");
      end if;
      Param_Table (Param_No).Seq              := SeqAlgebra.SeqToNatural (Refs);
      Param_Table (Param_No).Entire_Array_Sym := Entire_Array_Sym;
   end Add_Seq;

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

   procedure Build_IO_Relation
     (Node                                        : in     STree.SyntaxNode;
      Scope                                       : in     Dictionary.Scopes;
      Root_Parameter_Sym, Prefix_Symbol, Proc_Sym : in     Dictionary.Symbol;
      Param_Table                                 : in     Param_Tables;
      Abstraction                                 : in     Dictionary.Abstractions;
      Component_Data                              : in out ComponentManager.ComponentData;
      Table                                       : in out RefList.HashTable)
   --# global in     CommandLineData.Content;
   --#        in     ContextManager.Ops.Unit_Stack;
   --#        in     LexTokenManager.State;
   --#        in     STree.Table;
   --#        in out Dictionary.Dict;
   --#        in out ErrorHandler.Error_Context;
   --#        in out SPARK_IO.File_Sys;
   --#        in out Statistics.TableUsage;
   --#        in out TheHeap;
   --# derives Component_Data,
   --#         Dictionary.Dict,
   --#         Statistics.TableUsage,
   --#         Table,
   --#         TheHeap                    from *,
   --#                                         Abstraction,
   --#                                         Component_Data,
   --#                                         ContextManager.Ops.Unit_Stack,
   --#                                         Dictionary.Dict,
   --#                                         Node,
   --#                                         Param_Table,
   --#                                         Prefix_Symbol,
   --#                                         Proc_Sym,
   --#                                         Root_Parameter_Sym,
   --#                                         Table,
   --#                                         TheHeap &
   --#         ErrorHandler.Error_Context,
   --#         SPARK_IO.File_Sys          from Abstraction,
   --#                                         CommandLineData.Content,
   --#                                         Component_Data,
   --#                                         ContextManager.Ops.Unit_Stack,
   --#                                         Dictionary.Dict,
   --#                                         ErrorHandler.Error_Context,
   --#                                         LexTokenManager.State,
   --#                                         Node,
   --#                                         Param_Table,
   --#                                         Prefix_Symbol,
   --#                                         Proc_Sym,
   --#                                         Root_Parameter_Sym,
   --#                                         Scope,
   --#                                         SPARK_IO.File_Sys,
   --#                                         STree.Table,
   --#                                         Table,
   --#                                         TheHeap;
   --# pre Syntax_Node_Type (Node, STree.Table) = SP_Symbols.procedure_call_statement;
   is
      Export_It, Import_It   : Dictionary.Iterator;
      Import_Seq             : SeqAlgebra.Seq;
      Export_Sym, Import_Sym : Dictionary.Symbol;
      Param_No               : Positive;
      Actual_Sym             : Dictionary.Symbol;

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

      procedure Check_Relation_Info_Flow_Policy
        (Node_Pos    : in LexTokenManager.Token_Position;
         Scope       : in Dictionary.Scopes;
         The_Export  : in Dictionary.Symbol;
         The_Imports : in SeqAlgebra.Seq;
         The_Heap    : in Heap.HeapRecord)
      --# 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,
      --#                                         LexTokenManager.State,
      --#                                         Node_Pos,
      --#                                         Scope,
      --#                                         SPARK_IO.File_Sys,
      --#                                         The_Export,
      --#                                         The_Heap,
      --#                                         The_Imports;
      is
         Current_Member : SeqAlgebra.MemberOfSeq;
         The_Import_Sym : Dictionary.Symbol;
      begin
         Current_Member := SeqAlgebra.FirstMember (The_Heap, The_Imports);
         while not SeqAlgebra.IsNullMember (Current_Member) loop
            The_Import_Sym :=
              Dictionary.ConvertSymbolRef
              (ExaminerConstants.RefType (SeqAlgebra.Value_Of_Member (The_Heap => The_Heap,
                                                                      M        => Current_Member)));
            if Dictionary.RelationViolatesInfoFlowPolicy (The_Export, The_Import_Sym) then
               ErrorHandler.Dependency_Error
                 (Err_Type       => ErrorHandler.Policy_Violation,
                  Position       => Node_Pos,
                  Import_Var_Sym => The_Import_Sym,
                  Export_Var_Sym => The_Export,
                  Scope          => Scope);
            end if;
            Current_Member := SeqAlgebra.NextMember (The_Heap, Current_Member);
         end loop;
      end Check_Relation_Info_Flow_Policy;

   begin -- Build_IO_Relation
      Export_It := Dictionary.FirstExport (Abstraction, Proc_Sym);
      if Dictionary.IsNullIterator (Export_It) then
         RefList.AddNullRelation (Table, TheHeap, Node);
      else
         while not Dictionary.IsNullIterator (Export_It) loop
            --# assert Syntax_Node_Type (Node, STree.Table) = SP_Symbols.procedure_call_statement;
            Export_Sym := Dictionary.CurrentSymbol (Export_It);
            SeqAlgebra.CreateSeq (TheHeap, Import_Seq);
            Import_It := Dictionary.FirstDependency (Abstraction, Proc_Sym, Export_Sym);
            while not Dictionary.IsNullIterator (Import_It) loop
               --# assert Syntax_Node_Type (Node, STree.Table) = SP_Symbols.procedure_call_statement;
               Import_Sym := Dictionary.CurrentSymbol (Import_It);
               if Dictionary.Is_Global_Variable (Abstraction, Proc_Sym, Import_Sym) then
                  SeqAlgebra.AddMember
                    (TheHeap,
                     Import_Seq,
                     Natural (Dictionary.SymbolRef
                                (Substitute_Protected_Type_Self_Reference (Sym           => Import_Sym,
                                                                           Prefix_Symbol => Prefix_Symbol))));
               else
                  Param_No := Dictionary.GetSubprogramParameterNumber (Import_Sym);
                  if Param_No <= Param_Index'Last and then Param_Table (Param_No).Seq /= 0 then
                     SeqAlgebra.AugmentSeq (TheHeap, Import_Seq, SeqAlgebra.NaturalToSeq (Param_Table (Param_No).Seq));
                  end if;
               end if;
               Import_It := Dictionary.NextSymbol (Import_It);
            end loop;

            -- now substitue export if necessary
            if Dictionary.Is_Global_Variable (Abstraction, Proc_Sym, Export_Sym) then
               Export_Sym := Substitute_Protected_Type_Self_Reference (Sym           => Export_Sym,
                                                                       Prefix_Symbol => Prefix_Symbol);
            else -- parameter
               Param_No := Dictionary.GetSubprogramParameterNumber (Export_Sym);
               if Param_No <= Param_Index'Last
                 and then Param_Table (Param_No).Seq /= 0
                 and then not SeqAlgebra.IsEmptySeq (TheHeap, SeqAlgebra.NaturalToSeq (Param_Table (Param_No).Seq)) then
                  -- we have an export to process.
                  -- There are two cases:
                  -- (1) It's NOT an array element.  In which case we know that the export is a single
                  --     variable symbol and must be the sole member of the set of vars associated with the
                  --     current parameter; or
                  -- (2) It is an array element in which case the set of vars includes both the array and the
                  --     indexing expressions.

                  -- We can distinguish these case because the field Entire_Array_Sym
                  --     associated with the current parameter will be null in case 1 and non null in case 2 .

                  if Dictionary.Is_Null_Symbol (Param_Table (Param_No).Entire_Array_Sym) then
                     -- case 1
                     -- extract singleton from set
                     Actual_Sym :=
                       Dictionary.ConvertSymbolRef
                       (ExaminerConstants.RefType (SeqAlgebra.Value_Of_Member
                                                     (The_Heap => TheHeap,
                                                      M        => SeqAlgebra.FirstMember
                                                        (TheHeap,
                                                         SeqAlgebra.NaturalToSeq (Param_Table (Param_No).Seq)))));
                  else
                     -- case 2
                     -- use array symbol stored especially for this case
                     Actual_Sym := Param_Table (Param_No).Entire_Array_Sym;
                     -- Add a self reference here because the actual parameter is an array element.
                     -- Necessary because, for example, SetToZero (A (1));, must derives A from A.
                     -- Secondly, as well as adding self, add all things the selected array
                     -- element depends on (e.g. variables controlling the selected element).
                     -- The array and all the things it depends on are in the Param_Table, thus:
                     SeqAlgebra.AugmentSeq (TheHeap, Import_Seq, SeqAlgebra.NaturalToSeq (Param_Table (Param_No).Seq));
                  end if;

                  if Tagged_Substitution_Required
                    (Formal             => Export_Sym,
                     Actual_Type        => Dictionary.GetType (Actual_Sym),
                     Root_Parameter_Sym => Root_Parameter_Sym) then
                     -- before we can convert the actual parameter to the appropriate root type
                     -- we must add all its subcomponents to the Dictionary and ComponentManager
                     Add_Record_Sub_Components
                       (Record_Var_Sym  => Actual_Sym,
                        Record_Type_Sym => Dictionary.GetType (Actual_Sym),
                        Component_Data  => Component_Data,
                        The_Heap        => TheHeap);
                     Export_Sym := Convert_Tagged_Actual (Actual               => Actual_Sym,
                                                          Tagged_Parameter_Sym => Root_Parameter_Sym);
                  else
                     Export_Sym := Actual_Sym;
                  end if;
               end if;
            end if;

            RefList.AddRelation (Table, TheHeap, Node, Export_Sym, Import_Seq);

            Check_Relation_Info_Flow_Policy
              (Node_Pos    => Node_Position (Node => Node),
               Scope       => Scope,
               The_Export  => Export_Sym,
               The_Imports => Import_Seq,
               The_Heap    => TheHeap);

            Export_It := Dictionary.NextSymbol (Export_It);
         end loop;
      end if;
   end Build_IO_Relation;

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

   function Actual_Parameter_At (Position              : Positive;
                                 Actual_Parameter_List : SimpleLists.SimpleList) return Dictionary.Symbol is
      Ok  : Boolean;
      Val : Natural;
      Sym : Dictionary.Symbol;
   begin
      SimpleLists.GetItem (Actual_Parameter_List, Position,
                           --to get
                           Val, Ok);
      if Ok then
         Sym := Dictionary.ConvertSymbolRef (ExaminerConstants.RefType (Val));
      else
         Sym := Dictionary.NullSymbol;
      end if;
      return Sym;
   end Actual_Parameter_At;

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

   procedure Check_Procedure_Name
     (Node                                                              : in     STree.SyntaxNode;
      Scope                                                             : in     Dictionary.Scopes;
      Root_Parameter_Sym, Prefix_Symbol, Proc_Sym, Tagged_Parameter_Sym :    out Dictionary.Symbol;
      Name_Node                                                         :    out STree.SyntaxNode;
      Dotted, Valid                                                     :    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,
   --#         Name_Node,
   --#         Prefix_Symbol,
   --#         Proc_Sym,
   --#         Root_Parameter_Sym,
   --#         STree.Table,
   --#         Tagged_Parameter_Sym,
   --#         Valid                      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.procedure_call_statement;
   --# post Syntax_Node_Type (Name_Node, STree.Table) = SP_Symbols.name and
   --#   (Dictionary.Is_Null_Symbol (Proc_Sym) or Dictionary.IsProcedure (Proc_Sym, Dictionary.Dict)) and
   --#   STree.Table = STree.Table~;
   is
      Ident_Node, Prefix_Node : STree.SyntaxNode;

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

      procedure Check_Symbol
        (Node                                               : in     STree.SyntaxNode;
         Sym                                                : in     Dictionary.Symbol;
         Prefix                                             : in     LexTokenManager.Lex_String;
         Name                                               : in     LexTokenManager.Lex_String;
         Prefix_Sym                                         : in     Dictionary.Symbol;
         Scope                                              : in     Dictionary.Scopes;
         Root_Parameter_Sym, Proc_Sym, Tagged_Parameter_Sym :    out Dictionary.Symbol;
         Valid                                              :    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 ErrorHandler.Error_Context,
      --#         SPARK_IO.File_Sys          from CommandLineData.Content,
      --#                                         Dictionary.Dict,
      --#                                         ErrorHandler.Error_Context,
      --#                                         LexTokenManager.State,
      --#                                         Name,
      --#                                         Node,
      --#                                         Prefix,
      --#                                         Prefix_Sym,
      --#                                         Scope,
      --#                                         SPARK_IO.File_Sys,
      --#                                         STree.Table,
      --#                                         Sym &
      --#         Proc_Sym,
      --#         Root_Parameter_Sym,
      --#         Tagged_Parameter_Sym,
      --#         Valid                      from CommandLineData.Content,
      --#                                         Dictionary.Dict,
      --#                                         LexTokenManager.State,
      --#                                         Name,
      --#                                         Prefix_Sym,
      --#                                         Scope,
      --#                                         Sym &
      --#         STree.Table                from *,
      --#                                         Dictionary.Dict,
      --#                                         Node,
      --#                                         Sym;
      --# pre Syntax_Node_Type (Node, STree.Table) = SP_Symbols.identifier;
      --# post (Dictionary.Is_Null_Symbol (Proc_Sym) or
      --#         Dictionary.IsProcedure (Proc_Sym, Dictionary.Dict)) and
      --#   STree.Table = STree.Table~;
      is
         Proc_Sym_Local : Dictionary.Symbol;
         Sym2           : Dictionary.Symbol;
      begin
         Tagged_Parameter_Sym := Dictionary.NullSymbol;
         Root_Parameter_Sym   := Dictionary.NullSymbol;
         Proc_Sym_Local       := Sym;
         if Dictionary.Is_Null_Symbol (Proc_Sym_Local) then -- not declared

            -- If we have failed to find an operation by here then we
            -- need to look for an inherited one of the same name in
            -- some root package from which tagged types may have been
            -- extended.
            --
            -- This search is only made if the prefix is a package.  If it is a protected
            -- object then there is no question of there being any inherited operations to find.
            -- We only need to search if there is no prefix or the prefix is a package
            if Dictionary.Is_Null_Symbol (Prefix_Sym) or else Dictionary.IsPackage (Prefix_Sym) then
               Dictionary.SearchForInheritedOperations
                 (Name             => Name,
                  Scope            => Scope,
                  Prefix           => Prefix_Sym,
                  Context          => Dictionary.ProgramContext,
                  OpSym            => Proc_Sym_Local,
                  ActualTaggedType => Tagged_Parameter_Sym);
            end if;

            if Dictionary.Is_Null_Symbol (Proc_Sym_Local) then
               -- we still didn't find anything
               Valid    := False;
               Proc_Sym := Dictionary.NullSymbol;
               -- if "Prefix.Name" is NOT visible, but "Name" is visible AND it has been renamed,
               -- then issue the more helpful semantic error 419, otherwise error 143.
               Sym2 :=
                 Dictionary.LookupItem
                 (Name              => Name,
                  Scope             => Scope,
                  Context           => Dictionary.ProgramContext,
                  Full_Package_Name => False);
               if not Dictionary.Is_Null_Symbol (Sym2) and then Dictionary.Is_Renamed (Subprogram => Sym2,
                                                                                       Scope      => Scope) then
                  ErrorHandler.Semantic_Error2
                    (Err_Num   => 419,
                     Reference => ErrorHandler.No_Reference,
                     Position  => Node_Position (Node => Node),
                     Id_Str1   => Name,
                     Id_Str2   => Prefix);
               else
                  ErrorHandler.Semantic_Error2
                    (Err_Num   => 143,
                     Reference => ErrorHandler.No_Reference,
                     Position  => Node_Position (Node => Node),
                     Id_Str1   => Node_Lex_String (Node => Node),
                     Id_Str2   => Prefix);
               end if;
            else
               -- the inherit search did find something
               if Dictionary.IsProcedure (Proc_Sym_Local) then
                  Valid              := True;
                  Proc_Sym           := Proc_Sym_Local;
                  Root_Parameter_Sym := Dictionary.GetSubprogramControllingType (Proc_Sym_Local);
               else -- found but not a procedure
                  Valid    := False;
                  Proc_Sym := Dictionary.NullSymbol;
               end if;
            end if;
         elsif Dictionary.IsProcedure (Proc_Sym_Local) then -- ok
            if Dictionary.Is_Generic_Subprogram (The_Symbol => Proc_Sym_Local) then
               Valid    := False;
               Proc_Sym := Dictionary.NullSymbol;
               ErrorHandler.Semantic_Error
                 (Err_Num   => 654,
                  Reference => ErrorHandler.No_Reference,
                  Position  => Node_Position (Node => Node),
                  Id_Str    => Node_Lex_String (Node => Node));
            else
               Valid := True;
               STree.Set_Node_Lex_String (Sym  => Sym,
                                          Node => Node);
               Proc_Sym           := Proc_Sym_Local;
               Root_Parameter_Sym := Dictionary.GetSubprogramControllingType (Proc_Sym_Local);
            end if;
         else -- there but not a procedure
            Valid    := False;
            Proc_Sym := Dictionary.NullSymbol;
            ErrorHandler.Semantic_Error
              (Err_Num   => 7,
               Reference => ErrorHandler.No_Reference,
               Position  => Node_Position (Node => Node),
               Id_Str    => Node_Lex_String (Node => Node));
         end if;
      end Check_Symbol;

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

      procedure Do_Simple_Name
        (Ident_Node                                         : in     STree.SyntaxNode;
         Scope                                              : in     Dictionary.Scopes;
         Root_Parameter_Sym, Proc_Sym, Tagged_Parameter_Sym :    out Dictionary.Symbol;
         Name_Node                                          :    out STree.SyntaxNode;
         Valid                                              :    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 ErrorHandler.Error_Context,
      --#         SPARK_IO.File_Sys          from CommandLineData.Content,
      --#                                         Dictionary.Dict,
      --#                                         ErrorHandler.Error_Context,
      --#                                         Ident_Node,
      --#                                         LexTokenManager.State,
      --#                                         Scope,
      --#                                         SPARK_IO.File_Sys,
      --#                                         STree.Table &
      --#         Name_Node,
      --#         Proc_Sym,
      --#         Root_Parameter_Sym,
      --#         STree.Table,
      --#         Tagged_Parameter_Sym,
      --#         Valid                      from CommandLineData.Content,
      --#                                         Dictionary.Dict,
      --#                                         Ident_Node,
      --#                                         LexTokenManager.State,
      --#                                         Scope,
      --#                                         STree.Table;
      --# pre Syntax_Node_Type (Ident_Node, STree.Table) = SP_Symbols.identifier;
      --# post Syntax_Node_Type (Name_Node, STree.Table) = SP_Symbols.name and
      --#   (Dictionary.Is_Null_Symbol (Proc_Sym) or Dictionary.IsProcedure (Proc_Sym, Dictionary.Dict)) and
      --#   STree.Table = STree.Table~;
      is
      begin
         Check_Symbol
           (Node                 => Ident_Node,
            Sym                  => Dictionary.LookupItem
              (Name              => Node_Lex_String (Node => Ident_Node),
               Scope             => Scope,
               Context           => Dictionary.ProgramContext,
               Full_Package_Name => False),
            Prefix               => LexTokenManager.Null_String,
            Name                 => Node_Lex_String (Node => Ident_Node),
            Prefix_Sym           => Dictionary.NullSymbol,
            Scope                => Scope,
            Root_Parameter_Sym   => Root_Parameter_Sym,
            Proc_Sym             => Proc_Sym,
            Tagged_Parameter_Sym => Tagged_Parameter_Sym,
            Valid                => Valid);
         Name_Node := Parent_Node (Current_Node => Parent_Node (Current_Node => Ident_Node));
         -- ASSUME Name_Node = name
         SystemErrors.RT_Assert
           (C       => Syntax_Node_Type (Node => Name_Node) = SP_Symbols.name,
            Sys_Err => SystemErrors.Invalid_Syntax_Tree,
            Msg     => "Expect Name_Node = name in Do_Simple_Name");
      end Do_Simple_Name;

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

      procedure Do_Dotted_Name
        (Ident_Node                                                        : in     STree.SyntaxNode;
         Prefix                                                            : in     STree.SyntaxNode;
         Scope                                                             : in     Dictionary.Scopes;
         Root_Parameter_Sym, Prefix_Symbol, Proc_Sym, Tagged_Parameter_Sym :    out Dictionary.Symbol;
         Name_Node                                                         :    out STree.SyntaxNode;
         Valid                                                             :    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 ErrorHandler.Error_Context,
      --#         SPARK_IO.File_Sys          from CommandLineData.Content,
      --#                                         Dictionary.Dict,
      --#                                         ErrorHandler.Error_Context,
      --#                                         Ident_Node,
      --#                                         LexTokenManager.State,
      --#                                         Prefix,
      --#                                         Scope,
      --#                                         SPARK_IO.File_Sys,
      --#                                         STree.Table &
      --#         Name_Node,
      --#         Prefix_Symbol,
      --#         Proc_Sym,
      --#         Root_Parameter_Sym,
      --#         STree.Table,
      --#         Tagged_Parameter_Sym,
      --#         Valid                      from CommandLineData.Content,
      --#                                         Dictionary.Dict,
      --#                                         Ident_Node,
      --#                                         LexTokenManager.State,
      --#                                         Prefix,
      --#                                         Scope,
      --#                                         STree.Table;
      --# pre Syntax_Node_Type (Ident_Node, STree.Table) = SP_Symbols.identifier and
      --#   Syntax_Node_Type (Prefix, STree.Table) = SP_Symbols.prefix;
      --# post Syntax_Node_Type (Name_Node, STree.Table) = SP_Symbols.name and
      --#   (Dictionary.Is_Null_Symbol (Proc_Sym) or Dictionary.IsProcedure (Proc_Sym, Dictionary.Dict)) and
      --#   STree.Table = STree.Table~;
      is
         Sym              : Dictionary.Symbol;
         Ident_Node_Local : STree.SyntaxNode;
         Ident_Node_Prev  : STree.SyntaxNode;
         Prefix_Local     : STree.SyntaxNode;
         Prefix_OK        : Boolean;
      begin
         -- on entry, Ident_Node points at the first identifier in the prefix so if the proc
         -- called is P.C.K then Ident_Node points at P

         Root_Parameter_Sym   := Dictionary.NullSymbol; -- in case path taken misses Check_Symbol
         Prefix_Symbol        := Dictionary.NullSymbol;
         Proc_Sym             := Dictionary.NullSymbol;
         Tagged_Parameter_Sym := Dictionary.NullSymbol; -- in case path taken misses Check_Symbol

         Ident_Node_Local := Ident_Node;
         -- ASSUME Ident_Node_Local = identifier

         Prefix_Local := Prefix;
         -- ASSUME Prefix_Local = prefix

         -- look up start of prefix
         Sym :=
           Dictionary.LookupItem
           (Name              => Node_Lex_String (Node => Ident_Node_Local),
            Scope             => Scope,
            Context           => Dictionary.ProgramContext,
            Full_Package_Name => False);
         loop -- loop over multiple prefixes

            --# assert Syntax_Node_Type (Ident_Node_Local, STree.Table) = SP_Symbols.identifier and
            --#   Syntax_Node_Type (Prefix_Local, STree.Table) = SP_Symbols.prefix and
            --#   (Dictionary.Is_Null_Symbol (Proc_Sym) or Dictionary.IsProcedure (Proc_Sym, Dictionary.Dict)) and
            --#   STree.Table = STree.Table~;
            if Dictionary.Is_Null_Symbol (Sym) then -- not found
               Valid := False;
               ErrorHandler.Semantic_Error
                 (Err_Num   => 142,
                  Reference => ErrorHandler.No_Reference,
                  Position  => Node_Position (Node => Ident_Node_Local),
                  Id_Str    => Node_Lex_String (Node => Ident_Node_Local));
               exit;
            end if;

            if not (Dictionary.IsPackage (Sym)
                      or else (Dictionary.IsObject (Sym) and then Dictionary.IsProtectedTypeMark (Dictionary.GetType (Sym)))) then
               -- not a valid prefix
               Valid := False;
               ErrorHandler.Semantic_Error
                 (Err_Num   => 9,
                  Reference => ErrorHandler.No_Reference,
                  Position  => Node_Position (Node => Ident_Node_Local),
                  Id_Str    => Node_Lex_String (Node => Ident_Node_Local));
               exit;
            end if;

            Check_Package_Prefix
              (Node_Pos => Node_Position (Node => Ident_Node_Local),
               Pack_Sym => Sym,
               Scope    => Scope,
               OK       => Prefix_OK);

            if not Prefix_OK then
               Valid := False;
               exit;
            end if;
            STree.Set_Node_Lex_String (Sym  => Sym,
                                       Node => Ident_Node_Local);
            Ident_Node_Prev := Ident_Node_Local;
            -- ASSUME Ident_Node_Prev = identifier

            -- move on to next identifier in prefix chain
            Ident_Node_Local :=
              Child_Node (Current_Node => Child_Node (Current_Node => Next_Sibling (Current_Node => Prefix_Local)));
            -- ASSUME Ident_Node_Local = identifier
            SystemErrors.RT_Assert
              (C       => Syntax_Node_Type (Node => Ident_Node_Local) = SP_Symbols.identifier,
               Sys_Err => SystemErrors.Invalid_Syntax_Tree,
               Msg     => "Expect Ident_Node_Local = identifier in Do_Dotted_Name");
            Prefix_Local :=
              Parent_Node (Current_Node => Parent_Node (Current_Node => Parent_Node (Current_Node => Prefix_Local)));
            while Syntax_Node_Type (Node => Prefix_Local) = SP_Symbols.name loop
               --# assert Syntax_Node_Type (Ident_Node_Local, STree.Table) = SP_Symbols.identifier and
               --#   Syntax_Node_Type (Prefix_Local, STree.Table) = SP_Symbols.name and
               --#   Syntax_Node_Type (Ident_Node_Prev, STree.Table) = SP_Symbols.identifier and
               --#   (Dictionary.Is_Null_Symbol (Proc_Sym) or Dictionary.IsProcedure (Proc_Sym, Dictionary.Dict)) and
               --#   STree.Table = STree.Table~;
               Prefix_Local := Parent_Node (Current_Node => Prefix_Local);
            end loop;
            -- ASSUME Prefix_Local = prefix OR procedure_call_statement
            if Syntax_Node_Type (Node => Prefix_Local) = SP_Symbols.procedure_call_statement then
               -- ASSUME Prefix_Local = procedure_call_statement
               -- store package prefix in case we have to search for inherited ops in it
               Prefix_Symbol := Sym;
               -- then check procedure name
               Check_Symbol
                 (Node                 => Ident_Node_Local,
                  Sym                  => Dictionary.LookupSelectedItem
                    (Prefix   => Sym,
                     Selector => Node_Lex_String (Node => Ident_Node_Local),
                     Scope    => Scope,
                     Context  => Dictionary.ProgramContext),
                  Prefix               => Node_Lex_String (Node => Ident_Node_Prev),
                  Name                 => Node_Lex_String (Node => Ident_Node_Local),
                  Prefix_Sym           => Prefix_Symbol,
                  Scope                => Scope,
                  Root_Parameter_Sym   => Root_Parameter_Sym,
                  Proc_Sym             => Proc_Sym,
                  Tagged_Parameter_Sym => Tagged_Parameter_Sym,
                  Valid                => Valid);
               exit;
            end if;
            -- elsif Syntax_Node_Type (Node => Prefix_Local) /= SP_Symbols.prefix then
            SystemErrors.RT_Assert
              (C       => Syntax_Node_Type (Node => Prefix_Local) = SP_Symbols.prefix,
               Sys_Err => SystemErrors.Invalid_Syntax_Tree,
               Msg     => "Expect Prefix_Local = prefix OR procedure_call_statement in Do_Dotted_Name");
            -- end if;

            -- otherwise we have another prefix to deal with
            Sym :=
              Dictionary.LookupSelectedItem
              (Prefix   => Sym,
               Selector => Node_Lex_String (Node => Ident_Node_Local),
               Scope    => Scope,
               Context  => Dictionary.ProgramContext);
         end loop;
         Name_Node := Parent_Node (Current_Node => Parent_Node (Current_Node => Ident_Node_Local));
         -- ASSUME Name_Node = name OR selector
         if Syntax_Node_Type (Node => Name_Node) = SP_Symbols.selector then
            Name_Node := Parent_Node (Current_Node => Parent_Node (Current_Node => Name_Node));
         elsif Syntax_Node_Type (Node => Name_Node) /= SP_Symbols.name then
            SystemErrors.Fatal_Error
              (Sys_Err => SystemErrors.Invalid_Syntax_Tree,
               Msg     => "Expect Name_Node = name OR selector in Do_Dotted_Name");
         end if;
         -- ASSUME Name_Node = name
         SystemErrors.RT_Assert
           (C       => Syntax_Node_Type (Node => Name_Node) = SP_Symbols.name,
            Sys_Err => SystemErrors.Invalid_Syntax_Tree,
            Msg     => "Expect Name_Node = name in Do_Dotted_Name");
      end Do_Dotted_Name;

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

      function Really_Has_Package_Prefix (Proc_Sym : Dictionary.Symbol;
                                          Scope    : Dictionary.Scopes) return Boolean
      --# global in Dictionary.Dict;
      is
         Declared_Scope  : Dictionary.Scopes;
         Declared_Region : Dictionary.Symbol;
         Calling_Region  : Dictionary.Symbol;
         Result          : Boolean := False;
      begin
         -- Before protected operations, we knew syntactically whether a subprogram had a
         -- package prefix on it.  Now we don't because even a local protected operation call
         -- is prefixed with the protected object name.  We need to distinguish between
         -- PO.Op which is "not dotted" and P.PO.Op which is.

         if not Dictionary.Is_Null_Symbol (Proc_Sym) then
            -- Get Region in which caller is declared
            Calling_Region := Dictionary.GetEnclosingPackage (Scope);

            -- get scope where called subprogram is declared
            Declared_Scope  := Dictionary.GetScope (Proc_Sym);
            Declared_Region := Dictionary.GetRegion (Declared_Scope);
            if Dictionary.IsProtectedType (Declared_Region) then
               -- we want the scope where the protected type is declared
               Declared_Scope := Dictionary.GetScope (Declared_Region);
            end if;

            -- function is true if declared region and calling region are different
            Result :=
              not Dictionary.Packages_Are_Equal
              (Left_Symbol  => Dictionary.GetRegion (Declared_Scope),
               Right_Symbol => Calling_Region);
         end if;
         return Result;
      end Really_Has_Package_Prefix;

   begin -- Check_Procedure_Name
      Ident_Node := Last_Child_Of (Start_Node => Node);
      -- ASSUME Ident_Node = identifier
      SystemErrors.RT_Assert
        (C       => Syntax_Node_Type (Node => Ident_Node) = SP_Symbols.identifier,
         Sys_Err => SystemErrors.Invalid_Syntax_Tree,
         Msg     => "Expect Ident_Node = identifier in Check_Procedure_Name");

      Prefix_Symbol := Dictionary.NullSymbol;
      Prefix_Node   := Parent_Node (Current_Node => Parent_Node (Current_Node => Parent_Node (Current_Node => Ident_Node)));
      -- ASSUME Prefix_Node = name OR prefix OR procedure_call_statement
      SystemErrors.RT_Assert
        (C       => Syntax_Node_Type (Node => Prefix_Node) = SP_Symbols.name
           or else Syntax_Node_Type (Node => Prefix_Node) = SP_Symbols.prefix
           or else Syntax_Node_Type (Node => Prefix_Node) = SP_Symbols.procedure_call_statement,
         Sys_Err => SystemErrors.Invalid_Syntax_Tree,
         Msg     => "Expect Prefix_Node = name OR prefix OR procedure_call_statement in Check_Procedure_Name");
      while Syntax_Node_Type (Node => Prefix_Node) = SP_Symbols.name loop
         --# assert Syntax_Node_Type (Ident_Node, STree.Table) = SP_Symbols.identifier and
         --#   Syntax_Node_Type (Prefix_Node, STree.Table) = SP_Symbols.name and
         --#   STree.Table = STree.Table~;
         Prefix_Node := Parent_Node (Current_Node => Prefix_Node);
         -- ASSUME Prefix_Node = name OR prefix OR procedure_call_statement
         SystemErrors.RT_Assert
           (C       => Syntax_Node_Type (Node => Prefix_Node) = SP_Symbols.name
              or else Syntax_Node_Type (Node => Prefix_Node) = SP_Symbols.prefix
              or else Syntax_Node_Type (Node => Prefix_Node) = SP_Symbols.procedure_call_statement,
            Sys_Err => SystemErrors.Invalid_Syntax_Tree,
            Msg     => "Expect Prefix_Node = name OR prefix OR procedure_call_statement in Check_Procedure_Name");
      end loop;
      -- ASSUME Prefix_Node = prefix OR procedure_call_statement
      if Syntax_Node_Type (Node => Prefix_Node) = SP_Symbols.prefix then
         -- ASSUME Prefix_Node = prefix
         Do_Dotted_Name
           (Ident_Node           => Ident_Node,
            Prefix               => Prefix_Node,
            Scope                => Scope,
            Root_Parameter_Sym   => Root_Parameter_Sym,
            Prefix_Symbol        => Prefix_Symbol,
            Proc_Sym             => Proc_Sym,
            Tagged_Parameter_Sym => Tagged_Parameter_Sym,
            Name_Node            => Name_Node,
            Valid                => Valid);
         Dotted := Really_Has_Package_Prefix (Proc_Sym => Proc_Sym,
                                              Scope    => Scope);
      elsif Syntax_Node_Type (Node => Prefix_Node) = SP_Symbols.procedure_call_statement then
         -- ASSUME Prefix_Node = procedure_call_statement
         Do_Simple_Name
           (Ident_Node           => Ident_Node,
            Scope                => Scope,
            Root_Parameter_Sym   => Root_Parameter_Sym,
            Proc_Sym             => Proc_Sym,
            Tagged_Parameter_Sym => Tagged_Parameter_Sym,
            Name_Node            => Name_Node,
            Valid                => Valid);
         Dotted := False;
      else
         Root_Parameter_Sym   := Dictionary.NullSymbol;
         Proc_Sym             := Dictionary.NullSymbol;
         Tagged_Parameter_Sym := Dictionary.NullSymbol;
         Name_Node            := STree.NullNode;
         Dotted               := False;
         Valid                := False;
      end if;
   end Check_Procedure_Name;

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

   procedure Check_Globals_Are_Visible
     (Node_Pos                : in LexTokenManager.Token_Position;
      Prefix_Symbol, Proc_Sym : in Dictionary.Symbol;
      Scope                   : in Dictionary.Scopes;
      Abstraction             : in Dictionary.Abstractions)
   --# 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,
   --#                                         ErrorHandler.Error_Context,
   --#                                         LexTokenManager.State,
   --#                                         Node_Pos,
   --#                                         Prefix_Symbol,
   --#                                         Proc_Sym,
   --#                                         Scope,
   --#                                         SPARK_IO.File_Sys;
   is
      It                    : Dictionary.Iterator;
      Calling_Sym, Glob_Sym : Dictionary.Symbol;
      Calling_Abstraction   : Dictionary.Abstractions;

      function Is_Local_Variable (Calling_Sym, Glob_Sym : Dictionary.Symbol) return Boolean
      --# global in Dictionary.Dict;
      is
      begin
         return Dictionary.GetRegion (Dictionary.GetScope (Glob_Sym)) = Calling_Sym;
      end Is_Local_Variable;

      function Is_Own_Var_Of_Embedded_Package (Calling_Sym, Glob_Sym : Dictionary.Symbol) return Boolean
      --# global in Dictionary.Dict;
      is
      begin
         return Dictionary.IsOwnVariable (Glob_Sym)
           and then Dictionary.GetScope (Dictionary.GetOwner (Glob_Sym)) =
           Dictionary.Set_Visibility (The_Visibility => Dictionary.Local,
                                      The_Unit       => Calling_Sym);
      end Is_Own_Var_Of_Embedded_Package;

      -- this procedure can be extended to deal with error case of vars which
      -- are exported by a called procedure but not exported by calling procedure

      procedure Check_Illegal_Update
        (Node_Pos                         : in LexTokenManager.Token_Position;
         Calling_Abstraction, Abstraction : in Dictionary.Abstractions;
         Calling_Sym, Proc_Sym, Glob_Sym  : in Dictionary.Symbol)
      --# 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,
      --#                                         Calling_Abstraction,
      --#                                         Calling_Sym,
      --#                                         CommandLineData.Content,
      --#                                         Dictionary.Dict,
      --#                                         ErrorHandler.Error_Context,
      --#                                         Glob_Sym,
      --#                                         LexTokenManager.State,
      --#                                         Node_Pos,
      --#                                         Proc_Sym,
      --#                                         SPARK_IO.File_Sys;
      is
      begin
         if Dictionary.IsFunction (Calling_Sym)
           and then Dictionary.Is_Global_Variable (Calling_Abstraction, Calling_Sym, Glob_Sym)
           and then Dictionary.IsExport (Abstraction, Proc_Sym, Glob_Sym)
           and then not
           -- if the global is a mode in own variable then the "exporting" is only
           -- a modelling artefact that we can ignore
           (Dictionary.GetOwnVariableOrConstituentMode (Glob_Sym) = Dictionary.InMode) then
            ErrorHandler.Semantic_Error
              (Err_Num   => 328,
               Reference => ErrorHandler.No_Reference,
               Position  => Node_Pos,
               Id_Str    => Dictionary.GetSimpleName (Glob_Sym));
         end if;
      end Check_Illegal_Update;

   begin -- Check_Globals_Are_Visible
      Calling_Sym         := Dictionary.GetEnclosingCompilationUnit (Scope);
      Calling_Abstraction := Dictionary.GetAbstraction (Calling_Sym, Scope);
      It                  := Dictionary.FirstGlobalVariable (Abstraction, Proc_Sym);
      while not Dictionary.IsNullIterator (It) loop
         Glob_Sym :=
           Substitute_Protected_Type_Self_Reference (Sym           => Dictionary.CurrentSymbol (It),
                                                     Prefix_Symbol => Prefix_Symbol);

         if not Dictionary.Is_Global_Variable (Calling_Abstraction, Calling_Sym, Glob_Sym)
           and then not Dictionary.IsFormalParameter (Calling_Sym, Glob_Sym)
           and then not Is_Local_Variable (Calling_Sym => Calling_Sym,
                                           Glob_Sym    => Glob_Sym)
           and then not Is_Own_Var_Of_Embedded_Package (Calling_Sym => Calling_Sym,
                                                        Glob_Sym    => Glob_Sym)
           and then not Dictionary.Is_Null_Variable (Glob_Sym) then
            -- null variable always deemed visible
            if Dictionary.IsImport (Abstraction, Proc_Sym, Glob_Sym)
              and then Dictionary.GetOwnVariableOrConstituentMode (Glob_Sym) /= Dictionary.OutMode then
               ErrorHandler.Semantic_Error_Sym
                 (Err_Num   => 25,
                  Reference => ErrorHandler.No_Reference,
                  Position  => Node_Pos,
                  Sym       => Glob_Sym,
                  Scope     => Scope);
            end if;
            if Dictionary.IsExport (Abstraction, Proc_Sym, Glob_Sym)
              and then Dictionary.GetOwnVariableOrConstituentMode (Glob_Sym) /= Dictionary.InMode then
               ErrorHandler.Semantic_Error_Sym
                 (Err_Num   => 24,
                  Reference => ErrorHandler.No_Reference,
                  Position  => Node_Pos,
                  Sym       => Glob_Sym,
                  Scope     => Scope);
            end if;
         end if;

         Check_Illegal_Update
           (Node_Pos            => Node_Pos,
            Calling_Abstraction => Calling_Abstraction,
            Abstraction         => Abstraction,
            Calling_Sym         => Calling_Sym,
            Proc_Sym            => Proc_Sym,
            Glob_Sym            => Glob_Sym);

         It := Dictionary.NextSymbol (It);
      end loop;
   end Check_Globals_Are_Visible;

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

   procedure Check_Actual
     (Root_Parameter_Sym, Proc_Sym, Formal_Sym, Tagged_Parameter_Sym : in     Dictionary.Symbol;
      Formal_Pos                                                     : in     Positive;
      Actual_Node                                                    : in     STree.SyntaxNode;
      Ref_Var_Param                                                  : in     SeqAlgebra.Seq;
      Abstraction                                                    : in     Dictionary.Abstractions;
      Scope                                                          : in     Dictionary.Scopes;
      Actual_Parameter_List, Formal_Position_List                    : in out SimpleLists.SimpleList;
      Component_Data                                                 : in out ComponentManager.ComponentData;
      Entire_Array_Sym                                               :    out Dictionary.Symbol)
   --# global in     CommandLineData.Content;
   --#        in     ContextManager.Ops.File_Heap;
   --#        in     ContextManager.Ops.Unit_Heap;
   --#        in     ContextManager.Ops.Unit_Stack;
   --#        in out Aggregate_Stack.State;
   --#        in out Dictionary.Dict;
   --#        in out ErrorHandler.Error_Context;
   --#        in out LexTokenManager.State;
   --#        in out SLI.State;
   --#        in out SPARK_IO.File_Sys;
   --#        in out Statistics.TableUsage;
   --#        in out STree.Table;
   --#        in out TheHeap;
   --# derives Actual_Parameter_List,
   --#         Aggregate_Stack.State,
   --#         LexTokenManager.State,
   --#         STree.Table                from *,
   --#                                         Abstraction,
   --#                                         Actual_Node,
   --#                                         CommandLineData.Content,
   --#                                         Component_Data,
   --#                                         ContextManager.Ops.Unit_Stack,
   --#                                         Dictionary.Dict,
   --#                                         Formal_Sym,
   --#                                         LexTokenManager.State,
   --#                                         Proc_Sym,
   --#                                         Ref_Var_Param,
   --#                                         Scope,
   --#                                         STree.Table,
   --#                                         TheHeap &
   --#         Component_Data,
   --#         Dictionary.Dict,
   --#         Statistics.TableUsage,
   --#         TheHeap                    from *,
   --#                                         Abstraction,
   --#                                         Actual_Node,
   --#                                         CommandLineData.Content,
   --#                                         Component_Data,
   --#                                         ContextManager.Ops.Unit_Stack,
   --#                                         Dictionary.Dict,
   --#                                         Formal_Sym,
   --#                                         LexTokenManager.State,
   --#                                         Proc_Sym,
   --#                                         Ref_Var_Param,
   --#                                         Root_Parameter_Sym,
   --#                                         Scope,
   --#                                         STree.Table,
   --#                                         TheHeap &
   --#         Entire_Array_Sym           from Abstraction,
   --#                                         Actual_Node,
   --#                                         CommandLineData.Content,
   --#                                         Component_Data,
   --#                                         ContextManager.Ops.Unit_Stack,
   --#                                         Dictionary.Dict,
   --#                                         Formal_Sym,
   --#                                         LexTokenManager.State,
   --#                                         Proc_Sym,
   --#                                         Ref_Var_Param,
   --#                                         Scope,
   --#                                         STree.Table,
   --#                                         TheHeap &
   --#         ErrorHandler.Error_Context,
   --#         SPARK_IO.File_Sys          from Abstraction,
   --#                                         Actual_Node,
   --#                                         CommandLineData.Content,
   --#                                         Component_Data,
   --#                                         ContextManager.Ops.File_Heap,
   --#                                         ContextManager.Ops.Unit_Heap,
   --#                                         ContextManager.Ops.Unit_Stack,
   --#                                         Dictionary.Dict,
   --#                                         ErrorHandler.Error_Context,
   --#                                         Formal_Sym,
   --#                                         LexTokenManager.State,
   --#                                         Proc_Sym,
   --#                                         Ref_Var_Param,
   --#                                         Root_Parameter_Sym,
   --#                                         Scope,
   --#                                         SLI.State,
   --#                                         SPARK_IO.File_Sys,
   --#                                         STree.Table,
   --#                                         Tagged_Parameter_Sym,
   --#                                         TheHeap &
   --#         Formal_Position_List       from *,
   --#                                         Abstraction,
   --#                                         Actual_Node,
   --#                                         CommandLineData.Content,
   --#                                         Component_Data,
   --#                                         ContextManager.Ops.Unit_Stack,
   --#                                         Dictionary.Dict,
   --#                                         Formal_Pos,
   --#                                         Formal_Sym,
   --#                                         LexTokenManager.State,
   --#                                         Proc_Sym,
   --#                                         Ref_Var_Param,
   --#                                         Scope,
   --#                                         STree.Table,
   --#                                         TheHeap &
   --#         SLI.State                  from *,
   --#                                         Abstraction,
   --#                                         Actual_Node,
   --#                                         CommandLineData.Content,
   --#                                         Component_Data,
   --#                                         ContextManager.Ops.File_Heap,
   --#                                         ContextManager.Ops.Unit_Heap,
   --#                                         ContextManager.Ops.Unit_Stack,
   --#                                         Dictionary.Dict,
   --#                                         ErrorHandler.Error_Context,
   --#                                         Formal_Sym,
   --#                                         LexTokenManager.State,
   --#                                         Proc_Sym,
   --#                                         Ref_Var_Param,
   --#                                         Scope,
   --#                                         SPARK_IO.File_Sys,
   --#                                         STree.Table,
   --#                                         TheHeap;
   --# pre Syntax_Node_Type (Actual_Node, STree.Table) = SP_Symbols.expression;
   --# post STree.Table = STree.Table~;
   is
      Entire_Var_Sym, Var_Type       : Dictionary.Symbol;
      Mode_Of_Formal                 : Dictionary.Modes;
      Exp_Result                     : Exp_Record;
      Is_A_Name                      : Boolean;
      Actual_Type                    : Dictionary.Symbol;
      Actual_Parameter_Is_A_Variable : Boolean := False;
      Actual_Parameter_Is_A_Constant : Boolean := False;

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

      procedure Check_Valid_Mode
        (Actual_Node_Pos : in LexTokenManager.Token_Position;
         Scope           : in Dictionary.Scopes;
         Actual_Sym      : in Dictionary.Symbol;
         Mode_Of_Formal  : in Dictionary.Modes)
      --# 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 Actual_Node_Pos,
      --#                                         Actual_Sym,
      --#                                         CommandLineData.Content,
      --#                                         Dictionary.Dict,
      --#                                         ErrorHandler.Error_Context,
      --#                                         LexTokenManager.State,
      --#                                         Mode_Of_Formal,
      --#                                         Scope,
      --#                                         SPARK_IO.File_Sys;
      -- Actual_Sym represents an actual parameter, whose corresponding formal
      -- parameter is of mode in out or out.  It is the symbol of the associated
      -- entire variable (if the parameter is an entire variable or a
      -- subcomponent of a variable).
      --
      -- The procedure checks that every actual parameter of mode in out or out
      -- is not
      --       -  a formal parameter of mode in, or
      --       -  a loop parameter,
      -- and that an actual parameter of mode in out is not itself a formal
      -- parameter of mode out, or a subcomponent thereof.
      -- Also warns of direct update of non-enclosing package own variable
      --
      is
         Actual_Mode : Dictionary.Modes;
      begin
         if Dictionary.IsLoopParameter (Actual_Sym) then
            ErrorHandler.Semantic_Error
              (Err_Num   => 168,
               Reference => ErrorHandler.No_Reference,
               Position  => Actual_Node_Pos,
               Id_Str    => Dictionary.GetSimpleName (Actual_Sym));
         elsif Dictionary.IsOwnVariable (Actual_Sym)
           and then not Is_Enclosing_Package (Outer_Pack => Dictionary.GetOwner (Actual_Sym),
                                              Scope      => Scope) then
            ErrorHandler.Semantic_Warning_Sym (Err_Num  => 169,
                                               Position => Actual_Node_Pos,
                                               Sym      => Actual_Sym,
                                               Scope    => Scope);
         end if;

         if Dictionary.IsSubprogramParameter (Actual_Sym) then
            Actual_Mode := Dictionary.GetSubprogramParameterMode (Actual_Sym);
            if Actual_Mode = Dictionary.InMode or else Actual_Mode = Dictionary.DefaultMode then
               ErrorHandler.Semantic_Error
                 (Err_Num   => 170,
                  Reference => ErrorHandler.No_Reference,
                  Position  => Actual_Node_Pos,
                  Id_Str    => Dictionary.GetSimpleName (Actual_Sym));
            elsif CommandLineData.Content.Language_Profile = CommandLineData.SPARK83
              and then Actual_Mode = Dictionary.OutMode
              and then Mode_Of_Formal = Dictionary.InOutMode then
               ErrorHandler.Semantic_Error
                 (Err_Num   => 171,
                  Reference => ErrorHandler.No_Reference,
                  Position  => Actual_Node_Pos,
                  Id_Str    => Dictionary.GetSimpleName (Actual_Sym));
            end if;
         end if;
      end Check_Valid_Mode;

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

      procedure Check_Type
        (Actual_Type          : in Dictionary.Symbol;
         Scope                : in Dictionary.Scopes;
         Actual_Range_RHS     : in Maths.Value;
         Formal_Sym           : in Dictionary.Symbol;
         Tagged_Parameter_Sym : in Dictionary.Symbol;
         Actual_Node_Pos      : in LexTokenManager.Token_Position)
      --# 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 Actual_Node_Pos,
      --#                                         Actual_Range_RHS,
      --#                                         Actual_Type,
      --#                                         CommandLineData.Content,
      --#                                         Dictionary.Dict,
      --#                                         ErrorHandler.Error_Context,
      --#                                         Formal_Sym,
      --#                                         LexTokenManager.State,
      --#                                         Scope,
      --#                                         SPARK_IO.File_Sys,
      --#                                         Tagged_Parameter_Sym;
      is
         Expected_Type : Dictionary.Symbol;
      begin
         Expected_Type := Dictionary.GetType (Formal_Sym);

         if not (Dictionary.Types_Are_Equal
                   (Left_Symbol        => Tagged_Parameter_Sym,
                    Right_Symbol       => Actual_Type,
                    Full_Range_Subtype => False)
                   or else -- inherited call, right type
                   (Dictionary.Is_Null_Symbol (Tagged_Parameter_Sym)
                      and then -- no inheritance, normal rules
                      Dictionary.CompatibleTypes (Scope, Actual_Type, Expected_Type))
                   or else (not Dictionary.IsAnExtensionOf (Actual_Type, Tagged_Parameter_Sym)
                              and then -- trap use of root type
                              Dictionary.CompatibleTypes (Scope, Actual_Type, Expected_Type))) then
            -- we have a type mismatch but there are two cases to consider: (1) the failure is in an inherited call
            -- indicated by Tagged_Parameter_Sym /= NullSymbol or (2) in a normal proc call.  To provide the right
            -- information in the error message we need a condition thus:
            if Dictionary.Is_Null_Symbol (Tagged_Parameter_Sym) then -- normal case
               ErrorHandler.Semantic_Error_Sym2
                 (Err_Num   => 107,
                  Reference => ErrorHandler.No_Reference,
                  Position  => Actual_Node_Pos,
                  Sym       => Actual_Type,
                  Sym2      => Expected_Type,
                  Scope     => Scope);
            else -- inherited call
               ErrorHandler.Semantic_Error_Sym2
                 (Err_Num   => 107,
                  Reference => ErrorHandler.No_Reference,
                  Position  => Actual_Node_Pos,
                  Sym       => Actual_Type,
                  Sym2      => Tagged_Parameter_Sym,
                  Scope     => Scope);
            end if;
            -- if types match ok, do checks for array bounds, strings etc
         elsif Dictionary.Is_Constrained_Array_Type_Mark (Expected_Type, Scope) then
            -- Formal parameter type is Constrained.
            if Dictionary.Is_Unconstrained_Array_Type_Mark (Actual_Type, Scope) then
               -- Actual is unconstrained.  In SPARK95 or 2005, this is OK if
               -- the actual is a static String expression, but illegal
               -- otherwise.
               if CommandLineData.Content.Language_Profile /= CommandLineData.SPARK83
                 and then Dictionary.IsPredefinedStringType (Actual_Type) then
                  -- Formal must be a constrained String subtype, so we need
                  -- to check the upper bound of the actual (if it has one) against
                  -- the expected upper bound of the formal.
                  if Actual_Range_RHS = Maths.NoValue then
                     -- Actual is not static, so must be illegal
                     ErrorHandler.Semantic_Error
                       (Err_Num   => 39,
                        Reference => ErrorHandler.No_Reference,
                        Position  => Actual_Node_Pos,
                        Id_Str    => LexTokenManager.Null_String);
                  else
                     -- Actual is static, so check upper-bound against that expected
                     if Actual_Range_RHS /=
                       Maths.ValueRep (Dictionary.GetScalarAttributeValue (False, LexTokenManager.Last_Token, Expected_Type)) then
                        ErrorHandler.Semantic_Error
                          (Err_Num   => 418,
                           Reference => ErrorHandler.No_Reference,
                           Position  => Actual_Node_Pos,
                           Id_Str    => LexTokenManager.Null_String);

                     end if;
                  end if;
               else
                  ErrorHandler.Semantic_Error
                    (Err_Num   => 39,
                     Reference => ErrorHandler.No_Reference,
                     Position  => Actual_Node_Pos,
                     Id_Str    => LexTokenManager.Null_String);
               end if;
            elsif Illegal_Unconstrained (Left_Type  => Expected_Type,
                                         Right_Type => Actual_Type) then
               ErrorHandler.Semantic_Error
                 (Err_Num   => 418,
                  Reference => ErrorHandler.No_Reference,
                  Position  => Actual_Node_Pos,
                  Id_Str    => LexTokenManager.Null_String);
            end if;
         end if;
      end Check_Type;

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

      function Is_Global_Of (Var_Sym, Proc_Sym : Dictionary.Symbol;
                             Abstraction       : Dictionary.Abstractions) return Boolean
      --# global in Dictionary.Dict;
      is
         It    : Dictionary.Iterator;
         Found : Boolean;
      begin
         Found := False;
         It    := Dictionary.FirstGlobalVariable (Abstraction, Proc_Sym);
         while not Dictionary.IsNullIterator (It) loop
            if Dictionary.CurrentSymbol (It) = Var_Sym then
               Found := True;
               exit;
            end if;
            It := Dictionary.NextSymbol (It);
         end loop;
         return Found;
      end Is_Global_Of;

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

      function Is_Exported_Global_Of
        (Var_Sym, Proc_Sym : Dictionary.Symbol;
         Abstraction       : Dictionary.Abstractions)
        return              Boolean
      --# global in Dictionary.Dict;
      is
         It    : Dictionary.Iterator;
         Found : Boolean;
      begin
         Found := False;
         It    := Dictionary.FirstGlobalVariable (Abstraction, Proc_Sym);
         while not Dictionary.IsNullIterator (It) loop
            if Dictionary.CurrentSymbol (It) = Var_Sym then
               Found := Dictionary.IsExport (Abstraction, Proc_Sym, Dictionary.CurrentSymbol (It));
               exit;
            end if;
            It := Dictionary.NextSymbol (It);
         end loop;
         return Found;
      end Is_Exported_Global_Of;

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

      procedure Check_For_Use_Of_Protected_Or_Stream_Vars
        (Var_Sym, Proc_Sym : in Dictionary.Symbol;
         Scope             : in Dictionary.Scopes;
         Actual_Node_Pos   : in LexTokenManager.Token_Position)
      --# 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 Actual_Node_Pos,
      --#                                         CommandLineData.Content,
      --#                                         Dictionary.Dict,
      --#                                         ErrorHandler.Error_Context,
      --#                                         LexTokenManager.State,
      --#                                         Proc_Sym,
      --#                                         Scope,
      --#                                         SPARK_IO.File_Sys,
      --#                                         Var_Sym;
      is
      begin
         -- Stream variables cannot be passed as parameters
         if Dictionary.IsOwnVariableOrConstituentWithMode (Var_Sym) then
            ErrorHandler.Semantic_Error_Sym
              (Err_Num   => 716,
               Reference => ErrorHandler.No_Reference,
               Position  => Actual_Node_Pos,
               Sym       => Var_Sym,
               Scope     => Scope);
            -- Protected variable cannot be passed as parameters
         elsif Dictionary.IsOwnVariable (Var_Sym) and then Dictionary.GetOwnVariableProtected (Var_Sym) then
            -- unless it is a suspension object to a predefined operation.
            if not (Dictionary.IsPredefinedSuspensionObjectType (Dictionary.GetType (Var_Sym))
                      and then Dictionary.IsPredefined (Proc_Sym)) then
               ErrorHandler.Semantic_Error_Sym
                 (Err_Num   => 725,
                  Reference => ErrorHandler.No_Reference,
                  Position  => Actual_Node_Pos,
                  Sym       => Var_Sym,
                  Scope     => Scope);
            end if;
         end if;
      end Check_For_Use_Of_Protected_Or_Stream_Vars;

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

      -- procedure maintains two parallel list one of actual symbols
      -- and the other of the formal parameter position number
      -- applicable to each.
      procedure Add_Sym
        (Sym                                         : in     Dictionary.Symbol;
         Formal_Pos                                  : in     Positive;
         Actual_Parameter_List, Formal_Position_List : in out SimpleLists.SimpleList)
      --# derives Actual_Parameter_List from *,
      --#                                    Sym &
      --#         Formal_Position_List  from *,
      --#                                    Formal_Pos;
      is
         Ok : Boolean;
      begin
         SimpleLists.AddItem (Natural (Dictionary.SymbolRef (Sym)), Actual_Parameter_List, Ok);
         if not Ok then
            SystemErrors.Fatal_Error (Sys_Err => SystemErrors.List_Overflow_In_Procedure_Call,
                                      Msg     => "");
         end if;

         SimpleLists.AddItem (Formal_Pos, Formal_Position_List, Ok);
         if not Ok then
            SystemErrors.Fatal_Error (Sys_Err => SystemErrors.List_Overflow_In_Procedure_Call,
                                      Msg     => "");
         end if;
      end Add_Sym;

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

      function Is_Global_Of_An_Enclosing_Function
        (Calling_Scope : Dictionary.Scopes;
         Param_Sym     : Dictionary.Symbol)
        return          Boolean
      --# global in Dictionary.Dict;
      is
         Calling_Sym         : Dictionary.Symbol;
         Calling_Abstraction : Dictionary.Abstractions;
         Result              : Boolean := False;
      begin
         Calling_Sym := Dictionary.GetEnclosingCompilationUnit (Calling_Scope);
         if Dictionary.IsFunction (Calling_Sym) then
            -- Procedure that exports Param_Sym is being called from inside a function body
            -- so there is a possibility that an indirect function side efefct is occurring
            Calling_Abstraction := Dictionary.GetAbstraction (Calling_Sym, Calling_Scope);
            Result              := Dictionary.Is_Global_Variable (Calling_Abstraction, Calling_Sym, Param_Sym);
         end if;
         return Result;
      end Is_Global_Of_An_Enclosing_Function;

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

      procedure Substitute_Root_Type_For_Extended_Type_In_Sequence
        (The_Seq              : in     SeqAlgebra.Seq;
         Tagged_Parameter_Sym : in     Dictionary.Symbol;
         Component_Data       : in out ComponentManager.ComponentData)
      --# global in     CommandLineData.Content;
      --#        in     ContextManager.Ops.Unit_Stack;
      --#        in out Dictionary.Dict;
      --#        in out Statistics.TableUsage;
      --#        in out TheHeap;
      --# derives Component_Data,
      --#         Dictionary.Dict,
      --#         Statistics.TableUsage,
      --#         TheHeap               from *,
      --#                                    Component_Data,
      --#                                    ContextManager.Ops.Unit_Stack,
      --#                                    Dictionary.Dict,
      --#                                    Tagged_Parameter_Sym,
      --#                                    TheHeap,
      --#                                    The_Seq &
      --#         null                  from CommandLineData.Content;
      is
         Actual_Sym    : Dictionary.Symbol;
         Member_Of_Seq : SeqAlgebra.MemberOfSeq;
      begin
         Member_Of_Seq := SeqAlgebra.FirstMember (TheHeap, The_Seq);
         while not SeqAlgebra.IsNullMember (Member_Of_Seq) loop
            -- process each member of sequence in turn
            Actual_Sym :=
              Dictionary.ConvertSymbolRef
              (ExaminerConstants.RefType (SeqAlgebra.Value_Of_Member (The_Heap => TheHeap,
                                                                      M        => Member_Of_Seq)));
            -- we only need to do things to tagged types that extend Tagged_Parameter_Sym
            if Dictionary.IsAnExtensionOf (Tagged_Parameter_Sym, Dictionary.GetType (Actual_Sym)) then
               -- We can't replace X with X.Inherit unless we add X's subcomponents first
               Add_Record_Sub_Components
                 (Record_Var_Sym  => Actual_Sym,
                  Record_Type_Sym => Dictionary.GetType (Actual_Sym),
                  Component_Data  => Component_Data,
                  The_Heap        => TheHeap);
               -- now add as may .Inherits as needed to get type match
               Actual_Sym := Convert_Tagged_Actual (Actual               => Actual_Sym,
                                                    Tagged_Parameter_Sym => Tagged_Parameter_Sym);
               -- replace existing sequence member with converted one
               SeqAlgebra.RemoveMember (TheHeap, The_Seq, SeqAlgebra.Value_Of_Member (The_Heap => TheHeap,
                                                                                      M        => Member_Of_Seq));
               SeqAlgebra.AddMember (TheHeap, The_Seq, Natural (Dictionary.SymbolRef (Actual_Sym)));
            end if;
            Member_Of_Seq := SeqAlgebra.NextMember (TheHeap, Member_Of_Seq);
         end loop;
      end Substitute_Root_Type_For_Extended_Type_In_Sequence;

   begin -- Check_Actual
      Actual_Type      := Dictionary.GetUnknownTypeMark;
      Entire_Array_Sym := Dictionary.NullSymbol; -- default value for all except actual param which is array element
      Mode_Of_Formal   := Dictionary.GetSubprogramParameterMode (Formal_Sym);
      if Dictionary.IsExport (Abstraction, Proc_Sym, Formal_Sym)
        or else Mode_Of_Formal = Dictionary.InOutMode
        or else Mode_Of_Formal = Dictionary.OutMode then
         -- no array elements or indexing permitted
         Walk_Name
           (Exp_Node       => Actual_Node,
            Scope          => Scope,
            Component_Data => Component_Data,
            The_Heap       => TheHeap,
            Result         => Exp_Result,
            Is_A_Name      => Is_A_Name,
            Ref_Var_Param  => Ref_Var_Param);
         if Is_A_Name then
            if Exp_Result.Is_AVariable then -- valid variable found, do further checks
               Actual_Parameter_Is_A_Variable := True;
               Entire_Var_Sym                 := Exp_Result.Variable_Symbol;
               if Exp_Result.Arg_List_Found then
                  -- actual parameter is an array reference so we need to return the entire array symbol
                  -- so we can correctly handle the flow analysis of calls such as SetToZero (A (I));
                  --
                  -- If it's an entire variable, then the symbol we need is in Exp_Result.Variable_Symbol
                  --
                  -- If it's NOT an entire var, then it must be record field such as R.F (I).
                  -- If that case, the flow analyser needs the symbol of the field itself,
                  -- which is in Exp_Result.Other_Symbol
                  if Exp_Result.Is_An_Entire_Variable then
                     Entire_Array_Sym := Exp_Result.Variable_Symbol;
                  else
                     Entire_Array_Sym := Exp_Result.Other_Symbol;
                  end if;
               end if;
               Var_Type    := Exp_Result.Type_Symbol;
               Actual_Type := Exp_Result.Type_Symbol;
               Plant_Constraining_Type
                 (Expression_Type => Actual_Type,
                  String_Length   => Maths.NoValue,
                  Actual_Node     => Actual_Node);
               if Dictionary.Is_Null_Symbol (Exp_Result.Other_Symbol) then
                  Add_Sym
                    (Sym                   => Exp_Result.Variable_Symbol,
                     Formal_Pos            => Formal_Pos,
                     Actual_Parameter_List => Actual_Parameter_List,
                     Formal_Position_List  => Formal_Position_List);
               else
                  Add_Sym
                    (Sym                   => Exp_Result.Other_Symbol,
                     Formal_Pos            => Formal_Pos,
                     Actual_Parameter_List => Actual_Parameter_List,
                     Formal_Position_List  => Formal_Position_List);
               end if;
               Check_Type
                 (Actual_Type          => Var_Type,
                  Scope                => Scope,
                  Actual_Range_RHS     => Maths.NoValue,
                  Formal_Sym           => Formal_Sym,
                  Tagged_Parameter_Sym => Tagged_Parameter_Sym,
                  Actual_Node_Pos      => Node_Position (Node => Actual_Node));
               Check_Valid_Mode
                 (Actual_Node_Pos => Node_Position (Node => Actual_Node),
                  Scope           => Scope,
                  Actual_Sym      => Entire_Var_Sym,
                  Mode_Of_Formal  => Mode_Of_Formal);
               Check_For_Use_Of_Protected_Or_Stream_Vars
                 (Var_Sym         => Entire_Var_Sym,
                  Proc_Sym        => Proc_Sym,
                  Scope           => Scope,
                  Actual_Node_Pos => Node_Position (Node => Actual_Node));
               if Is_Global_Of_An_Enclosing_Function (Calling_Scope => Scope,
                                                      Param_Sym     => Entire_Var_Sym) then
                  -- We are attempting to change a function's global via it's use as an actual parameter
                  -- to an procedure within the function
                  ErrorHandler.Semantic_Error_Sym
                    (Err_Num   => 328,
                     Reference => ErrorHandler.No_Reference,
                     Position  => Node_Position (Node => Actual_Node),
                     Sym       => Entire_Var_Sym,
                     Scope     => Scope);
               end if;

               if Is_Global_Of (Var_Sym     => Entire_Var_Sym,
                                Proc_Sym    => Proc_Sym,
                                Abstraction => Abstraction) then
                  -- export overlapping global
                  ErrorHandler.Semantic_Error
                    (Err_Num   => 173,
                     Reference => ErrorHandler.No_Reference,
                     Position  => Node_Position (Node => Actual_Node),
                     Id_Str    => LexTokenManager.Null_String);
               end if;
            else -- expression is not an entire variable
               Add_Sym
                 (Sym                   => Dictionary.NullSymbol,
                  Formal_Pos            => Formal_Pos,
                  Actual_Parameter_List => Actual_Parameter_List,
                  Formal_Position_List  => Formal_Position_List); -- put place holder in parameter list
               ErrorHandler.Semantic_Error
                 (Err_Num   => 172,
                  Reference => ErrorHandler.No_Reference,
                  Position  => Node_Position (Node => Actual_Node),
                  Id_Str    => LexTokenManager.Null_String);
            end if;
         else -- its not even a name
            Add_Sym
              (Sym                   => Dictionary.NullSymbol,
               Formal_Pos            => Formal_Pos,
               Actual_Parameter_List => Actual_Parameter_List,
               Formal_Position_List  => Formal_Position_List); -- put place holder in parameter list
            ErrorHandler.Semantic_Error
              (Err_Num   => 172,
               Reference => ErrorHandler.No_Reference,
               Position  => Node_Position (Node => Actual_Node),
               Id_Str    => LexTokenManager.Null_String);
         end if;
      else
         -- Mode is "in", so any expression will do but vars need special alias checks
         Walk_Expression_P.Walk_Expression
           (Exp_Node                => Actual_Node,
            Scope                   => Scope,
            Type_Context            => Dictionary.GetType (Formal_Sym),
            Context_Requires_Static => False,
            Ref_Var                 => Ref_Var_Param,
            Result                  => Exp_Result,
            Component_Data          => Component_Data,
            The_Heap                => TheHeap);

         if Exp_Result.Is_AVariable then
            --# accept F, 10, Is_A_Name, "We already know.";
            --  We need to use walk_name in order to get a more useful
            --  name for the variable. We only do this if the previous
            --  call to WalkExpression says that this refers to a
            --  variable.
            Walk_Name
              (Exp_Node       => Actual_Node,
               Scope          => Scope,
               Component_Data => Component_Data,
               The_Heap       => TheHeap,
               Result         => Exp_Result,
               Is_A_Name      => Is_A_Name,
               Ref_Var_Param  => Ref_Var_Param);
            --# end accept;
         end if;

         Actual_Type := Exp_Result.Type_Symbol;
         Plant_Constraining_Type
           (Expression_Type => Actual_Type,
            String_Length   => Exp_Result.Range_RHS,
            Actual_Node     => Actual_Node);
         if not Dictionary.Is_Null_Symbol (Exp_Result.Variable_Symbol) then
            -- we have a variable or 'disguised' variable
            Actual_Parameter_Is_A_Variable := True;
            Entire_Var_Sym                 := Exp_Result.Variable_Symbol;
            Var_Type                       := Exp_Result.Type_Symbol;
            if Dictionary.Is_Null_Symbol (Exp_Result.Other_Symbol) then
               Add_Sym
                 (Sym                   => Exp_Result.Variable_Symbol,
                  Formal_Pos            => Formal_Pos,
                  Actual_Parameter_List => Actual_Parameter_List,
                  Formal_Position_List  => Formal_Position_List);
            else
               Add_Sym
                 (Sym                   => Exp_Result.Other_Symbol,
                  Formal_Pos            => Formal_Pos,
                  Actual_Parameter_List => Actual_Parameter_List,
                  Formal_Position_List  => Formal_Position_List);
            end if;
            Check_Type
              (Actual_Type          => Var_Type,
               Scope                => Scope,
               Actual_Range_RHS     => Maths.NoValue,
               Formal_Sym           => Formal_Sym,
               Tagged_Parameter_Sym => Tagged_Parameter_Sym,
               Actual_Node_Pos      => Node_Position (Node => Actual_Node));
            if CommandLineData.Content.Language_Profile = CommandLineData.SPARK83
              and then Dictionary.IsSubprogramParameter (Entire_Var_Sym)
              and then Dictionary.GetSubprogramParameterMode (Entire_Var_Sym) = Dictionary.OutMode then
               ErrorHandler.Semantic_Error
                 (Err_Num   => 171,
                  Reference => ErrorHandler.No_Reference,
                  Position  => Node_Position (Node => Actual_Node),
                  Id_Str    => Dictionary.GetSimpleName (Entire_Var_Sym));
            end if;
            if Is_Exported_Global_Of (Var_Sym     => Entire_Var_Sym,
                                      Proc_Sym    => Proc_Sym,
                                      Abstraction => Abstraction) then
               ErrorHandler.Semantic_Error
                 (Err_Num   => 166,
                  Reference => ErrorHandler.No_Reference,
                  Position  => Node_Position (Node => Actual_Node),
                  Id_Str    => LexTokenManager.Null_String);
            end if;
         elsif Exp_Result.Is_ARange then -- check that a type mark isn't being used as an actual parameter
            ErrorHandler.Semantic_Error
              (Err_Num   => 5,
               Reference => ErrorHandler.No_Reference,
               Position  => Node_Position (Node => Actual_Node),
               Id_Str    => Dictionary.GetSimpleName (Exp_Result.Type_Symbol));
         else -- True expression, does not represent a variable and isn't a typemark
            Actual_Parameter_Is_A_Constant := Exp_Result.Is_Constant;
            Add_Sym
              (Sym                   => Dictionary.NullSymbol,
               Formal_Pos            => Formal_Pos,
               Actual_Parameter_List => Actual_Parameter_List,
               Formal_Position_List  => Formal_Position_List); -- put place holder in parameter list
            Check_Type
              (Actual_Type          => Exp_Result.Type_Symbol,
               Scope                => Scope,
               Actual_Range_RHS     => Exp_Result.Range_RHS,
               Formal_Sym           => Formal_Sym,
               Tagged_Parameter_Sym => Tagged_Parameter_Sym,
               Actual_Node_Pos      => Node_Position (Node => Actual_Node));
         end if;
      end if;
      -- We might need to substitute a subtype of the actual paramter
      -- if an inherited root op is being called
      if Tagged_Substitution_Required
        (Formal             => Formal_Sym,
         Actual_Type        => Actual_Type,
         Root_Parameter_Sym => Root_Parameter_Sym) then
         if Actual_Parameter_Is_A_Variable then
            Substitute_Root_Type_For_Extended_Type_In_Sequence
              (The_Seq              => Ref_Var_Param,
               Tagged_Parameter_Sym => Root_Parameter_Sym,
               Component_Data       => Component_Data);
         elsif not Actual_Parameter_Is_A_Constant then
            ErrorHandler.Semantic_Error
              (Err_Num   => 827,
               Reference => ErrorHandler.No_Reference,
               Position  => Node_Position (Node => Actual_Node),
               Id_Str    => LexTokenManager.Null_String);
         end if;
      end if;
   end Check_Actual;

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

   procedure Handle_Named_Association
     (Named_Argument_Assoc_Node                          : in     STree.SyntaxNode;
      Root_Parameter_Sym, Proc_Sym, Tagged_Parameter_Sym : in     Dictionary.Symbol;
      Scope                                              : in     Dictionary.Scopes;
      Abstraction                                        : in     Dictionary.Abstractions;
      Actual_Parameter_List, Formal_Position_List        : in out SimpleLists.SimpleList;
      Param_Table                                        : in out Param_Tables;
      Component_Data                                     : in out ComponentManager.ComponentData)
   --# global in     CommandLineData.Content;
   --#        in     ContextManager.Ops.File_Heap;
   --#        in     ContextManager.Ops.Unit_Heap;
   --#        in     ContextManager.Ops.Unit_Stack;
   --#        in out Aggregate_Stack.State;
   --#        in out Dictionary.Dict;
   --#        in out ErrorHandler.Error_Context;
   --#        in out LexTokenManager.State;
   --#        in out SLI.State;
   --#        in out SPARK_IO.File_Sys;
   --#        in out Statistics.TableUsage;
   --#        in out STree.Table;
   --#        in out TheHeap;
   --# derives Actual_Parameter_List,
   --#         Aggregate_Stack.State,
   --#         Component_Data,
   --#         Dictionary.Dict,
   --#         Formal_Position_List,
   --#         LexTokenManager.State,
   --#         Param_Table,
   --#         Statistics.TableUsage,
   --#         STree.Table,
   --#         TheHeap                    from *,
   --#                                         Abstraction,
   --#                                         CommandLineData.Content,
   --#                                         Component_Data,
   --#                                         ContextManager.Ops.Unit_Stack,
   --#                                         Dictionary.Dict,
   --#                                         LexTokenManager.State,
   --#                                         Named_Argument_Assoc_Node,
   --#                                         Proc_Sym,
   --#                                         Root_Parameter_Sym,
   --#                                         Scope,
   --#                                         STree.Table,
   --#                                         TheHeap &
   --#         ErrorHandler.Error_Context,
   --#         SLI.State,
   --#         SPARK_IO.File_Sys          from Abstraction,
   --#                                         CommandLineData.Content,
   --#                                         Component_Data,
   --#                                         ContextManager.Ops.File_Heap,
   --#                                         ContextManager.Ops.Unit_Heap,
   --#                                         ContextManager.Ops.Unit_Stack,
   --#                                         Dictionary.Dict,
   --#                                         ErrorHandler.Error_Context,
   --#                                         LexTokenManager.State,
   --#                                         Named_Argument_Assoc_Node,
   --#                                         Proc_Sym,
   --#                                         Root_Parameter_Sym,
   --#                                         Scope,
   --#                                         SLI.State,
   --#                                         SPARK_IO.File_Sys,
   --#                                         STree.Table,
   --#                                         Tagged_Parameter_Sym,
   --#                                         TheHeap;
   --# pre Syntax_Node_Type (Named_Argument_Assoc_Node, STree.Table) = SP_Symbols.named_argument_association;
   --# post STree.Table = STree.Table~;
   is
      Check_Named_Association_Ref_Var : SeqAlgebra.Seq;
      Expression_Node                 : STree.SyntaxNode;
      Formal_It                       : Dictionary.Iterator;
      Formal_Sym                      : Dictionary.Symbol;
      Entire_Array_Sym                : Dictionary.Symbol;
   begin
      -- Check that each named assoication appears and appears once only
      Check_Named_Association (The_Formals               => Proc_Sym,
                               Scope                     => Scope,
                               Named_Argument_Assoc_Node => Named_Argument_Assoc_Node);

      -- now process each formal in turn
      Formal_It := Dictionary.FirstSubprogramParameter (Proc_Sym);
      while not Dictionary.IsNullIterator (Formal_It) loop
         --# assert Syntax_Node_Type (Named_Argument_Assoc_Node, STree.Table) = SP_Symbols.named_argument_association and
         --#   STree.Table = STree.Table~;
         Formal_Sym := Dictionary.CurrentSymbol (Formal_It);
         Find_Actual_Node
           (For_Formal                => Formal_Sym,
            Named_Argument_Assoc_Node => Named_Argument_Assoc_Node,
            Expression_Node           => Expression_Node);
         -- ASSUME Expression_Node = expression OR NULL
         --# check Syntax_Node_Type (Expression_Node, STree.Table) = SP_Symbols.expression or
         --#   Expression_Node = STree.NullNode;
         if Syntax_Node_Type (Node => Expression_Node) = SP_Symbols.expression then
            -- ASSUME Expression_Node = expression
            SeqAlgebra.CreateSeq (TheHeap, Check_Named_Association_Ref_Var);
            Check_Actual
              (Root_Parameter_Sym    => Root_Parameter_Sym,
               Proc_Sym              => Proc_Sym,
               Formal_Sym            => Formal_Sym,
               Tagged_Parameter_Sym  => Tagged_Parameter_Sym,
               Formal_Pos            => Dictionary.GetSubprogramParameterNumber (Formal_Sym),
               Actual_Node           => Expression_Node,
               Ref_Var_Param         => Check_Named_Association_Ref_Var,
               Abstraction           => Abstraction,
               Scope                 => Scope,
               Actual_Parameter_List => Actual_Parameter_List,
               Formal_Position_List  => Formal_Position_List,
               Component_Data        => Component_Data,
               Entire_Array_Sym      => Entire_Array_Sym);
            Add_Seq
              (Param_No         => Dictionary.GetSubprogramParameterNumber (Formal_Sym),
               Refs             => Check_Named_Association_Ref_Var,
               Entire_Array_Sym => Entire_Array_Sym,
               Param_Table      => Param_Table);
         end if;
         Formal_It := Dictionary.NextSymbol (Formal_It);
      end loop;
   end Handle_Named_Association;

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

   procedure Handle_Positional_Association
     (Positional_Argument_Assoc_Node                     : in     STree.SyntaxNode;
      Root_Parameter_Sym, Proc_Sym, Tagged_Parameter_Sym : in     Dictionary.Symbol;
      Scope                                              : in     Dictionary.Scopes;
      Abstraction                                        : in     Dictionary.Abstractions;
      Actual_Parameter_List, Formal_Position_List        : in out SimpleLists.SimpleList;
      Param_Table                                        : in out Param_Tables;
      Component_Data                                     : in out ComponentManager.ComponentData)
   --# global in     CommandLineData.Content;
   --#        in     ContextManager.Ops.File_Heap;
   --#        in     ContextManager.Ops.Unit_Heap;
   --#        in     ContextManager.Ops.Unit_Stack;
   --#        in out Aggregate_Stack.State;
   --#        in out Dictionary.Dict;
   --#        in out ErrorHandler.Error_Context;
   --#        in out LexTokenManager.State;
   --#        in out SLI.State;
   --#        in out SPARK_IO.File_Sys;
   --#        in out Statistics.TableUsage;
   --#        in out STree.Table;
   --#        in out TheHeap;
   --# derives Actual_Parameter_List,
   --#         Aggregate_Stack.State,
   --#         Component_Data,
   --#         Dictionary.Dict,
   --#         Formal_Position_List,
   --#         LexTokenManager.State,
   --#         Param_Table,
   --#         Statistics.TableUsage,
   --#         STree.Table,
   --#         TheHeap                    from *,
   --#                                         Abstraction,
   --#                                         CommandLineData.Content,
   --#                                         Component_Data,
   --#                                         ContextManager.Ops.Unit_Stack,
   --#                                         Dictionary.Dict,
   --#                                         LexTokenManager.State,
   --#                                         Positional_Argument_Assoc_Node,
   --#                                         Proc_Sym,
   --#                                         Root_Parameter_Sym,
   --#                                         Scope,
   --#                                         STree.Table,
   --#                                         TheHeap &
   --#         ErrorHandler.Error_Context,
   --#         SLI.State,
   --#         SPARK_IO.File_Sys          from Abstraction,
   --#                                         CommandLineData.Content,
   --#                                         Component_Data,
   --#                                         ContextManager.Ops.File_Heap,
   --#                                         ContextManager.Ops.Unit_Heap,
   --#                                         ContextManager.Ops.Unit_Stack,
   --#                                         Dictionary.Dict,
   --#                                         ErrorHandler.Error_Context,
   --#                                         LexTokenManager.State,
   --#                                         Positional_Argument_Assoc_Node,
   --#                                         Proc_Sym,
   --#                                         Root_Parameter_Sym,
   --#                                         Scope,
   --#                                         SLI.State,
   --#                                         SPARK_IO.File_Sys,
   --#                                         STree.Table,
   --#                                         Tagged_Parameter_Sym,
   --#                                         TheHeap;
   --# pre Syntax_Node_Type (Positional_Argument_Assoc_Node, STree.Table) = SP_Symbols.positional_argument_association;
   --# post STree.Table = STree.Table~;
   is
      Check_Positional_Association_Ref_Var : SeqAlgebra.Seq;
      Expression_Node                      : STree.SyntaxNode;
      Formal_It                            : Dictionary.Iterator;
      Actual_It                            : STree.Iterator;
      Formal_Sym                           : Dictionary.Symbol;
      Parameter_Number                     : Positive;
      Entire_Array_Sym                     : Dictionary.Symbol;
   begin
      Expression_Node := Positional_Argument_Assoc_Node;

      Actual_It :=
        Find_First_Node
        (Node_Kind    => SP_Symbols.expression,
         From_Root    => Positional_Argument_Assoc_Node,
         In_Direction => STree.Down);

      Formal_It := Dictionary.FirstSubprogramParameter (Proc_Sym);
      while not Dictionary.IsNullIterator (Formal_It) and then not STree.IsNull (Actual_It) loop
         Formal_Sym      := Dictionary.CurrentSymbol (Formal_It);
         Expression_Node := Get_Node (It => Actual_It);
         --# assert Syntax_Node_Type (Expression_Node, STree.Table) = SP_Symbols.expression and
         --#   Expression_Node = Get_Node (Actual_It) and
         --#   STree.Table = STree.Table~;
         Parameter_Number := Dictionary.GetSubprogramParameterNumber (Formal_Sym);
         SeqAlgebra.CreateSeq (TheHeap, Check_Positional_Association_Ref_Var);
         Check_Actual
           (Root_Parameter_Sym    => Root_Parameter_Sym,
            Proc_Sym              => Proc_Sym,
            Formal_Sym            => Formal_Sym,
            Tagged_Parameter_Sym  => Tagged_Parameter_Sym,
            Formal_Pos            => Parameter_Number,
            Actual_Node           => Expression_Node,
            Ref_Var_Param         => Check_Positional_Association_Ref_Var,
            Abstraction           => Abstraction,
            Scope                 => Scope,
            Actual_Parameter_List => Actual_Parameter_List,
            Formal_Position_List  => Formal_Position_List,
            Component_Data        => Component_Data,
            Entire_Array_Sym      => Entire_Array_Sym);
         Add_Seq
           (Param_No         => Parameter_Number,
            Refs             => Check_Positional_Association_Ref_Var,
            Entire_Array_Sym => Entire_Array_Sym,
            Param_Table      => Param_Table);
         Formal_It := Dictionary.NextSymbol (Formal_It);
         Actual_It := STree.NextNode (Actual_It);
      end loop;

      -- completeness check, both loops should run out at same time
      if not Dictionary.IsNullIterator (Formal_It) or else not STree.IsNull (Actual_It) then
         ErrorHandler.Semantic_Error
           (Err_Num   => 3,
            Reference => ErrorHandler.No_Reference,
            Position  => Node_Position (Node => Expression_Node),
            Id_Str    => Dictionary.GetSimpleName (Proc_Sym));
      end if;
   end Handle_Positional_Association;

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

   procedure Check_Parameter_Overlap
     (Arg_List_Node                               : in STree.SyntaxNode;
      Proc_Sym                                    : in Dictionary.Symbol;
      Actual_Parameter_List, Formal_Position_List : in SimpleLists.SimpleList;
      Abstraction                                 : in Dictionary.Abstractions)
   --# global in     CommandLineData.Content;
   --#        in     Dictionary.Dict;
   --#        in     LexTokenManager.State;
   --#        in     STree.Table;
   --#        in out ErrorHandler.Error_Context;
   --#        in out SPARK_IO.File_Sys;
   --# derives ErrorHandler.Error_Context,
   --#         SPARK_IO.File_Sys          from Abstraction,
   --#                                         Actual_Parameter_List,
   --#                                         Arg_List_Node,
   --#                                         CommandLineData.Content,
   --#                                         Dictionary.Dict,
   --#                                         ErrorHandler.Error_Context,
   --#                                         Formal_Position_List,
   --#                                         LexTokenManager.State,
   --#                                         Proc_Sym,
   --#                                         SPARK_IO.File_Sys,
   --#                                         STree.Table;
   --# pre Syntax_Node_Type (Arg_List_Node, STree.Table) = SP_Symbols.named_argument_association or
   --#   Syntax_Node_Type (Arg_List_Node, STree.Table) = SP_Symbols.positional_argument_association;
   is
      Actual_Node : STree.SyntaxNode;
      Err_Pos     : LexTokenManager.Token_Position;

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

      procedure Next_Err_Pos (Actual_Node : in out STree.SyntaxNode;
                              Err_Pos     :    out LexTokenManager.Token_Position)
      --# global in STree.Table;
      --# derives Actual_Node,
      --#         Err_Pos     from Actual_Node,
      --#                          STree.Table;
      --# pre Syntax_Node_Type (Actual_Node, STree.Table) = SP_Symbols.expression or
      --#   Syntax_Node_Type (Actual_Node, STree.Table) = SP_Symbols.named_argument_association or
      --#   Syntax_Node_Type (Actual_Node, STree.Table) = SP_Symbols.positional_argument_association;
      --# post Syntax_Node_Type (Actual_Node, STree.Table) = SP_Symbols.expression or
      --#   Syntax_Node_Type (Actual_Node, STree.Table) = SP_Symbols.named_argument_association or
      --#   Syntax_Node_Type (Actual_Node, STree.Table) = SP_Symbols.positional_argument_association;
      is
      begin
         -- ASSUME Actual_Node = expression OR named_argument_association OR positional_argument_association
         if Syntax_Node_Type (Node => Actual_Node) = SP_Symbols.expression then
            -- ASSUME Actual_Node = expression
            Actual_Node := Last_Sibling_Of (Start_Node => Parent_Node (Current_Node => Actual_Node));
         end if;
         Err_Pos := Node_Position (Node => Actual_Node);

         -- ASSUME Actual_Node = expression OR named_argument_association OR positional_argument_association
         SystemErrors.RT_Assert
           (C       => Syntax_Node_Type (Node => Actual_Node) = SP_Symbols.expression
              or else Syntax_Node_Type (Node => Actual_Node) = SP_Symbols.named_argument_association
              or else Syntax_Node_Type (Node => Actual_Node) = SP_Symbols.positional_argument_association,
            Sys_Err => SystemErrors.Invalid_Syntax_Tree,
            Msg     => "Expect Actual_Node = expression OR named_argument_association OR " &
              "positional_argument_association in Next_Err_Pos");
      end Next_Err_Pos;

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

      -- This will check a given actual parameter (Sym at Position)
      -- against all other actual parameters. Returns true if
      -- the given symbol is a subcomponent of another or if another
      -- parameter is a subcomponent of it.
      --
      -- The check works by looking at the string representation
      -- of any two actual parameters and identifying the common
      -- prefix. We then check if this common prefix is identical
      -- to one or both of the given parameters, if it is they
      -- necessarily overlap. This is best shown with a few
      -- examples:
      --
      -- Parameters   Common Prefix   Overlap
      -- R.A, R.B   | R.            | No
      -- R, R.B     | R             | Yes, because R = R
      -- R, R       | R             | Yes, because R = R and R = R
      -- A, B       | -             | No
      -- A.B.C, A.D | A.            | No
      --
      -- The symbol used to represent the parameters is Other_Symbol
      -- in the record returned by WalkExpression.
      procedure Check_Overlap_Of_Exported_Parameter
        (Position                                    : Positive;
         Proc_Sym                                    : Dictionary.Symbol;
         Err_Pos                                     : LexTokenManager.Token_Position;
         Actual_Parameter_List, Formal_Position_List : SimpleLists.SimpleList;
         Abstraction                                 : Dictionary.Abstractions)
      --# 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,
      --#                                         Actual_Parameter_List,
      --#                                         CommandLineData.Content,
      --#                                         Dictionary.Dict,
      --#                                         ErrorHandler.Error_Context,
      --#                                         Err_Pos,
      --#                                         Formal_Position_List,
      --#                                         LexTokenManager.State,
      --#                                         Position,
      --#                                         Proc_Sym,
      --#                                         SPARK_IO.File_Sys;
      is
         Current_Actual, Actual_Sym : Dictionary.Symbol;
         Sym_Str_A, Sym_Str_B       : E_Strings.T;
         Prefix_Str_A, Prefix_Str_B : E_Strings.T;
         Len_A, Len_B               : E_Strings.Lengths;
         Common_Prefix_Length       : E_Strings.Lengths;
         Overlaps                   : Boolean;
         Current_Formal             : Natural;

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

         function Formal_Number_Of_Actual_Parameter_At
           (Position             : Positive;
            Formal_Position_List : SimpleLists.SimpleList)
           return                 Natural
         is
            OK     : Boolean;
            Pos_No : Natural;
         begin
            SimpleLists.GetItem (Formal_Position_List, Position,
                                 --to get
                                 Pos_No, OK);
            if not OK then
               Pos_No := 0;
            end if;
            return Pos_No;
         end Formal_Number_Of_Actual_Parameter_At;

      begin -- Check_Overlap_Of_Exported_Parameter

         Actual_Sym := Actual_Parameter_At (Position              => Position,
                                            Actual_Parameter_List => Actual_Parameter_List);
         if not Dictionary.Is_Null_Symbol (Actual_Sym) then
            -- Cache the name and length of then given parameter
            Prefix_Str_A := Dictionary.GetAnyPrefixNeeded (Sym       => Actual_Sym,
                                                           Scope     => Dictionary.GlobalScope,
                                                           Separator => ".");
            Sym_Str_A    := Dictionary.GenerateSimpleName (Item      => Actual_Sym,
                                                           Separator => ".");
            Len_A        := E_Strings.Get_Length (Sym_Str_A);

            -- No overlap until shown otherwise
            Overlaps := False;

            for Current_Pos in Positive range 1 .. SimpleLists.NumberOfItems (Actual_Parameter_List)
            --# assert SimpleLists.NumberOfItems (Actual_Parameter_List) in Natural and
            --#   Actual_Parameter_List = Actual_Parameter_List%;
            loop
               Current_Actual := Actual_Parameter_At (Position              => Current_Pos,
                                                      Actual_Parameter_List => Actual_Parameter_List);
               Current_Formal :=
                 Formal_Number_Of_Actual_Parameter_At (Position             => Current_Pos,
                                                       Formal_Position_List => Formal_Position_List);
               if not Dictionary.Is_Null_Symbol (Current_Actual)
                 and then Position /= Current_Pos
                 and then Current_Formal /= 0
                 and then Dictionary.IsExport
                 (Abstraction,
                  Proc_Sym,
                  Dictionary.GetSubprogramParameter (Proc_Sym, Current_Formal)) then
                  Prefix_Str_B :=
                    Dictionary.GetAnyPrefixNeeded (Sym       => Current_Actual,
                                                   Scope     => Dictionary.GlobalScope,
                                                   Separator => ".");
                  Sym_Str_B    := Dictionary.GenerateSimpleName (Item      => Current_Actual,
                                                                 Separator => ".");
                  Len_B        := E_Strings.Get_Length (Sym_Str_B);

                  Common_Prefix_Length := E_Strings.Get_Dotted_Common_Prefix_Length (Sym_Str_A, Sym_Str_B);

                  -- If the lengths of a string are equal to the length of the
                  -- common prefix, they must be equal.
                  Overlaps := E_Strings.Eq_String (E_Str1 => Prefix_Str_A,
                                                   E_Str2 => Prefix_Str_B)
                    and then (Len_A = Common_Prefix_Length or else Len_B = Common_Prefix_Length);
               end if;

               -- It's enough to find a single instance
               exit when Overlaps;
            end loop;
            if Overlaps then
               ErrorHandler.Semantic_Error
                 (Err_Num   => 165,
                  Reference => ErrorHandler.No_Reference,
                  Position  => Err_Pos,
                  Id_Str    => LexTokenManager.Null_String);
            end if;
         end if;
      end Check_Overlap_Of_Exported_Parameter;

   begin -- Check_Parameter_Overlap

      -- Work out a position to include in any error messages. The
      -- first proper expression or simple_name will do.
      Actual_Node := Child_Node (Current_Node => Arg_List_Node);
      while Syntax_Node_Type (Node => Actual_Node) /= SP_Symbols.simple_name
        and then Syntax_Node_Type (Node => Actual_Node) /= SP_Symbols.expression loop
         -- ASSUME Actual_Node = named_argument_association OR positional_argument_association
         SystemErrors.RT_Assert
           (C       => Syntax_Node_Type (Node => Actual_Node) = SP_Symbols.named_argument_association
              or else Syntax_Node_Type (Node => Actual_Node) = SP_Symbols.positional_argument_association,
            Sys_Err => SystemErrors.Invalid_Syntax_Tree,
            Msg     => "Expect Actual_Node = named_argument_association OR positional_argument_association OR " &
              "in Check_Parameter_Overlap");
         --# assert Syntax_Node_Type (Actual_Node, STree.Table) = SP_Symbols.named_argument_association or
         --#   Syntax_Node_Type (Actual_Node, STree.Table) = SP_Symbols.positional_argument_association;
         Actual_Node := Child_Node (Current_Node => Actual_Node);
      end loop;
      -- ASSUME Actual_Node = simple_name OR expression
      if Syntax_Node_Type (Node => Actual_Node) = SP_Symbols.simple_name then
         -- ASSUME Actual_Node = simple_name
         -- named association
         Actual_Node := Next_Sibling (Current_Node => Actual_Node);
      elsif Syntax_Node_Type (Node => Actual_Node) /= SP_Symbols.expression then
         SystemErrors.Fatal_Error
           (Sys_Err => SystemErrors.Invalid_Syntax_Tree,
            Msg     => "Expect Actual_Node = simple_name OR expression in Check_Parameter_Overlap");
      end if;
      -- ASSUME Actual_Node = expression
      SystemErrors.RT_Assert
        (C       => Syntax_Node_Type (Node => Actual_Node) = SP_Symbols.expression,
         Sys_Err => SystemErrors.Invalid_Syntax_Tree,
         Msg     => "Expect Actual_Node = expression in Check_Parameter_Overlap");

      Err_Pos := Node_Position (Node => Actual_Node);

      -- Search for parameter overlap.
      for I in Positive range 1 .. SimpleLists.NumberOfItems (Actual_Parameter_List) loop
         --# assert SimpleLists.NumberOfItems (Actual_Parameter_List) in Natural and
         --#   Actual_Parameter_List = Actual_Parameter_List% and
         --#   (Syntax_Node_Type (Actual_Node, STree.Table) = SP_Symbols.expression or
         --#      Syntax_Node_Type (Actual_Node, STree.Table) = SP_Symbols.named_argument_association or
         --#      Syntax_Node_Type (Actual_Node, STree.Table) = SP_Symbols.positional_argument_association);
         Check_Overlap_Of_Exported_Parameter
           (Position              => I,
            Proc_Sym              => Proc_Sym,
            Err_Pos               => Err_Pos,
            Actual_Parameter_List => Actual_Parameter_List,
            Formal_Position_List  => Formal_Position_List,
            Abstraction           => Abstraction);
         Next_Err_Pos (Actual_Node => Actual_Node,
                       Err_Pos     => Err_Pos);
      end loop;
   end Check_Parameter_Overlap;

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

   procedure Check_Callable
     (Node_Pos : in     LexTokenManager.Token_Position;
      Proc_Sym : in     Dictionary.Symbol;
      Dotted   : in     Boolean;
      Scope    : in     Dictionary.Scopes;
      OK       :    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,
   --#                                         Dotted,
   --#                                         ErrorHandler.Error_Context,
   --#                                         LexTokenManager.State,
   --#                                         Node_Pos,
   --#                                         Proc_Sym,
   --#                                         Scope,
   --#                                         SPARK_IO.File_Sys &
   --#         OK                         from Dictionary.Dict,
   --#                                         Dotted,
   --#                                         Proc_Sym,
   --#                                         Scope;
   is
   begin
      if Dictionary.IsCallable (Proc_Sym, Dotted, Scope) then
         OK := True;
      else
         OK := False;
         ErrorHandler.Semantic_Error
           (Err_Num   => 163,
            Reference => ErrorHandler.No_Reference,
            Position  => Node_Pos,
            Id_Str    => Dictionary.GetSimpleName (Proc_Sym));
      end if;
   end Check_Callable;

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

   procedure Check_Not_Local_Procedure_Call_From_Protected_Function
     (Node_Pos : in     LexTokenManager.Token_Position;
      Proc_Sym : in     Dictionary.Symbol;
      Scope    : in     Dictionary.Scopes;
      OK       :    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,
   --#                                         LexTokenManager.State,
   --#                                         Node_Pos,
   --#                                         Proc_Sym,
   --#                                         Scope,
   --#                                         SPARK_IO.File_Sys &
   --#         OK                         from Dictionary.Dict,
   --#                                         Proc_Sym,
   --#                                         Scope;
   is
      Calling_Sym, Calling_Region : Dictionary.Symbol;
      Calling_Scope               : Dictionary.Scopes;
   begin
      OK := True;
      -- get symbol of caller
      Calling_Sym := Dictionary.GetEnclosingCompilationUnit (Scope);

      -- get package or protected type where caller is declared
      Calling_Scope := Dictionary.GetScope (Calling_Sym);
      loop
         Calling_Region := Dictionary.GetRegion (Calling_Scope);
         exit when Dictionary.IsProtectedType (TheSymbol => Calling_Region) or else Dictionary.IsPackage (Calling_Region);
         Calling_Scope := Dictionary.GetEnclosingScope (Calling_Scope);
      end loop;

      if Dictionary.IsFunction (Calling_Sym)
        and then Dictionary.IsProtectedType (TheSymbol => Calling_Region)
        and then Dictionary.IsTypeMark (Dictionary.GetRegion (Dictionary.GetScope (Proc_Sym)))
        and then Dictionary.Types_Are_Equal
        (Left_Symbol        => Dictionary.GetRegion (Dictionary.GetScope (Proc_Sym)),
         Right_Symbol       => Calling_Region,
         Full_Range_Subtype => False) then
         OK := False;
         ErrorHandler.Semantic_Error
           (Err_Num   => 986,
            Reference => ErrorHandler.No_Reference,
            Position  => Node_Pos,
            Id_Str    => Dictionary.GetSimpleName (Proc_Sym));
      end if;
   end Check_Not_Local_Procedure_Call_From_Protected_Function;

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

   procedure Check_Property_Consistency
     (Node_Pos                : in LexTokenManager.Token_Position;
      Prefix_Symbol, Proc_Sym : in Dictionary.Symbol;
      Actual_Parameter_List   : in SimpleLists.SimpleList;
      Scope                   : in Dictionary.Scopes)
   --# global in     CommandLineData.Content;
   --#        in     LexTokenManager.State;
   --#        in out Dictionary.Dict;
   --#        in out ErrorHandler.Error_Context;
   --#        in out SPARK_IO.File_Sys;
   --# derives Dictionary.Dict            from *,
   --#                                         Actual_Parameter_List,
   --#                                         CommandLineData.Content,
   --#                                         Prefix_Symbol,
   --#                                         Proc_Sym,
   --#                                         Scope &
   --#         ErrorHandler.Error_Context,
   --#         SPARK_IO.File_Sys          from Actual_Parameter_List,
   --#                                         CommandLineData.Content,
   --#                                         Dictionary.Dict,
   --#                                         ErrorHandler.Error_Context,
   --#                                         LexTokenManager.State,
   --#                                         Node_Pos,
   --#                                         Prefix_Symbol,
   --#                                         Proc_Sym,
   --#                                         Scope,
   --#                                         SPARK_IO.File_Sys;
   is
      The_PO_Or_SO_Sym : Dictionary.Symbol;
      Enc_Unit_Sym     : Dictionary.Symbol;
   begin
      Enc_Unit_Sym := Dictionary.GetEnclosingCompilationUnit (Scope);

      -- Check that if the procedure has a delay property then there is a
      -- delay property for the enclosing unit (if it is a procedure).
      -- Also mark the enclosing procedure as having come across a
      -- potentially delaying operation.
      if Dictionary.HasDelayProperty (Proc_Sym) and then Dictionary.Is_Subprogram (Enc_Unit_Sym) then
         if Dictionary.HasDelayProperty (Enc_Unit_Sym) then
            Dictionary.MarkAccountsForDelay (Enc_Unit_Sym);
         else
            ErrorHandler.Semantic_Error
              (Err_Num   => 912,
               Reference => ErrorHandler.No_Reference,
               Position  => Node_Pos,
               Id_Str    => Dictionary.GetSimpleName (Proc_Sym));
         end if;
      end if;

      -- Check that if this is a call to Suspend_Until_True then the actual parameter
      -- appears in the suspends list for the enclosing procedure. Also mark the
      -- enclosing unit as having seen the suspend until true call.
      if CommandLineData.Ravenscar_Selected and then Dictionary.IsPredefinedSuspendUntilTrueOperation (Proc_Sym) then
         The_PO_Or_SO_Sym := Actual_Parameter_At (Position              => 1,
                                                  Actual_Parameter_List => Actual_Parameter_List);
         if Dictionary.SuspendsOn (TheTaskOrProc => Enc_Unit_Sym,
                                   ThePOorSO     => The_PO_Or_SO_Sym) then
            Dictionary.MarkAccountsForSuspendsListItem (TheTaskOrProc => Enc_Unit_Sym,
                                                        ThePOorSO     => The_PO_Or_SO_Sym);
         else
            -- The suspension object does not appear in the suspends list for the
            -- enclosing unit.
            ErrorHandler.Semantic_Error_Sym
              (Err_Num   => 910,
               Reference => ErrorHandler.No_Reference,
               Position  => Node_Pos,
               Sym       => The_PO_Or_SO_Sym,
               Scope     => Scope);
         end if;
      end if;

      -- Check that if this is an entry then the protected object appears in the
      -- suspends list for the enclosing procedure. Also mark the enclosing unit
      -- as having seen the entry.
      if Dictionary.IsEntry (Proc_Sym) then
         if Dictionary.SuspendsOn (TheTaskOrProc => Enc_Unit_Sym,
                                   ThePOorSO     => Prefix_Symbol) then
            Dictionary.MarkAccountsForSuspendsListItem (TheTaskOrProc => Enc_Unit_Sym,
                                                        ThePOorSO     => Prefix_Symbol);
         else
            -- The protected object does not appear in the entry annotation for the enclosing
            -- unit.
            ErrorHandler.Semantic_Error_Sym
              (Err_Num   => 910,
               Reference => ErrorHandler.No_Reference,
               Position  => Node_Pos,
               Sym       => Prefix_Symbol,
               Scope     => Scope);
         end if;
      end if;

      -- Check that all the items in the suspends list for the procedure appear
      -- in the suspends list for the enclosing unit.
      if not Dictionary.SuspendsListIsPropagated (FromProcedure => Proc_Sym,
                                                  ToTaskOrProc  => Enc_Unit_Sym) then
         -- The operation being called contains entries that are not present in the
         -- entry list of the calling procedure.
         ErrorHandler.Semantic_Error
           (Err_Num   => 913,
            Reference => ErrorHandler.No_Reference,
            Position  => Node_Pos,
            Id_Str    => Dictionary.GetSimpleName (Proc_Sym));
      end if;
      -- Mark the entries declared in the called procedure as having been seen by the
      -- enclosing procedure. Any entries not propagated are ignored.
      Dictionary.MarkAccountsForSuspendsListItems (TheTaskOrProc       => Enc_Unit_Sym,
                                                   TheItemsInProcedure => Proc_Sym);
   end Check_Property_Consistency;

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

   -- In flow=auto we need to guard against a subprogram with a derives annotation calling
   -- a procedure without a derives annotation. In such cases, the body of the caller is
   -- subject to full information flow analysis, but using the synthesised dependency of
   -- the callee. This can give rise to 'false alarm' flow errors or, worse, absence of
   -- flow errors which could only be detected if there was a derives anno for the callee.
   procedure Check_For_Subprog_With_Derives_Calling_Proc_Without_Derives
     (Proc_Sym : in     Dictionary.Symbol;
      Scope    : in     Dictionary.Scopes;
      Node     : in     STree.SyntaxNode;
      OK       :    out Boolean)
   --# global in     CommandLineData.Content;
   --#        in     Dictionary.Dict;
   --#        in     LexTokenManager.State;
   --#        in     STree.Table;
   --#        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,
   --#                                         LexTokenManager.State,
   --#                                         Node,
   --#                                         Proc_Sym,
   --#                                         Scope,
   --#                                         SPARK_IO.File_Sys,
   --#                                         STree.Table &
   --#         OK                         from CommandLineData.Content,
   --#                                         Dictionary.Dict,
   --#                                         Proc_Sym,
   --#                                         Scope;
   is
      Calling_Sym : Dictionary.Symbol;
   begin
      OK := True;
      -- Get the symbol for the caller (ie the current subrogram)
      Calling_Sym := Dictionary.GetEnclosingCompilationUnit (Scope);

      -- This check is only relevant for flow=auto. In other modes it is always OK.
      -- Is the current subprogram a procedure, task or entry with a derives, or a function? If not then we are OK.
      -- If caller is a function or has a derives, does callee have a derives? If it does then we are OK,
      -- but if it doesn't then raise an error.
      if CommandLineData.Content.Flow_Option = CommandLineData.Auto_Flow
        and then Dictionary.GetHasDerivesAnnotation (Calling_Sym)
        and then not Dictionary.GetHasDerivesAnnotation (Proc_Sym) then
         -- If a function is calling a procedure without a derives anno the analysis will generally be
         -- correct but if, for example, the procedure derives null from one of its exports the analysis
         -- can be misleading. So we raise a warning if the caller is a function. If the caller is a
         -- procedure then the analysis cannot proceed - raise an error.
         if Dictionary.IsFunction (Calling_Sym) then
            ErrorHandler.Semantic_Warning_Sym
              (Err_Num  => 315,
               Position => Node_Position (Node => Node),
               Sym      => Proc_Sym,
               Scope    => Scope);
         else
            OK := False;
            ErrorHandler.Semantic_Error_Sym2
              (Err_Num   => 176,
               Reference => ErrorHandler.No_Reference,
               Position  => Node_Position (Node => Node),
               Sym       => Proc_Sym,
               Sym2      => Calling_Sym,
               Scope     => Scope);
         end if;
      end if;
   end Check_For_Subprog_With_Derives_Calling_Proc_Without_Derives;

begin -- Wf_Proc_Call
   if In_Package_Initialization (Scope => Scope) then
      ErrorHandler.Semantic_Error
        (Err_Num   => 34,
         Reference => ErrorHandler.No_Reference,
         Position  => Node_Position (Node => Node),
         Id_Str    => LexTokenManager.Null_String);
   else -- not in package initialization
      Param_Table := Param_Tables'(Param_Index => Param_Info'(0, Dictionary.NullSymbol));
      Check_Procedure_Name
        (Node                 => Node,
         Scope                => Scope,
         Root_Parameter_Sym   => Root_Parameter_Sym,
         Prefix_Symbol        => Prefix_Symbol,
         Proc_Sym             => Proc_Sym,
         Tagged_Parameter_Sym => Tagged_Parameter_Sym,
         Name_Node            => Name_Node,
         Dotted               => Dotted,
         Valid                => Valid);

      -- above call will also have set Tagged_Parameter_Sym which if not null is
      -- the type of the formal parameter to which an actual parameter of some
      -- extended type will have to be converted

      if Valid then
         -- determine which set of annotation to use
         Abstraction := Dictionary.GetAbstraction (Proc_Sym, Scope);

         if not Dictionary.SubprogramSignatureIsWellformed (Abstraction, Proc_Sym) then
            ErrorHandler.Semantic_Warning
              (Err_Num  => 399,
               Position => Node_Position (Node => Node),
               Id_Str   => LexTokenManager.Null_String);
         end if;

         if Child_Node (Current_Node => Node) /= Name_Node
           and then Child_Node (Current_Node => Child_Node (Current_Node => Node)) /= Name_Node then
            Valid := False;
            ErrorHandler.Semantic_Error
              (Err_Num   => 34,
               Reference => ErrorHandler.No_Reference,
               Position  => Node_Position (Node => Node),
               Id_Str    => LexTokenManager.Null_String);
         end if;
      end if;

      --# assert Syntax_Node_Type (Node, STree.Table) = SP_Symbols.procedure_call_statement and
      --#   Syntax_Node_Type (Name_Node, STree.Table) = SP_Symbols.name and
      --#   (Dictionary.Is_Null_Symbol (Proc_Sym) or Dictionary.IsProcedure (Proc_Sym, Dictionary.Dict)) and
      --#   STree.Table = STree.Table~;

      if Valid then
         Check_Callable
           (Node_Pos => Node_Position (Node => Node),
            Proc_Sym => Proc_Sym,
            Dotted   => Dotted,
            Scope    => Scope,
            OK       => Valid);
      end if;

      --# assert Syntax_Node_Type (Node, STree.Table) = SP_Symbols.procedure_call_statement and
      --#   Syntax_Node_Type (Name_Node, STree.Table) = SP_Symbols.name and
      --#   (Dictionary.Is_Null_Symbol (Proc_Sym) or Dictionary.IsProcedure (Proc_Sym, Dictionary.Dict)) and
      --#   STree.Table = STree.Table~;

      if Valid then
         Check_Not_Local_Procedure_Call_From_Protected_Function
           (Node_Pos => Node_Position (Node => Node),
            Proc_Sym => Proc_Sym,
            Scope    => Scope,
            OK       => Valid);
      end if;

      --# assert Syntax_Node_Type (Node, STree.Table) = SP_Symbols.procedure_call_statement and
      --#   Syntax_Node_Type (Name_Node, STree.Table) = SP_Symbols.name and
      --#   (Dictionary.Is_Null_Symbol (Proc_Sym) or Dictionary.IsProcedure (Proc_Sym, Dictionary.Dict)) and
      --#   STree.Table = STree.Table~;

      if Valid
        and then CommandLineData.Ravenscar_Selected
        and then Dictionary.IsOrIsInProtectedScope (Scope)
        and then Dictionary.SubprogramMayBlock (Proc_Sym) then
         Valid := False;
         ErrorHandler.Semantic_Error
           (Err_Num   => 917,
            Reference => ErrorHandler.No_Reference,
            Position  => Node_Position (Node => Node),
            Id_Str    => Dictionary.GetSimpleName (Proc_Sym));
      end if;

      --# assert Syntax_Node_Type (Node, STree.Table) = SP_Symbols.procedure_call_statement and
      --#   Syntax_Node_Type (Name_Node, STree.Table) = SP_Symbols.name and
      --#   (Dictionary.Is_Null_Symbol (Proc_Sym) or Dictionary.IsProcedure (Proc_Sym, Dictionary.Dict)) and
      --#   STree.Table = STree.Table~;

      if Valid
        and then CommandLineData.Ravenscar_Selected
        and then Dictionary.IsFunction (Dictionary.GetRegion (Scope))
        and then Dictionary.SubprogramMayBlock (Proc_Sym) then
         Valid := False;
         ErrorHandler.Semantic_Error
           (Err_Num   => 923,
            Reference => ErrorHandler.No_Reference,
            Position  => Node_Position (Node => Node),
            Id_Str    => Dictionary.GetSimpleName (Proc_Sym));
      end if;

      --# assert Syntax_Node_Type (Node, STree.Table) = SP_Symbols.procedure_call_statement and
      --#   Syntax_Node_Type (Name_Node, STree.Table) = SP_Symbols.name and
      --#   (Dictionary.Is_Null_Symbol (Proc_Sym) or Dictionary.IsProcedure (Proc_Sym, Dictionary.Dict)) and
      --#   STree.Table = STree.Table~;

      if Valid and then Dictionary.IsInterruptHandler (Proc_Sym) then
         Valid := False;
         ErrorHandler.Semantic_Error_Sym
           (Err_Num   => 952,
            Reference => ErrorHandler.No_Reference,
            Position  => Node_Position (Node => Node),
            Sym       => Proc_Sym,
            Scope     => Scope);
      end if;

      --# assert Syntax_Node_Type (Node, STree.Table) = SP_Symbols.procedure_call_statement and
      --#   Syntax_Node_Type (Name_Node, STree.Table) = SP_Symbols.name and
      --#   (Dictionary.Is_Null_Symbol (Proc_Sym) or Dictionary.IsProcedure (Proc_Sym, Dictionary.Dict)) and
      --#   STree.Table = STree.Table~;

      if Valid then
         Check_For_Subprog_With_Derives_Calling_Proc_Without_Derives
           (Proc_Sym => Proc_Sym,
            Scope    => Scope,
            Node     => Node,
            OK       => Valid);
      end if;

      --# assert Syntax_Node_Type (Node, STree.Table) = SP_Symbols.procedure_call_statement and
      --#   Syntax_Node_Type (Name_Node, STree.Table) = SP_Symbols.name and
      --#   (Dictionary.Is_Null_Symbol (Proc_Sym) or Dictionary.IsProcedure (Proc_Sym, Dictionary.Dict)) and
      --#   STree.Table = STree.Table~;

      if Valid then
         SimpleLists.Init (Actual_Parameter_List);
         SimpleLists.Init (Formal_Position_List);

         Check_Globals_Are_Visible
           (Node_Pos      => Node_Position (Node => Node),
            Prefix_Symbol => Prefix_Symbol,
            Proc_Sym      => Proc_Sym,
            Scope         => Scope,
            Abstraction   => Abstraction);
         Arg_List_Node := Next_Sibling (Current_Node => Name_Node);
         -- ASSUME Arg_List_Node = name_argument_list OR NULL
         if Arg_List_Node = STree.NullNode then
            -- ASSUME Arg_List_Node = NULL
            -- parameterless procedure call
            if Dictionary.GetNumberOfSubprogramParameters (Proc_Sym) /= 0 then
               ErrorHandler.Semantic_Error
                 (Err_Num   => 3,
                  Reference => ErrorHandler.No_Reference,
                  Position  => Node_Position (Node => Node),
                  Id_Str    => Dictionary.GetSimpleName (Proc_Sym));
            end if;
         elsif Syntax_Node_Type (Node => Arg_List_Node) = SP_Symbols.name_argument_list then
            -- ASSUME Arg_List_Node = name_argument_list
            -- parameter node found
            if Dictionary.GetNumberOfSubprogramParameters (Proc_Sym) = 0 then
               ErrorHandler.Semantic_Error
                 (Err_Num   => 3,
                  Reference => ErrorHandler.No_Reference,
                  Position  => Node_Position (Node => Arg_List_Node),
                  Id_Str    => Dictionary.GetSimpleName (Proc_Sym));
            else
               Arg_List_Node := Child_Node (Current_Node => Arg_List_Node);
               -- ASSUME Arg_List_Node = named_argument_association OR positional_argument_association
               if Syntax_Node_Type (Node => Arg_List_Node) = SP_Symbols.named_argument_association then
                  -- ASSUME Arg_List_Node = named_argument_association
                  Handle_Named_Association
                    (Named_Argument_Assoc_Node => Arg_List_Node,
                     Root_Parameter_Sym        => Root_Parameter_Sym,
                     Proc_Sym                  => Proc_Sym,
                     Tagged_Parameter_Sym      => Tagged_Parameter_Sym,
                     Scope                     => Scope,
                     Abstraction               => Abstraction,
                     Actual_Parameter_List     => Actual_Parameter_List,
                     Formal_Position_List      => Formal_Position_List,
                     Param_Table               => Param_Table,
                     Component_Data            => Component_Data); -- Abstraction defined since Valid
               elsif Syntax_Node_Type (Node => Arg_List_Node) = SP_Symbols.positional_argument_association then
                  -- ASSUME Arg_List_Node = positional_argument_association
                  Handle_Positional_Association
                    (Positional_Argument_Assoc_Node => Arg_List_Node,
                     Root_Parameter_Sym             => Root_Parameter_Sym,
                     Proc_Sym                       => Proc_Sym,
                     Tagged_Parameter_Sym           => Tagged_Parameter_Sym,
                     Scope                          => Scope,
                     Abstraction                    => Abstraction,
                     Actual_Parameter_List          => Actual_Parameter_List,
                     Formal_Position_List           => Formal_Position_List,
                     Param_Table                    => Param_Table,
                     Component_Data                 => Component_Data); -- Abstraction defined since Valid
               else
                  SystemErrors.Fatal_Error
                    (Sys_Err => SystemErrors.Invalid_Syntax_Tree,
                     Msg     => "Expect Arg_List_Node = named_argument_association OR " &
                       "positional_argument_association in Wf_Proc_Call");
               end if;
               Check_Parameter_Overlap
                 (Arg_List_Node         => Arg_List_Node,
                  Proc_Sym              => Proc_Sym,
                  Actual_Parameter_List => Actual_Parameter_List,
                  Formal_Position_List  => Formal_Position_List,
                  Abstraction           => Abstraction); -- Abstraction defined since Valid
            end if;
         else
            SystemErrors.Fatal_Error
              (Sys_Err => SystemErrors.Invalid_Syntax_Tree,
               Msg     => "Expect Arg_List_Node = name_argument_list OR NULL in Wf_Proc_Call");
         end if;

         Build_IO_Relation
           (Node               => Node,
            Scope              => Scope,
            Root_Parameter_Sym => Root_Parameter_Sym,
            Prefix_Symbol      => Prefix_Symbol,
            Proc_Sym           => Proc_Sym,
            Param_Table        => Param_Table,
            Abstraction        => Abstraction,
            Component_Data     => Component_Data,
            Table              => Table);

         Check_Property_Consistency
           (Node_Pos              => Node_Position (Node => Node),
            Prefix_Symbol         => Prefix_Symbol,
            Proc_Sym              => Proc_Sym,
            Actual_Parameter_List => Actual_Parameter_List,
            Scope                 => Scope);
      end if;

      SystemErrors.RT_Assert
        (C       => Dictionary.Is_Null_Symbol (Proc_Sym) or else Dictionary.IsProcedure (Proc_Sym),
         Sys_Err => SystemErrors.Invalid_Syntax_Tree,
         Msg     => "Expect Proc_Sym to be a procedure in Wf_Proc_Call");

      --# assert Syntax_Node_Type (Node, STree.Table) = SP_Symbols.procedure_call_statement and
      --#   (Dictionary.Is_Null_Symbol (Proc_Sym) or Dictionary.IsProcedure (Proc_Sym, Dictionary.Dict)) and
      --#   STree.Table = STree.Table~;

      -- If we have ended calling an inherited root operation then we need to tell
      -- the VCG which subprogram actually got called.  We know that a root op has
      -- been called if Tagged_Parameter_Sym is not null.  In that case we seed the
      -- procedure_call_statement syntax node with the symbol of the root procedure
      -- called.
      if not Dictionary.Is_Null_Symbol (Tagged_Parameter_Sym) then
         STree.Add_Node_Symbol (Node => Node,
                                Sym  => Proc_Sym);
         -- If we are not dealing with an inherited root operation then we MAY be dealing with
         -- a protected operation call.  Such calls are annotated in terms of their TYPE but we
         -- will want to substitute the particular PO instance of the type.  We can pass this
         -- prefix (PO in this case) to the VCG via the syntax tree.  Note that previous and
         -- current if clauses are mutually exclusive - there are no protected tagged ops.
      elsif not Dictionary.Is_Null_Symbol (Prefix_Symbol)
        and then Dictionary.IsOwnVariable (Prefix_Symbol)
        and then Dictionary.GetOwnVariableProtected (Prefix_Symbol) then
         STree.Add_Node_Symbol (Node => Node,
                                Sym  => Prefix_Symbol);
      end if;
   end if; -- in package initialization
end Wf_Proc_Call; -- Abstraction always defined if used
