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

with SLI;

separate (Sem.Dependency_Relation)
procedure Wf_Dependency_Relation
  (Node         : in     STree.SyntaxNode;
   Scope        : in     Dictionary.Scopes;
   Subprog_Sym  : in     Dictionary.Symbol;
   First_Seen   : in     Boolean;
   Glob_Def_Err : in     Boolean;
   The_Heap     : in out Heap.HeapRecord)
is
   It                                                                 : STree.Iterator;
   Next_Node                                                          : STree.SyntaxNode;
   Position                                                           : LexTokenManager.Token_Position;
   Abstraction                                                        : Dictionary.Abstractions;
   Error, Semantic_Error_Found                                        : Boolean;
   Export_List, Import_List, Exports_In_Relation, Imports_In_Relation : SeqAlgebra.Seq;
   Null_Import_Node                                                   : STree.SyntaxNode; -- location of "derives null..."

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

   procedure Wf_Dependency_Clause
     (Node                     : in     STree.SyntaxNode;
      Scope                    : in     Dictionary.Scopes;
      Subprog_Sym              : in     Dictionary.Symbol;
      Abstraction              : in     Dictionary.Abstractions;
      Do_IFA                   : in     Boolean;
      The_Heap                 : in out Heap.HeapRecord;
      Export_List, Import_List :    out SeqAlgebra.Seq;
      Error_Found              :    out Boolean)
   --# global in     CommandLineData.Content;
   --#        in     ContextManager.Ops.Unit_Stack;
   --#        in     LexTokenManager.State;
   --#        in out Dictionary.Dict;
   --#        in out ErrorHandler.Error_Context;
   --#        in out SPARK_IO.File_Sys;
   --#        in out Statistics.TableUsage;
   --#        in out STree.Table;
   --# derives Dictionary.Dict,
   --#         Statistics.TableUsage,
   --#         STree.Table,
   --#         The_Heap                   from *,
   --#                                         Abstraction,
   --#                                         CommandLineData.Content,
   --#                                         ContextManager.Ops.Unit_Stack,
   --#                                         Dictionary.Dict,
   --#                                         Do_IFA,
   --#                                         LexTokenManager.State,
   --#                                         Node,
   --#                                         STree.Table,
   --#                                         Subprog_Sym,
   --#                                         The_Heap &
   --#         ErrorHandler.Error_Context,
   --#         SPARK_IO.File_Sys          from Abstraction,
   --#                                         CommandLineData.Content,
   --#                                         ContextManager.Ops.Unit_Stack,
   --#                                         Dictionary.Dict,
   --#                                         Do_IFA,
   --#                                         ErrorHandler.Error_Context,
   --#                                         LexTokenManager.State,
   --#                                         Node,
   --#                                         Scope,
   --#                                         SPARK_IO.File_Sys,
   --#                                         STree.Table,
   --#                                         Subprog_Sym,
   --#                                         The_Heap &
   --#         Error_Found                from Abstraction,
   --#                                         CommandLineData.Content,
   --#                                         ContextManager.Ops.Unit_Stack,
   --#                                         Dictionary.Dict,
   --#                                         Do_IFA,
   --#                                         LexTokenManager.State,
   --#                                         Node,
   --#                                         STree.Table,
   --#                                         Subprog_Sym,
   --#                                         The_Heap &
   --#         Export_List,
   --#         Import_List                from The_Heap;
   --# pre STree.Syntax_Node_Type (Node, STree.Table) = SP_Symbols.dependency_clause or
   --#   STree.Syntax_Node_Type (Node, STree.Table) = SP_Symbols.null_import_list;
   --# post STree.Table = STree.Table~;
   is
      Star_Node, Import_List_Node : STree.SyntaxNode := STree.NullNode;
      Export_List_Node            : STree.SyntaxNode;
      First_Valid_Export          : Dictionary.Symbol;
      Global_Variable_Sym         : Dictionary.Symbol;
      Null_List                   : Boolean          := False;

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

      procedure Valid_Export_List_Add
        (Sym         : in     Dictionary.Symbol;
         Export_List : in     SeqAlgebra.Seq;
         The_Heap    : in out Heap.HeapRecord)
      --# global in out Statistics.TableUsage;
      --# derives Statistics.TableUsage,
      --#         The_Heap              from *,
      --#                                    Export_List,
      --#                                    Sym,
      --#                                    The_Heap;
      is
      begin
         SeqAlgebra.AddMember (The_Heap, Export_List, Natural (Dictionary.SymbolRef (Sym)));
      end Valid_Export_List_Add;

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

      -- We check that imports are of the correct mode and (at the
      -- main progam level) that they are initialized.  If the import list
      -- includes a * self reference we do not need to make these checks where the
      -- import being checked is also an export since the checks will already have
      -- been made at the * node.  This function is used by Check_Import_Mode and
      -- Check_Import_Init because the check needed is the same in both cases.

      function Export_Imported_By_Star
        (Import_Sym  : Dictionary.Symbol;
         Export_List : SeqAlgebra.Seq;
         Star_Found  : Boolean;
         The_Heap    : Heap.HeapRecord)
        return        Boolean
      is
      begin
         return Star_Found and then SeqAlgebra.IsMember (The_Heap, Export_List, Natural (Dictionary.SymbolRef (Import_Sym)));
      end Export_Imported_By_Star;

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

      -- ignore checks if the import is an export which has already been
      -- imported by use of the * abbreviation; this is because checks will already
      -- have been carried out at the * node.

      procedure Check_Import_Mode
        (Import_Sym  : in     Dictionary.Symbol;
         Subprog_Sym : in     Dictionary.Symbol;
         Scope       : in     Dictionary.Scopes;
         Abstraction : in     Dictionary.Abstractions;
         Export_List : in     SeqAlgebra.Seq;
         Error_Pos   : in     LexTokenManager.Token_Position;
         Star_Found  : in     Boolean;
         The_Heap    : in     Heap.HeapRecord;
         Error_Found : in out Boolean)
      --# global in     CommandLineData.Content;
      --#        in     Dictionary.Dict;
      --#        in     LexTokenManager.State;
      --#        in out ErrorHandler.Error_Context;
      --#        in out SPARK_IO.File_Sys;
      --# derives ErrorHandler.Error_Context,
      --#         SPARK_IO.File_Sys          from Abstraction,
      --#                                         CommandLineData.Content,
      --#                                         Dictionary.Dict,
      --#                                         ErrorHandler.Error_Context,
      --#                                         Error_Pos,
      --#                                         Export_List,
      --#                                         Import_Sym,
      --#                                         LexTokenManager.State,
      --#                                         Scope,
      --#                                         SPARK_IO.File_Sys,
      --#                                         Star_Found,
      --#                                         Subprog_Sym,
      --#                                         The_Heap &
      --#         Error_Found                from *,
      --#                                         Abstraction,
      --#                                         Dictionary.Dict,
      --#                                         Export_List,
      --#                                         Import_Sym,
      --#                                         Star_Found,
      --#                                         Subprog_Sym,
      --#                                         The_Heap;
      is
      begin
         if not Export_Imported_By_Star
           (Import_Sym  => Import_Sym,
            Export_List => Export_List,
            Star_Found  => Star_Found,
            The_Heap    => The_Heap) then
            if Dictionary.IsFormalParameter (Subprog_Sym, Import_Sym) then
               if Dictionary.GetSubprogramParameterMode (Import_Sym) = Dictionary.OutMode then
                  Error_Found := True;
                  ErrorHandler.Semantic_Error
                    (Err_Num   => 162,
                     Reference => ErrorHandler.No_Reference,
                     Position  => Error_Pos,
                     Id_Str    => Dictionary.GetSimpleName (Import_Sym));
               end if;
            elsif -- check mode, only "OUT" is unacceptable
              Dictionary.GetGlobalMode (Abstraction, Subprog_Sym, Import_Sym) = Dictionary.OutMode then
               Error_Found := True;
               ErrorHandler.Semantic_Error_Sym
                 (Err_Num   => 503,
                  Reference => ErrorHandler.No_Reference,
                  Position  => Error_Pos,
                  Sym       => Import_Sym,
                  Scope     => Scope);
            end if;
            -- check here that we are not trying to import a mode out stream variable
            if Dictionary.GetOwnVariableOrConstituentMode (Import_Sym) = Dictionary.OutMode then
               ErrorHandler.Semantic_Error
                 (Err_Num   => 714,
                  Reference => ErrorHandler.No_Reference,
                  Position  => Error_Pos,
                  Id_Str    => Dictionary.GetSimpleName (Import_Sym));
               Error_Found := True;
            end if;
         end if;
      end Check_Import_Mode;

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

      -- ignore checks if the import is an export which has already been
      -- imported by use of the * abbreviation; this is because checks will already
      -- have been carried out at the * node.

      procedure Check_Import_Init
        (Import_Node_Pos         : in     LexTokenManager.Token_Position;
         Import_Sym, Subprog_Sym : in     Dictionary.Symbol;
         Scope                   : in     Dictionary.Scopes;
         Abstraction             : in     Dictionary.Abstractions;
         Export_List             : in     SeqAlgebra.Seq;
         Star_Found              : in     Boolean;
         The_Heap                : in     Heap.HeapRecord;
         Error_Found             : in out Boolean)
      --# global in     CommandLineData.Content;
      --#        in     Dictionary.Dict;
      --#        in     LexTokenManager.State;
      --#        in out ErrorHandler.Error_Context;
      --#        in out SPARK_IO.File_Sys;
      --# derives ErrorHandler.Error_Context,
      --#         SPARK_IO.File_Sys          from Abstraction,
      --#                                         CommandLineData.Content,
      --#                                         Dictionary.Dict,
      --#                                         ErrorHandler.Error_Context,
      --#                                         Export_List,
      --#                                         Import_Node_Pos,
      --#                                         Import_Sym,
      --#                                         LexTokenManager.State,
      --#                                         Scope,
      --#                                         SPARK_IO.File_Sys,
      --#                                         Star_Found,
      --#                                         Subprog_Sym,
      --#                                         The_Heap &
      --#         Error_Found                from *,
      --#                                         Abstraction,
      --#                                         Dictionary.Dict,
      --#                                         Export_List,
      --#                                         Import_Sym,
      --#                                         Star_Found,
      --#                                         Subprog_Sym,
      --#                                         The_Heap;
      is
      begin
         if not Export_Imported_By_Star
           (Import_Sym  => Import_Sym,
            Export_List => Export_List,
            Star_Found  => Star_Found,
            The_Heap    => The_Heap) then
            if Dictionary.IsTaskType (Subprog_Sym)
              and then Dictionary.IsOwnVariable (Import_Sym)
              and then not Dictionary.GetOwnVariableProtected (Import_Sym)
              and then Dictionary.GetOwnVariableMode (Import_Sym) /= Dictionary.InMode then
               -- This is an unprotected import to a task that is not of mode in.
               -- The elaboration policy is concurrent and hence we cannot
               -- guarantee the import is initialised before it is used.
               Error_Found := True;
               ErrorHandler.Semantic_Error_Sym
                 (Err_Num   => 958,
                  Reference => ErrorHandler.No_Reference,
                  Position  => Import_Node_Pos,
                  Sym       => Import_Sym,
                  Scope     => Scope);

            elsif (Dictionary.IsMainProgram (Subprog_Sym) or else Dictionary.IsTaskType (Subprog_Sym)) then
               if Dictionary.Is_Global_Variable (Abstraction, Subprog_Sym, Import_Sym)
                 and then Dictionary.IsOwnVariable (Import_Sym)
                 and then not Dictionary.OwnVariableIsInitialized (Import_Sym)
                 and then Dictionary.GetOwnVariableOrConstituentMode (Import_Sym) = Dictionary.DefaultMode then
                  Error_Found := True;
                  ErrorHandler.Semantic_Error
                    (Err_Num   => 167,
                     Reference => ErrorHandler.No_Reference,
                     Position  => Import_Node_Pos,
                     Id_Str    => Dictionary.GetSimpleName (Import_Sym));
               end if;
            end if;
         end if;
      end Check_Import_Init;

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

      procedure Do_Export_List
        (Node        : in     STree.SyntaxNode;
         Subprog_Sym : in     Dictionary.Symbol;
         Scope       : in     Dictionary.Scopes;
         Abstraction : in     Dictionary.Abstractions;
         Export_List : in     SeqAlgebra.Seq;
         The_Heap    : in out Heap.HeapRecord;
         Error_Found : in out Boolean)
      --# global in     CommandLineData.Content;
      --#        in     LexTokenManager.State;
      --#        in out Dictionary.Dict;
      --#        in out ErrorHandler.Error_Context;
      --#        in out SPARK_IO.File_Sys;
      --#        in out Statistics.TableUsage;
      --#        in out STree.Table;
      --# derives Dictionary.Dict,
      --#         Error_Found,
      --#         STree.Table                from *,
      --#                                         Abstraction,
      --#                                         CommandLineData.Content,
      --#                                         Dictionary.Dict,
      --#                                         LexTokenManager.State,
      --#                                         Node,
      --#                                         STree.Table,
      --#                                         Subprog_Sym &
      --#         ErrorHandler.Error_Context,
      --#         SPARK_IO.File_Sys          from Abstraction,
      --#                                         CommandLineData.Content,
      --#                                         Dictionary.Dict,
      --#                                         ErrorHandler.Error_Context,
      --#                                         LexTokenManager.State,
      --#                                         Node,
      --#                                         Scope,
      --#                                         SPARK_IO.File_Sys,
      --#                                         STree.Table,
      --#                                         Subprog_Sym &
      --#         Statistics.TableUsage,
      --#         The_Heap                   from *,
      --#                                         Abstraction,
      --#                                         CommandLineData.Content,
      --#                                         Dictionary.Dict,
      --#                                         Export_List,
      --#                                         LexTokenManager.State,
      --#                                         Node,
      --#                                         STree.Table,
      --#                                         Subprog_Sym,
      --#                                         The_Heap;
      --# pre STree.Syntax_Node_Type (Node, STree.Table) = SP_Symbols.dependency_clause_optrep;
      --# post STree.Table = STree.Table~;
      is
         Sym         : Dictionary.Symbol;
         It          : STree.Iterator;
         Export_Node : STree.SyntaxNode;
         Unused      : Boolean;

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

         procedure Check_Export_Mode
           (Export_Sym  : in     Dictionary.Symbol;
            Subprog_Sym : in     Dictionary.Symbol;
            Scope       : in     Dictionary.Scopes;
            Abstraction : in     Dictionary.Abstractions;
            Error_Pos   : in     LexTokenManager.Token_Position;
            Error_Found : in out Boolean)
         --# global in     CommandLineData.Content;
         --#        in     Dictionary.Dict;
         --#        in     LexTokenManager.State;
         --#        in out ErrorHandler.Error_Context;
         --#        in out SPARK_IO.File_Sys;
         --# derives ErrorHandler.Error_Context,
         --#         SPARK_IO.File_Sys          from Abstraction,
         --#                                         CommandLineData.Content,
         --#                                         Dictionary.Dict,
         --#                                         ErrorHandler.Error_Context,
         --#                                         Error_Pos,
         --#                                         Export_Sym,
         --#                                         LexTokenManager.State,
         --#                                         Scope,
         --#                                         SPARK_IO.File_Sys,
         --#                                         Subprog_Sym &
         --#         Error_Found                from *,
         --#                                         Abstraction,
         --#                                         Dictionary.Dict,
         --#                                         Export_Sym,
         --#                                         Subprog_Sym;
         --#
         is
            Mode : Dictionary.Modes;
         begin
            if Dictionary.IsFormalParameter (Subprog_Sym, Export_Sym) then
               Mode := Dictionary.GetSubprogramParameterMode (Export_Sym);
               if Mode = Dictionary.InMode or else Mode = Dictionary.DefaultMode then
                  Error_Found := True;
                  ErrorHandler.Semantic_Error
                    (Err_Num   => 161,
                     Reference => ErrorHandler.No_Reference,
                     Position  => Error_Pos,
                     Id_Str    => Dictionary.GetSimpleName (Export_Sym));
               end if;
            else -- check mode, only "IN" is unacceptable
               Mode := Dictionary.GetGlobalMode (Abstraction, Subprog_Sym, Export_Sym);
               if Mode = Dictionary.InMode then
                  Error_Found := True;
                  ErrorHandler.Semantic_Error_Sym
                    (Err_Num   => 502,
                     Reference => ErrorHandler.No_Reference,
                     Position  => Error_Pos,
                     Sym       => Export_Sym,
                     Scope     => Scope);
               end if;
            end if;
         end Check_Export_Mode;

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

         procedure Unique_Export
           (Export_Sym  : in out Dictionary.Symbol;
            Error_Pos   : in     LexTokenManager.Token_Position;
            Subprog_Sym : in     Dictionary.Symbol;
            Abstraction : in     Dictionary.Abstractions;
            Error_Found : in out Boolean)
         --# global in     CommandLineData.Content;
         --#        in     Dictionary.Dict;
         --#        in     LexTokenManager.State;
         --#        in out ErrorHandler.Error_Context;
         --#        in out SPARK_IO.File_Sys;
         --# derives ErrorHandler.Error_Context,
         --#         SPARK_IO.File_Sys          from Abstraction,
         --#                                         CommandLineData.Content,
         --#                                         Dictionary.Dict,
         --#                                         ErrorHandler.Error_Context,
         --#                                         Error_Pos,
         --#                                         Export_Sym,
         --#                                         LexTokenManager.State,
         --#                                         SPARK_IO.File_Sys,
         --#                                         Subprog_Sym &
         --#         Error_Found,
         --#         Export_Sym                 from *,
         --#                                         Abstraction,
         --#                                         Dictionary.Dict,
         --#                                         Export_Sym,
         --#                                         Subprog_Sym;
         is
            Next_Export : Dictionary.Iterator;
         begin
            Next_Export := Dictionary.FirstExport (Abstraction, Subprog_Sym);
            while Next_Export /= Dictionary.NullIterator loop
               if Export_Sym = Dictionary.CurrentSymbol (Next_Export) then
                  Error_Found := True;
                  ErrorHandler.Semantic_Error
                    (Err_Num   => 159,
                     Reference => ErrorHandler.No_Reference,
                     Position  => Error_Pos,
                     Id_Str    => Dictionary.GetSimpleName (Export_Sym));
                  Export_Sym := Dictionary.NullSymbol;
                  exit;
               end if;
               Next_Export := Dictionary.NextSymbol (Next_Export);
            end loop;
         end Unique_Export;

      begin -- Do_Export_List
         It := STree.Find_First_Node (Node_Kind    => SP_Symbols.entire_variable,
                                      From_Root    => Node,
                                      In_Direction => STree.Down);
         while not STree.IsNull (It) loop
            Export_Node := STree.Get_Node (It => It);
            --# assert STree.Table = STree.Table~ and
            --#   STree.Syntax_Node_Type (Node, STree.Table) = SP_Symbols.dependency_clause_optrep and
            --#   STree.Syntax_Node_Type (Export_Node, STree.Table) = SP_Symbols.entire_variable and
            --#   Export_Node = STree.Get_Node (It);
            --# accept Flow, 10, Unused, "Expected ineffective assignment";
            Sem.Wf_Entire_Variable
              (Node       => Export_Node,
               Scope      => Dictionary.Set_Visibility (The_Visibility => Dictionary.Local,
                                                        The_Unit       => Subprog_Sym),
               Error_Hint => Sem.In_Derives_Export_List,
               Var_Sym    => Sym,
               Dotted     => Unused);
            --# end accept;
            Error_Found := Error_Found or else Dictionary.Is_Null_Symbol (Sym);
            if not Dictionary.Is_Null_Symbol (Sym) then
               Unique_Export
                 (Export_Sym  => Sym,
                  Error_Pos   => STree.Node_Position (Node => Export_Node),
                  Subprog_Sym => Subprog_Sym,
                  Abstraction => Abstraction,
                  Error_Found => Error_Found);
            end if;
            -- check that the export is not a stream variable of mode in
            if not Dictionary.Is_Null_Symbol (Sym) then
               if Dictionary.GetOwnVariableOrConstituentMode (Sym) = Dictionary.InMode then
                  ErrorHandler.Semantic_Error
                    (Err_Num   => 713,
                     Reference => ErrorHandler.No_Reference,
                     Position  => STree.Node_Position (Node => Export_Node),
                     Id_Str    => Dictionary.GetSimpleName (Sym));
                  Error_Found := True;
                  Sym         := Dictionary.NullSymbol;
               end if;
            end if;
            if Dictionary.IsTaskType (Subprog_Sym)
              and then Dictionary.IsOwnVariable (Sym)
              and then not Dictionary.GetOwnVariableProtected (Sym)
              and then Dictionary.OwnVariableIsInitialized (Sym) then
               -- This export is defined during elaboration as well by this task.
               -- The order is non-deterministic. Hence we must prohibit the export
               -- being initialised during elaboration.
               ErrorHandler.Semantic_Error_Sym
                 (Err_Num   => 959,
                  Reference => ErrorHandler.No_Reference,
                  Position  => STree.Node_Position (Node => Export_Node),
                  Sym       => Sym,
                  Scope     => Scope);
            end if;
            if not Dictionary.Is_Null_Symbol (Sym) then
               Check_Export_Mode
                 (Export_Sym  => Sym,
                  Subprog_Sym => Subprog_Sym,
                  Scope       => Scope,
                  Abstraction => Abstraction,
                  Error_Pos   => STree.Node_Position (Node => Export_Node),
                  Error_Found => Error_Found);
               Dictionary.AddExport
                 (Abstraction     => Abstraction,
                  TheProcedure    => Subprog_Sym,
                  TheExport       => Sym,
                  ExportReference => Dictionary.Location'(Start_Position => STree.Node_Position (Node => Export_Node),
                                                          End_Position   => STree.Node_Position (Node => Export_Node)),
                  Annotation      => Dictionary.Location'(Start_Position => STree.Node_Position (Node => Node),
                                                          End_Position   => STree.Node_Position (Node => Node)));
               Valid_Export_List_Add (Sym         => Sym,
                                      Export_List => Export_List,
                                      The_Heap    => The_Heap);
            end if;
            It := STree.NextNode (It);
         end loop;
         --# accept Flow, 33, Unused, "Expected to be neither referenced nor exported";
      end Do_Export_List;

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

      procedure Do_Import_List
        (Node                     : in     STree.SyntaxNode;
         Subprog_Sym              : in     Dictionary.Symbol;
         Scope                    : in     Dictionary.Scopes;
         Abstraction              : in     Dictionary.Abstractions;
         Do_IFA                   : in     Boolean;
         Export_List, Import_List : in     SeqAlgebra.Seq;
         Null_List                : in     Boolean;
         Star_Found               : in     Boolean;
         The_Heap                 : in out Heap.HeapRecord;
         Error_Found              : in out Boolean;
         First_Valid_Export       :    out Dictionary.Symbol)
      --# global in     CommandLineData.Content;
      --#        in     ContextManager.Ops.Unit_Stack;
      --#        in     LexTokenManager.State;
      --#        in out Dictionary.Dict;
      --#        in out ErrorHandler.Error_Context;
      --#        in out SPARK_IO.File_Sys;
      --#        in out Statistics.TableUsage;
      --#        in out STree.Table;
      --# derives Dictionary.Dict,
      --#         Error_Found,
      --#         Statistics.TableUsage,
      --#         STree.Table,
      --#         The_Heap                   from *,
      --#                                         Abstraction,
      --#                                         CommandLineData.Content,
      --#                                         ContextManager.Ops.Unit_Stack,
      --#                                         Dictionary.Dict,
      --#                                         Do_IFA,
      --#                                         Export_List,
      --#                                         Import_List,
      --#                                         LexTokenManager.State,
      --#                                         Node,
      --#                                         Null_List,
      --#                                         Star_Found,
      --#                                         STree.Table,
      --#                                         Subprog_Sym,
      --#                                         The_Heap &
      --#         ErrorHandler.Error_Context,
      --#         SPARK_IO.File_Sys          from Abstraction,
      --#                                         CommandLineData.Content,
      --#                                         ContextManager.Ops.Unit_Stack,
      --#                                         Dictionary.Dict,
      --#                                         Do_IFA,
      --#                                         ErrorHandler.Error_Context,
      --#                                         Export_List,
      --#                                         Import_List,
      --#                                         LexTokenManager.State,
      --#                                         Node,
      --#                                         Null_List,
      --#                                         Scope,
      --#                                         SPARK_IO.File_Sys,
      --#                                         Star_Found,
      --#                                         STree.Table,
      --#                                         Subprog_Sym,
      --#                                         The_Heap &
      --#         First_Valid_Export         from Export_List,
      --#                                         The_Heap;
      --# pre STree.Syntax_Node_Type (Node, STree.Table) = SP_Symbols.dependency_clause_opt or
      --#   STree.Syntax_Node_Type (Node, STree.Table) = SP_Symbols.dependency_clause_optrep;
      --# post STree.Table = STree.Table~;
      is
         Sym         : Dictionary.Symbol;
         It          : STree.Iterator;
         Import_Node : STree.SyntaxNode;
         Unused      : Boolean;

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

         function Get_First_Valid_Export (Export_List : SeqAlgebra.Seq;
                                          The_Heap    : Heap.HeapRecord) return Dictionary.Symbol is
            Member : SeqAlgebra.MemberOfSeq;
            Sym    : Dictionary.Symbol;
         begin
            Member := SeqAlgebra.FirstMember (The_Heap, Export_List);
            if SeqAlgebra.IsNullMember (Member) then
               Sym := Dictionary.NullSymbol;
            else
               Sym :=
                 Dictionary.ConvertSymbolRef
                 (ExaminerConstants.RefType (SeqAlgebra.Value_Of_Member (The_Heap => The_Heap,
                                                                         M        => Member)));
            end if;
            return Sym;
         end Get_First_Valid_Export;

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

         -- Uses an explicit import list.  The import is passed in,
         -- if it is already in the import list an error is reported and a null symbol
         -- returned; else it is added to the list.  Imports by virtue of * never
         -- appear in the list and do not give rise to duplicate errors.

         procedure Unique_Import
           (Import_Sym  : in out Dictionary.Symbol;
            Import_List : in     SeqAlgebra.Seq;
            Error_Pos   : in     LexTokenManager.Token_Position;
            The_Heap    : in out Heap.HeapRecord;
            Error_Found : in out Boolean)
         --# global in     CommandLineData.Content;
         --#        in     Dictionary.Dict;
         --#        in     LexTokenManager.State;
         --#        in out ErrorHandler.Error_Context;
         --#        in out SPARK_IO.File_Sys;
         --#        in out Statistics.TableUsage;
         --# derives ErrorHandler.Error_Context,
         --#         SPARK_IO.File_Sys          from CommandLineData.Content,
         --#                                         Dictionary.Dict,
         --#                                         ErrorHandler.Error_Context,
         --#                                         Error_Pos,
         --#                                         Import_List,
         --#                                         Import_Sym,
         --#                                         LexTokenManager.State,
         --#                                         SPARK_IO.File_Sys,
         --#                                         The_Heap &
         --#         Error_Found,
         --#         Import_Sym,
         --#         Statistics.TableUsage,
         --#         The_Heap                   from *,
         --#                                         Import_List,
         --#                                         Import_Sym,
         --#                                         The_Heap;
         is
            Import_Rep : Natural;
         begin
            Import_Rep := Natural (Dictionary.SymbolRef (Import_Sym));
            if SeqAlgebra.IsMember (The_Heap, Import_List, Import_Rep) then
               Error_Found := True;
               ErrorHandler.Semantic_Error
                 (Err_Num   => 160,
                  Reference => ErrorHandler.No_Reference,
                  Position  => Error_Pos,
                  Id_Str    => Dictionary.GetSimpleName (Import_Sym));
               Import_Sym := Dictionary.NullSymbol;
            else
               SeqAlgebra.AddMember (The_Heap, Import_List, Import_Rep);
            end if;
         end Unique_Import;

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

         -- Similar to Unique_Import but this checks that the import has not appeared as
         -- an import anywhere in the dependency relation whereas Unique_Import only checks
         -- it is not duplicated in the current clause. Check_Not_Imported_Before is for use
         -- in handling "derives null from ..." cases where the imports must not have
         -- been imported before.

         procedure Check_Not_Imported_Before
           (Import_Sym  : in out Dictionary.Symbol;
            Subprog_Sym : in     Dictionary.Symbol;
            Abstraction : in     Dictionary.Abstractions;
            Import_List : in     SeqAlgebra.Seq;
            Error_Pos   : in     LexTokenManager.Token_Position;
            The_Heap    : in out Heap.HeapRecord;
            Error_Found : in out Boolean)
         --# global in     CommandLineData.Content;
         --#        in     Dictionary.Dict;
         --#        in     LexTokenManager.State;
         --#        in out ErrorHandler.Error_Context;
         --#        in out SPARK_IO.File_Sys;
         --#        in out Statistics.TableUsage;
         --# derives ErrorHandler.Error_Context,
         --#         SPARK_IO.File_Sys          from Abstraction,
         --#                                         CommandLineData.Content,
         --#                                         Dictionary.Dict,
         --#                                         ErrorHandler.Error_Context,
         --#                                         Error_Pos,
         --#                                         Import_Sym,
         --#                                         LexTokenManager.State,
         --#                                         SPARK_IO.File_Sys,
         --#                                         Subprog_Sym &
         --#         Error_Found,
         --#         Import_Sym                 from *,
         --#                                         Abstraction,
         --#                                         Dictionary.Dict,
         --#                                         Import_Sym,
         --#                                         Subprog_Sym &
         --#         Statistics.TableUsage,
         --#         The_Heap                   from *,
         --#                                         Abstraction,
         --#                                         Dictionary.Dict,
         --#                                         Import_List,
         --#                                         Import_Sym,
         --#                                         Subprog_Sym,
         --#                                         The_Heap;
         is
            It : Dictionary.Iterator;
         begin
            It := Dictionary.FirstImport (Abstraction, Subprog_Sym);
            while not Dictionary.IsNullIterator (It) loop
               if Dictionary.CurrentSymbol (It) = Import_Sym then -- duplicate
                  Error_Found := True;
                  ErrorHandler.Semantic_Error
                    (Err_Num   => 160,
                     Reference => ErrorHandler.No_Reference,
                     Position  => Error_Pos,
                     Id_Str    => Dictionary.GetSimpleName (Import_Sym));
                  Import_Sym := Dictionary.NullSymbol;
               else
                  SeqAlgebra.AddMember (The_Heap, Import_List, Natural (Dictionary.SymbolRef (Import_Sym)));
               end if;
               It := Dictionary.NextSymbol (It);
            end loop;
         end Check_Not_Imported_Before;

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

         procedure Add_Dependencies
           (Abstraction     : in Dictionary.Abstractions;
            The_Procedure   : in Dictionary.Symbol;
            Export_List     : in SeqAlgebra.Seq;
            First_Export    : in Dictionary.Symbol;
            The_Import      : in Dictionary.Symbol;
            Import_Node_Pos : in Dictionary.Location;
            Star_Found      : in Boolean;
            The_Heap        : in Heap.HeapRecord)
         --# global in     ContextManager.Ops.Unit_Stack;
         --#        in     LexTokenManager.State;
         --#        in out Dictionary.Dict;
         --#        in out SPARK_IO.File_Sys;
         --# derives Dictionary.Dict   from *,
         --#                                Abstraction,
         --#                                ContextManager.Ops.Unit_Stack,
         --#                                Export_List,
         --#                                First_Export,
         --#                                Import_Node_Pos,
         --#                                Star_Found,
         --#                                The_Heap,
         --#                                The_Import,
         --#                                The_Procedure &
         --#         SPARK_IO.File_Sys from *,
         --#                                Abstraction,
         --#                                ContextManager.Ops.Unit_Stack,
         --#                                Dictionary.Dict,
         --#                                Export_List,
         --#                                First_Export,
         --#                                Import_Node_Pos,
         --#                                LexTokenManager.State,
         --#                                Star_Found,
         --#                                The_Heap,
         --#                                The_Import,
         --#                                The_Procedure;
         is
            Member         : SeqAlgebra.MemberOfSeq;
            Current_Export : Dictionary.Symbol;
         begin
            if Star_Found then
               Member := SeqAlgebra.FirstMember (The_Heap, Export_List);
               while not SeqAlgebra.IsNullMember (Member) loop
                  Current_Export :=
                    Dictionary.ConvertSymbolRef
                    (ExaminerConstants.RefType (SeqAlgebra.Value_Of_Member (The_Heap => The_Heap,
                                                                            M        => Member)));
                  if The_Import /= Current_Export then -- don't add if already added by *
                     Dictionary.AddDependency
                       (Abstraction     => Abstraction,
                        Comp_Unit       => ContextManager.Ops.Current_Unit,
                        TheProcedure    => The_Procedure,
                        TheExport       => Current_Export,
                        TheImport       => The_Import,
                        ImportReference => Import_Node_Pos);
                  end if;
                  Member := SeqAlgebra.NextMember (The_Heap, Member);
               end loop;

            else -- only need to copy it to first export (Copy_Imports will do rest)
               Dictionary.AddDependency
                 (Abstraction     => Abstraction,
                  Comp_Unit       => ContextManager.Ops.Current_Unit,
                  TheProcedure    => The_Procedure,
                  TheExport       => First_Export,
                  TheImport       => The_Import,
                  ImportReference => Import_Node_Pos);
            end if;
         end Add_Dependencies;

      begin -- Do_Import_List
         First_Valid_Export := Get_First_Valid_Export (Export_List => Export_List,
                                                       The_Heap    => The_Heap);
         It                 :=
           STree.Find_First_Node (Node_Kind    => SP_Symbols.entire_variable,
                                  From_Root    => Node,
                                  In_Direction => STree.Down);
         while not STree.IsNull (It) loop
            Import_Node := STree.Get_Node (It => It);
            --# assert STree.Table = STree.Table~ and
            --#   STree.Syntax_Node_Type (Import_Node, STree.Table) = SP_Symbols.entire_variable and
            --#   Import_Node = STree.Get_Node (It);
            --# accept Flow, 10, Unused, "Expected ineffective assignment";
            Sem.Wf_Entire_Variable
              (Node       => Import_Node,
               Scope      => Dictionary.Set_Visibility (The_Visibility => Dictionary.Local,
                                                        The_Unit       => Subprog_Sym),
               Error_Hint => Sem.In_Derives_Import_List,
               Var_Sym    => Sym,
               Dotted     => Unused);
            --# end accept;
            Error_Found := Error_Found or else Dictionary.Is_Null_Symbol (Sym);
            if not Dictionary.Is_Null_Symbol (Sym) and then not Dictionary.Is_Null_Symbol (First_Valid_Export) then
               -- also covers Null_List case
               Unique_Import
                 (Import_Sym  => Sym,
                  Import_List => Import_List,
                  Error_Pos   => STree.Node_Position (Node => Import_Node),
                  The_Heap    => The_Heap,
                  Error_Found => Error_Found);
            end if;
            -- new check, similar to Unique_Import except that for a null import clause
            -- we require that the variable has not appeared as an import anywhere else rather
            -- than just in the current clause
            if Null_List and then not Dictionary.Is_Null_Symbol (Sym) then
               Check_Not_Imported_Before
                 (Import_Sym  => Sym,
                  Subprog_Sym => Subprog_Sym,
                  Abstraction => Abstraction,
                  Import_List => Import_List,
                  Error_Pos   => STree.Node_Position (Node => Import_Node),
                  The_Heap    => The_Heap,
                  Error_Found => Error_Found);
            end if;
            if not Dictionary.Is_Null_Symbol (Sym) then  -- we have valid import so far
               Check_Import_Mode
                 (Import_Sym  => Sym,
                  Subprog_Sym => Subprog_Sym,
                  Scope       => Scope,
                  Abstraction => Abstraction,
                  Export_List => Export_List,
                  Error_Pos   => STree.Node_Position (Node => Import_Node),
                  Star_Found  => Star_Found,
                  The_Heap    => The_Heap,
                  Error_Found => Error_Found);
               Check_Import_Init
                 (Import_Node_Pos => STree.Node_Position (Node => Import_Node),
                  Import_Sym      => Sym,
                  Subprog_Sym     => Subprog_Sym,
                  Scope           => Scope,
                  Abstraction     => Abstraction,
                  Export_List     => Export_List,
                  Star_Found      => Star_Found,
                  The_Heap        => The_Heap,
                  Error_Found     => Error_Found);
               -- One of two things must happen to the valid import we have at this point.
               -- If we are doing IFA and we have valid export to associated it with we do so;
               -- however, if we are not doing IFA or there is no valid export we just
               -- mark the import in the dictionary as being an import usign the force call
               --# accept Flow, 41, "Expected stable expression";
               if Do_IFA and then not Dictionary.Is_Null_Symbol (First_Valid_Export) then
                  --# end accept;
                  Add_Dependencies
                    (Abstraction     => Abstraction,
                     The_Procedure   => Subprog_Sym,
                     Export_List     => Export_List,
                     First_Export    => First_Valid_Export,
                     The_Import      => Sym,
                     Import_Node_Pos => Dictionary.Location'(Start_Position => STree.Node_Position (Node => Import_Node),
                                                             End_Position   => STree.Node_Position (Node => Import_Node)),
                     Star_Found      => Star_Found,
                     The_Heap        => The_Heap);
               else
                  -- No valid export (including null derives case) to associate with  or else we
                  -- are just doing DFA.  In either case mark as import to avoid
                  -- knock-on errors
                  Dictionary.ForceImport
                    (Abstraction,
                     Subprog_Sym,
                     Sym,
                     Dictionary.Location'(Start_Position => STree.Node_Position (Node => Import_Node),
                                          End_Position   => STree.Node_Position (Node => Import_Node)));
               end if;
            end if;
            It := STree.NextNode (It);
         end loop;
         --# accept Flow, 33, Unused, "Expected to be neither referenced nor exported";
      end Do_Import_List;

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

      procedure Do_Self_References
        (Star_Node_Pos : in     LexTokenManager.Token_Position;
         Subprog_Sym   : in     Dictionary.Symbol;
         Scope         : in     Dictionary.Scopes;
         Abstraction   : in     Dictionary.Abstractions;
         Export_List   : in     SeqAlgebra.Seq;
         The_Heap      : in     Heap.HeapRecord;
         Error_Found   : in out Boolean)
      --# global in     CommandLineData.Content;
      --#        in     ContextManager.Ops.Unit_Stack;
      --#        in     LexTokenManager.State;
      --#        in out Dictionary.Dict;
      --#        in out ErrorHandler.Error_Context;
      --#        in out SPARK_IO.File_Sys;
      --# derives Dictionary.Dict,
      --#         Error_Found                from *,
      --#                                         Abstraction,
      --#                                         ContextManager.Ops.Unit_Stack,
      --#                                         Dictionary.Dict,
      --#                                         Export_List,
      --#                                         Star_Node_Pos,
      --#                                         Subprog_Sym,
      --#                                         The_Heap &
      --#         ErrorHandler.Error_Context,
      --#         SPARK_IO.File_Sys          from Abstraction,
      --#                                         CommandLineData.Content,
      --#                                         ContextManager.Ops.Unit_Stack,
      --#                                         Dictionary.Dict,
      --#                                         ErrorHandler.Error_Context,
      --#                                         Export_List,
      --#                                         LexTokenManager.State,
      --#                                         Scope,
      --#                                         SPARK_IO.File_Sys,
      --#                                         Star_Node_Pos,
      --#                                         Subprog_Sym,
      --#                                         The_Heap;
      is
         Member     : SeqAlgebra.MemberOfSeq;
         The_Export : Dictionary.Symbol;
      begin
         Member := SeqAlgebra.FirstMember (The_Heap, Export_List);
         while not SeqAlgebra.IsNullMember (Member) loop
            The_Export :=
              Dictionary.ConvertSymbolRef
              (ExaminerConstants.RefType (SeqAlgebra.Value_Of_Member (The_Heap => The_Heap,
                                                                      M        => Member)));
            Check_Import_Mode
              (Import_Sym  => The_Export,
               Subprog_Sym => Subprog_Sym,
               Scope       => Scope,
               Abstraction => Abstraction,
               Export_List => Export_List,
               Error_Pos   => Star_Node_Pos,
               Star_Found  => False,
               The_Heap    => The_Heap,
               Error_Found => Error_Found);
            Check_Import_Init
              (Import_Node_Pos => Star_Node_Pos,
               Import_Sym      => The_Export,
               Subprog_Sym     => Subprog_Sym,
               Scope           => Scope,
               Abstraction     => Abstraction,
               Export_List     => Export_List,
               Star_Found      => False,
               The_Heap        => The_Heap,
               Error_Found     => Error_Found);
            Dictionary.AddDependency
              (Abstraction     => Abstraction,
               Comp_Unit       => ContextManager.Ops.Current_Unit,
               TheProcedure    => Subprog_Sym,
               TheExport       => The_Export,
               TheImport       => The_Export,
               ImportReference => Dictionary.Location'(Start_Position => Star_Node_Pos,
                                                       End_Position   => Star_Node_Pos));
            Member := SeqAlgebra.NextMember (The_Heap, Member);
         end loop;
      end Do_Self_References;

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

      -- This procedure does checks on * node when no IFA selected
      procedure Append_Self_References
        (Star_Node_Pos            : in     LexTokenManager.Token_Position;
         Subprog_Sym              : in     Dictionary.Symbol;
         Scope                    : in     Dictionary.Scopes;
         Abstraction              : in     Dictionary.Abstractions;
         Export_List, Import_List : in     SeqAlgebra.Seq;
         The_Heap                 : in out Heap.HeapRecord;
         Error_Found              : in out Boolean)
      --# global in     CommandLineData.Content;
      --#        in     Dictionary.Dict;
      --#        in     LexTokenManager.State;
      --#        in out ErrorHandler.Error_Context;
      --#        in out SPARK_IO.File_Sys;
      --#        in out Statistics.TableUsage;
      --# derives ErrorHandler.Error_Context,
      --#         SPARK_IO.File_Sys          from Abstraction,
      --#                                         CommandLineData.Content,
      --#                                         Dictionary.Dict,
      --#                                         ErrorHandler.Error_Context,
      --#                                         Export_List,
      --#                                         LexTokenManager.State,
      --#                                         Scope,
      --#                                         SPARK_IO.File_Sys,
      --#                                         Star_Node_Pos,
      --#                                         Subprog_Sym,
      --#                                         The_Heap &
      --#         Error_Found                from *,
      --#                                         Abstraction,
      --#                                         Dictionary.Dict,
      --#                                         Export_List,
      --#                                         Subprog_Sym,
      --#                                         The_Heap &
      --#         Statistics.TableUsage,
      --#         The_Heap                   from *,
      --#                                         Export_List,
      --#                                         Import_List,
      --#                                         The_Heap;
      is
         Member     : SeqAlgebra.MemberOfSeq;
         The_Export : Dictionary.Symbol;
      begin
         Member := SeqAlgebra.FirstMember (The_Heap, Export_List);
         while not SeqAlgebra.IsNullMember (Member) loop
            The_Export :=
              Dictionary.ConvertSymbolRef
              (ExaminerConstants.RefType (SeqAlgebra.Value_Of_Member (The_Heap => The_Heap,
                                                                      M        => Member)));
            Check_Import_Mode
              (Import_Sym  => The_Export,
               Subprog_Sym => Subprog_Sym,
               Scope       => Scope,
               Abstraction => Abstraction,
               Export_List => Export_List,
               Error_Pos   => Star_Node_Pos,
               Star_Found  => False,
               The_Heap    => The_Heap,
               Error_Found => Error_Found);
            Check_Import_Init
              (Import_Node_Pos => Star_Node_Pos,
               Import_Sym      => The_Export,
               Subprog_Sym     => Subprog_Sym,
               Scope           => Scope,
               Abstraction     => Abstraction,
               Export_List     => Export_List,
               Star_Found      => False,
               The_Heap        => The_Heap,
               Error_Found     => Error_Found);
            Member := SeqAlgebra.NextMember (The_Heap, Member);
         end loop;
         SeqAlgebra.AugmentSeq (The_Heap, Import_List, Export_List);
      end Append_Self_References;

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

      procedure Copy_Imports
        (Subprog_Sym        : in Dictionary.Symbol;
         Abstraction        : in Dictionary.Abstractions;
         Export_List        : in SeqAlgebra.Seq;
         First_Valid_Export : in Dictionary.Symbol;
         The_Heap           : in Heap.HeapRecord)
      --# global in out Dictionary.Dict;
      --# derives Dictionary.Dict from *,
      --#                              Abstraction,
      --#                              Export_List,
      --#                              First_Valid_Export,
      --#                              Subprog_Sym,
      --#                              The_Heap;
      is
         Member : SeqAlgebra.MemberOfSeq;
      begin
         Member := SeqAlgebra.FirstMember (The_Heap, Export_List);
         if not SeqAlgebra.IsNullMember (Member) then
            -- there is at leat one valid export, we want to loop through rest
            loop
               Member := SeqAlgebra.NextMember (The_Heap, Member);
               exit when SeqAlgebra.IsNullMember (Member);
               Dictionary.CopyDependencyList
                 (Abstraction,
                  Subprog_Sym,
                  First_Valid_Export,
                  Dictionary.ConvertSymbolRef
                    (ExaminerConstants.RefType (SeqAlgebra.Value_Of_Member (The_Heap => The_Heap,
                                                                            M        => Member))));
            end loop;
         end if;
      end Copy_Imports;

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

      procedure Check_Star (Node                : in     STree.SyntaxNode;
                            Star_Node, Imp_Node :    out STree.SyntaxNode)
      --# global in STree.Table;
      --# derives Imp_Node,
      --#         Star_Node from Node,
      --#                        STree.Table;
      --# pre STree.Syntax_Node_Type (Node, STree.Table) = SP_Symbols.dependency_clause;
      --# post STree.Syntax_Node_Type (Imp_Node, STree.Table) = SP_Symbols.dependency_clause_opt and
      --#   (STree.Syntax_Node_Type (Star_Node, STree.Table) = SP_Symbols.multiply or
      --#      Star_Node = STree.NullNode);
      is
      begin
         Imp_Node := STree.Next_Sibling (Current_Node => STree.Child_Node (Current_Node => Node));
         -- ASSUME Imp_Node = dependency_clause_opt
         SystemErrors.RT_Assert
           (C       => STree.Syntax_Node_Type (Node => Imp_Node) = SP_Symbols.dependency_clause_opt,
            Sys_Err => SystemErrors.Invalid_Syntax_Tree,
            Msg     => "Expect Imp_Node = dependency_clause_opt in Check_Star");
         Star_Node := STree.Child_Node (Current_Node => Imp_Node);
         -- ASSUME Star_Node = multiply OR dependency_clause_optrep OR NULL
         if Star_Node = STree.NullNode
           or else STree.Syntax_Node_Type (Node => Star_Node) = SP_Symbols.dependency_clause_optrep then
            -- ASSUME Star_Node = dependency_clause_optrep OR NULL
            Star_Node := STree.NullNode;
         elsif STree.Syntax_Node_Type (Node => Star_Node) /= SP_Symbols.multiply then
            Star_Node := STree.NullNode;
            SystemErrors.Fatal_Error
              (Sys_Err => SystemErrors.Invalid_Syntax_Tree,
               Msg     => "Expect Star_Node = multiply OR dependency_clause_optrep OR NULL in Check_Star");
         end if;
      end Check_Star;

   begin -- Wf_Dependency_Clause

      --  For each exported variable E : E is a visible entire
      --  variable; occurrence of E as an export is unique (Section
      --  6.1.2 Rule 6); mode of E is in out or out (Section 6.1.2
      --  Rule 2); for each imported variable I : I is a visible
      --  entire variable; occurrence of I as an import is unique
      --  (Section 6.1.2 Rule 6); mode of I is in or in out (Section
      --  6.1.2 Rule 1); if dependency clause belongs to main_program,
      --  then I is initialized by the package of which it is an own
      --  variable;

      SeqAlgebra.CreateSeq (The_Heap, Export_List);
      SeqAlgebra.CreateSeq (The_Heap, Import_List);
      Error_Found := False;

      -- ASSUME Node = dependency_clause OR null_import_list
      if STree.Syntax_Node_Type (Node => Node) = SP_Symbols.null_import_list then
         -- ASSUME Node = null_import_list
         -- we are dealing with " derives null from ..." so there are no stars to worry
         -- about and we don't have to go looking for the node holding the list of imports
         -- because that is what has been passed in
         Null_List        := True;
         Star_Node        := STree.NullNode; -- not used but removes apparent DFA
         Import_List_Node := STree.Next_Sibling (Current_Node => STree.Child_Node (Current_Node => Node));
         -- ASSUME Import_List_Node = dependency_clause_optrep
         SystemErrors.RT_Assert
           (C       => STree.Syntax_Node_Type (Node => Import_List_Node) = SP_Symbols.dependency_clause_optrep,
            Sys_Err => SystemErrors.Invalid_Syntax_Tree,
            Msg     => "Expect Import_List_Node = dependency_clause_optrep in Wf_Dependency_Clause");
         -- Add NullVariable as an export to provide a data sink for the imported items
         Dictionary.AddGlobalVariable
           (Abstraction         => Abstraction,
            Subprogram          => Subprog_Sym,
            Variable            => Dictionary.GetNullVariable,
            Mode                => Dictionary.OutMode,
            PrefixNeeded        => False,
            Comp_Unit           => ContextManager.Ops.Current_Unit,
            VariableReference   => Dictionary.Location'(Start_Position => STree.Node_Position (Node => Import_List_Node),
                                                        End_Position   => STree.Node_Position (Node => Import_List_Node)),
            Global_Variable_Sym => Global_Variable_Sym);
         STree.Add_Node_Symbol (Node => Node,
                                Sym  => Global_Variable_Sym);
         Dictionary.AddExport
           (Abstraction     => Abstraction,
            TheProcedure    => Subprog_Sym,
            TheExport       => Dictionary.GetNullVariable,
            ExportReference => Dictionary.Location'(Start_Position => STree.Node_Position (Node => Import_List_Node),
                                                    End_Position   => STree.Node_Position (Node => Import_List_Node)),
            Annotation      => Dictionary.Location'(Start_Position => STree.Node_Position (Node => Import_List_Node),
                                                    End_Position   => STree.Node_Position (Node => Import_List_Node)));
         Valid_Export_List_Add (Sym         => Dictionary.GetNullVariable,
                                Export_List => Export_List,
                                The_Heap    => The_Heap);
      elsif STree.Syntax_Node_Type (Node => Node) = SP_Symbols.dependency_clause then
         -- ASSUME Node = dependency_clause
         Null_List := False;
         -- it's an ordinary dependency clause
         Export_List_Node := STree.Child_Node (Current_Node => Node);
         -- ASSUME Export_List_Node = dependency_clause_optrep
         SystemErrors.RT_Assert
           (C       => STree.Syntax_Node_Type (Node => Export_List_Node) = SP_Symbols.dependency_clause_optrep,
            Sys_Err => SystemErrors.Invalid_Syntax_Tree,
            Msg     => "Expect Export_List_Node = dependency_clause_optrep in Wf_Dependency_Clause");
         Check_Star (Node      => Node,
                     Star_Node => Star_Node,
                     Imp_Node  => Import_List_Node);
         Do_Export_List
           (Node        => Export_List_Node,
            Subprog_Sym => Subprog_Sym,
            Scope       => Scope,
            Abstraction => Abstraction,
            Export_List => Export_List,
            The_Heap    => The_Heap,
            Error_Found => Error_Found);
      end if;

      if Do_IFA then -- Do_IFA can only be False here in SPARK 83 DFA mode
         if STree.Syntax_Node_Type (Node => Star_Node) = SP_Symbols.multiply then
            -- ASSUME Star_Node = multiply
            Do_Self_References
              (Star_Node_Pos => STree.Node_Position (Node => Star_Node),
               Subprog_Sym   => Subprog_Sym,
               Scope         => Scope,
               Abstraction   => Abstraction,
               Export_List   => Export_List,
               The_Heap      => The_Heap,
               Error_Found   => Error_Found);
            --# accept Flow, 10, First_Valid_Export, "Expected ineffective assignment";
            Do_Import_List
              (Node               => Import_List_Node,
               Subprog_Sym        => Subprog_Sym,
               Scope              => Scope,
               Abstraction        => Abstraction,
               Do_IFA             => Do_IFA,
               Export_List        => Export_List,
               Import_List        => Import_List,
               Null_List          => Null_List,
               Star_Found         => True,
               The_Heap           => The_Heap,
               Error_Found        => Error_Found,
               First_Valid_Export => First_Valid_Export);
            --# end accept;
         elsif Star_Node = STree.NullNode then
            -- ASSUME Star_Node = NULL
            Do_Import_List
              (Node               => Import_List_Node,
               Subprog_Sym        => Subprog_Sym,
               Scope              => Scope,
               Abstraction        => Abstraction,
               Do_IFA             => Do_IFA,
               Export_List        => Export_List,
               Import_List        => Import_List,
               Null_List          => Null_List,
               Star_Found         => False,
               The_Heap           => The_Heap,
               Error_Found        => Error_Found,
               First_Valid_Export => First_Valid_Export);
            Copy_Imports
              (Subprog_Sym        => Subprog_Sym,
               Abstraction        => Abstraction,
               Export_List        => Export_List,
               First_Valid_Export => First_Valid_Export,
               The_Heap           => The_Heap);
         end if;
      else
         --# accept Flow, 10, First_Valid_Export, "Expected ineffective assignment";
         Do_Import_List
           (Node               => Import_List_Node,
            Subprog_Sym        => Subprog_Sym,
            Scope              => Scope,
            Abstraction        => Abstraction,
            Do_IFA             => Do_IFA,
            Export_List        => Export_List,
            Import_List        => Import_List,
            Null_List          => Null_List,
            Star_Found         => STree.Syntax_Node_Type (Node => Star_Node) = SP_Symbols.multiply,
            The_Heap           => The_Heap,
            Error_Found        => Error_Found,
            First_Valid_Export => First_Valid_Export);
         --# end accept;
         if STree.Syntax_Node_Type (Node => Star_Node) = SP_Symbols.multiply then
            -- ASSUME Star_Node = multiply
            Append_Self_References
              (Star_Node_Pos => STree.Node_Position (Node => Star_Node),
               Subprog_Sym   => Subprog_Sym,
               Scope         => Scope,
               Abstraction   => Abstraction,
               Export_List   => Export_List,
               Import_List   => Import_List,
               The_Heap      => The_Heap,
               Error_Found   => Error_Found);
         end if;
      end if;
   end Wf_Dependency_Clause;

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

   procedure Params_Are_Imports_Or_Exports
     (Subprog_Sym          : in     Dictionary.Symbol;
      Abstraction          : in     Dictionary.Abstractions;
      Error_Pos            : in     LexTokenManager.Token_Position;
      Semantic_Error_Found : in out Boolean)
   --# global in     CommandLineData.Content;
   --#        in     Dictionary.Dict;
   --#        in     LexTokenManager.State;
   --#        in out ErrorHandler.Error_Context;
   --#        in out SPARK_IO.File_Sys;
   --# derives ErrorHandler.Error_Context,
   --#         SPARK_IO.File_Sys          from Abstraction,
   --#                                         CommandLineData.Content,
   --#                                         Dictionary.Dict,
   --#                                         ErrorHandler.Error_Context,
   --#                                         Error_Pos,
   --#                                         LexTokenManager.State,
   --#                                         SPARK_IO.File_Sys,
   --#                                         Subprog_Sym &
   --#         Semantic_Error_Found       from *,
   --#                                         Abstraction,
   --#                                         CommandLineData.Content,
   --#                                         Dictionary.Dict,
   --#                                         Subprog_Sym;
   is
      Next_Param : Dictionary.Iterator;
      Param_Sym  : Dictionary.Symbol;
   begin
      Next_Param := Dictionary.FirstSubprogramParameter (Subprog_Sym);
      while Next_Param /= Dictionary.NullIterator loop
         Param_Sym := Dictionary.CurrentSymbol (Next_Param);
         if not Dictionary.IsImport (Abstraction, Subprog_Sym, Param_Sym)
           and then not Dictionary.IsExport (Abstraction, Subprog_Sym, Param_Sym) then
            Semantic_Error_Found := True;
            ErrorHandler.Semantic_Error
              (Err_Num   => 200,
               Reference => ErrorHandler.No_Reference,
               Position  => Error_Pos,
               Id_Str    => Dictionary.GetSimpleName (Param_Sym));
         end if;

         -- test to ensure that parameters of mode IN OUT are imported
         if Dictionary.GetSubprogramParameterMode (Param_Sym) = Dictionary.InOutMode then
            if not Dictionary.IsImport (Abstraction, Subprog_Sym, Param_Sym) then
               --# accept Flow, 41, "Expected stable expression";
               if CommandLineData.Content.Language_Profile /= CommandLineData.SPARK83 then
                  --# end accept;
                  Semantic_Error_Found := True;
                  ErrorHandler.Semantic_Error
                    (Err_Num   => 504,
                     Reference => ErrorHandler.No_Reference,
                     Position  => Error_Pos,
                     Id_Str    => Dictionary.GetSimpleName (Param_Sym));

               elsif Dictionary.TypeIsScalar (Dictionary.GetType (Param_Sym)) then
                  Semantic_Error_Found := True;
                  ErrorHandler.Semantic_Error
                    (Err_Num   => 338,
                     Reference => ErrorHandler.No_Reference,
                     Position  => Error_Pos,
                     Id_Str    => Dictionary.GetSimpleName (Param_Sym));
               end if;
            end if; --end of checks that in out is an import

            -- check that in out is exported
            if CommandLineData.Content.Language_Profile /= CommandLineData.SPARK83
              and then not Dictionary.IsExport (Abstraction, Subprog_Sym, Param_Sym) then
               Semantic_Error_Found := True;
               ErrorHandler.Semantic_Error
                 (Err_Num   => 506,
                  Reference => ErrorHandler.No_Reference,
                  Position  => Error_Pos,
                  Id_Str    => Dictionary.GetSimpleName (Param_Sym));
            end if;
         end if;
         Next_Param := Dictionary.NextSymbol (Next_Param);
      end loop;
   end Params_Are_Imports_Or_Exports;

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

   procedure Globals_Are_Imports_Or_Exports
     (Subprog_Sym          : in     Dictionary.Symbol;
      Scope                : in     Dictionary.Scopes;
      Abstraction          : in     Dictionary.Abstractions;
      Error_Pos            : in     LexTokenManager.Token_Position;
      Semantic_Error_Found : in out Boolean)
   --# global in     CommandLineData.Content;
   --#        in     Dictionary.Dict;
   --#        in     LexTokenManager.State;
   --#        in out ErrorHandler.Error_Context;
   --#        in out SPARK_IO.File_Sys;
   --# derives ErrorHandler.Error_Context,
   --#         SPARK_IO.File_Sys          from Abstraction,
   --#                                         CommandLineData.Content,
   --#                                         Dictionary.Dict,
   --#                                         ErrorHandler.Error_Context,
   --#                                         Error_Pos,
   --#                                         LexTokenManager.State,
   --#                                         Scope,
   --#                                         SPARK_IO.File_Sys,
   --#                                         Subprog_Sym &
   --#         Semantic_Error_Found       from *,
   --#                                         Abstraction,
   --#                                         Dictionary.Dict,
   --#                                         Subprog_Sym;
   --#
   is
      Next_Global : Dictionary.Iterator;
      Global_Sym  : Dictionary.Symbol;
   begin
      Next_Global := Dictionary.FirstGlobalVariable (Abstraction, Subprog_Sym);
      while Next_Global /= Dictionary.NullIterator loop
         Global_Sym := Dictionary.CurrentSymbol (Next_Global);
         if not Dictionary.IsImport (Abstraction, Subprog_Sym, Global_Sym)
           and then not Dictionary.IsExport (Abstraction, Subprog_Sym, Global_Sym) then
            Semantic_Error_Found := True;
            ErrorHandler.Semantic_Error_Sym
              (Err_Num   => 201,
               Reference => ErrorHandler.No_Reference,
               Position  => Error_Pos,
               Sym       => Global_Sym,
               Scope     => Scope);
         end if;
         -- check that globals with mode in out are both imported and exported.
         if Dictionary.GetGlobalMode (Abstraction, Subprog_Sym, Global_Sym) = Dictionary.InOutMode then
            if not Dictionary.IsImport (Abstraction, Subprog_Sym, Global_Sym) then
               Semantic_Error_Found := True;
               ErrorHandler.Semantic_Error_Sym
                 (Err_Num   => 505,
                  Reference => ErrorHandler.No_Reference,
                  Position  => Error_Pos,
                  Sym       => Global_Sym,
                  Scope     => Scope);
            end if;
            if not Dictionary.IsExport (Abstraction, Subprog_Sym, Global_Sym) then
               Semantic_Error_Found := True;
               ErrorHandler.Semantic_Error_Sym
                 (Err_Num   => 507,
                  Reference => ErrorHandler.No_Reference,
                  Position  => Error_Pos,
                  Sym       => Global_Sym,
                  Scope     => Scope);
            end if;
         end if;
         Next_Global := Dictionary.NextSymbol (Next_Global);
      end loop;
   end Globals_Are_Imports_Or_Exports;

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

   procedure Check_Information_Flow_Policy
     (Subprog_Sym : in Dictionary.Symbol;
      Scope       : in Dictionary.Scopes;
      First_Seen  : in Boolean;
      Position    : 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 CommandLineData.Content,
   --#                                         Dictionary.Dict,
   --#                                         ErrorHandler.Error_Context,
   --#                                         First_Seen,
   --#                                         LexTokenManager.State,
   --#                                         Position,
   --#                                         Scope,
   --#                                         SPARK_IO.File_Sys,
   --#                                         Subprog_Sym;
   is
      type FS_To_Abs_Table is array (Boolean) of Dictionary.Abstractions;
      To_Abs : constant FS_To_Abs_Table := FS_To_Abs_Table'(False => Dictionary.IsRefined,
                                                            True  => Dictionary.IsAbstract);

      Export_It  : Dictionary.Iterator;
      Import_It  : Dictionary.Iterator;
      The_Export : Dictionary.Symbol;
      The_Import : Dictionary.Symbol;
   begin
      -- Iterate over all the Exports of this subprogram...
      Export_It := Dictionary.FirstExport (To_Abs (First_Seen), Subprog_Sym);
      while Export_It /= Dictionary.NullIterator loop
         The_Export := Dictionary.CurrentSymbol (Export_It);
         Import_It  := Dictionary.FirstDependency (To_Abs (First_Seen), Subprog_Sym, The_Export);
         -- For each export, iterate over all the imports...
         while Import_It /= Dictionary.NullIterator loop
            The_Import := Dictionary.CurrentSymbol (Import_It);
            -- ...and see if each relation violates the current information
            -- flow policy.
            if Dictionary.RelationViolatesInfoFlowPolicy (The_Export, The_Import) then
               ErrorHandler.Dependency_Error
                 (Err_Type       => ErrorHandler.Policy_Violation,
                  Position       => Position,
                  Import_Var_Sym => The_Import,
                  Export_Var_Sym => The_Export,
                  Scope          => Scope);
            end if;
            Import_It := Dictionary.NextSymbol (Import_It);
         end loop;
         Export_It := Dictionary.NextSymbol (Export_It);
      end loop;
   end Check_Information_Flow_Policy;

