-------------------------------------------------------------------------------
-- (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.Wf_Basic_Declarative_Item.Wf_Basic_Declaration)
procedure Wf_Variable_Declaration
  (Node                 : in     STree.SyntaxNode;
   Enclosing_Unit_Scope : in     Dictionary.Scopes;
   Declaration_Scope    : in     Dictionary.Scopes;
   The_Heap             : in out Heap.HeapRecord)
is
   type Declaration_Sorts is (In_Package, In_Subprogram, In_Protected_Type);

   Declaration_Sort      : Declaration_Sorts;
   Type_Node             : STree.SyntaxNode;
   Exp_Node              : STree.SyntaxNode;
   Alias_Node            : STree.SyntaxNode;
   Var_Is_Init           : Boolean;
   Is_Aliased            : Boolean := False;
   Unwanted_Seq          : SeqAlgebra.Seq;
   Exp_Type              : Exp_Record;
   Type_Sym              : Dictionary.Symbol;
   Unused_Component_Data : ComponentManager.ComponentData;

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

   function Get_Declaration_Sort (Scope : Dictionary.Scopes) return Declaration_Sorts
   --# global in Dictionary.Dict;
   is
      The_Region : Dictionary.Symbol;
      Result     : Declaration_Sorts;
   begin
      The_Region := Dictionary.GetRegion (Scope);
      if Dictionary.IsPackage (The_Region) then
         Result := In_Package;
      elsif Dictionary.IsType (The_Region) and then Dictionary.IsProtectedTypeMark (The_Region) then
         Result := In_Protected_Type;
      else
         -- assume subprogram
         Result := In_Subprogram;
      end if;
      return Result;
   end Get_Declaration_Sort;

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

   procedure Alias_Check
     (Type_Sym       : in Dictionary.Symbol;
      Alias_Node_Pos : in LexTokenManager.Token_Position;
      Is_Aliased     : in 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 Alias_Node_Pos,
   --#                                         CommandLineData.Content,
   --#                                         Dictionary.Dict,
   --#                                         ErrorHandler.Error_Context,
   --#                                         Is_Aliased,
   --#                                         LexTokenManager.State,
   --#                                         SPARK_IO.File_Sys,
   --#                                         Type_Sym;
   is
   begin
      if Is_Aliased and then not Dictionary.IsProtectedTypeMark (Type_Sym) then
         ErrorHandler.Semantic_Error
           (Err_Num   => 894,
            Reference => ErrorHandler.No_Reference,
            Position  => Alias_Node_Pos,
            Id_Str    => LexTokenManager.Null_String);
      end if;
   end Alias_Check;

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

   procedure Wf_Package_Variable
     (Node, Exp_Node                : in STree.SyntaxNode;
      Alias_Node_Pos, Type_Node_Pos : in LexTokenManager.Token_Position;
      Type_Sym                      : in Dictionary.Symbol;
      Current_Scope                 : in Dictionary.Scopes;
      Is_Aliased, Var_Is_Init       : in Boolean)
   --# global in     CommandLineData.Content;
   --#        in     ContextManager.Ops.File_Heap;
   --#        in     ContextManager.Ops.Unit_Heap;
   --#        in     ContextManager.Ops.Unit_Stack;
   --#        in     LexTokenManager.State;
   --#        in out Dictionary.Dict;
   --#        in out ErrorHandler.Error_Context;
   --#        in out SLI.State;
   --#        in out SPARK_IO.File_Sys;
   --#        in out STree.Table;
   --# derives Dictionary.Dict,
   --#         STree.Table                from CommandLineData.Content,
   --#                                         ContextManager.Ops.Unit_Stack,
   --#                                         Current_Scope,
   --#                                         Dictionary.Dict,
   --#                                         Exp_Node,
   --#                                         Is_Aliased,
   --#                                         LexTokenManager.State,
   --#                                         Node,
   --#                                         STree.Table,
   --#                                         Type_Sym,
   --#                                         Var_Is_Init &
   --#         ErrorHandler.Error_Context,
   --#         SLI.State,
   --#         SPARK_IO.File_Sys          from Alias_Node_Pos,
   --#                                         CommandLineData.Content,
   --#                                         ContextManager.Ops.File_Heap,
   --#                                         ContextManager.Ops.Unit_Heap,
   --#                                         ContextManager.Ops.Unit_Stack,
   --#                                         Current_Scope,
   --#                                         Dictionary.Dict,
   --#                                         ErrorHandler.Error_Context,
   --#                                         Exp_Node,
   --#                                         Is_Aliased,
   --#                                         LexTokenManager.State,
   --#                                         Node,
   --#                                         SLI.State,
   --#                                         SPARK_IO.File_Sys,
   --#                                         STree.Table,
   --#                                         Type_Node_Pos,
   --#                                         Type_Sym,
   --#                                         Var_Is_Init;
   --# pre Syntax_Node_Type (Node, STree.Table) = SP_Symbols.variable_declaration and
   --#   (Exp_Node = STree.NullNode or Syntax_Node_Type (Exp_Node, STree.Table) = SP_Symbols.expression);
   --# post STree.Table = STree.Table~;
   is
      It                 : STree.Iterator;
      Next_Node          : STree.SyntaxNode;
      Ident_Str          : LexTokenManager.Lex_String;
      Root_Type_Sym      : Dictionary.Symbol;
      Variable_Symbol    : Dictionary.Symbol;
      Declaration_Symbol : Dictionary.Symbol;
      OK_To_Add          : Boolean;

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

      procedure Check_Type_Consistency
        (Sym        : in     Dictionary.Symbol;
         Type_Sym   : in     Dictionary.Symbol;
         Scope      : in     Dictionary.Scopes;
         Error_Node : in     STree.SyntaxNode;
         OK_To_Add  :    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,
      --#                                         Error_Node,
      --#                                         LexTokenManager.State,
      --#                                         Scope,
      --#                                         SPARK_IO.File_Sys,
      --#                                         STree.Table,
      --#                                         Sym,
      --#                                         Type_Sym &
      --#         OK_To_Add                  from Dictionary.Dict,
      --#                                         Scope,
      --#                                         Sym,
      --#                                         Type_Sym;
      --# pre Syntax_Node_Type (Error_Node, STree.Table) = SP_Symbols.identifier;
      is
         Announced_Type : Dictionary.Symbol;
         Root_Type_Sym  : Dictionary.Symbol;
         Consistent     : Boolean;
      begin
         Announced_Type := Dictionary.GetType (Sym);
         Root_Type_Sym  := Dictionary.GetRootType (Type_Sym);

         if Dictionary.IsOwnVariable (Sym) then
            if Dictionary.OwnVariableHasType (Sym, Scope) then
               if Dictionary.IsSubtype (Type_Sym) then
                  if Dictionary.IsProtectedTypeMark (Root_Type_Sym) then
                     -- Protected types may be declared using a subtype of
                     -- the type used in the own variable declaration.
                     if Dictionary.IsSubtype (Dictionary.GetType (Sym)) then
                        -- The own variable was declared using a subtype.
                        -- Report this error rather than the type mismatch error
                        ErrorHandler.Semantic_Error
                          (Err_Num   => 948,
                           Reference => ErrorHandler.No_Reference,
                           Position  => Node_Position (Node => Error_Node),
                           Id_Str    => Dictionary.GetSimpleName (Sym));
                        Consistent := True;
                     else
                        Consistent :=
                          Dictionary.Types_Are_Equal
                          (Left_Symbol        => Root_Type_Sym,
                           Right_Symbol       => Announced_Type,
                           Full_Range_Subtype => False);
                     end if;
                  else
                     -- The types must be the same
                     Consistent :=
                       Dictionary.Types_Are_Equal
                       (Left_Symbol        => Type_Sym,
                        Right_Symbol       => Announced_Type,
                        Full_Range_Subtype => False);
                  end if;
               else
                  -- The types must be the same
                  Consistent :=
                    Dictionary.Types_Are_Equal
                    (Left_Symbol        => Type_Sym,
                     Right_Symbol       => Announced_Type,
                     Full_Range_Subtype => False);
               end if;
            else
               -- No announced type so consistent by default
               Consistent := True;
            end if;
         else -- This is an own task
            Consistent :=
              Dictionary.Types_Are_Equal
              (Left_Symbol        => Root_Type_Sym,
               Right_Symbol       => Announced_Type,
               Full_Range_Subtype => False);
         end if;

         if not Consistent then
            -- Type mismatch between declaration and own variable annotation
            ErrorHandler.Semantic_Error
              (Err_Num   => 22,
               Reference => ErrorHandler.No_Reference,
               Position  => Node_Position (Node => Error_Node),
               Id_Str    => Node_Lex_String (Node => Error_Node));
         end if;
         OK_To_Add := Consistent;
      end Check_Type_Consistency;

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

      function Is_A_Protected_Own_Variable (Sym : Dictionary.Symbol) return Boolean
      --# global in Dictionary.Dict;
      is
      begin
         return Dictionary.IsOwnVariable (Sym) and then Dictionary.GetOwnVariableProtected (Sym);
      end Is_A_Protected_Own_Variable;

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

      procedure Check_PO_Declaration
        (Sym            : in     Dictionary.Symbol;
         Type_Sym       : in     Dictionary.Symbol;
         Scope          : in     Dictionary.Scopes;
         Error_Node_Pos : in     LexTokenManager.Token_Position;
         Valid          :    out Boolean)
      --# global in     CommandLineData.Content;
      --#        in     Dictionary.Dict;
      --#        in     LexTokenManager.State;
      --#        in out ErrorHandler.Error_Context;
      --#        in out SPARK_IO.File_Sys;
      --# derives ErrorHandler.Error_Context,
      --#         SPARK_IO.File_Sys          from CommandLineData.Content,
      --#                                         Dictionary.Dict,
      --#                                         ErrorHandler.Error_Context,
      --#                                         Error_Node_Pos,
      --#                                         LexTokenManager.State,
      --#                                         Scope,
      --#                                         SPARK_IO.File_Sys,
      --#                                         Sym,
      --#                                         Type_Sym &
      --#         Valid                      from Dictionary.Dict,
      --#                                         Scope,
      --#                                         Sym,
      --#                                         Type_Sym;
      is

         procedure Check_For_Multiple_Instances
           (Sym            : in     Dictionary.Symbol;
            Type_Sym       : in     Dictionary.Symbol;
            Scope          : in     Dictionary.Scopes;
            Error_Node_Pos : in     LexTokenManager.Token_Position;
            Valid          :    out Boolean)
         --# global in     CommandLineData.Content;
         --#        in     Dictionary.Dict;
         --#        in     LexTokenManager.State;
         --#        in out ErrorHandler.Error_Context;
         --#        in out SPARK_IO.File_Sys;
         --# derives ErrorHandler.Error_Context,
         --#         SPARK_IO.File_Sys          from CommandLineData.Content,
         --#                                         Dictionary.Dict,
         --#                                         ErrorHandler.Error_Context,
         --#                                         Error_Node_Pos,
         --#                                         LexTokenManager.State,
         --#                                         Scope,
         --#                                         SPARK_IO.File_Sys,
         --#                                         Sym,
         --#                                         Type_Sym &
         --#         Valid                      from Dictionary.Dict,
         --#                                         Sym,
         --#                                         Type_Sym;
         is
            It            : Dictionary.Iterator;
            Root_Type_Sym : Dictionary.Symbol;
         begin
            Valid         := True;
            Root_Type_Sym := Dictionary.GetRootType (Type_Sym);
            It            := Dictionary.FirstVirtualElement (Root_Type_Sym);
            if It /= Dictionary.NullIterator
              and then Dictionary.GetVirtualElementOwner (Dictionary.CurrentSymbol (It)) /= Sym then
               -- Illegal instance. This variable is not the one associated with
               -- the protects list in the own variable clause.
               Valid := False;
               ErrorHandler.Semantic_Error_Sym
                 (Err_Num   => 942,
                  Reference => ErrorHandler.No_Reference,
                  Position  => Error_Node_Pos,
                  Sym       => Root_Type_Sym,
                  Scope     => Scope);
            end if;
         end Check_For_Multiple_Instances;

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

         procedure Check_PO_Operations
           (Sym            : in Dictionary.Symbol;
            Type_Sym       : in Dictionary.Symbol;
            Scope          : in Dictionary.Scopes;
            Error_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 CommandLineData.Content,
         --#                                         Dictionary.Dict,
         --#                                         ErrorHandler.Error_Context,
         --#                                         Error_Node_Pos,
         --#                                         LexTokenManager.State,
         --#                                         Scope,
         --#                                         SPARK_IO.File_Sys,
         --#                                         Sym,
         --#                                         Type_Sym;
         is
            Subprogram_It      : Dictionary.Iterator;
            Subprogram_Sym     : Dictionary.Symbol;
            Global_Variable_It : Dictionary.Iterator;
         begin
            -- Get the first subprogram for the protected type.
            Subprogram_It := Dictionary.First_Visible_Subprogram (The_Package_Or_Type => Dictionary.GetRootType (Type_Sym));

            while not Dictionary.IsNullIterator (Subprogram_It) loop

               Subprogram_Sym := Dictionary.CurrentSymbol (Subprogram_It);

               -- Get the first global variable for this subprogram.
               Global_Variable_It :=
                 Dictionary.FirstGlobalVariable (Dictionary.GetAbstraction (Subprogram_Sym, Scope), Subprogram_Sym);

               -- Check the ceiling priority
               Check_Ceiling_Priority
                 (Sym                => Sym,
                  Scope              => Scope,
                  Check_List         => Global_Variable_It,
                  Priority_Lex_Value => Dictionary.GetTypePriority (Type_Sym),
                  Error_Node_Pos     => Error_Node_Pos);

               while not Dictionary.IsNullIterator (Global_Variable_It) loop

                  if Dictionary.CurrentSymbol (Global_Variable_It) = Sym then
                     -- A circular dependency has been found
                     ErrorHandler.Semantic_Error2
                       (Err_Num   => 916,
                        Reference => ErrorHandler.No_Reference,
                        Position  => Error_Node_Pos,
                        Id_Str1   => Dictionary.GetSimpleName (Sym),
                        Id_Str2   => Dictionary.GetSimpleName (Subprogram_Sym));
                  end if;

                  Global_Variable_It := Dictionary.NextSymbol (Global_Variable_It);
               end loop;

               -- Get the next subprogram.
               Subprogram_It := Dictionary.NextSymbol (Subprogram_It);
            end loop;
         end Check_PO_Operations;

         procedure Warn_Of_Interrupt_IDs
           (Sym            : in Dictionary.Symbol;
            Scope          : in Dictionary.Scopes;
            Error_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 CommandLineData.Content,
         --#                                         Dictionary.Dict,
         --#                                         ErrorHandler.Error_Context,
         --#                                         Error_Node_Pos,
         --#                                         LexTokenManager.State,
         --#                                         Scope,
         --#                                         SPARK_IO.File_Sys,
         --#                                         Sym;
         is
         begin
            if Dictionary.GetHasInterruptProperty (Sym) then
               ErrorHandler.Semantic_Warning_Sym (Err_Num  => 5,
                                                  Position => Error_Node_Pos,
                                                  Sym      => Sym,
                                                  Scope    => Scope);
            end if;
         end Warn_Of_Interrupt_IDs;

      begin -- Check_PO_Declaration
         if Dictionary.IsLibraryLevel (Scope) then
            if Dictionary.OwnVariableHasType (Sym, Scope) then
               Check_For_Multiple_Instances
                 (Sym            => Sym,
                  Type_Sym       => Type_Sym,
                  Scope          => Scope,
                  Error_Node_Pos => Error_Node_Pos,
                  Valid          => Valid);
               Check_PO_Operations (Sym            => Sym,
                                    Type_Sym       => Type_Sym,
                                    Scope          => Scope,
                                    Error_Node_Pos => Error_Node_Pos);
               Warn_Of_Interrupt_IDs (Sym            => Sym,
                                      Scope          => Scope,
                                      Error_Node_Pos => Error_Node_Pos);
            else
               -- The own variable was not type announced.
               Valid := False;
               ErrorHandler.Semantic_Error
                 (Err_Num   => 925,
                  Reference => ErrorHandler.No_Reference,
                  Position  => Error_Node_Pos,
                  Id_Str    => Dictionary.GetSimpleName (Sym));
            end if;
         else
            Valid := False;

            -- Illegal declaration of protected object
            ErrorHandler.Semantic_Error
              (Err_Num   => 868,
               Reference => ErrorHandler.No_Reference,
               Position  => Error_Node_Pos,
               Id_Str    => Dictionary.GetSimpleName (Sym));
         end if;
      end Check_PO_Declaration;

   begin -- Wf_Package_Variable
      Alias_Check (Type_Sym       => Type_Sym,
                   Alias_Node_Pos => Alias_Node_Pos,
                   Is_Aliased     => Is_Aliased);

      Root_Type_Sym := Dictionary.GetRootType (Type_Sym);

      --# assert STree.Table = STree.Table~;

      It :=
        Find_First_Node
        (Node_Kind    => SP_Symbols.identifier,
         From_Root    => Child_Node (Current_Node => Node),
         In_Direction => STree.Down);
      while not STree.IsNull (It) loop
         Next_Node := Get_Node (It => It);
         --# assert STree.Table = STree.Table~ and
         --#   Syntax_Node_Type (Next_Node, STree.Table) = SP_Symbols.identifier and
         --#   Next_Node = Get_Node (It);
         OK_To_Add       := False;
         Ident_Str       := Node_Lex_String (Node => Next_Node);
         Variable_Symbol := Dictionary.LookupItem
           (Name              => Ident_Str,
            Scope             => Current_Scope,
            Context           => Dictionary.ProofContext,
            Full_Package_Name => False);
         if Dictionary.Is_Null_Symbol (Variable_Symbol) then
            -- package state variable not previously announced
            if Dictionary.TypeIsTask (Type_Sym) then
               ErrorHandler.Semantic_Error
                 (Err_Num   => 930,
                  Reference => ErrorHandler.No_Reference,
                  Position  => Node_Position (Node => Next_Node),
                  Id_Str    => Ident_Str);
            else
               ErrorHandler.Semantic_Error
                 (Err_Num   => 151,
                  Reference => ErrorHandler.No_Reference,
                  Position  => Node_Position (Node => Next_Node),
                  Id_Str    => Ident_Str);
            end if;
         elsif Dictionary.GetContext (Variable_Symbol) = Dictionary.ProgramContext then
            ErrorHandler.Semantic_Error
              (Err_Num   => 10,
               Reference => ErrorHandler.No_Reference,
               Position  => Node_Position (Node => Next_Node),
               Id_Str    => Ident_Str);
         elsif not (Dictionary.IsOwnVariable (Variable_Symbol)
                      or else Dictionary.IsConstituent (Variable_Symbol)
                      or else Dictionary.IsOwnTask (Variable_Symbol)) then
            ErrorHandler.Semantic_Error
              (Err_Num   => 10,
               Reference => ErrorHandler.No_Reference,
               Position  => Node_Position (Node => Next_Node),
               Id_Str    => Ident_Str);
         elsif Dictionary.IsRefinedOwnVariable (Variable_Symbol) then
            ErrorHandler.Semantic_Error
              (Err_Num   => 73,
               Reference => ErrorHandler.No_Reference,
               Position  => Node_Position (Node => Next_Node),
               Id_Str    => Ident_Str);
         else
            OK_To_Add := True;
         end if;

         --# assert STree.Table = STree.Table~ and
         --#   Syntax_Node_Type (Next_Node, STree.Table) = SP_Symbols.identifier and
         --#   Next_Node = Get_Node (It) and
         --#   (OK_To_Add -> (not Dictionary.Is_Null_Symbol (Variable_Symbol)));

         if OK_To_Add then
            Check_Task_Modifier_Consistency
              (The_Own_Var_Type => Dictionary.GetType (Variable_Symbol),
               The_Var_Type     => Type_Sym,
               Modifier_Is_Task => Dictionary.IsOwnTask (Variable_Symbol),
               Error_Node       => Next_Node,
               Consistent       => OK_To_Add);
         end if;

         --# assert STree.Table = STree.Table~ and
         --#   Syntax_Node_Type (Next_Node, STree.Table) = SP_Symbols.identifier and
         --#   Next_Node = Get_Node (It) and
         --#   (OK_To_Add -> (not Dictionary.Is_Null_Symbol (Variable_Symbol)));

         if OK_To_Add then
            Check_Protected_Modifier_Consistency
              (The_Type              => Type_Sym,
               Modifier_Is_Protected => Dictionary.IsOwnVariable (Variable_Symbol)
                 and then Dictionary.GetOwnVariableProtected (Variable_Symbol),
               Error_Node            => Next_Node,
               Consistent            => OK_To_Add);
         end if;

         --# assert STree.Table = STree.Table~ and
         --#   Syntax_Node_Type (Next_Node, STree.Table) = SP_Symbols.identifier and
         --#   Next_Node = Get_Node (It) and
         --#   (OK_To_Add -> (not Dictionary.Is_Null_Symbol (Variable_Symbol)));

         if OK_To_Add
           and then ((Dictionary.IsOwnVariable (Variable_Symbol)
                        or else (Dictionary.IsConstituent (Variable_Symbol)))) then
            Check_Suspendable_Property_Consistency
              (Sym                 => Variable_Symbol,
               Type_Sym            => Type_Sym,
               Is_In_Suspends_List => Dictionary.GetIsSuspendable (Variable_Symbol),
               Error_Node_Pos      => Node_Position (Node => Node),
               Consistent          => OK_To_Add);
         end if;

         --# assert STree.Table = STree.Table~ and
         --#   Syntax_Node_Type (Next_Node, STree.Table) = SP_Symbols.identifier and
         --#   Next_Node = Get_Node (It) and
         --#   (OK_To_Add -> (not Dictionary.Is_Null_Symbol (Variable_Symbol)));

         if OK_To_Add
           and then (Dictionary.IsOwnVariable (Variable_Symbol)
                       or else Dictionary.IsConstituent (Variable_Symbol)) then
            Check_Priority_Property_Consistency
              (Sym                     => Variable_Symbol,
               Type_Sym                => Type_Sym,
               Priority_Property_Value => Dictionary.GetPriorityProperty (Variable_Symbol),
               Error_Node_Pos          => Node_Position (Node => Next_Node),
               Consistent              => OK_To_Add);
         end if;

         --# assert STree.Table = STree.Table~ and
         --#   Syntax_Node_Type (Next_Node, STree.Table) = SP_Symbols.identifier and
         --#   Next_Node = Get_Node (It) and
         --#   (OK_To_Add -> (not Dictionary.Is_Null_Symbol (Variable_Symbol)));

         if OK_To_Add
           and then (Dictionary.IsOwnVariable (Variable_Symbol)
                       or else Dictionary.IsConstituent (Variable_Symbol)) then
            Check_Interrupt_Property_Consistency
              (Has_Interrupt_Property => Dictionary.GetHasInterruptProperty (Variable_Symbol),
               Sym                    => Variable_Symbol,
               Type_Sym               => Type_Sym,
               Error_Node_Pos         => Node_Position (Node => Next_Node),
               Consistent             => OK_To_Add);
         end if;

         --# assert STree.Table = STree.Table~ and
         --#   Syntax_Node_Type (Next_Node, STree.Table) = SP_Symbols.identifier and
         --#   Next_Node = Get_Node (It) and
         --#   (OK_To_Add -> (not Dictionary.Is_Null_Symbol (Variable_Symbol)));

         if OK_To_Add
           and then ((Dictionary.IsOwnVariable (Variable_Symbol)
                        and then Dictionary.OwnVariableHasType (Variable_Symbol, Current_Scope))
                     or else (Dictionary.IsOwnTask (Variable_Symbol))) then
            -- This is a type announced own variable or task own variable.
            -- Check that announced type matches the one used in the declaration.
            Check_Type_Consistency
              (Sym        => Variable_Symbol,
               Type_Sym   => Type_Sym,
               Scope      => Current_Scope,
               Error_Node => Next_Node,
               OK_To_Add  => OK_To_Add);
         end if;

         --# assert STree.Table = STree.Table~ and
         --#   Syntax_Node_Type (Next_Node, STree.Table) = SP_Symbols.identifier and
         --#   Next_Node = Get_Node (It) and
         --#   (OK_To_Add -> (not Dictionary.Is_Null_Symbol (Variable_Symbol)));

         if OK_To_Add and then Dictionary.TypeIsTask (Type_Sym) then
            Check_Ceiling_Priority
              (Sym                => Variable_Symbol,
               Scope              => Current_Scope,
               Check_List         => Dictionary.FirstGlobalVariable (Dictionary.IsAbstract, Root_Type_Sym),
               Priority_Lex_Value => Dictionary.GetTypePriority (Type_Sym),
               Error_Node_Pos     => Node_Position (Node => Next_Node));
         end if;

         --# assert STree.Table = STree.Table~ and
         --#   Syntax_Node_Type (Next_Node, STree.Table) = SP_Symbols.identifier and
         --#   Next_Node = Get_Node (It) and
         --#   (OK_To_Add -> (not Dictionary.Is_Null_Symbol (Variable_Symbol)));

         if OK_To_Add
           and then Var_Is_Init
           and then Dictionary.IsOwnVariableOrConstituentWithMode (Variable_Symbol)
           and then not Is_A_Protected_Own_Variable (Sym => Variable_Symbol) then
            ErrorHandler.Semantic_Error
              (Err_Num   => 720,
               Reference => ErrorHandler.No_Reference,
               Position  => Node_Position (Node => Next_Node),
               Id_Str    => Ident_Str);
            OK_To_Add := False;
         end if;

         --# assert STree.Table = STree.Table~ and
         --#   Syntax_Node_Type (Next_Node, STree.Table) = SP_Symbols.identifier and
         --#   Next_Node = Get_Node (It) and
         --#   (OK_To_Add -> (not Dictionary.Is_Null_Symbol (Variable_Symbol)));

         if Dictionary.FirstVirtualElement (Root_Type_Sym) /= Dictionary.NullIterator
           and then not Dictionary.IsProtectedTypeMark (Root_Type_Sym) then
            -- A protects property has been given in an own variable declaration that
            -- announces a type that is not a protected type.
            OK_To_Add := False;
            ErrorHandler.Semantic_Error
              (Err_Num   => 937,
               Reference => ErrorHandler.No_Reference,
               Position  => Node_Position (Node => Next_Node),
               Id_Str    => Dictionary.GetSimpleName (Variable_Symbol));
         end if;

         --# assert STree.Table = STree.Table~ and
         --#   Syntax_Node_Type (Next_Node, STree.Table) = SP_Symbols.identifier and
         --#   Next_Node = Get_Node (It) and
         --#   (OK_To_Add -> (not Dictionary.Is_Null_Symbol (Variable_Symbol)));

         if OK_To_Add and then Dictionary.IsProtectedTypeMark (Type_Sym) then
            Check_PO_Declaration
              (Sym            => Variable_Symbol,
               Type_Sym       => Type_Sym,
               Scope          => Current_Scope,
               Error_Node_Pos => Node_Position (Node => Next_Node),
               Valid          => OK_To_Add);
         end if;

         --# assert STree.Table = STree.Table~ and
         --#   Syntax_Node_Type (Next_Node, STree.Table) = SP_Symbols.identifier and
         --#   Next_Node = Get_Node (It) and
         --#   (OK_To_Add -> (not Dictionary.Is_Null_Symbol (Variable_Symbol)));

         if OK_To_Add and then Var_Is_Init and then Unexpected_Initialization (Sym => Variable_Symbol) then
            ErrorHandler.Semantic_Error
              (Err_Num   => 333,
               Reference => ErrorHandler.No_Reference,
               Position  => Node_Position (Node => Next_Node),
               Id_Str    => Ident_Str);
         end if;

         --# assert STree.Table = STree.Table~ and
         --#   Syntax_Node_Type (Next_Node, STree.Table) = SP_Symbols.identifier and
         --#   Next_Node = Get_Node (It) and
         --#   (OK_To_Add -> (not Dictionary.Is_Null_Symbol (Variable_Symbol)));

         if OK_To_Add
           and then not Var_Is_Init
           and then Dictionary.IsOwnVariable (Variable_Symbol)
           and then Dictionary.GetOwnVariableMode (Variable_Symbol) = Dictionary.DefaultMode
           and then (Dictionary.GetOwnVariableProtected (Variable_Symbol)
                       or else Dictionary.IsVirtualElement (Variable_Symbol)) then
            -- Non moded protected state must be initialized at declaration.
            ErrorHandler.Semantic_Error
              (Err_Num   => 874,
               Reference => ErrorHandler.No_Reference,
               Position  => Node_Position (Node => Next_Node),
               Id_Str    => Ident_Str);
         end if;

         --# assert STree.Table = STree.Table~ and
         --#   Syntax_Node_Type (Next_Node, STree.Table) = SP_Symbols.identifier and
         --#   Next_Node = Get_Node (It) and
         --#   (OK_To_Add -> (not Dictionary.Is_Null_Symbol (Variable_Symbol)));

         if OK_To_Add then
            --# accept F, 10, Declaration_Symbol, "Expected ineffective assignment";
            Dictionary.Add_Variable_Declaration
              (Variable_Sym       => Variable_Symbol,
               The_Type           => Type_Sym,
               Initialized        => Var_Is_Init,
               Is_Aliased         => Is_Aliased,
               Exp_Node           => STree.NodeToRef (Exp_Node),
               Type_Reference     => Dictionary.Location'(Start_Position => Type_Node_Pos,
                                                          End_Position   => Type_Node_Pos),
               Comp_Unit          => ContextManager.Ops.Current_Unit,
               Declaration        => Dictionary.Location'(Start_Position => Node_Position (Node => Next_Node),
                                                          End_Position   => Node_Position (Node => Next_Node)),
               Scope              => Current_Scope,
               Declaration_Symbol => Declaration_Symbol);
            --# end accept;
            SystemErrors.RT_Assert
              (C       => Dictionary.IsVariable (Variable_Symbol),
               Sys_Err => SystemErrors.Invalid_Syntax_Tree,
               Msg     => "in Wf_Package_Variable");
            STree.Add_Node_Symbol (Node => Next_Node,
                                   Sym  => Variable_Symbol);
            if ErrorHandler.Generate_SLI then
               SLI.Generate_Xref_Symbol
                 (Comp_Unit      => ContextManager.Ops.Current_Unit,
                  Parse_Tree     => Next_Node,
                  Symbol         => Variable_Symbol,
                  Is_Declaration => True);
            end if;
            -- if we have an in stream, then initially mark it as invalid
            if Dictionary.GetOwnVariableOrConstituentMode (Variable_Symbol) = Dictionary.InMode then
               Dictionary.SetVariableMarkedValid (Variable_Symbol, False);
            end if;
            STree.Set_Node_Lex_String (Sym  => Variable_Symbol,
                                       Node => Next_Node);
         end if;
         It := STree.NextNode (It);
      end loop;
      --# accept F, 33, Declaration_Symbol, "Expected unused variable";
   end Wf_Package_Variable;

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

   procedure Wf_Procedure_Variable
     (Node, Exp_Node                : in STree.SyntaxNode;
      Alias_Node_Pos, Type_Node_Pos : in LexTokenManager.Token_Position;
      Type_Sym                      : in Dictionary.Symbol;
      Current_Scope                 : in Dictionary.Scopes;
      Is_Aliased, Var_Is_Init       : in Boolean)
   --# global in     CommandLineData.Content;
   --#        in     ContextManager.Ops.File_Heap;
   --#        in     ContextManager.Ops.Unit_Heap;
   --#        in     ContextManager.Ops.Unit_Stack;
   --#        in     LexTokenManager.State;
   --#        in out Dictionary.Dict;
   --#        in out ErrorHandler.Error_Context;
   --#        in out SLI.State;
   --#        in out SPARK_IO.File_Sys;
   --#        in out STree.Table;
   --# derives Dictionary.Dict,
   --#         STree.Table                from CommandLineData.Content,
   --#                                         ContextManager.Ops.Unit_Stack,
   --#                                         Current_Scope,
   --#                                         Dictionary.Dict,
   --#                                         Exp_Node,
   --#                                         LexTokenManager.State,
   --#                                         Node,
   --#                                         STree.Table,
   --#                                         Type_Sym,
   --#                                         Var_Is_Init &
   --#         ErrorHandler.Error_Context,
   --#         SLI.State,
   --#         SPARK_IO.File_Sys          from Alias_Node_Pos,
   --#                                         CommandLineData.Content,
   --#                                         ContextManager.Ops.File_Heap,
   --#                                         ContextManager.Ops.Unit_Heap,
   --#                                         ContextManager.Ops.Unit_Stack,
   --#                                         Current_Scope,
   --#                                         Dictionary.Dict,
   --#                                         ErrorHandler.Error_Context,
   --#                                         Exp_Node,
   --#                                         Is_Aliased,
   --#                                         LexTokenManager.State,
   --#                                         Node,
   --#                                         SLI.State,
   --#                                         SPARK_IO.File_Sys,
   --#                                         STree.Table,
   --#                                         Type_Node_Pos,
   --#                                         Type_Sym,
   --#                                         Var_Is_Init;
   --# pre Syntax_Node_Type (Node, STree.Table) = SP_Symbols.variable_declaration and
   --#   (Exp_Node = STree.NullNode or Syntax_Node_Type (Exp_Node, STree.Table) = SP_Symbols.expression);
   --# post STree.Table = STree.Table~;
   is
      It                 : STree.Iterator;
      Next_Node          : STree.SyntaxNode;
      Ident_Str          : LexTokenManager.Lex_String;
      Sym                : Dictionary.Symbol;
      Declaration_Symbol : Dictionary.Symbol;
      Variable_Symbol    : Dictionary.Symbol;
      OK_To_Add          : Boolean;
   begin
      Alias_Check (Type_Sym       => Type_Sym,
                   Alias_Node_Pos => Alias_Node_Pos,
                   Is_Aliased     => Is_Aliased);

      It := Find_First_Node
        (Node_Kind    => SP_Symbols.identifier,
         From_Root    => Child_Node (Current_Node => Node),
         In_Direction => STree.Down);
      while not STree.IsNull (It) loop
         Next_Node := Get_Node (It => It);
         --# assert STree.Table = STree.Table~ and
         --#   Syntax_Node_Type (Next_Node, STree.Table) = SP_Symbols.identifier and
         --#   Next_Node = Get_Node (It);
         Ident_Str := Node_Lex_String (Node => Next_Node);
         Sym       := Dictionary.LookupItem
           (Name              => Ident_Str,
            Scope             => Current_Scope,
            Context           => Dictionary.ProofContext,
            Full_Package_Name => False);
         OK_To_Add := True;
         if Dictionary.IsProtectedTypeMark (Type_Sym) then
            OK_To_Add := False;
            -- Illegal declaration of protected object
            ErrorHandler.Semantic_Error
              (Err_Num   => 868,
               Reference => ErrorHandler.No_Reference,
               Position  => Node_Position (Node => Next_Node),
               Id_Str    => Ident_Str);
         elsif Dictionary.IsPredefinedSuspensionObjectType (Type_Sym) then
            OK_To_Add := False;
            -- Illegal declaration of suspension object
            ErrorHandler.Semantic_Error
              (Err_Num   => 901,
               Reference => ErrorHandler.No_Reference,
               Position  => Node_Position (Node => Next_Node),
               Id_Str    => Ident_Str);
         elsif Dictionary.TypeIsTask (Type_Sym) then
            OK_To_Add := False;
            -- illegal declaration of task object.
            ErrorHandler.Semantic_Error
              (Err_Num   => 926,
               Reference => ErrorHandler.No_Reference,
               Position  => Node_Position (Node => Next_Node),
               Id_Str    => Ident_Str);
         end if;

         if not Dictionary.Is_Null_Symbol (Sym) then
            OK_To_Add := False;
            -- already exists
            ErrorHandler.Semantic_Error
              (Err_Num   => 10,
               Reference => ErrorHandler.No_Reference,
               Position  => Node_Position (Node => Next_Node),
               Id_Str    => Ident_Str);
         end if;

         if OK_To_Add then
            Dictionary.Add_Variable
              (Name               => Ident_Str,
               The_Type           => Type_Sym,
               Initialized        => Var_Is_Init,
               Is_Aliased         => False,
               Exp_Node           => STree.NodeToRef (Exp_Node),
               Type_Reference     => Dictionary.Location'(Start_Position => Type_Node_Pos,
                                                          End_Position   => Type_Node_Pos),
               Comp_Unit          => ContextManager.Ops.Current_Unit,
               Declaration        => Dictionary.Location'(Start_Position => Node_Position (Node => Next_Node),
                                                          End_Position   => Node_Position (Node => Next_Node)),
               Scope              => Current_Scope,
               Declaration_Symbol => Declaration_Symbol,
               Variable_Symbol    => Variable_Symbol);
            STree.Add_Node_Symbol (Node => Next_Node,
                                   Sym  => Variable_Symbol);
            if ErrorHandler.Generate_SLI then
               SLI.Generate_Xref_Symbol
                 (Comp_Unit      => ContextManager.Ops.Current_Unit,
                  Parse_Tree     => Next_Node,
                  Symbol         => Declaration_Symbol,
                  Is_Declaration => True);
            end if;
         end if;
         It := STree.NextNode (It);
      end loop;
   end Wf_Procedure_Variable;

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

   procedure Wf_Protected_Element
     (Node, Exp_Node                : in STree.SyntaxNode;
      Alias_Node_Pos, Type_Node_Pos : in LexTokenManager.Token_Position;
      Type_Sym                      : in Dictionary.Symbol;
      Current_Scope                 : in Dictionary.Scopes;
      Is_Aliased, Var_Is_Init       : in Boolean)
   --# global in     CommandLineData.Content;
   --#        in     ContextManager.Ops.File_Heap;
   --#        in     ContextManager.Ops.Unit_Heap;
   --#        in     ContextManager.Ops.Unit_Stack;
   --#        in     LexTokenManager.State;
   --#        in out Dictionary.Dict;
   --#        in out ErrorHandler.Error_Context;
   --#        in out SLI.State;
   --#        in out SPARK_IO.File_Sys;
   --#        in out STree.Table;
   --# derives Dictionary.Dict,
   --#         STree.Table                from CommandLineData.Content,
   --#                                         ContextManager.Ops.Unit_Stack,
   --#                                         Current_Scope,
   --#                                         Dictionary.Dict,
   --#                                         Exp_Node,
   --#                                         LexTokenManager.State,
   --#                                         Node,
   --#                                         STree.Table,
   --#                                         Type_Sym,
   --#                                         Var_Is_Init &
   --#         ErrorHandler.Error_Context,
   --#         SLI.State,
   --#         SPARK_IO.File_Sys          from Alias_Node_Pos,
   --#                                         CommandLineData.Content,
   --#                                         ContextManager.Ops.File_Heap,
   --#                                         ContextManager.Ops.Unit_Heap,
   --#                                         ContextManager.Ops.Unit_Stack,
   --#                                         Current_Scope,
   --#                                         Dictionary.Dict,
   --#                                         ErrorHandler.Error_Context,
   --#                                         Exp_Node,
   --#                                         Is_Aliased,
   --#                                         LexTokenManager.State,
   --#                                         Node,
   --#                                         SLI.State,
   --#                                         SPARK_IO.File_Sys,
   --#                                         STree.Table,
   --#                                         Type_Node_Pos,
   --#                                         Type_Sym,
   --#                                         Var_Is_Init;
   --# pre Syntax_Node_Type (Node, STree.Table) = SP_Symbols.variable_declaration and
   --#   (Exp_Node = STree.NullNode or Syntax_Node_Type (Exp_Node, STree.Table) = SP_Symbols.expression);
   --# post STree.Table = STree.Table~;
   is
      It                 : STree.Iterator;
      Next_Node          : STree.SyntaxNode;
      Ident_Str          : LexTokenManager.Lex_String;
      Declaration_Symbol : Dictionary.Symbol;
      Variable_Symbol    : Dictionary.Symbol;
      OK_To_Add          : Boolean;
   begin
      Alias_Check (Type_Sym       => Type_Sym,
                   Alias_Node_Pos => Alias_Node_Pos,
                   Is_Aliased     => Is_Aliased);

      It := Find_First_Node
        (Node_Kind    => SP_Symbols.identifier,
         From_Root    => Child_Node (Current_Node => Node),
         In_Direction => STree.Down);
      while not STree.IsNull (It) loop
         Next_Node := Get_Node (It => It);
         --# assert STree.Table = STree.Table~ and
         --#   Syntax_Node_Type (Next_Node, STree.Table) = SP_Symbols.identifier and
         --#   Next_Node = Get_Node (It);
         Ident_Str       := Node_Lex_String (Node => Next_Node);
         Variable_Symbol := Dictionary.LookupItem
           (Name              => Ident_Str,
            Scope             => Current_Scope,
            Context           => Dictionary.ProofContext,
            Full_Package_Name => False);
         OK_To_Add := True;
         if Dictionary.IsProtectedTypeMark (Type_Sym) then
            OK_To_Add := False;
            -- Illegal declaration of protected object
            ErrorHandler.Semantic_Error
              (Err_Num   => 868,
               Reference => ErrorHandler.No_Reference,
               Position  => Node_Position (Node => Next_Node),
               Id_Str    => Ident_Str);
         elsif Dictionary.IsPredefinedSuspensionObjectType (Type_Sym) then
            OK_To_Add := False;
            -- Illegal declaration of suspension object
            ErrorHandler.Semantic_Error
              (Err_Num   => 901,
               Reference => ErrorHandler.No_Reference,
               Position  => Node_Position (Node => Next_Node),
               Id_Str    => Ident_Str);
         elsif Dictionary.TypeIsTask (Type_Sym) then
            OK_To_Add := False;
            -- illegal declaration of task object.
            ErrorHandler.Semantic_Error
              (Err_Num   => 926,
               Reference => ErrorHandler.No_Reference,
               Position  => Node_Position (Node => Next_Node),
               Id_Str    => Ident_Str);
         elsif not Dictionary.Is_Null_Symbol (Variable_Symbol) then
            OK_To_Add := False;
            -- already exists
            ErrorHandler.Semantic_Error
              (Err_Num   => 10,
               Reference => ErrorHandler.No_Reference,
               Position  => Node_Position (Node => Next_Node),
               Id_Str    => Ident_Str);
         end if;

         if OK_To_Add then
            -- Declaration is legal
            -- First add variable as a refinement constituent of the implicit own variable associated
            -- with the protected type
            Dictionary.AddConstituent
              (Name                 => Ident_Str,
               Subject              => Dictionary.GetProtectedTypeOwnVariable (Dictionary.GetRegion (Current_Scope)),
               Mode                 => Dictionary.DefaultMode,
               SubjectReference     => Dictionary.Location'(Start_Position => Node_Position (Node => Next_Node),
                                                            End_Position   => Node_Position (Node => Next_Node)),
               Comp_Unit            => ContextManager.Ops.Current_Unit,
               ConstituentReference => Dictionary.Location'(Start_Position => Node_Position (Node => Next_Node),
                                                            End_Position   => Node_Position (Node => Next_Node)));
            Variable_Symbol := Dictionary.LookupImmediateScope
              (Name    => Ident_Str,
               Scope   => Dictionary.Set_Visibility (The_Visibility => Dictionary.Privat,
                                                     The_Unit       => Dictionary.GetRegion (Current_Scope)),
               Context => Dictionary.ProofContext);
            SystemErrors.RT_Assert
              (C       => not Dictionary.Is_Null_Symbol (Variable_Symbol),
               Sys_Err => SystemErrors.Invalid_Syntax_Tree,
               Msg     => "in Wf_Protected_Element");
            -- then add the variable itself
            Dictionary.Add_Variable_Declaration
              (Variable_Sym       => Variable_Symbol,
               The_Type           => Type_Sym,
               Initialized        => Var_Is_Init,
               Is_Aliased         => False,
               Exp_Node           => STree.NodeToRef (Exp_Node),
               Type_Reference     => Dictionary.Location'(Start_Position => Type_Node_Pos,
                                                          End_Position   => Type_Node_Pos),
               Comp_Unit          => ContextManager.Ops.Current_Unit,
               Declaration        => Dictionary.Location'(Start_Position => Node_Position (Node => Next_Node),
                                                          End_Position   => Node_Position (Node => Next_Node)),
               Scope              => Current_Scope,
               Declaration_Symbol => Declaration_Symbol);
            SystemErrors.RT_Assert
              (C       => Dictionary.IsVariable (Variable_Symbol),
               Sys_Err => SystemErrors.Invalid_Syntax_Tree,
               Msg     => "in Wf_Protected_Element");
            STree.Add_Node_Symbol (Node => Next_Node,
                                   Sym  => Variable_Symbol);
            if ErrorHandler.Generate_SLI then
               SLI.Generate_Xref_Symbol
                 (Comp_Unit      => ContextManager.Ops.Current_Unit,
                  Parse_Tree     => Next_Node,
                  Symbol         => Declaration_Symbol,
                  Is_Declaration => True);
            end if;
            -- Checking that protected elements are initialized is now done
            -- in wf_protected_type_declaration to allow for justification of
            -- these errors.
         end if;
         It := STree.NextNode (It);
      end loop;
   end Wf_Protected_Element;