begin -- Wf_Dependency_Relation
   Position := STree.FindLastItemInDependencyRelation (Node => Node);
   if CommandLineData.Content.Language_Profile /= CommandLineData.SPARK83
     and then CommandLineData.Content.Flow_Option = CommandLineData.Data_Flow then
      -- derives not used in this case, don't process, just issue note
      ErrorHandler.Semantic_Note (Err_Num  => 1,
                                  Position => Position,
                                  Id_Str   => LexTokenManager.Null_String);
   else -- proceed as usual (even if doing DFA in 83 mode)
      if First_Seen then
         Abstraction := Dictionary.IsAbstract;
      else
         Abstraction := Dictionary.IsRefined;
      end if;

      SeqAlgebra.CreateSeq (The_Heap, Exports_In_Relation);
      SeqAlgebra.CreateSeq (The_Heap, Imports_In_Relation);

      Semantic_Error_Found := Glob_Def_Err;
      Dictionary.AddDependencyRelation
        (Abstraction,
         Subprog_Sym,
         Dictionary.Location'(Start_Position => STree.Node_Position (Node => Node),
                              End_Position   => STree.Node_Position (Node => Node)));
      --# assert STree.Table = STree.Table~ and
      --#   STree.Syntax_Node_Type (Node, STree.Table) = SP_Symbols.dependency_relation;
      It := STree.Find_First_Node (Node_Kind    => SP_Symbols.dependency_clause,
                                   From_Root    => Node,
                                   In_Direction => STree.Down);
      while not STree.IsNull (It) loop
         Next_Node := STree.Get_Node (It => It);
         --# assert STree.Table = STree.Table~ and
         --#   STree.Syntax_Node_Type (Node, STree.Table) = SP_Symbols.dependency_relation and
         --#   STree.Syntax_Node_Type (Next_Node, STree.Table) = SP_Symbols.dependency_clause and
         --#   Next_Node = STree.Get_Node (It);
         -- globals Import_List, Export_List are created in wf_dependency_clause
         Wf_Dependency_Clause
           (Node        => Next_Node,
            Scope       => Scope,
            Subprog_Sym => Subprog_Sym,
            Abstraction => Abstraction,
            Do_IFA      => CommandLineData.Content.Flow_Option /= CommandLineData.Data_Flow,
            The_Heap    => The_Heap,
            Export_List => Export_List,
            Import_List => Import_List,
            Error_Found => Error);
         Semantic_Error_Found := Semantic_Error_Found or else Error;

         -- add in the imports and exports from this clause to the total imports/exports
         --# accept Flow, 41, "Expected stable expression";
         if CommandLineData.Content.Flow_Option = CommandLineData.Data_Flow then
            --# end accept;
            SeqAlgebra.AugmentSeq (The_Heap, Exports_In_Relation, Export_List);
            SeqAlgebra.AugmentSeq (The_Heap, Imports_In_Relation, Import_List);
         end if;
         SeqAlgebra.DisposeOfSeq (The_Heap, Export_List);
         SeqAlgebra.DisposeOfSeq (The_Heap, Import_List);
         It := STree.NextNode (It);
      end loop;
      --# assert STree.Table = STree.Table~ and
      --#   STree.Syntax_Node_Type (Node, STree.Table) = SP_Symbols.dependency_relation;
      -- Process any import list of the form "derives null from x, y, z;"
      Null_Import_Node := STree.Child_Node (Current_Node => STree.Child_Node (Current_Node => Node));
      -- ASSUME Null_Import_Node = dependency_relation_rep OR null_import_list OR NULL
      if STree.Syntax_Node_Type (Node => Null_Import_Node) = SP_Symbols.dependency_relation_rep then
         -- ASSUME Null_Import_Node = dependency_relation_rep
         Null_Import_Node := STree.Next_Sibling (Current_Node => Null_Import_Node);
         -- ASSUME Null_Import_Node = ampersand OR NULL
         if STree.Syntax_Node_Type (Node => Null_Import_Node) = SP_Symbols.ampersand then
            -- ASSUME Null_Import_Node = ampersand
            Null_Import_Node := STree.Next_Sibling (Current_Node => Null_Import_Node);
         elsif Null_Import_Node /= STree.NullNode then
            SystemErrors.Fatal_Error
              (Sys_Err => SystemErrors.Invalid_Syntax_Tree,
               Msg     => "Expect Null_Import_Node = ampersand OR NULL in Wf_Dependency_Relation");
         end if;
      elsif Null_Import_Node /= STree.NullNode
        and then STree.Syntax_Node_Type (Node => Null_Import_Node) /= SP_Symbols.null_import_list then
         SystemErrors.Fatal_Error
           (Sys_Err => SystemErrors.Invalid_Syntax_Tree,
            Msg     => "Expect Null_Import_Node = dependency_relation_rep OR null_import_list OR NULL in Wf_Dependency_Relation");
      end if;
      -- ASSUME Null_Import_Node = null_import_list OR NULL
      -- if there is a null import clause then Null_Import_Node is now pointing at it
      if STree.Syntax_Node_Type (Node => Null_Import_Node) = SP_Symbols.null_import_list then
         Wf_Dependency_Clause
           (Node        => Null_Import_Node,
            Scope       => Scope,
            Subprog_Sym => Subprog_Sym,
            Abstraction => Abstraction,
            Do_IFA      => CommandLineData.Content.Flow_Option /= CommandLineData.Data_Flow,
            The_Heap    => The_Heap,
            Export_List => Export_List,
            Import_List => Import_List,
            Error_Found => Error);
         Semantic_Error_Found := Semantic_Error_Found or else Error;

         -- add in the imports and exports from this clause to the total imports/exports
         if CommandLineData.Content.Flow_Option = CommandLineData.Data_Flow then -- stable index OK
            SeqAlgebra.AugmentSeq (The_Heap, Exports_In_Relation, Export_List);
            SeqAlgebra.AugmentSeq (The_Heap, Imports_In_Relation, Import_List);
         end if;
         SeqAlgebra.DisposeOfSeq (The_Heap, Export_List);
         SeqAlgebra.DisposeOfSeq (The_Heap, Import_List);
      elsif Null_Import_Node /= STree.NullNode then
         SystemErrors.Fatal_Error
           (Sys_Err => SystemErrors.Invalid_Syntax_Tree,
            Msg     => "Expect Null_Import_Node = null_import_list OR NULL in Wf_Dependency_Relation");
      end if;
      --# assert STree.Table = STree.Table~ and
      --#   STree.Syntax_Node_Type (Node, STree.Table) = SP_Symbols.dependency_relation;
      -- make all exports depend on all imports here
      if CommandLineData.Content.Flow_Option = CommandLineData.Data_Flow then
         ErrorHandler.Semantic_Note (Err_Num  => 2,
                                     Position => Position,
                                     Id_Str   => LexTokenManager.Null_String);
         Create_Full_Dependency
           (Node_Pos    => STree.Node_Position (Node => Node),
            Subprog_Sym => Subprog_Sym,
            Abstraction => Abstraction,
            Import_List => Imports_In_Relation,
            Export_List => Exports_In_Relation,
            The_Heap    => The_Heap);
      end if;

      SeqAlgebra.DisposeOfSeq (The_Heap, Exports_In_Relation);
      SeqAlgebra.DisposeOfSeq (The_Heap, Imports_In_Relation);

      Params_Are_Imports_Or_Exports
        (Subprog_Sym          => Subprog_Sym,
         Abstraction          => Abstraction,
         Error_Pos            => Position,
         Semantic_Error_Found => Semantic_Error_Found);
      Globals_Are_Imports_Or_Exports
        (Subprog_Sym          => Subprog_Sym,
         Scope                => Scope,
         Abstraction          => Abstraction,
         Error_Pos            => Position,
         Semantic_Error_Found => Semantic_Error_Found);

      -- If this is the first derives anno then record the fact that it was present
      -- Record in the dictionary that this subprogram has an explicit derives annotation,
      -- unless in data-flow mode when the derives annotation is ignored. (If it was
      -- recorded as being present in data-flow mode then the flow analyser would check it
      -- against the calculated rho relation.)
      --
      -- There is a special case for when we are doing data-flow analysis in 83 mode. In
      -- 83 there are no moded globals, so the derives anno is used (only) to work out the
      -- modes for the globals, but the full dependency relation is not stored and is not
      -- checked against calculated information flow. Subsequent analysis proceeds just as
      -- if there had been a moded global anno and no derives, so we do not record the
      -- presence of a derives anno in data-flow mode, even if language=83, although the
      -- flag Dependency_Found is still set to suppress error 501 (see below).

      if First_Seen and then CommandLineData.Content.Flow_Option /= CommandLineData.Data_Flow then
         Dictionary.SetHasDerivesAnnotation (Subprog_Sym);
      end if;

      -- do consistency checks if second anno and no semantic errors found and
      -- second global annotation is not missing completely
      if not (First_Seen
                or else Semantic_Error_Found
                or else (STree.Syntax_Node_Type
                           (Node => STree.Child_Node (Current_Node => STree.Parent_Node (Current_Node => Node))) =
                           SP_Symbols.dependency_relation)) then
         Check_Derives_Consistency (Subprog_Sym => Subprog_Sym,
                                    Position    => Position,
                                    The_Heap    => The_Heap);
      end if;

      if not Semantic_Error_Found then
         Check_Information_Flow_Policy
           (Subprog_Sym => Subprog_Sym,
            Scope       => Scope,
            First_Seen  => First_Seen,
            Position    => Position);
      end if;

      -- mark subprogram as having incorrect signature if necessary
      if Semantic_Error_Found then
         Dictionary.SetSubprogramSignatureNotWellformed (Abstraction, Subprog_Sym);
      end if;
   end if;
   --# assert STree.Table = STree.Table~ and
   --#   STree.Syntax_Node_Type (Node, STree.Table) = SP_Symbols.dependency_relation;
   if ErrorHandler.Generate_SLI then
      SLI.Generate_Xref_Derives
        (Comp_Unit   => ContextManager.Ops.Current_Unit,
         Parse_Tree  => Node,
         Scope       => Dictionary.Set_Visibility (The_Visibility => Dictionary.Local,
                                                   The_Unit       => Subprog_Sym),
         Subprog_Sym => Subprog_Sym);
   end if;
end Wf_Dependency_Relation;