begin -- Wf_Variable_Declaration
   Heap.Reset (The_Heap);

   Alias_Node       := STree.NullNode;
   Declaration_Sort := Get_Declaration_Sort (Scope => Declaration_Scope);
   Type_Node        := Next_Sibling (Current_Node => Child_Node (Current_Node => Node));
   -- ASSUME Type_Node = RWaliased OR type_mark
   if Syntax_Node_Type (Node => Type_Node) = SP_Symbols.RWaliased then
      -- ASSUME Type_Node = RWaliased
      Is_Aliased := True;
      Alias_Node := Type_Node;
      Type_Node  := Next_Sibling (Current_Node => Type_Node);
   elsif Syntax_Node_Type (Node => Type_Node) /= SP_Symbols.type_mark then
      SystemErrors.Fatal_Error
        (Sys_Err => SystemErrors.Invalid_Syntax_Tree,
         Msg     => "Expect Type_Node = RWaliased OR type_mark in Wf_Variable_Declaration");
   end if;
   -- ASSUME Type_Node = type_mark
   SystemErrors.RT_Assert
     (C       => Syntax_Node_Type (Node => Type_Node) = SP_Symbols.type_mark,
      Sys_Err => SystemErrors.Invalid_Syntax_Tree,
      Msg     => "Expect Type_Node = type_mark in Wf_Variable_Declaration");
   -- ASSUME Alias_Node = RWaliased OR NULL
   SystemErrors.RT_Assert
     (C       => Alias_Node = STree.NullNode or else Syntax_Node_Type (Node => Alias_Node) = SP_Symbols.RWaliased,
      Sys_Err => SystemErrors.Invalid_Syntax_Tree,
      Msg     => "Expect Alias_Node = RWaliased OR NULL in Wf_Variable_Declaration");

   Wf_Type_Mark
     (Node          => Type_Node,
      Current_Scope => Enclosing_Unit_Scope,
      Context       => Dictionary.ProgramContext,
      Type_Sym      => Type_Sym);

   -- variable initialization
   -- Protected and suspension objects are implicitly initialised on declaration.
   Var_Is_Init := Dictionary.IsPredefinedSuspensionObjectType (Type_Sym) or else Dictionary.IsProtectedTypeMark (Type_Sym);

   Exp_Node := Next_Sibling (Current_Node => Type_Node);
   -- ASSUME Exp_Node = expression OR NULL
   if Syntax_Node_Type (Node => Exp_Node) = SP_Symbols.expression then
      -- ASSUME Exp_Node = expression
      if Dictionary.TypeIsGeneric (Type_Sym) then
         -- Initialization of such variables not allowed in generic bodies because we rely on VCs
         -- to do range checks that in non-generic situations can be done statically and
         -- no VCs are generated for variable initializations.
         ErrorHandler.Semantic_Error
           (Err_Num   => 651,
            Reference => ErrorHandler.No_Reference,
            Position  => Node_Position (Node => Exp_Node),
            Id_Str    => LexTokenManager.Null_String);
      else
         -- Non-generic case, initialization is ok
         Var_Is_Init := True;
         SeqAlgebra.CreateSeq (The_Heap, Unwanted_Seq);
         ComponentManager.Initialise (Unused_Component_Data);
         --# accept Flow, 10, Unused_Component_Data, "Unused_Component_Data is discarded";
         Walk_Expression_P.Walk_Expression
           (Exp_Node                => Exp_Node,
            Scope                   => Declaration_Scope,
            Type_Context            => Type_Sym,
            Context_Requires_Static => False,
            Ref_Var                 => Unwanted_Seq,
            Result                  => Exp_Type,
            Component_Data          => Unused_Component_Data,
            The_Heap                => The_Heap);
         --# end accept;
         SeqAlgebra.DisposeOfSeq (The_Heap, Unwanted_Seq);
         Assignment_Check
           (Position    => Node_Position (Node => Exp_Node),
            Scope       => Enclosing_Unit_Scope,
            Target_Type => Type_Sym,
            Exp_Result  => Exp_Type);
         if not Exp_Type.Is_Constant then
            ErrorHandler.Semantic_Error
              (Err_Num   => 50,
               Reference => ErrorHandler.No_Reference,
               Position  => Node_Position (Node => Exp_Node),
               Id_Str    => LexTokenManager.Null_String);
         end if;
      end if;
   elsif Exp_Node /= STree.NullNode then
      SystemErrors.Fatal_Error
        (Sys_Err => SystemErrors.Invalid_Syntax_Tree,
         Msg     => "Expect Exp_Node = expression OR NULL in Wf_Variable_Declaration");
   end if;
   case Declaration_Sort is
      when In_Package =>
         Wf_Package_Variable
           (Node           => Node,
            Exp_Node       => Exp_Node,
            Alias_Node_Pos => Node_Position (Node => Alias_Node),
            Type_Node_Pos  => Node_Position (Node => Type_Node),
            Type_Sym       => Type_Sym,
            Current_Scope  => Declaration_Scope,
            Is_Aliased     => Is_Aliased,
            Var_Is_Init    => Var_Is_Init);
      when In_Subprogram =>
         Wf_Procedure_Variable
           (Node           => Node,
            Exp_Node       => Exp_Node,
            Alias_Node_Pos => Node_Position (Node => Alias_Node),
            Type_Node_Pos  => Node_Position (Node => Type_Node),
            Type_Sym       => Type_Sym,
            Current_Scope  => Declaration_Scope,
            Is_Aliased     => Is_Aliased,
            Var_Is_Init    => Var_Is_Init);
      when In_Protected_Type =>
         Wf_Protected_Element
           (Node           => Node,
            Exp_Node       => Exp_Node,
            Alias_Node_Pos => Node_Position (Node => Alias_Node),
            Type_Node_Pos  => Node_Position (Node => Type_Node),
            Type_Sym       => Type_Sym,
            Current_Scope  => Declaration_Scope,
            Is_Aliased     => Is_Aliased,
            Var_Is_Init    => Var_Is_Init);
   end case;

   if Dictionary.Is_Unconstrained_Array_Type_Mark (Type_Sym, Enclosing_Unit_Scope)
     or else Dictionary.IsUnconstrainedTaskType (Type_Sym)
     or else Dictionary.IsUnconstrainedProtectedType (Type_Sym) then
      ErrorHandler.Semantic_Error
        (Err_Num   => 39,
         Reference => ErrorHandler.No_Reference,
         Position  => Node_Position (Node => Type_Node),
         Id_Str    => LexTokenManager.Null_String);
   end if;

   Heap.ReportUsage (The_Heap);
end Wf_Variable_Declaration;
