-------------------------------------------------------------------------------
-- (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 Clists;
with DAG_IO;
with Debug;
with ExaminerConstants;
with SeqAlgebra;
with SystemErrors;

separate (DAG)
procedure BuildGraph
  (StartNode                    : in     STree.SyntaxNode;
   SubprogSym                   : in     Dictionary.Symbol;
   Scope                        : in     Dictionary.Scopes;
   OutputFile                   : in     SPARK_IO.File_Type;
   EndPosition                  : in     LexTokenManager.Token_Position;
   VCGFailure                   : in out Boolean;
   VCGHeap                      : in out Cells.Heap_Record;
   FlowHeap                     : in out Heap.HeapRecord;
   Semantic_Error_In_Subprogram : in     Boolean;
   DataFlowErrorInSubprogram    : in     Boolean;
   Type_Check_Exports           : in     Boolean)
is
   InitialRecord              : StmtStack.StmtRecord;
   LastNode, Local_Node, Node : STree.SyntaxNode;
   NodeType                   : SP_Symbols.SP_Symbol;
   StmtLabel                  : Labels.Label;
   LineNmbr                   : Integer;
   LScope                     : Dictionary.Scopes;
   SubprogramCalls            : Natural;

   ShortCircuitStack : CStacks.Stack;

   CheckStack : CStacks.Stack;

   ContainsReals : Boolean;

   PreConstraints : Cells.Cell;

   ImportConstraints : Cells.Cell := Cells.Null_Cell;

   -- global used to distinguish Run_Time_Check from PreConCheck
   KindOfStackedCheck : Graph.Proof_Context_Type := Graph.Run_Time_Check;

   DoAssumeLocalRvalues : Boolean;

   LoopStack : LoopContext.T;

   -------------------------------------------------------------------------
   --                    Cell Creation Utilities
   -------------------------------------------------------------------------

   procedure SubstituteTwiddled
     (Abstraction    : in Dictionary.Abstractions;
      SubProg        : in Dictionary.Symbol;
      ConstraintRoot : in Cells.Cell)
   -- replace import-export variables by their twiddled version
   -- in a precondition.
   -- This has been plagiarised from SubstituteParameters in
   -- ModelPrecondition.
   --# global in     Dictionary.Dict;
   --#        in out Statistics.TableUsage;
   --#        in out VCGHeap;
   --# derives Statistics.TableUsage,
   --#         VCGHeap               from *,
   --#                                    Abstraction,
   --#                                    ConstraintRoot,
   --#                                    Dictionary.Dict,
   --#                                    SubProg,
   --#                                    VCGHeap;
   is
      P      : Cells.Cell;
      S      : CStacks.Stack;
      VarSym : Dictionary.Symbol;
   begin
      -- DAG traversal algorithm of D.E. Knuth, Fundamental Algorithms, p.317;
      CStacks.CreateStack (S);
      P := ConstraintRoot;
      loop
         loop
            exit when Cells.Is_Null_Cell (P);
            CStacks.Push (VCGHeap, P, S);
            if Is_Leaf (Node     => P,
                        VCG_Heap => VCGHeap) then
               P := Cells.Null_Cell;
            else
               P := LeftPtr (VCGHeap, P);
            end if;
         end loop;
         exit when CStacks.IsEmpty (S);
         P := CStacks.Top (VCGHeap, S);
         CStacks.Pop (VCGHeap, S);
         if Is_Leaf (Node     => P,
                     VCG_Heap => VCGHeap) then
            if Cells.Get_Kind (VCGHeap, P) = Cell_Storage.Reference then
               VarSym := Cells.Get_Symbol_Value (VCGHeap, P);
               if Dictionary.IsImportExport (Abstraction, SubProg, VarSym) then
                  SetTilde (P, VCGHeap);
               end if;
            end if;
            P := Cells.Null_Cell;
         else
            P := RightPtr (VCGHeap, P);
         end if;
      end loop;
   end SubstituteTwiddled;

   ---------------------------------------------------------------------
   -- More cell creation utilities
   ---------------------------------------------------------------------

   procedure Advance (NodeNmbr : in Natural)
   --# global in out StmtStack.S;
   --# derives StmtStack.S from *,
   --#                          NodeNmbr;
   is
      S : StmtStack.StmtRecord;
   begin
      S := StmtStack.Top;
      StmtStack.Pop;
      S.StmtNmbr := NodeNmbr;
      StmtStack.Push (S);
   end Advance;

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

   -- function return true if VarSym is visible in Ada context from Scope
   function IsDirectlyVisible (VarSym : Dictionary.Symbol;
                               Scope  : Dictionary.Scopes) return Boolean
   --# global in CommandLineData.Content;
   --#        in Dictionary.Dict;
   --#        in LexTokenManager.State;
   is
      Result : Boolean;
   begin
      -- first check to see if we can see the VarSym directly without prefixing
      Result :=
        Dictionary.LookupItem
        (Name              => Dictionary.GetSimpleName (VarSym),
         Scope             => Scope,
         Context           => Dictionary.ProgramContext,
         Full_Package_Name => False) =
        VarSym;

      -- if not look it up in the package it belongs to
      if not Result then
         Result :=
           Dictionary.LookupSelectedItem
           (Dictionary.GetRegion (Dictionary.GetScope (VarSym)),
            Dictionary.GetSimpleName (VarSym),
            Scope,
            Dictionary.ProgramContext) =
           VarSym;
      end if;

      return Result;
   end IsDirectlyVisible;
   --883

   procedure ConjoinParamConstraint
     (Type_Sym              : in     Dictionary.Symbol;
      Var_Sym               : in     Dictionary.Symbol;
      Scope                 : in     Dictionary.Scopes;
      Consider_Always_Valid : in     Boolean;
      DAGCell               : in out Cells.Cell)
   --# global in out ContainsReals;
   --#        in out Dictionary.Dict;
   --#        in out LexTokenManager.State;
   --#        in out SPARK_IO.File_Sys;
   --#        in out Statistics.TableUsage;
   --#        in out VCGFailure;
   --#        in out VCGHeap;
   --# derives ContainsReals,
   --#         DAGCell,
   --#         Dictionary.Dict,
   --#         LexTokenManager.State,
   --#         SPARK_IO.File_Sys,
   --#         VCGFailure            from *,
   --#                                    Consider_Always_Valid,
   --#                                    Dictionary.Dict,
   --#                                    LexTokenManager.State,
   --#                                    Scope,
   --#                                    Type_Sym,
   --#                                    Var_Sym,
   --#                                    VCGHeap &
   --#         Statistics.TableUsage,
   --#         VCGHeap               from *,
   --#                                    Consider_Always_Valid,
   --#                                    DAGCell,
   --#                                    Dictionary.Dict,
   --#                                    LexTokenManager.State,
   --#                                    Scope,
   --#                                    Type_Sym,
   --#                                    Var_Sym,
   --#                                    VCGHeap;
   is
      Constr, VarCell : Cells.Cell;
   begin
      CreateReferenceCell (VarCell, VCGHeap, Var_Sym);

      Type_Constraint.Make
        (The_Type              => Type_Sym,
         The_Expression        => VarCell,
         Scope                 => Scope,
         Consider_Always_Valid => Consider_Always_Valid,
         The_Constraint        => Constr,
         VCG_Heap              => VCGHeap,
         VC_Contains_Reals     => ContainsReals,
         VC_Failure            => VCGFailure);

      if not Cells.Is_Null_Cell (Constr) then
         Cells.Utility.Conjoin (VCGHeap, Constr, DAGCell);
      end if;
   end ConjoinParamConstraint;

   procedure AssumeTypesOfFormalImportParams
     (Abstraction : in     Dictionary.Abstractions;
      SubProg     : in     Dictionary.Symbol;
      Scope       : in     Dictionary.Scopes;
      DAGCell     : in out Cells.Cell)
   --# global in out ContainsReals;
   --#        in out Dictionary.Dict;
   --#        in out LexTokenManager.State;
   --#        in out SPARK_IO.File_Sys;
   --#        in out Statistics.TableUsage;
   --#        in out VCGFailure;
   --#        in out VCGHeap;
   --# derives ContainsReals,
   --#         DAGCell,
   --#         Dictionary.Dict,
   --#         LexTokenManager.State,
   --#         SPARK_IO.File_Sys,
   --#         Statistics.TableUsage,
   --#         VCGFailure,
   --#         VCGHeap               from *,
   --#                                    Abstraction,
   --#                                    DAGCell,
   --#                                    Dictionary.Dict,
   --#                                    LexTokenManager.State,
   --#                                    Scope,
   --#                                    SubProg,
   --#                                    VCGHeap;
   is
      NumOfParams : Natural;
      FormalParam : Dictionary.Symbol;
      Type_Sym    : Dictionary.Symbol;
   begin
      NumOfParams := Dictionary.GetNumberOfSubprogramParameters (SubProg);
      for ParamNum in Natural range 1 .. NumOfParams loop
         FormalParam := Dictionary.GetSubprogramParameter (SubProg, ParamNum);
         if Dictionary.IsFunction (SubProg) or else Dictionary.IsImport (Abstraction, SubProg, FormalParam) then
            Type_Sym := Dictionary.GetType (FormalParam);
            -- suppress assumption for private types
            if not Dictionary.IsPrivateType (Type_Sym, Scope) or else Dictionary.IsPredefinedTimeType (Type_Sym) then
               ConjoinParamConstraint (Type_Sym, FormalParam, Scope, False, DAGCell);
            end if;
         end if;
      end loop;
   end AssumeTypesOfFormalImportParams;

   procedure AssumeTypesOfImportGlobals
     (Abstraction : in     Dictionary.Abstractions;
      SubProg     : in     Dictionary.Symbol;
      Scope       : in     Dictionary.Scopes;
      DAGCell     : in out Cells.Cell)
   --# global in     CommandLineData.Content;
   --#        in out ContainsReals;
   --#        in out Dictionary.Dict;
   --#        in out LexTokenManager.State;
   --#        in out SPARK_IO.File_Sys;
   --#        in out Statistics.TableUsage;
   --#        in out VCGFailure;
   --#        in out VCGHeap;
   --# derives ContainsReals,
   --#         DAGCell,
   --#         Dictionary.Dict,
   --#         LexTokenManager.State,
   --#         SPARK_IO.File_Sys,
   --#         Statistics.TableUsage,
   --#         VCGFailure,
   --#         VCGHeap               from *,
   --#                                    Abstraction,
   --#                                    CommandLineData.Content,
   --#                                    DAGCell,
   --#                                    Dictionary.Dict,
   --#                                    LexTokenManager.State,
   --#                                    Scope,
   --#                                    SubProg,
   --#                                    VCGHeap;
   is
      It        : Dictionary.Iterator;
      GlobalVar : Dictionary.Symbol;
      Type_Sym  : Dictionary.Symbol;
   begin
      It := Dictionary.FirstGlobalVariable (Abstraction, SubProg);
      while not Dictionary.IsNullIterator (It) loop
         GlobalVar := Dictionary.CurrentSymbol (It);

         if Dictionary.IsFunction (SubProg) or else Dictionary.IsImport (Abstraction, SubProg, GlobalVar) then
            -- In mode stream are treated with normal variables, since we now
            -- use the MarkedValid bit in the symbol table to remember if they
            -- produce values in-type, or not. The test occurs as the
            -- hypotheses are generated, since it can vary subcomponent by
            -- subcomponent with in-mode record variables.
            if Dictionary.GetOwnVariableOrConstituentMode (GlobalVar) = Dictionary.DefaultMode
              or else (Dictionary.GetOwnVariableOrConstituentMode (GlobalVar) = Dictionary.InMode) then
               if IsDirectlyVisible (GlobalVar, Scope) then
                  Type_Sym := Dictionary.GetType (GlobalVar);
                  if not Dictionary.IsPrivateType (Type_Sym, Scope) or else Dictionary.IsPredefinedTimeType (Type_Sym) then
                     -- Hack to avoid generating extra true hypotheses in most
                     -- cases - now a true hypothesis will only be generated in
                     -- record variables with some valid fields (new case, and
                     -- hence OK), or when a whole stream in record is invalid.
                     -- Stream-in invalid discretes are short-cut here
                     if Dictionary.IsRecordTypeMark (Type_Sym, Scope)
                       or else Dictionary.IsArrayTypeMark (Type_Sym, Scope)
                       or else ((Dictionary.TypeIsScalar (Type_Sym) or else Dictionary.IsPredefinedTimeType (Type_Sym))
                                and then Dictionary.VariableOrSubcomponentIsMarkedValid (GlobalVar)) then
                        ConjoinParamConstraint (Type_Sym, GlobalVar, Scope, True, DAGCell);
                     end if;
                  end if;
               end if;
            end if;
         end if;
         It := Dictionary.NextSymbol (It);
      end loop;
   end AssumeTypesOfImportGlobals;

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

   procedure ModelCheckStmt (Expn_Node : in STree.SyntaxNode)
   --# global in     CommandLineData.Content;
   --#        in     LineNmbr;
   --#        in     LoopStack;
   --#        in     LScope;
   --#        in     STree.Table;
   --#        in out ContainsReals;
   --#        in out Dictionary.Dict;
   --#        in out ErrorHandler.Error_Context;
   --#        in out Graph.Table;
   --#        in out LexTokenManager.State;
   --#        in out SPARK_IO.File_Sys;
   --#        in out Statistics.TableUsage;
   --#        in out StmtStack.S;
   --#        in out VCGFailure;
   --#        in out VCGHeap;
   --# derives ContainsReals,
   --#         Dictionary.Dict,
   --#         LexTokenManager.State,
   --#         VCGFailure                 from *,
   --#                                         CommandLineData.Content,
   --#                                         Dictionary.Dict,
   --#                                         Expn_Node,
   --#                                         LexTokenManager.State,
   --#                                         LoopStack,
   --#                                         LScope,
   --#                                         STree.Table,
   --#                                         VCGHeap &
   --#         ErrorHandler.Error_Context,
   --#         SPARK_IO.File_Sys          from CommandLineData.Content,
   --#                                         Dictionary.Dict,
   --#                                         ErrorHandler.Error_Context,
   --#                                         Expn_Node,
   --#                                         LexTokenManager.State,
   --#                                         LoopStack,
   --#                                         LScope,
   --#                                         SPARK_IO.File_Sys,
   --#                                         STree.Table,
   --#                                         VCGHeap &
   --#         Graph.Table,
   --#         Statistics.TableUsage,
   --#         StmtStack.S,
   --#         VCGHeap                    from *,
   --#                                         CommandLineData.Content,
   --#                                         Dictionary.Dict,
   --#                                         Expn_Node,
   --#                                         Graph.Table,
   --#                                         LexTokenManager.State,
   --#                                         LineNmbr,
   --#                                         LoopStack,
   --#                                         LScope,
   --#                                         StmtStack.S,
   --#                                         STree.Table,
   --#                                         VCGHeap;
   is
      Conjunct, DAG_Cell : Cells.Cell;
      DAG_Cell_Copy      : Cells.Cell;
      Function_Defs      : CStacks.Stack;
   begin
      CStacks.CreateStack (Function_Defs);

      Build_Annotation_Expression
        (Exp_Node                         => Expn_Node,
         Instantiated_Subprogram          => Dictionary.NullSymbol,
         Scope                            => LScope,
         Calling_Scope                    => LScope,
         Force_Abstract                   => False,
         Loop_Stack                       => LoopStack,
         Generate_Function_Instantiations => True,
         VC_Failure                       => VCGFailure,
         VC_Contains_Reals                => ContainsReals,
         VCG_Heap                         => VCGHeap,
         DAG_Root                         => DAG_Cell,
         Function_Defs                    => Function_Defs);

      -- Create a copy as the DAG is used in both the check and the assumption
      Structures.CopyStructure (Heap     => VCGHeap,
                                Root     => DAG_Cell,
                                RootCopy => DAG_Cell_Copy);

      if not CStacks.IsEmpty (Function_Defs) then
         -- Use null statement as place holder for function definitions
         ModelNullStmt (VCGHeap);
         -- Conjoin all the function definitions on the stack
         --# accept F, 10, Function_Defs, "The stack has been emptied";
         Join_And (Stack    => Function_Defs,
                   Conjunct => Conjunct,
                   VCG_Heap => VCGHeap);
         --# end accept;
         -- Assume the function definitions from the point of the null statement
         IncorporateAssumption (VCGHeap, Conjunct);
      end if;

      -- Use null statement to hold the check predicate
      ModelNullStmt (VCGHeap);
      Graph.Set_Proof_Context (X => Graph.Check_Statement);
      Graph.Set_Text_Line_Nmbr (X => LineNmbr);
      Graph.Set_Assertion_Locn (X => DAG_Cell);

      -- Use a null statement as a place holder for the assumption that the
      -- check predicate is true.
      ModelNullStmt (VCGHeap);
      IncorporateAssumption (VCGHeap, DAG_Cell_Copy);
   end ModelCheckStmt;

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

   procedure Model_Assume_Statement (Expn_Node : in STree.SyntaxNode)
   --# global in     CommandLineData.Content;
   --#        in     LoopStack;
   --#        in     LScope;
   --#        in     STree.Table;
   --#        in out ContainsReals;
   --#        in out Dictionary.Dict;
   --#        in out ErrorHandler.Error_Context;
   --#        in out Graph.Table;
   --#        in out LexTokenManager.State;
   --#        in out SPARK_IO.File_Sys;
   --#        in out Statistics.TableUsage;
   --#        in out StmtStack.S;
   --#        in out VCGFailure;
   --#        in out VCGHeap;
   --# derives ContainsReals,
   --#         Dictionary.Dict,
   --#         LexTokenManager.State,
   --#         VCGFailure                 from *,
   --#                                         CommandLineData.Content,
   --#                                         Dictionary.Dict,
   --#                                         Expn_Node,
   --#                                         LexTokenManager.State,
   --#                                         LoopStack,
   --#                                         LScope,
   --#                                         STree.Table,
   --#                                         VCGHeap &
   --#         ErrorHandler.Error_Context,
   --#         SPARK_IO.File_Sys          from CommandLineData.Content,
   --#                                         Dictionary.Dict,
   --#                                         ErrorHandler.Error_Context,
   --#                                         Expn_Node,
   --#                                         LexTokenManager.State,
   --#                                         LoopStack,
   --#                                         LScope,
   --#                                         SPARK_IO.File_Sys,
   --#                                         STree.Table,
   --#                                         VCGHeap &
   --#         Graph.Table,
   --#         Statistics.TableUsage,
   --#         StmtStack.S,
   --#         VCGHeap                    from *,
   --#                                         CommandLineData.Content,
   --#                                         Dictionary.Dict,
   --#                                         Expn_Node,
   --#                                         Graph.Table,
   --#                                         LexTokenManager.State,
   --#                                         LoopStack,
   --#                                         LScope,
   --#                                         StmtStack.S,
   --#                                         STree.Table,
   --#                                         VCGHeap;
   is
      Conjunct, DAG_Cell : Cells.Cell;
      Function_Defs      : CStacks.Stack;
   begin
      CStacks.CreateStack (Function_Defs);

      Build_Annotation_Expression
        (Exp_Node                         => Expn_Node,
         Instantiated_Subprogram          => Dictionary.NullSymbol,
         Scope                            => LScope,
         Calling_Scope                    => LScope,
         Force_Abstract                   => False,
         Loop_Stack                       => LoopStack,
         Generate_Function_Instantiations => True,
         VC_Failure                       => VCGFailure,
         VC_Contains_Reals                => ContainsReals,
         VCG_Heap                         => VCGHeap,
         DAG_Root                         => DAG_Cell,
         Function_Defs                    => Function_Defs);

      if not CStacks.IsEmpty (Function_Defs) then
         -- Use null statement as place holder for function definitions
         ModelNullStmt (VCGHeap);
         -- Conjoin all the function definitions on the stack
         --# accept F, 10, Function_Defs, "The stack has been emptied";
         Join_And (Stack    => Function_Defs,
                   Conjunct => Conjunct,
                   VCG_Heap => VCGHeap);
         --# end accept;
         -- Assume the function definitions from the point of the null statement
         IncorporateAssumption (VCGHeap, Conjunct);
      end if;

      --  Use a null statement as a place holder for the assumption
      --  that the assume predicate is true.
      ModelNullStmt (VCGHeap);
      IncorporateAssumption (VCGHeap, DAG_Cell);
   end Model_Assume_Statement;

   -------------------------------------------------------------------------
   -- procedure used by ModelAssertStmt and CheckPlantAssert to provide RTC
   -- information about for loop counters
   procedure AssertForLoopCounterProperties (StartingScope : in     Dictionary.Scopes;
                                             CellToConjoin : in out Cells.Cell)
   --# global in     Dictionary.Dict;
   --#        in     LexTokenManager.State;
   --#        in out Statistics.TableUsage;
   --#        in out VCGHeap;
   --# derives CellToConjoin,
   --#         Statistics.TableUsage,
   --#         VCGHeap               from *,
   --#                                    CellToConjoin,
   --#                                    Dictionary.Dict,
   --#                                    LexTokenManager.State,
   --#                                    StartingScope,
   --#                                    VCGHeap;
   is
      LocalScope       : Dictionary.Scopes;
      TheLoop          : Dictionary.Symbol;
      LoopCounterCell  : Cells.Cell;
      LoopCounterCheck : Cells.Cell;
      LoopCounterSym   : Dictionary.Symbol;
      -- following used to assert that loop counter variable <= loop exit expression
      OpCell    : Cells.Cell;
      ExitExpn  : Cells.Cell;
      EntryExpn : Cells.Cell;
      -- following  used to assert that vars used in for loop  exit expn are in type
      ExitExpnVarsIt     : Dictionary.Iterator;
      ExitVarInTypeCheck : Cells.Cell;
      VarInExitExpn      : Cells.Cell;
      VarSym             : Dictionary.Symbol;
      VarTypeSym         : Dictionary.Symbol;

      -- Plant assertions that:
      -- (1) Loop counter is in its type (except Boolean)
      -- (2a) Loop counter is >= EntryExpn or <= EntryExpn (for reverse loops) (except for Boolean)
      -- (2b) Loop counter is <= ExitExpn or >= ExitExpn (for reverse loops) (except for Boolean)
      -- (2c) Loop counter is >= A'First if A is an unconstrained formal array parameter
      -- (3) That each variable that appears in the exit expression (and is therefore frozen in the
      --     loop body is in its type
      -----------------------------------------

      procedure PossiblyCreateLoopCounterInitialValueAssertion
        (ExitExpn       : in     Cells.Cell;
         LoopCounterSym : in     Dictionary.Symbol;
         CellToConjoin  : in out Cells.Cell)
      --# global in     Dictionary.Dict;
      --#        in     LexTokenManager.State;
      --#        in out Statistics.TableUsage;
      --#        in out VCGHeap;
      --# derives CellToConjoin,
      --#         Statistics.TableUsage,
      --#         VCGHeap               from *,
      --#                                    CellToConjoin,
      --#                                    Dictionary.Dict,
      --#                                    ExitExpn,
      --#                                    LexTokenManager.State,
      --#                                    LoopCounterSym,
      --#                                    VCGHeap;
      is
         ConstraintSymbol : Dictionary.Symbol;
         ExitAttribute    : LexTokenManager.Lex_String;

         CounterInitialValueAssertion : Cells.Cell;
         EntryAttribute               : Cells.Cell;
         EntryExpression              : Cells.Cell;
         EntryConstraint              : Cells.Cell;
         LoopCounterCell              : Cells.Cell;

      begin
         -- We first check that the exits condition is in terms of an attribute.  Nothing else
         -- happens unless this is the case.
         if Cells.Get_Kind (VCGHeap, ExitExpn) = Cell_Storage.Op
           and then (Cells.Get_Op_Symbol (VCGHeap, ExitExpn) = SP_Symbols.apostrophe) then
            -- Obtain the prefix of the attribute
            ConstraintSymbol := Cells.Get_Symbol_Value (VCGHeap, LeftPtr (VCGHeap, ExitExpn));
            -- Again, nothing happens unless this prefix is a Dictionary.ParameterConstraintSymbol
            if Dictionary.IsParameterConstraint (ConstraintSymbol) then
               -- Obtain the attribute value used in the exit condition of the loop
               ExitAttribute := Cells.Get_Lex_Str (VCGHeap, RightPtr (VCGHeap, ExitExpn));

               -- We now have everything we need to construct the additional constraint on the loop counter

               -- the prefix of the entry constraint is the same as that of the exit
               CreateFixedVarCell (EntryConstraint, VCGHeap, ConstraintSymbol);

               -- the attribute value is the "opposite" of that used in the exit expression
               if LexTokenManager.Lex_String_Case_Insensitive_Compare
                 (Lex_Str1 => ExitAttribute,
                  Lex_Str2 => LexTokenManager.First_Token) =
                 LexTokenManager.Str_Eq then
                  CreateAttribValueCell (EntryAttribute, VCGHeap, LexTokenManager.Last_Token);
               else
                  CreateAttribValueCell (EntryAttribute, VCGHeap, LexTokenManager.First_Token);
               end if;

               -- the expression itself is the ' operator joining the prefix and the attribute
               CreateOpCell (EntryExpression, VCGHeap, SP_Symbols.apostrophe);

               -- Assemble attribute expression
               SetLeftArgument (EntryExpression, EntryConstraint, VCGHeap);
               SetRightArgument (EntryExpression, EntryAttribute, VCGHeap);

               -- the actual assertion is that the loop counter is >= this expresson (<= for reverse loops)
               if Dictionary.LoopParameterMovesInReverse (LoopCounterSym) then
                  CreateOpCell (CounterInitialValueAssertion, VCGHeap, SP_Symbols.less_or_equal);
               else -- forward
                  CreateOpCell (CounterInitialValueAssertion, VCGHeap, SP_Symbols.greater_or_equal);
               end if;
               CreateReferenceCell (LoopCounterCell, VCGHeap, LoopCounterSym);

               -- Construct the assertion
               SetLeftArgument (CounterInitialValueAssertion, LoopCounterCell, VCGHeap);
               SetRightArgument (CounterInitialValueAssertion, EntryExpression, VCGHeap);

               -- And add it to the overall assertion
               Cells.Utility.Conjoin (VCGHeap, CounterInitialValueAssertion, CellToConjoin);
            end if;
         end if;
      end PossiblyCreateLoopCounterInitialValueAssertion;

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

   begin -- AssertForLoopCounterProperties
      LocalScope := StartingScope;
      TheLoop    := Dictionary.GetRegion (LocalScope);
      while Dictionary.IsLoop (TheLoop) loop
         LoopCounterSym := Dictionary.GetLoopParameter (TheLoop);
         if not Dictionary.Is_Null_Symbol (LoopCounterSym) then
            if not Dictionary.TypeIsBoolean (Dictionary.GetType (LoopCounterSym)) then
               -- (1) ----------------------------------------------------------------------------
               -- it's a for loop so add assertion that counter is in type (unless Boolean)
               CreateReferenceCell (LoopCounterCell, VCGHeap, LoopCounterSym);
               Type_Constraint.Process_Discrete
                 (The_Type       => Dictionary.GetType (LoopCounterSym),
                  The_Expression => LoopCounterCell,
                  The_Constraint => LoopCounterCheck,
                  VCG_Heap       => VCGHeap);
               Cells.Utility.Conjoin (VCGHeap, LoopCounterCheck, CellToConjoin);

               -- (2a) ---------------------------------------------------------------------------
               -- Loop counter >= EntryExpn (<= for reverse loops)
               if Dictionary.LoopParameterMovesInReverse (LoopCounterSym) then
                  CreateOpCell (OpCell, VCGHeap, SP_Symbols.less_or_equal);
               else -- forward
                  CreateOpCell (OpCell, VCGHeap, SP_Symbols.greater_or_equal);
               end if;
               CreateReferenceCell (LoopCounterCell, VCGHeap, LoopCounterSym);
               -- Recover entry expression put in Dict by AssignLoopCounterEntryValue
               EntryExpn := Cells.Cell (Dictionary.GetLoopEntryExpn (TheLoop));

               -- There should always be an expression to get since it is planted by
               -- AssignLoopCounterEntryValue which is always called by StartForStmtModel.
               -- Therefore, the following assertion should never fail
               SystemErrors.RT_Assert
                 (C       => not Cells.Is_Null_Cell (EntryExpn),
                  Sys_Err => SystemErrors.Assertion_Failure,
                  Msg     => "EntryExpn Null in AssertForLoopCounterProperties");
               SetLeftArgument (OpCell, LoopCounterCell, VCGHeap);
               SetRightArgument (OpCell, EntryExpn, VCGHeap);
               Cells.Utility.Conjoin (VCGHeap, OpCell, CellToConjoin);

               -- (2b) ---------------------------------------------------------------------------
               -- Loop counter <= ExitExpn (>= for reverse loops)
               if Dictionary.LoopParameterMovesInReverse (LoopCounterSym) then
                  CreateOpCell (OpCell, VCGHeap, SP_Symbols.greater_or_equal);
               else -- forward
                  CreateOpCell (OpCell, VCGHeap, SP_Symbols.less_or_equal);
               end if;
               CreateReferenceCell (LoopCounterCell, VCGHeap, LoopCounterSym);
               -- Recover exit expression put in Dict by AssignLoopBoundsToExitVariable
               ExitExpn := Cells.Cell (Dictionary.GetLoopExitExpn (TheLoop));

               -- There should always be an expression to get since it is planted by
               -- AssignLoopBoundsToExitVariable which is always called by StartForStmtModel.
               -- Therefore, the following assertion should never fail
               SystemErrors.RT_Assert
                 (C       => not Cells.Is_Null_Cell (ExitExpn),
                  Sys_Err => SystemErrors.Assertion_Failure,
                  Msg     => "ExitExpn Null in AssertForLoopCounterProperties");
               SetLeftArgument (OpCell, LoopCounterCell, VCGHeap);
               SetRightArgument (OpCell, ExitExpn, VCGHeap);
               Cells.Utility.Conjoin (VCGHeap, OpCell, CellToConjoin);

               -- (2c) ---------------------------------------------------------------------------
               -- if, and only if, the exit condition is in the form of an attribute of a
               -- Dictionary.ParameterConstraintSymbol then that indicates that we are looping
               -- over an unconstrained formal parameter.  In this case, the assertion that the
               -- for loop counter is in its type (Step 1 above) and <= exit value (code of step 2 above) is
               -- too weak: we also know that the loop counter is >= the first value of the ParameterConstraintSymbol
               PossiblyCreateLoopCounterInitialValueAssertion (ExitExpn, LoopCounterSym, CellToConjoin);
            end if; -- Boolean loop counter

            -- (3) --------------------------------------------------------------------------------
            -- Any variable used in the for loop exit expn must be in type too.
            -- We can do this check even if the for loop is over Boolean because it might still
            -- contain non-Boolean variables in its exit condition (hence this block is outside
            -- the Boolean loop counter if statement just above)
            -- (e.g. "for i in Boolean range False .. (X > Y)")

            -- Get each variable used in for loop exit expression.  These have already been
            -- turned in to special % variables by FreezeExitExpn.
            ExitExpnVarsIt := Dictionary.FirstLoopOnEntryVar (TheLoop);
            while not Dictionary.IsNullIterator (ExitExpnVarsIt) loop
               VarSym     := Dictionary.CurrentSymbol (ExitExpnVarsIt);
               VarTypeSym := Dictionary.GetType (VarSym);
               -- build check for suitable scalars only
               if DiscreteTypeWithCheck (VarTypeSym, LocalScope) then
                  CreateReferenceCell (VarInExitExpn, VCGHeap, VarSym);
                  Type_Constraint.Process_Discrete
                    (The_Type       => Dictionary.GetType (VarSym),
                     The_Expression => VarInExitExpn,
                     The_Constraint => ExitVarInTypeCheck,
                     VCG_Heap       => VCGHeap);
                  Cells.Utility.Conjoin (VCGHeap, ExitVarInTypeCheck, CellToConjoin);
               end if;
               ExitExpnVarsIt := Dictionary.NextSymbol (ExitExpnVarsIt);
            end loop;
            -- end of  (3) --------------------------------------------
         end if; -- its a for loop
         LocalScope := Dictionary.GetEnclosingScope (LocalScope);
         TheLoop    := Dictionary.GetRegion (LocalScope);
      end loop;
   end AssertForLoopCounterProperties;

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

   procedure ModelAssertStmt (Expn_Node : in STree.SyntaxNode)
   --# global in     CommandLineData.Content;
   --#        in     ImportConstraints;
   --#        in     LineNmbr;
   --#        in     LoopStack;
   --#        in     LScope;
   --#        in     PreConstraints;
   --#        in     STree.Table;
   --#        in out ContainsReals;
   --#        in out Dictionary.Dict;
   --#        in out ErrorHandler.Error_Context;
   --#        in out Graph.Table;
   --#        in out LexTokenManager.State;
   --#        in out SPARK_IO.File_Sys;
   --#        in out Statistics.TableUsage;
   --#        in out StmtStack.S;
   --#        in out VCGFailure;
   --#        in out VCGHeap;
   --# derives ContainsReals,
   --#         Dictionary.Dict,
   --#         LexTokenManager.State,
   --#         VCGFailure                 from *,
   --#                                         CommandLineData.Content,
   --#                                         Dictionary.Dict,
   --#                                         Expn_Node,
   --#                                         LexTokenManager.State,
   --#                                         LoopStack,
   --#                                         LScope,
   --#                                         STree.Table,
   --#                                         VCGHeap &
   --#         ErrorHandler.Error_Context,
   --#         SPARK_IO.File_Sys          from CommandLineData.Content,
   --#                                         Dictionary.Dict,
   --#                                         ErrorHandler.Error_Context,
   --#                                         Expn_Node,
   --#                                         LexTokenManager.State,
   --#                                         LoopStack,
   --#                                         LScope,
   --#                                         SPARK_IO.File_Sys,
   --#                                         STree.Table,
   --#                                         VCGHeap &
   --#         Graph.Table,
   --#         StmtStack.S,
   --#         VCGHeap                    from CommandLineData.Content,
   --#                                         Dictionary.Dict,
   --#                                         Expn_Node,
   --#                                         Graph.Table,
   --#                                         ImportConstraints,
   --#                                         LexTokenManager.State,
   --#                                         LineNmbr,
   --#                                         LoopStack,
   --#                                         LScope,
   --#                                         PreConstraints,
   --#                                         StmtStack.S,
   --#                                         STree.Table,
   --#                                         VCGHeap &
   --#         Statistics.TableUsage      from *,
   --#                                         CommandLineData.Content,
   --#                                         Dictionary.Dict,
   --#                                         Expn_Node,
   --#                                         Graph.Table,
   --#                                         ImportConstraints,
   --#                                         LexTokenManager.State,
   --#                                         LoopStack,
   --#                                         LScope,
   --#                                         PreConstraints,
   --#                                         StmtStack.S,
   --#                                         STree.Table,
   --#                                         VCGHeap;
   is
      Conjoined_Function_Defs      : Cells.Cell;
      Copy_Conjoined_Function_Defs : Cells.Cell;
      Copy_Import_Constraints      : Cells.Cell;
      Copy_Pre_Constraints         : Cells.Cell;
      DAG_Cell                     : Cells.Cell;
      Function_Defs                : CStacks.Stack;
   begin
      CStacks.CreateStack (Function_Defs);

      Build_Annotation_Expression
        (Exp_Node                         => Expn_Node,
         Instantiated_Subprogram          => Dictionary.NullSymbol,
         Scope                            => LScope,
         Calling_Scope                    => LScope,
         Force_Abstract                   => False,
         Loop_Stack                       => LoopStack,
         Generate_Function_Instantiations => True,
         VC_Failure                       => VCGFailure,
         VC_Contains_Reals                => ContainsReals,
         VCG_Heap                         => VCGHeap,
         DAG_Root                         => DAG_Cell,
         Function_Defs                    => Function_Defs);

      if not CStacks.IsEmpty (Function_Defs) then
         -- Use null statement as place holder for function definitions
         ModelNullStmt (VCGHeap);
         -- Conjoin all the function definitions on the stack
         --# accept F, 10, Function_Defs, "The stack has been emptied";
         Join_And (Stack    => Function_Defs,
                   Conjunct => Conjoined_Function_Defs,
                   VCG_Heap => VCGHeap);
         --# end accept;
         -- Assume the function definitions from the point of the null statement
         IncorporateAssumption (VCGHeap, Conjoined_Function_Defs);
      else
         Conjoined_Function_Defs := Cells.Null_Cell;
      end if;

      -- Use null statement to hold the assertion
      ModelNullStmt (VCGHeap);
      Graph.Set_Proof_Context (X => Graph.Assertion);
      Graph.Set_Text_Line_Nmbr (X => LineNmbr);

      if not Cells.Is_Null_Cell (ImportConstraints) then
         -- propagate import constraints in assertion
         Structures.CopyStructure (VCGHeap, ImportConstraints, Copy_Import_Constraints);
         Cells.Utility.Conjoin (VCGHeap, Copy_Import_Constraints, DAG_Cell);
      end if;
      if not Cells.Is_Null_Cell (PreConstraints) then
         -- propagate precondition in assertion
         Structures.CopyStructure (VCGHeap, PreConstraints, Copy_Pre_Constraints);
         Cells.Utility.Conjoin (VCGHeap, Copy_Pre_Constraints, DAG_Cell);
      end if;
      if not Cells.Is_Null_Cell (Conjoined_Function_Defs) then
         -- propagate function defs in assertion
         Structures.CopyStructure (VCGHeap, Conjoined_Function_Defs, Copy_Conjoined_Function_Defs);
         Cells.Utility.Conjoin (VCGHeap, Copy_Conjoined_Function_Defs, DAG_Cell);
      end if;

      -- see if we have a for loop and append loop counter in range info if so
      AssertForLoopCounterProperties (LScope, DAG_Cell);
      Graph.Set_Assertion_Locn (X => DAG_Cell);
      ModelNullStmt (VCGHeap);
   end ModelAssertStmt;

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

   procedure ModelAssignmentStmt
   --# global in     CommandLineData.Content;
   --#        in     DoAssumeLocalRvalues;
   --#        in     LineNmbr;
   --#        in     LoopStack;
   --#        in     LScope;
   --#        in     Node;
   --#        in     Scope;
   --#        in     STree.Table;
   --#        in out CheckStack;
   --#        in out ContainsReals;
   --#        in out Dictionary.Dict;
   --#        in out ErrorHandler.Error_Context;
   --#        in out FlowHeap;
   --#        in out Graph.Table;
   --#        in out KindOfStackedCheck;
   --#        in out LexTokenManager.State;
   --#        in out ShortCircuitStack;
   --#        in out SPARK_IO.File_Sys;
   --#        in out Statistics.TableUsage;
   --#        in out StmtStack.S;
   --#        in out VCGFailure;
   --#        in out VCGHeap;
   --# derives CheckStack,
   --#         ContainsReals,
   --#         Dictionary.Dict,
   --#         FlowHeap,
   --#         Graph.Table,
   --#         KindOfStackedCheck,
   --#         LexTokenManager.State,
   --#         ShortCircuitStack,
   --#         Statistics.TableUsage,
   --#         StmtStack.S,
   --#         VCGFailure,
   --#         VCGHeap                    from *,
   --#                                         CheckStack,
   --#                                         CommandLineData.Content,
   --#                                         Dictionary.Dict,
   --#                                         DoAssumeLocalRvalues,
   --#                                         FlowHeap,
   --#                                         Graph.Table,
   --#                                         KindOfStackedCheck,
   --#                                         LexTokenManager.State,
   --#                                         LineNmbr,
   --#                                         LoopStack,
   --#                                         LScope,
   --#                                         Node,
   --#                                         Scope,
   --#                                         ShortCircuitStack,
   --#                                         StmtStack.S,
   --#                                         STree.Table,
   --#                                         VCGHeap &
   --#         ErrorHandler.Error_Context,
   --#         SPARK_IO.File_Sys          from CheckStack,
   --#                                         CommandLineData.Content,
   --#                                         Dictionary.Dict,
   --#                                         DoAssumeLocalRvalues,
   --#                                         ErrorHandler.Error_Context,
   --#                                         FlowHeap,
   --#                                         Graph.Table,
   --#                                         KindOfStackedCheck,
   --#                                         LexTokenManager.State,
   --#                                         LineNmbr,
   --#                                         LoopStack,
   --#                                         LScope,
   --#                                         Node,
   --#                                         Scope,
   --#                                         ShortCircuitStack,
   --#                                         SPARK_IO.File_Sys,
   --#                                         StmtStack.S,
   --#                                         STree.Table,
   --#                                         VCGHeap;
      is separate;

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

   procedure ModelInitialisedVariables
   --# global in     CommandLineData.Content;
   --#        in     LineNmbr;
   --#        in     LoopStack;
   --#        in     LScope;
   --#        in     Scope;
   --#        in     STree.Table;
   --#        in     SubprogSym;
   --#        in out CheckStack;
   --#        in out ContainsReals;
   --#        in out Dictionary.Dict;
   --#        in out ErrorHandler.Error_Context;
   --#        in out FlowHeap;
   --#        in out Graph.Table;
   --#        in out KindOfStackedCheck;
   --#        in out LexTokenManager.State;
   --#        in out ShortCircuitStack;
   --#        in out SPARK_IO.File_Sys;
   --#        in out Statistics.TableUsage;
   --#        in out StmtStack.S;
   --#        in out VCGFailure;
   --#        in out VCGHeap;
   --# derives CheckStack,
   --#         ContainsReals,
   --#         Dictionary.Dict,
   --#         FlowHeap,
   --#         Graph.Table,
   --#         KindOfStackedCheck,
   --#         LexTokenManager.State,
   --#         ShortCircuitStack,
   --#         Statistics.TableUsage,
   --#         StmtStack.S,
   --#         VCGFailure,
   --#         VCGHeap                    from *,
   --#                                         CheckStack,
   --#                                         CommandLineData.Content,
   --#                                         Dictionary.Dict,
   --#                                         FlowHeap,
   --#                                         Graph.Table,
   --#                                         KindOfStackedCheck,
   --#                                         LexTokenManager.State,
   --#                                         LineNmbr,
   --#                                         LoopStack,
   --#                                         LScope,
   --#                                         Scope,
   --#                                         ShortCircuitStack,
   --#                                         StmtStack.S,
   --#                                         STree.Table,
   --#                                         SubprogSym,
   --#                                         VCGHeap &
   --#         ErrorHandler.Error_Context,
   --#         SPARK_IO.File_Sys          from CheckStack,
   --#                                         CommandLineData.Content,
   --#                                         Dictionary.Dict,
   --#                                         ErrorHandler.Error_Context,
   --#                                         FlowHeap,
   --#                                         Graph.Table,
   --#                                         KindOfStackedCheck,
   --#                                         LexTokenManager.State,
   --#                                         LineNmbr,
   --#                                         LoopStack,
   --#                                         LScope,
   --#                                         Scope,
   --#                                         ShortCircuitStack,
   --#                                         SPARK_IO.File_Sys,
   --#                                         StmtStack.S,
   --#                                         STree.Table,
   --#                                         SubprogSym,
   --#                                         VCGHeap;
   is
      It : Dictionary.Iterator;

      procedure ModelOneVar (VarSym : in Dictionary.Symbol)
      --# global in     CommandLineData.Content;
      --#        in     LineNmbr;
      --#        in     LoopStack;
      --#        in     LScope;
      --#        in     Scope;
      --#        in     STree.Table;
      --#        in out CheckStack;
      --#        in out ContainsReals;
      --#        in out Dictionary.Dict;
      --#        in out ErrorHandler.Error_Context;
      --#        in out FlowHeap;
      --#        in out Graph.Table;
      --#        in out KindOfStackedCheck;
      --#        in out LexTokenManager.State;
      --#        in out ShortCircuitStack;
      --#        in out SPARK_IO.File_Sys;
      --#        in out Statistics.TableUsage;
      --#        in out StmtStack.S;
      --#        in out VCGFailure;
      --#        in out VCGHeap;
      --# derives CheckStack,
      --#         ContainsReals,
      --#         Dictionary.Dict,
      --#         FlowHeap,
      --#         Graph.Table,
      --#         KindOfStackedCheck,
      --#         LexTokenManager.State,
      --#         ShortCircuitStack,
      --#         Statistics.TableUsage,
      --#         StmtStack.S,
      --#         VCGFailure,
      --#         VCGHeap                    from *,
      --#                                         CheckStack,
      --#                                         CommandLineData.Content,
      --#                                         Dictionary.Dict,
      --#                                         FlowHeap,
      --#                                         Graph.Table,
      --#                                         KindOfStackedCheck,
      --#                                         LexTokenManager.State,
      --#                                         LineNmbr,
      --#                                         LoopStack,
      --#                                         LScope,
      --#                                         Scope,
      --#                                         ShortCircuitStack,
      --#                                         StmtStack.S,
      --#                                         STree.Table,
      --#                                         VarSym,
      --#                                         VCGHeap &
      --#         ErrorHandler.Error_Context,
      --#         SPARK_IO.File_Sys          from CheckStack,
      --#                                         CommandLineData.Content,
      --#                                         Dictionary.Dict,
      --#                                         ErrorHandler.Error_Context,
      --#                                         FlowHeap,
      --#                                         Graph.Table,
      --#                                         KindOfStackedCheck,
      --#                                         LexTokenManager.State,
      --#                                         LineNmbr,
      --#                                         LoopStack,
      --#                                         LScope,
      --#                                         Scope,
      --#                                         ShortCircuitStack,
      --#                                         SPARK_IO.File_Sys,
      --#                                         StmtStack.S,
      --#                                         STree.Table,
      --#                                         VarSym,
      --#                                         VCGHeap;
      is
         DAGRoot, VarCell, StmtCell, ModList : Cells.Cell;
         StmtLabel                           : Labels.Label;

      begin -- ModelOneVar
         PrepareLabel (VCGHeap, StmtLabel, StmtCell);
         Clists.CreateList (VCGHeap, ModList);

         CreateModifiedCell (VarCell, VCGHeap, VarSym);
         Clists.AppendCell (VCGHeap, VarCell, ModList);

         BuildExpnDAG
           (StartNode          => STree.RefToNode (Dictionary.GetVariableExpNode (VarSym)),
            ExpnScope          => LScope,
            Scope              => Scope,
            LineNmbr           => LineNmbr,
            DoRtc              => False,
            AssumeRvalues      => False,
            LoopStack          => LoopStack,
            FlowHeap           => FlowHeap,
            VCGHeap            => VCGHeap,
            ContainsReals      => ContainsReals,
            VCGFailure         => VCGFailure,
            ShortCircuitStack  => ShortCircuitStack,
            CheckStack         => CheckStack,
            KindOfStackedCheck => KindOfStackedCheck,
            DAGRoot            => DAGRoot);

         SetRightArgument (VarCell, DAGRoot, VCGHeap);
         SetAuxPtr (StmtCell, ModList, VCGHeap);
         Chain (StmtLabel, VCGHeap);
      end ModelOneVar;

   begin -- ModelInitialisedVariables
      It := Dictionary.First_Initialized_Variable (Subprogram => SubprogSym);
      while not Dictionary.IsNullIterator (It) loop
         ModelOneVar (Dictionary.CurrentSymbol (It));
         It := Dictionary.NextSymbol (It);
      end loop;
   end ModelInitialisedVariables;

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

   procedure ModelProcedureCall
   --# global in     CommandLineData.Content;
   --#        in     DoAssumeLocalRvalues;
   --#        in     LineNmbr;
   --#        in     LoopStack;
   --#        in     LScope;
   --#        in     Node;
   --#        in     Scope;
   --#        in     STree.Table;
   --#        in out CheckStack;
   --#        in out ContainsReals;
   --#        in out Dictionary.Dict;
   --#        in out ErrorHandler.Error_Context;
   --#        in out FlowHeap;
   --#        in out Graph.Table;
   --#        in out KindOfStackedCheck;
   --#        in out LexTokenManager.State;
   --#        in out ShortCircuitStack;
   --#        in out SPARK_IO.File_Sys;
   --#        in out Statistics.TableUsage;
   --#        in out StmtStack.S;
   --#        in out SubprogramCalls;
   --#        in out VCGFailure;
   --#        in out VCGHeap;
   --# derives CheckStack,
   --#         ContainsReals,
   --#         Graph.Table,
   --#         KindOfStackedCheck,
   --#         LexTokenManager.State,
   --#         ShortCircuitStack,
   --#         Statistics.TableUsage,
   --#         StmtStack.S,
   --#         VCGHeap                    from *,
   --#                                         CheckStack,
   --#                                         CommandLineData.Content,
   --#                                         Dictionary.Dict,
   --#                                         DoAssumeLocalRvalues,
   --#                                         FlowHeap,
   --#                                         Graph.Table,
   --#                                         KindOfStackedCheck,
   --#                                         LexTokenManager.State,
   --#                                         LineNmbr,
   --#                                         LoopStack,
   --#                                         LScope,
   --#                                         Node,
   --#                                         Scope,
   --#                                         ShortCircuitStack,
   --#                                         StmtStack.S,
   --#                                         STree.Table,
   --#                                         SubprogramCalls,
   --#                                         VCGHeap &
   --#         Dictionary.Dict,
   --#         FlowHeap,
   --#         VCGFailure                 from *,
   --#                                         CheckStack,
   --#                                         CommandLineData.Content,
   --#                                         Dictionary.Dict,
   --#                                         DoAssumeLocalRvalues,
   --#                                         FlowHeap,
   --#                                         Graph.Table,
   --#                                         KindOfStackedCheck,
   --#                                         LexTokenManager.State,
   --#                                         LineNmbr,
   --#                                         LoopStack,
   --#                                         LScope,
   --#                                         Node,
   --#                                         Scope,
   --#                                         ShortCircuitStack,
   --#                                         StmtStack.S,
   --#                                         STree.Table,
   --#                                         VCGHeap &
   --#         ErrorHandler.Error_Context,
   --#         SPARK_IO.File_Sys          from CheckStack,
   --#                                         CommandLineData.Content,
   --#                                         Dictionary.Dict,
   --#                                         DoAssumeLocalRvalues,
   --#                                         ErrorHandler.Error_Context,
   --#                                         FlowHeap,
   --#                                         Graph.Table,
   --#                                         KindOfStackedCheck,
   --#                                         LexTokenManager.State,
   --#                                         LineNmbr,
   --#                                         LoopStack,
   --#                                         LScope,
   --#                                         Node,
   --#                                         Scope,
   --#                                         ShortCircuitStack,
   --#                                         SPARK_IO.File_Sys,
   --#                                         StmtStack.S,
   --#                                         STree.Table,
   --#                                         VCGHeap &
   --#         SubprogramCalls            from *;
      is separate;

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

   procedure CreateSwitch (DAGRoot                           : in     Cells.Cell;
                           FalseBranchLabel, TrueBranchLabel :    out Labels.Label)
   --# global in out Statistics.TableUsage;
   --#        in out VCGHeap;
   --# derives FalseBranchLabel,
   --#         VCGHeap               from DAGRoot,
   --#                                    VCGHeap &
   --#         Statistics.TableUsage from *,
   --#                                    DAGRoot,
   --#                                    VCGHeap &
   --#         TrueBranchLabel       from VCGHeap;
   is
      LocalTrueBranchLabel                                            : Labels.Label;
      DAGRootCopy, FalseBranchLabelHead, TrueBranchPairCell, Negation : Cells.Cell;
   begin
      PrepareLabel (VCGHeap, LocalTrueBranchLabel, TrueBranchPairCell);
      TrueBranchLabel := LocalTrueBranchLabel;
      SetRightArgument (TrueBranchPairCell, DAGRoot, VCGHeap);
      Structures.CopyStructure (VCGHeap, Labels.LabelHead (LocalTrueBranchLabel), FalseBranchLabelHead);
      FalseBranchLabel := Labels.CellToLabel (FalseBranchLabelHead);
      DAGRootCopy      := RightPtr (VCGHeap, LeftPtr (VCGHeap, FalseBranchLabelHead));
      CreateOpCell (Negation, VCGHeap, SP_Symbols.RWnot);
      SetRightArgument (Negation, DAGRootCopy, VCGHeap);
      SetRightArgument (LeftPtr (VCGHeap, FalseBranchLabelHead), Negation, VCGHeap);
   end CreateSwitch;

   procedure StartIfModel
   --# global in     CommandLineData.Content;
   --#        in     DoAssumeLocalRvalues;
   --#        in     LineNmbr;
   --#        in     LoopStack;
   --#        in     LScope;
   --#        in     Node;
   --#        in     Scope;
   --#        in     STree.Table;
   --#        in out CheckStack;
   --#        in out ContainsReals;
   --#        in out Dictionary.Dict;
   --#        in out ErrorHandler.Error_Context;
   --#        in out FlowHeap;
   --#        in out Graph.Table;
   --#        in out KindOfStackedCheck;
   --#        in out LexTokenManager.State;
   --#        in out ShortCircuitStack;
   --#        in out SPARK_IO.File_Sys;
   --#        in out Statistics.TableUsage;
   --#        in out StmtStack.S;
   --#        in out VCGFailure;
   --#        in out VCGHeap;
   --# derives CheckStack,
   --#         ContainsReals,
   --#         Dictionary.Dict,
   --#         FlowHeap,
   --#         Graph.Table,
   --#         KindOfStackedCheck,
   --#         LexTokenManager.State,
   --#         ShortCircuitStack,
   --#         Statistics.TableUsage,
   --#         StmtStack.S,
   --#         VCGFailure,
   --#         VCGHeap                    from *,
   --#                                         CheckStack,
   --#                                         CommandLineData.Content,
   --#                                         Dictionary.Dict,
   --#                                         DoAssumeLocalRvalues,
   --#                                         FlowHeap,
   --#                                         Graph.Table,
   --#                                         KindOfStackedCheck,
   --#                                         LexTokenManager.State,
   --#                                         LineNmbr,
   --#                                         LoopStack,
   --#                                         LScope,
   --#                                         Node,
   --#                                         Scope,
   --#                                         ShortCircuitStack,
   --#                                         StmtStack.S,
   --#                                         STree.Table,
   --#                                         VCGHeap &
   --#         ErrorHandler.Error_Context,
   --#         SPARK_IO.File_Sys          from CheckStack,
   --#                                         CommandLineData.Content,
   --#                                         Dictionary.Dict,
   --#                                         DoAssumeLocalRvalues,
   --#                                         ErrorHandler.Error_Context,
   --#                                         FlowHeap,
   --#                                         Graph.Table,
   --#                                         KindOfStackedCheck,
   --#                                         LexTokenManager.State,
   --#                                         LineNmbr,
   --#                                         LoopStack,
   --#                                         LScope,
   --#                                         Node,
   --#                                         Scope,
   --#                                         ShortCircuitStack,
   --#                                         SPARK_IO.File_Sys,
   --#                                         StmtStack.S,
   --#                                         STree.Table,
   --#                                         VCGHeap;
   is
      DAGRoot                           : Cells.Cell;
      FalseBranchLabel, TrueBranchLabel : Labels.Label;
      R                                 : StmtStack.StmtRecord;
      Predecessor                       : Graph.Matrix_Index;
   begin
      BuildExpnDAG
        (StartNode          => Node,
         ExpnScope          => LScope,
         Scope              => Scope,
         LineNmbr           => LineNmbr,
         DoRtc              => True,
         AssumeRvalues      => DoAssumeLocalRvalues,
         LoopStack          => LoopStack,
         FlowHeap           => FlowHeap,
         VCGHeap            => VCGHeap,
         ContainsReals      => ContainsReals,
         VCGFailure         => VCGFailure,
         ShortCircuitStack  => ShortCircuitStack,
         CheckStack         => CheckStack,
         KindOfStackedCheck => KindOfStackedCheck,
         DAGRoot            => DAGRoot);

      UnStackRtcs (LineNmbr, VCGHeap, CheckStack, KindOfStackedCheck);

      CreateSwitch (DAGRoot, FalseBranchLabel, TrueBranchLabel);
      Predecessor := StmtStack.Top.StmtNmbr;

      -- push record holding nmbr of tail (exit) of if-statement;
      Graph.Inc_Nmbr_Of_Stmts;
      R.StmtNmbr := Graph.Get_Nmbr_Of_Stmts;
      R.Kind     := StmtStack.IfStart;
      StmtStack.Push (R);

      -- push False branch;
      Graph.Inc_Nmbr_Of_Stmts;
      Graph.Create_Coeff (Heap => VCGHeap,
                          I    => Predecessor,
                          J    => Graph.Get_Nmbr_Of_Stmts,
                          K    => FalseBranchLabel);
      R.StmtNmbr := Graph.Get_Nmbr_Of_Stmts;
      R.Kind     := StmtStack.IfFalseBranch;
      StmtStack.Push (R);

      -- push True branch;
      Graph.Inc_Nmbr_Of_Stmts;
      Graph.Create_Coeff (Heap => VCGHeap,
                          I    => Predecessor,
                          J    => Graph.Get_Nmbr_Of_Stmts,
                          K    => TrueBranchLabel);
      R.StmtNmbr := Graph.Get_Nmbr_Of_Stmts;
      R.Kind     := StmtStack.IfTrueBranch;
      StmtStack.Push (R);
   end StartIfModel;

   procedure StartElseModel
   --# global in out Graph.Table;
   --#        in out Statistics.TableUsage;
   --#        in out StmtStack.S;
   --#        in out VCGHeap;
   --# derives Graph.Table,
   --#         Statistics.TableUsage from *,
   --#                                    StmtStack.S,
   --#                                    VCGHeap &
   --#         StmtStack.S           from * &
   --#         VCGHeap               from *,
   --#                                    Graph.Table,
   --#                                    StmtStack.S;
   is
      NullStmtLabel           : Labels.Label;
      R                       : StmtStack.StmtRecord;
      InitialEndPoint, IfTail : Graph.Matrix_Index;
   begin
      if StmtStack.Top.Kind = StmtStack.LoopExit then
         StmtStack.Pop;
      else
         -- Here the stmtstack contains the final node of the last if or elsif branch.
         InitialEndPoint := StmtStack.Top.StmtNmbr;  -- tail of if-branch;
         StmtStack.Pop;                              -- eject if-branch data;
         R := StmtStack.Top;                         -- temporarily remove and store else-branch,
         StmtStack.Pop;                              -- to expose if-statement tail;
         IfTail := StmtStack.Top.StmtNmbr;
         StmtStack.Push (R);
         CreateUnitLabel (NullStmtLabel, VCGHeap);
         Graph.Create_Coeff (Heap => VCGHeap,
                             I    => InitialEndPoint,
                             J    => IfTail,
                             K    => NullStmtLabel);
      end if;
   end StartElseModel;

   procedure StartElsIfModel
   --# global in     CommandLineData.Content;
   --#        in     DoAssumeLocalRvalues;
   --#        in     LineNmbr;
   --#        in     LoopStack;
   --#        in     LScope;
   --#        in     Node;
   --#        in     Scope;
   --#        in     STree.Table;
   --#        in out CheckStack;
   --#        in out ContainsReals;
   --#        in out Dictionary.Dict;
   --#        in out ErrorHandler.Error_Context;
   --#        in out FlowHeap;
   --#        in out Graph.Table;
   --#        in out KindOfStackedCheck;
   --#        in out LexTokenManager.State;
   --#        in out ShortCircuitStack;
   --#        in out SPARK_IO.File_Sys;
   --#        in out Statistics.TableUsage;
   --#        in out StmtStack.S;
   --#        in out VCGFailure;
   --#        in out VCGHeap;
   --# derives CheckStack,
   --#         ContainsReals,
   --#         Dictionary.Dict,
   --#         FlowHeap,
   --#         Graph.Table,
   --#         KindOfStackedCheck,
   --#         LexTokenManager.State,
   --#         ShortCircuitStack,
   --#         Statistics.TableUsage,
   --#         StmtStack.S,
   --#         VCGFailure,
   --#         VCGHeap                    from *,
   --#                                         CheckStack,
   --#                                         CommandLineData.Content,
   --#                                         Dictionary.Dict,
   --#                                         DoAssumeLocalRvalues,
   --#                                         FlowHeap,
   --#                                         Graph.Table,
   --#                                         KindOfStackedCheck,
   --#                                         LexTokenManager.State,
   --#                                         LineNmbr,
   --#                                         LoopStack,
   --#                                         LScope,
   --#                                         Node,
   --#                                         Scope,
   --#                                         ShortCircuitStack,
   --#                                         StmtStack.S,
   --#                                         STree.Table,
   --#                                         VCGHeap &
   --#         ErrorHandler.Error_Context,
   --#         SPARK_IO.File_Sys          from CheckStack,
   --#                                         CommandLineData.Content,
   --#                                         Dictionary.Dict,
   --#                                         DoAssumeLocalRvalues,
   --#                                         ErrorHandler.Error_Context,
   --#                                         FlowHeap,
   --#                                         Graph.Table,
   --#                                         KindOfStackedCheck,
   --#                                         LexTokenManager.State,
   --#                                         LineNmbr,
   --#                                         LoopStack,
   --#                                         LScope,
   --#                                         Node,
   --#                                         Scope,
   --#                                         ShortCircuitStack,
   --#                                         SPARK_IO.File_Sys,
   --#                                         StmtStack.S,
   --#                                         STree.Table,
   --#                                         VCGHeap;
   is
      DAGRoot                                          : Cells.Cell;
      FalseBranchLabel, TrueBranchLabel, NullStmtLabel : Labels.Label;
      R                                                : StmtStack.StmtRecord;
      IfTail, InitialEndPoint, Predecessor             : Graph.Matrix_Index;
   begin
      -- Here the stmtstack contains the final node of the last if or elsif branch.
      InitialEndPoint := StmtStack.Top.StmtNmbr;  -- tail of current if- or elsif-branch;
      StmtStack.Pop;                              -- eject if-branch data;
      R := StmtStack.Top;                         -- temporarily remove and store else-branch,
      StmtStack.Pop;                              -- to expose if-statement tail;
      IfTail := StmtStack.Top.StmtNmbr;
      StmtStack.Push (R);
      CreateUnitLabel (NullStmtLabel, VCGHeap);
      Graph.Create_Coeff (Heap => VCGHeap,
                          I    => InitialEndPoint,
                          J    => IfTail,
                          K    => NullStmtLabel);

      BuildExpnDAG
        (StartNode          => Node,
         ExpnScope          => LScope,
         Scope              => Scope,
         LineNmbr           => LineNmbr,
         DoRtc              => True,
         AssumeRvalues      => DoAssumeLocalRvalues,
         LoopStack          => LoopStack,
         FlowHeap           => FlowHeap,
         VCGHeap            => VCGHeap,
         ContainsReals      => ContainsReals,
         VCGFailure         => VCGFailure,
         ShortCircuitStack  => ShortCircuitStack,
         CheckStack         => CheckStack,
         KindOfStackedCheck => KindOfStackedCheck,
         DAGRoot            => DAGRoot);

      UnStackRtcs (LineNmbr, VCGHeap, CheckStack, KindOfStackedCheck);

      CreateSwitch (DAGRoot, FalseBranchLabel, TrueBranchLabel);
      Predecessor := StmtStack.Top.StmtNmbr;
      StmtStack.Pop;
      -- push False branch;
      Graph.Inc_Nmbr_Of_Stmts;
      Graph.Create_Coeff (Heap => VCGHeap,
                          I    => Predecessor,
                          J    => Graph.Get_Nmbr_Of_Stmts,
                          K    => FalseBranchLabel);
      R.StmtNmbr := Graph.Get_Nmbr_Of_Stmts;
      R.Kind     := StmtStack.IfFalseBranch;
      StmtStack.Push (R);
      -- push True branch;
      Graph.Inc_Nmbr_Of_Stmts;
      Graph.Create_Coeff (Heap => VCGHeap,
                          I    => Predecessor,
                          J    => Graph.Get_Nmbr_Of_Stmts,
                          K    => TrueBranchLabel);
      R.StmtNmbr := Graph.Get_Nmbr_Of_Stmts;
      R.Kind     := StmtStack.IfTrueBranch;
      StmtStack.Push (R);
   end StartElsIfModel;

   procedure StartCaseModel
   --# global in     CommandLineData.Content;
   --#        in     DoAssumeLocalRvalues;
   --#        in     LineNmbr;
   --#        in     LoopStack;
   --#        in     LScope;
   --#        in     Node;
   --#        in     Scope;
   --#        in     STree.Table;
   --#        in out CheckStack;
   --#        in out ContainsReals;
   --#        in out Dictionary.Dict;
   --#        in out ErrorHandler.Error_Context;
   --#        in out FlowHeap;
   --#        in out Graph.Table;
   --#        in out KindOfStackedCheck;
   --#        in out LexTokenManager.State;
   --#        in out ShortCircuitStack;
   --#        in out SPARK_IO.File_Sys;
   --#        in out Statistics.TableUsage;
   --#        in out StmtStack.S;
   --#        in out VCGFailure;
   --#        in out VCGHeap;
   --# derives CheckStack,
   --#         ContainsReals,
   --#         Dictionary.Dict,
   --#         FlowHeap,
   --#         Graph.Table,
   --#         KindOfStackedCheck,
   --#         LexTokenManager.State,
   --#         ShortCircuitStack,
   --#         Statistics.TableUsage,
   --#         StmtStack.S,
   --#         VCGFailure,
   --#         VCGHeap                    from *,
   --#                                         CheckStack,
   --#                                         CommandLineData.Content,
   --#                                         Dictionary.Dict,
   --#                                         DoAssumeLocalRvalues,
   --#                                         FlowHeap,
   --#                                         Graph.Table,
   --#                                         KindOfStackedCheck,
   --#                                         LexTokenManager.State,
   --#                                         LineNmbr,
   --#                                         LoopStack,
   --#                                         LScope,
   --#                                         Node,
   --#                                         Scope,
   --#                                         ShortCircuitStack,
   --#                                         StmtStack.S,
   --#                                         STree.Table,
   --#                                         VCGHeap &
   --#         ErrorHandler.Error_Context,
   --#         SPARK_IO.File_Sys          from CheckStack,
   --#                                         CommandLineData.Content,
   --#                                         Dictionary.Dict,
   --#                                         DoAssumeLocalRvalues,
   --#                                         ErrorHandler.Error_Context,
   --#                                         FlowHeap,
   --#                                         Graph.Table,
   --#                                         KindOfStackedCheck,
   --#                                         LexTokenManager.State,
   --#                                         LineNmbr,
   --#                                         LoopStack,
   --#                                         LScope,
   --#                                         Node,
   --#                                         Scope,
   --#                                         ShortCircuitStack,
   --#                                         SPARK_IO.File_Sys,
   --#                                         StmtStack.S,
   --#                                         STree.Table,
   --#                                         VCGHeap;
   is
      R           : StmtStack.StmtRecord;
      Predecessor : Graph.Matrix_Index;
      CaseExpn    : Cells.Cell;

   begin
      Predecessor := StmtStack.Top.StmtNmbr;
      -- push record holding nmbr of exit of case-statement;
      Graph.Inc_Nmbr_Of_Stmts; --263
      R.StmtNmbr := Graph.Get_Nmbr_Of_Stmts;   -- ignore flow error about undefined R
      R.Kind     := StmtStack.CaseExit;
      StmtStack.Push (R);
      -- push record holding nmbr of start of case-statement;
      R.StmtNmbr := Predecessor;
      R.Kind     := StmtStack.CaseStart;
      StmtStack.Push (R);

      -- Build expn DAG just to generate VCs; so Examiner will detect
      -- that assignment to CaseExpn is ineffective.
      --# accept F, 10, CaseExpn, "CaseExpn unused here" &
      --#        F, 33, CaseExpn, "CaseExpn unused here";
      BuildExpnDAG
        (StartNode          => Node,
         ExpnScope          => LScope,
         Scope              => Scope,
         LineNmbr           => LineNmbr,
         DoRtc              => True,
         AssumeRvalues      => DoAssumeLocalRvalues,
         LoopStack          => LoopStack,
         FlowHeap           => FlowHeap,
         VCGHeap            => VCGHeap,
         ContainsReals      => ContainsReals,
         VCGFailure         => VCGFailure,
         ShortCircuitStack  => ShortCircuitStack,
         CheckStack         => CheckStack,
         KindOfStackedCheck => KindOfStackedCheck,
         DAGRoot            => CaseExpn);

      UnStackRtcs (LineNmbr, VCGHeap, CheckStack, KindOfStackedCheck);
   end StartCaseModel; -- Expect CaseExpn unused

   procedure ModelAlternative
   --# global in     CommandLineData.Content;
   --#        in     LineNmbr;
   --#        in     LoopStack;
   --#        in     LScope;
   --#        in     Node;
   --#        in     Scope;
   --#        in     STree.Table;
   --#        in out CheckStack;
   --#        in out ContainsReals;
   --#        in out Dictionary.Dict;
   --#        in out ErrorHandler.Error_Context;
   --#        in out FlowHeap;
   --#        in out Graph.Table;
   --#        in out KindOfStackedCheck;
   --#        in out LexTokenManager.State;
   --#        in out ShortCircuitStack;
   --#        in out SPARK_IO.File_Sys;
   --#        in out Statistics.TableUsage;
   --#        in out StmtStack.S;
   --#        in out VCGFailure;
   --#        in out VCGHeap;
   --# derives CheckStack,
   --#         ContainsReals,
   --#         Dictionary.Dict,
   --#         FlowHeap,
   --#         Graph.Table,
   --#         KindOfStackedCheck,
   --#         LexTokenManager.State,
   --#         ShortCircuitStack,
   --#         Statistics.TableUsage,
   --#         StmtStack.S,
   --#         VCGFailure,
   --#         VCGHeap                    from *,
   --#                                         CheckStack,
   --#                                         CommandLineData.Content,
   --#                                         Dictionary.Dict,
   --#                                         FlowHeap,
   --#                                         Graph.Table,
   --#                                         KindOfStackedCheck,
   --#                                         LexTokenManager.State,
   --#                                         LineNmbr,
   --#                                         LoopStack,
   --#                                         LScope,
   --#                                         Node,
   --#                                         Scope,
   --#                                         ShortCircuitStack,
   --#                                         StmtStack.S,
   --#                                         STree.Table,
   --#                                         VCGHeap &
   --#         ErrorHandler.Error_Context,
   --#         SPARK_IO.File_Sys          from CheckStack,
   --#                                         CommandLineData.Content,
   --#                                         Dictionary.Dict,
   --#                                         ErrorHandler.Error_Context,
   --#                                         FlowHeap,
   --#                                         Graph.Table,
   --#                                         KindOfStackedCheck,
   --#                                         LexTokenManager.State,
   --#                                         LineNmbr,
   --#                                         LoopStack,
   --#                                         LScope,
   --#                                         Node,
   --#                                         Scope,
   --#                                         ShortCircuitStack,
   --#                                         SPARK_IO.File_Sys,
   --#                                         StmtStack.S,
   --#                                         STree.Table,
   --#                                         VCGHeap;
   is
      AlternativeLabel, UnitLabel                                       : Labels.Label;
      AlternativeDAG, CaseExpnDAG, ChoiceDAG, CopyCaseExpnDAG, PairCell : Cells.Cell;
      FirstChoice                                                       : Boolean;
      LocalNode                                                         : STree.SyntaxNode;
      R, S                                                              : StmtStack.StmtRecord;

      procedure BuildChoiceDAG (CaseExpnDAG    : in     Cells.Cell;
                                CaseChoiceNode : in     STree.SyntaxNode;
                                ChoiceDAG      :    out Cells.Cell)
      --# global in     CommandLineData.Content;
      --#        in     LineNmbr;
      --#        in     LoopStack;
      --#        in     LScope;
      --#        in     Scope;
      --#        in     STree.Table;
      --#        in out CheckStack;
      --#        in out ContainsReals;
      --#        in out Dictionary.Dict;
      --#        in out ErrorHandler.Error_Context;
      --#        in out FlowHeap;
      --#        in out Graph.Table;
      --#        in out KindOfStackedCheck;
      --#        in out LexTokenManager.State;
      --#        in out ShortCircuitStack;
      --#        in out SPARK_IO.File_Sys;
      --#        in out Statistics.TableUsage;
      --#        in out StmtStack.S;
      --#        in out VCGFailure;
      --#        in out VCGHeap;
      --# derives CheckStack,
      --#         ContainsReals,
      --#         Dictionary.Dict,
      --#         FlowHeap,
      --#         Graph.Table,
      --#         KindOfStackedCheck,
      --#         LexTokenManager.State,
      --#         ShortCircuitStack,
      --#         Statistics.TableUsage,
      --#         StmtStack.S,
      --#         VCGFailure,
      --#         VCGHeap                    from *,
      --#                                         CaseChoiceNode,
      --#                                         CaseExpnDAG,
      --#                                         CheckStack,
      --#                                         CommandLineData.Content,
      --#                                         Dictionary.Dict,
      --#                                         FlowHeap,
      --#                                         Graph.Table,
      --#                                         KindOfStackedCheck,
      --#                                         LexTokenManager.State,
      --#                                         LineNmbr,
      --#                                         LoopStack,
      --#                                         LScope,
      --#                                         Scope,
      --#                                         ShortCircuitStack,
      --#                                         StmtStack.S,
      --#                                         STree.Table,
      --#                                         VCGHeap &
      --#         ChoiceDAG                  from CaseChoiceNode,
      --#                                         CaseExpnDAG,
      --#                                         CheckStack,
      --#                                         CommandLineData.Content,
      --#                                         Dictionary.Dict,
      --#                                         FlowHeap,
      --#                                         Graph.Table,
      --#                                         KindOfStackedCheck,
      --#                                         LexTokenManager.State,
      --#                                         LineNmbr,
      --#                                         LoopStack,
      --#                                         LScope,
      --#                                         Scope,
      --#                                         ShortCircuitStack,
      --#                                         StmtStack.S,
      --#                                         STree.Table,
      --#                                         VCGHeap &
      --#         ErrorHandler.Error_Context,
      --#         SPARK_IO.File_Sys          from CaseChoiceNode,
      --#                                         CaseExpnDAG,
      --#                                         CheckStack,
      --#                                         CommandLineData.Content,
      --#                                         Dictionary.Dict,
      --#                                         ErrorHandler.Error_Context,
      --#                                         FlowHeap,
      --#                                         Graph.Table,
      --#                                         KindOfStackedCheck,
      --#                                         LexTokenManager.State,
      --#                                         LineNmbr,
      --#                                         LoopStack,
      --#                                         LScope,
      --#                                         Scope,
      --#                                         ShortCircuitStack,
      --#                                         SPARK_IO.File_Sys,
      --#                                         StmtStack.S,
      --#                                         STree.Table,
      --#                                         VCGHeap;
      is
         CaseChoice, CopyCaseExpnDAG, FirstCell, LastCell, FirstApost, SecondApost, LTECell, GTECell, LocalDAG : Cells.Cell;

         procedure BuildDiscreteRange (LHSnode  : in     STree.SyntaxNode;
                                       RangeDAG :    out Cells.Cell)
         --# global in     CaseExpnDAG;
         --#        in     CommandLineData.Content;
         --#        in     LineNmbr;
         --#        in     LoopStack;
         --#        in     LScope;
         --#        in     Scope;
         --#        in     STree.Table;
         --#        in out CheckStack;
         --#        in out ContainsReals;
         --#        in out Dictionary.Dict;
         --#        in out ErrorHandler.Error_Context;
         --#        in out FlowHeap;
         --#        in out Graph.Table;
         --#        in out KindOfStackedCheck;
         --#        in out LexTokenManager.State;
         --#        in out ShortCircuitStack;
         --#        in out SPARK_IO.File_Sys;
         --#        in out Statistics.TableUsage;
         --#        in out StmtStack.S;
         --#        in out VCGFailure;
         --#        in out VCGHeap;
         --# derives CheckStack,
         --#         ContainsReals,
         --#         Dictionary.Dict,
         --#         FlowHeap,
         --#         Graph.Table,
         --#         KindOfStackedCheck,
         --#         LexTokenManager.State,
         --#         ShortCircuitStack,
         --#         Statistics.TableUsage,
         --#         StmtStack.S,
         --#         VCGFailure,
         --#         VCGHeap                    from *,
         --#                                         CaseExpnDAG,
         --#                                         CheckStack,
         --#                                         CommandLineData.Content,
         --#                                         Dictionary.Dict,
         --#                                         FlowHeap,
         --#                                         Graph.Table,
         --#                                         KindOfStackedCheck,
         --#                                         LexTokenManager.State,
         --#                                         LHSnode,
         --#                                         LineNmbr,
         --#                                         LoopStack,
         --#                                         LScope,
         --#                                         Scope,
         --#                                         ShortCircuitStack,
         --#                                         StmtStack.S,
         --#                                         STree.Table,
         --#                                         VCGHeap &
         --#         ErrorHandler.Error_Context,
         --#         SPARK_IO.File_Sys          from CaseExpnDAG,
         --#                                         CheckStack,
         --#                                         CommandLineData.Content,
         --#                                         Dictionary.Dict,
         --#                                         ErrorHandler.Error_Context,
         --#                                         FlowHeap,
         --#                                         Graph.Table,
         --#                                         KindOfStackedCheck,
         --#                                         LexTokenManager.State,
         --#                                         LHSnode,
         --#                                         LineNmbr,
         --#                                         LoopStack,
         --#                                         LScope,
         --#                                         Scope,
         --#                                         ShortCircuitStack,
         --#                                         SPARK_IO.File_Sys,
         --#                                         StmtStack.S,
         --#                                         STree.Table,
         --#                                         VCGHeap &
         --#         RangeDAG                   from CaseExpnDAG,
         --#                                         CheckStack,
         --#                                         CommandLineData.Content,
         --#                                         Dictionary.Dict,
         --#                                         FlowHeap,
         --#                                         Graph.Table,
         --#                                         KindOfStackedCheck,
         --#                                         LexTokenManager.State,
         --#                                         LHSnode,
         --#                                         LineNmbr,
         --#                                         LoopStack,
         --#                                         LScope,
         --#                                         Scope,
         --#                                         ShortCircuitStack,
         --#                                         StmtStack.S,
         --#                                         STree.Table,
         --#                                         VCGHeap;
         is
            CaseChoice, CopyCaseExpnDAG, LTECell, GTECell, LocalDAG : Cells.Cell;
         begin -- BuildDiscreteRange
            Structures.CopyStructure (VCGHeap, CaseExpnDAG, CopyCaseExpnDAG);

            CreateOpCell (GTECell, VCGHeap, SP_Symbols.greater_or_equal);
            SetLeftArgument (GTECell, CaseExpnDAG, VCGHeap);

            -- This call to BuildExpnDAG will not generate any checks.
            BuildExpnDAG
              (StartNode          => LHSnode,
               ExpnScope          => LScope,
               Scope              => Scope,
               LineNmbr           => LineNmbr,
               DoRtc              => False,
               AssumeRvalues      => False,
               LoopStack          => LoopStack,
               FlowHeap           => FlowHeap,
               VCGHeap            => VCGHeap,
               ContainsReals      => ContainsReals,
               VCGFailure         => VCGFailure,
               ShortCircuitStack  => ShortCircuitStack,
               CheckStack         => CheckStack,
               KindOfStackedCheck => KindOfStackedCheck,
               DAGRoot            => CaseChoice);

            SetRightArgument (GTECell, CaseChoice, VCGHeap);

            CreateOpCell (LTECell, VCGHeap, SP_Symbols.less_or_equal);
            SetLeftArgument (LTECell, CopyCaseExpnDAG, VCGHeap);

            -- This call to BuildExpnDAG will not generate any checks.
            BuildExpnDAG
              (StartNode          => STree.Next_Sibling (Current_Node => LHSnode),
               ExpnScope          => LScope,
               Scope              => Scope,
               LineNmbr           => LineNmbr,
               DoRtc              => False,
               AssumeRvalues      => False,
               LoopStack          => LoopStack,
               FlowHeap           => FlowHeap,
               VCGHeap            => VCGHeap,
               ContainsReals      => ContainsReals,
               VCGFailure         => VCGFailure,
               ShortCircuitStack  => ShortCircuitStack,
               CheckStack         => CheckStack,
               KindOfStackedCheck => KindOfStackedCheck,
               DAGRoot            => CaseChoice);

            SetRightArgument (LTECell, CaseChoice, VCGHeap);

            CreateOpCell (LocalDAG, VCGHeap, SP_Symbols.RWand);
            SetLeftArgument (LocalDAG, GTECell, VCGHeap);
            SetRightArgument (LocalDAG, LTECell, VCGHeap);

            RangeDAG := LocalDAG;
         end BuildDiscreteRange;

      begin -- BuildChoiceDAG
            -- CaseChoiceNode is Derivative of case_choice, of one of the following forms:
            --    simple_expression
            --    simple_expression range_constraint
            --    simple_expression double_dot simple_expression
         if STree.Next_Sibling (Current_Node => CaseChoiceNode) = STree.NullNode then
            -- choice is a simple_expression;
            -- it might be a type mark or a value

            -- This call to BuildExpnDAG will not generate any checks.
            BuildExpnDAG
              (StartNode          => CaseChoiceNode,
               ExpnScope          => LScope,
               Scope              => Scope,
               LineNmbr           => LineNmbr,
               DoRtc              => False,
               AssumeRvalues      => False,
               LoopStack          => LoopStack,
               FlowHeap           => FlowHeap,
               VCGHeap            => VCGHeap,
               ContainsReals      => ContainsReals,
               VCGFailure         => VCGFailure,
               ShortCircuitStack  => ShortCircuitStack,
               CheckStack         => CheckStack,
               KindOfStackedCheck => KindOfStackedCheck,
               DAGRoot            => CaseChoice);

            -- if choice is a type mark then CasChoice will be FixedVar cell and it Sym will
            -- be a type mark symbol.  Such choice needs a range model, any other is equality
            if Cells.Get_Kind (VCGHeap, CaseChoice) = Cell_Storage.Fixed_Var
              and then Dictionary.IsTypeMark (Cells.Get_Symbol_Value (VCGHeap, CaseChoice)) then -- process as range
               Structures.CopyStructure (VCGHeap, CaseExpnDAG, CopyCaseExpnDAG);
               CreateOpCell (FirstApost, VCGHeap, SP_Symbols.apostrophe);
               CreateOpCell (SecondApost, VCGHeap, SP_Symbols.apostrophe);
               CreateCellKind (FirstCell, VCGHeap, Cell_Storage.Attrib_Value);
               CreateCellKind (LastCell, VCGHeap, Cell_Storage.Attrib_Value);
               Cells.Set_Lex_Str (VCGHeap, FirstCell, LexTokenManager.First_Token);
               Cells.Set_Lex_Str (VCGHeap, LastCell, LexTokenManager.Last_Token);

               SetRightArgument (FirstApost, FirstCell, VCGHeap);
               SetLeftArgument (FirstApost, CaseChoice, VCGHeap);

               SetRightArgument (SecondApost, LastCell, VCGHeap);
               SetLeftArgument (SecondApost, CaseChoice, VCGHeap);

               CreateOpCell (GTECell, VCGHeap, SP_Symbols.greater_or_equal);
               CreateOpCell (LTECell, VCGHeap, SP_Symbols.less_or_equal);

               SetRightArgument (GTECell, FirstApost, VCGHeap);
               SetLeftArgument (GTECell, CaseExpnDAG, VCGHeap);

               SetRightArgument (LTECell, SecondApost, VCGHeap);
               SetLeftArgument (LTECell, CopyCaseExpnDAG, VCGHeap);

               CreateOpCell (LocalDAG, VCGHeap, SP_Symbols.RWand);
               SetRightArgument (LocalDAG, GTECell, VCGHeap);
               SetLeftArgument (LocalDAG, LTECell, VCGHeap);

            else -- process as equality
               CreateOpCell (LocalDAG, VCGHeap, SP_Symbols.equals);
               SetLeftArgument (LocalDAG, CaseExpnDAG, VCGHeap);
               SetRightArgument (LocalDAG, CaseChoice, VCGHeap);
            end if;

         elsif STree.Syntax_Node_Type (Node => STree.Next_Sibling (Current_Node => CaseChoiceNode)) =
           SP_Symbols.range_constraint then
            -- of the form "subtypemark range rangeconstraint"
            -- in this case the type mark adds no extra information so we just need to process
            -- the range.
            --
            -- The range can grammatically be a range attribute or simpex .. simpex; since it
            -- must be static in a case statement we can assume it is the latter and just dig
            -- down to the LHS simple_expression
            BuildDiscreteRange
              (STree.Child_Node
                 (Current_Node => STree.Child_Node (Current_Node => STree.Next_Sibling (Current_Node => CaseChoiceNode))),
               -- to get
               LocalDAG);

         else
            -- choice is of form simple_expression double_dot simple_expression
            BuildDiscreteRange (CaseChoiceNode,
                                -- to get
                                LocalDAG);

         end if;
         ChoiceDAG := LocalDAG;
      end BuildChoiceDAG;

      procedure BindChoiceDAGs
      --# global in     ChoiceDAG;
      --#        in     FirstChoice;
      --#        in out AlternativeDAG;
      --#        in out Statistics.TableUsage;
      --#        in out VCGHeap;
      --# derives AlternativeDAG        from ChoiceDAG,
      --#                                    FirstChoice,
      --#                                    VCGHeap &
      --#         Statistics.TableUsage from *,
      --#                                    FirstChoice,
      --#                                    VCGHeap &
      --#         VCGHeap               from *,
      --#                                    AlternativeDAG,
      --#                                    ChoiceDAG,
      --#                                    FirstChoice;
      is
         OrCell : Cells.Cell;
      begin
         if FirstChoice then
            AlternativeDAG := ChoiceDAG;
         else
            CreateOpCell (OrCell, VCGHeap, SP_Symbols.RWor);
            SetLeftArgument (OrCell, ChoiceDAG, VCGHeap);
            SetRightArgument (OrCell, AlternativeDAG, VCGHeap);
            AlternativeDAG := OrCell;
         end if;
      end BindChoiceDAGs;

   begin  -- ModelAlternative
      if StmtStack.Top.Kind = StmtStack.CaseBranch then
         -- close existing alternative;
         R := StmtStack.Top;                 -- existing alternative;
         StmtStack.Pop;
         S := StmtStack.Top;                 -- start of case_statement;
         StmtStack.Pop;
         -- top of stack holds exit of case-statement;
         CreateUnitLabel (UnitLabel, VCGHeap);
         Graph.Create_Coeff (Heap => VCGHeap,
                             I    => R.StmtNmbr,
                             J    => StmtStack.Top.StmtNmbr,
                             K    => UnitLabel);
         StmtStack.Push (S);
      end if;
      -- start new alternative;
      -- top of stack holds start of case-statement;
      -- Node is case_statement_alternative_rep;
      PrepareLabel (VCGHeap, AlternativeLabel, PairCell);
      LocalNode := Node;
      loop
         exit when STree.Syntax_Node_Type (Node => LocalNode) = SP_Symbols.case_statement;
         LocalNode := STree.Parent_Node (Current_Node => LocalNode);
      end loop;
      LocalNode := STree.Child_Node (Current_Node => LocalNode);
      -- LocalNode is case expression node;

      -- Do not generate checks with this call
      BuildExpnDAG
        (StartNode          => LocalNode,
         ExpnScope          => LScope,
         Scope              => Scope,
         LineNmbr           => LineNmbr,
         DoRtc              => False,
         AssumeRvalues      => False,
         LoopStack          => LoopStack,
         FlowHeap           => FlowHeap,
         VCGHeap            => VCGHeap,
         ContainsReals      => ContainsReals,
         VCGFailure         => VCGFailure,
         ShortCircuitStack  => ShortCircuitStack,
         CheckStack         => CheckStack,
         KindOfStackedCheck => KindOfStackedCheck,
         DAGRoot            => CaseExpnDAG);

      LocalNode := STree.Child_Node (Current_Node => Node);
      -- LocalNode is case_statement_alternative_rep;
      FirstChoice    := True;
      AlternativeDAG := Cells.Null_Cell; -- to avoid DFA on first call to BuildChoiceDAGs
      loop
         exit when STree.Syntax_Node_Type (Node => LocalNode) = SP_Symbols.case_choice;
         Structures.CopyStructure (VCGHeap, CaseExpnDAG, CopyCaseExpnDAG);
         BuildChoiceDAG
           (CopyCaseExpnDAG,
            STree.Child_Node (Current_Node => STree.Next_Sibling (Current_Node => LocalNode)),
            ChoiceDAG);
         BindChoiceDAGs;
         FirstChoice := False;
         LocalNode   := STree.Child_Node (Current_Node => LocalNode);
      end loop;

      BuildChoiceDAG (CaseExpnDAG, STree.Child_Node (Current_Node => LocalNode), ChoiceDAG);
      BindChoiceDAGs;

      SetRightArgument (PairCell, AlternativeDAG, VCGHeap);
      Graph.Inc_Nmbr_Of_Stmts;
      Graph.Create_Coeff (Heap => VCGHeap,
                          I    => StmtStack.Top.StmtNmbr,
                          J    => Graph.Get_Nmbr_Of_Stmts,
                          K    => AlternativeLabel);
      R := StmtStack.StmtRecord'(Graph.Get_Nmbr_Of_Stmts, StmtStack.CaseBranch);
      StmtStack.Push (R);
   end ModelAlternative;

   procedure ModelOthersPart
   --# global in     Dictionary.Dict;
   --#        in out Graph.Table;
   --#        in out Statistics.TableUsage;
   --#        in out StmtStack.S;
   --#        in out VCGHeap;
   --# derives Graph.Table,
   --#         Statistics.TableUsage,
   --#         StmtStack.S,
   --#         VCGHeap               from *,
   --#                                    Dictionary.Dict,
   --#                                    Graph.Table,
   --#                                    StmtStack.S,
   --#                                    VCGHeap;
   is
      OthersLabel, UnitLabel : Labels.Label;
      OthersDAG, PairCell    : Cells.Cell;
      R, S                   : StmtStack.StmtRecord;

      procedure FormOthersDAG
      --# global in     Dictionary.Dict;
      --#        in     Graph.Table;
      --#        in     StmtStack.S;
      --#        in out Statistics.TableUsage;
      --#        in out VCGHeap;
      --#           out OthersDAG;
      --# derives OthersDAG,
      --#         VCGHeap               from Dictionary.Dict,
      --#                                    Graph.Table,
      --#                                    StmtStack.S,
      --#                                    VCGHeap &
      --#         Statistics.TableUsage from *,
      --#                                    Dictionary.Dict,
      --#                                    Graph.Table,
      --#                                    StmtStack.S,
      --#                                    VCGHeap;
      is
         FirstLabel      : Boolean;
         CopyDAG, NewDAG : Cells.Cell;
      begin
         OthersDAG  := Cells.Null_Cell;   -- in case we fall right through proc
         FirstLabel := True;
         for I in Graph.Matrix_Index range 1 .. Graph.Get_Nmbr_Of_Stmts loop
            if not Labels.IsNull (Graph.Coefficient (VCGHeap, StmtStack.Top.StmtNmbr, I)) then
               Structures.CopyStructure
                 (VCGHeap,
                  Cells.Get_B_Ptr
                    (VCGHeap,
                     Pairs.PairHead (Labels.FirstPair (VCGHeap, Graph.Coefficient (VCGHeap, StmtStack.Top.StmtNmbr, I)))),
                  CopyDAG);
               CreateOpCell (NewDAG, VCGHeap, SP_Symbols.RWnot);
               SetRightArgument (NewDAG, CopyDAG, VCGHeap);

               if FirstLabel then
                  FirstLabel := False;
                  OthersDAG  := NewDAG;
               else
                  Cells.Utility.Conjoin (VCGHeap, NewDAG, OthersDAG);
               end if;
            end if;
         end loop;
      end FormOthersDAG;

   begin  -- ModelOthersPart
      if StmtStack.Top.Kind = StmtStack.CaseBranch then
         -- close existing alternative;
         R := StmtStack.Top;                 -- existing alternative;
         StmtStack.Pop;
         S := StmtStack.Top;                 -- start of case_statement;
         StmtStack.Pop;
         -- top of stack holds exit of case-statement;
         CreateUnitLabel (UnitLabel, VCGHeap);
         Graph.Create_Coeff (Heap => VCGHeap,
                             I    => R.StmtNmbr,
                             J    => StmtStack.Top.StmtNmbr,
                             K    => UnitLabel);
         StmtStack.Push (S);
      end if;
      -- start others part;
      -- top of stack holds start of case-statement;
      PrepareLabel (VCGHeap, OthersLabel, PairCell);
      FormOthersDAG;
      SetRightArgument (PairCell, OthersDAG, VCGHeap);
      Graph.Inc_Nmbr_Of_Stmts;
      Graph.Create_Coeff (Heap => VCGHeap,
                          I    => StmtStack.Top.StmtNmbr,
                          J    => Graph.Get_Nmbr_Of_Stmts,
                          K    => OthersLabel);
      R := StmtStack.StmtRecord'(Graph.Get_Nmbr_Of_Stmts, StmtStack.CaseBranch);
      StmtStack.Push (R);
   end ModelOthersPart;

   ----------------------------------------------------------------------
   --                                 Loops
   ----------------------------------------------------------------------

   procedure StartLoopModel (Node : in STree.SyntaxNode)
   --# global in     CommandLineData.Content;
   --#        in     DoAssumeLocalRvalues;
   --#        in     ImportConstraints;
   --#        in     LineNmbr;
   --#        in     LoopStack;
   --#        in     LScope;
   --#        in     PreConstraints;
   --#        in     Scope;
   --#        in     STree.Table;
   --#        in out CheckStack;
   --#        in out ContainsReals;
   --#        in out Dictionary.Dict;
   --#        in out ErrorHandler.Error_Context;
   --#        in out FlowHeap;
   --#        in out Graph.Table;
   --#        in out KindOfStackedCheck;
   --#        in out LexTokenManager.State;
   --#        in out ShortCircuitStack;
   --#        in out SPARK_IO.File_Sys;
   --#        in out Statistics.TableUsage;
   --#        in out StmtStack.S;
   --#        in out VCGFailure;
   --#        in out VCGHeap;
   --# derives CheckStack,
   --#         ContainsReals,
   --#         Dictionary.Dict,
   --#         FlowHeap,
   --#         Graph.Table,
   --#         KindOfStackedCheck,
   --#         LexTokenManager.State,
   --#         ShortCircuitStack,
   --#         Statistics.TableUsage,
   --#         StmtStack.S,
   --#         VCGFailure,
   --#         VCGHeap                    from *,
   --#                                         CheckStack,
   --#                                         CommandLineData.Content,
   --#                                         Dictionary.Dict,
   --#                                         DoAssumeLocalRvalues,
   --#                                         FlowHeap,
   --#                                         Graph.Table,
   --#                                         ImportConstraints,
   --#                                         KindOfStackedCheck,
   --#                                         LexTokenManager.State,
   --#                                         LineNmbr,
   --#                                         LoopStack,
   --#                                         LScope,
   --#                                         Node,
   --#                                         PreConstraints,
   --#                                         Scope,
   --#                                         ShortCircuitStack,
   --#                                         StmtStack.S,
   --#                                         STree.Table,
   --#                                         VCGHeap &
   --#         ErrorHandler.Error_Context,
   --#         SPARK_IO.File_Sys          from CheckStack,
   --#                                         CommandLineData.Content,
   --#                                         Dictionary.Dict,
   --#                                         DoAssumeLocalRvalues,
   --#                                         ErrorHandler.Error_Context,
   --#                                         FlowHeap,
   --#                                         Graph.Table,
   --#                                         ImportConstraints,
   --#                                         KindOfStackedCheck,
   --#                                         LexTokenManager.State,
   --#                                         LineNmbr,
   --#                                         LoopStack,
   --#                                         LScope,
   --#                                         Node,
   --#                                         PreConstraints,
   --#                                         Scope,
   --#                                         ShortCircuitStack,
   --#                                         SPARK_IO.File_Sys,
   --#                                         StmtStack.S,
   --#                                         STree.Table,
   --#                                         VCGHeap;
   is
      LocalNode, LoopInvariantNode : STree.SyntaxNode;
      LoopHead                     : Graph.Matrix_Index;
      R                            : StmtStack.StmtRecord;

      procedure StartLoopBody
      --# global in out Graph.Table;
      --#        in out Statistics.TableUsage;
      --#        in out StmtStack.S;
      --#        in out VCGHeap;
      --# derives Graph.Table,
      --#         StmtStack.S,
      --#         VCGHeap               from Graph.Table,
      --#                                    StmtStack.S,
      --#                                    VCGHeap &
      --#         Statistics.TableUsage from *,
      --#                                    VCGHeap;
      is
         LoopHead  : Graph.Matrix_Index;
         R         : StmtStack.StmtRecord;
         StmtLabel : Labels.Label;
      begin
         R := StmtStack.Top;                          -- store loop tail record;
         StmtStack.Pop;                               -- pop loop tail to expose loop head;
         LoopHead := StmtStack.Top.StmtNmbr;
         StmtStack.Push (R);                          -- restore loop tail record;
         Graph.Inc_Nmbr_Of_Stmts;
         CreateUnitLabel (StmtLabel, VCGHeap);        -- create null arc in body;
         Graph.Create_Coeff (Heap => VCGHeap,
                             I    => LoopHead,
                             J    => Graph.Get_Nmbr_Of_Stmts,
                             K    => StmtLabel);
         R.StmtNmbr := Graph.Get_Nmbr_Of_Stmts;          -- create loop body record;
         R.Kind     := StmtStack.Elementary;
         StmtStack.Push (R);
      end StartLoopBody;

      procedure ModelWhile
      --# global in     CommandLineData.Content;
      --#        in     DoAssumeLocalRvalues;
      --#        in     LineNmbr;
      --#        in     LocalNode;
      --#        in     LoopStack;
      --#        in     LScope;
      --#        in     Scope;
      --#        in     STree.Table;
      --#        in out CheckStack;
      --#        in out ContainsReals;
      --#        in out Dictionary.Dict;
      --#        in out ErrorHandler.Error_Context;
      --#        in out FlowHeap;
      --#        in out Graph.Table;
      --#        in out KindOfStackedCheck;
      --#        in out LexTokenManager.State;
      --#        in out ShortCircuitStack;
      --#        in out SPARK_IO.File_Sys;
      --#        in out Statistics.TableUsage;
      --#        in out StmtStack.S;
      --#        in out VCGFailure;
      --#        in out VCGHeap;
      --# derives CheckStack,
      --#         ContainsReals,
      --#         Dictionary.Dict,
      --#         FlowHeap,
      --#         Graph.Table,
      --#         KindOfStackedCheck,
      --#         LexTokenManager.State,
      --#         ShortCircuitStack,
      --#         Statistics.TableUsage,
      --#         StmtStack.S,
      --#         VCGFailure,
      --#         VCGHeap                    from *,
      --#                                         CheckStack,
      --#                                         CommandLineData.Content,
      --#                                         Dictionary.Dict,
      --#                                         DoAssumeLocalRvalues,
      --#                                         FlowHeap,
      --#                                         Graph.Table,
      --#                                         KindOfStackedCheck,
      --#                                         LexTokenManager.State,
      --#                                         LineNmbr,
      --#                                         LocalNode,
      --#                                         LoopStack,
      --#                                         LScope,
      --#                                         Scope,
      --#                                         ShortCircuitStack,
      --#                                         StmtStack.S,
      --#                                         STree.Table,
      --#                                         VCGHeap &
      --#         ErrorHandler.Error_Context,
      --#         SPARK_IO.File_Sys          from CheckStack,
      --#                                         CommandLineData.Content,
      --#                                         Dictionary.Dict,
      --#                                         DoAssumeLocalRvalues,
      --#                                         ErrorHandler.Error_Context,
      --#                                         FlowHeap,
      --#                                         Graph.Table,
      --#                                         KindOfStackedCheck,
      --#                                         LexTokenManager.State,
      --#                                         LineNmbr,
      --#                                         LocalNode,
      --#                                         LoopStack,
      --#                                         LScope,
      --#                                         Scope,
      --#                                         ShortCircuitStack,
      --#                                         SPARK_IO.File_Sys,
      --#                                         StmtStack.S,
      --#                                         STree.Table,
      --#                                         VCGHeap;
      is
         DAGRoot                           : Cells.Cell;
         FalseBranchLabel, TrueBranchLabel : Labels.Label;
         R                                 : StmtStack.StmtRecord;
         LoopTail, SwitchNode              : Graph.Matrix_Index;
      begin
         BuildExpnDAG
           (StartNode          => LocalNode,
            ExpnScope          => LScope,
            Scope              => Scope,
            LineNmbr           => LineNmbr,
            DoRtc              => True,
            AssumeRvalues      => DoAssumeLocalRvalues,
            LoopStack          => LoopStack,
            FlowHeap           => FlowHeap,
            VCGHeap            => VCGHeap,
            ContainsReals      => ContainsReals,
            VCGFailure         => VCGFailure,
            ShortCircuitStack  => ShortCircuitStack,
            CheckStack         => CheckStack,
            KindOfStackedCheck => KindOfStackedCheck,
            DAGRoot            => DAGRoot);

         UnStackRtcs (LineNmbr, VCGHeap, CheckStack, KindOfStackedCheck);

         SwitchNode := StmtStack.Top.StmtNmbr;
         StmtStack.Pop;                         -- pop last statement in loop body;
         LoopTail := StmtStack.Top.StmtNmbr;
         CreateSwitch (DAGRoot, FalseBranchLabel, TrueBranchLabel);
         Graph.Create_Coeff (Heap => VCGHeap,
                             I    => SwitchNode,
                             J    => LoopTail,
                             K    => FalseBranchLabel);
         -- push True branch;
         Graph.Inc_Nmbr_Of_Stmts;
         Graph.Create_Coeff (Heap => VCGHeap,
                             I    => SwitchNode,
                             J    => Graph.Get_Nmbr_Of_Stmts,
                             K    => TrueBranchLabel);
         R := StmtStack.StmtRecord'(Graph.Get_Nmbr_Of_Stmts, StmtStack.Elementary);
         StmtStack.Push (R);
      end ModelWhile;

      function FindAssert (LoopNode : STree.SyntaxNode) return Boolean
      --# global in STree.Table;
      is
         LastNode, StartNode, LocNode, Node : STree.SyntaxNode;
         NodeType                           : SP_Symbols.SP_Symbol;
         foundAssert                        : Boolean;

      begin
         -- LoopNode is a loop_statement_opt
         -- set StartNode to parent loop node
         StartNode := STree.Parent_Node (Current_Node => LoopNode);
         if STree.Syntax_Node_Type (Node => StartNode) /= SP_Symbols.loop_statement then
            StartNode := STree.Parent_Node (Current_Node => StartNode);
         end if;
         foundAssert := False;

         Node := StartNode;
         loop ---------------------------down loop------------------------------
            LastNode := Node;
            NodeType := STree.Syntax_Node_Type (Node => Node);
            case NodeType is
               when SP_Symbols.loop_statement =>
                  if Node = StartNode then
                     Node := STree.Child_Node (Current_Node => Node);
                  else
                     -- skip over any nested loops
                     Node := STree.NullNode;
                  end if;

               when SP_Symbols.sequence_of_statements |
                 SP_Symbols.simple_statement       |
                 SP_Symbols.compound_statement     |
                 SP_Symbols.elsif_part             |
                 SP_Symbols.else_part              |
                 SP_Symbols.statement              |
                 SP_Symbols.alternatives           =>
                  Node := STree.Child_Node (Current_Node => Node);

               when SP_Symbols.simple_name              |
                 SP_Symbols.apragma                  |
                 SP_Symbols.null_statement           |
                 SP_Symbols.assignment_statement     |
                 SP_Symbols.procedure_call_statement =>
                  Node := STree.NullNode;

               when SP_Symbols.proof_statement =>
                  if STree.Syntax_Node_Type (Node => STree.Child_Node (Current_Node => Node)) = SP_Symbols.assert_statement then
                     foundAssert := True;
                  else
                     Node := STree.NullNode;
                  end if;

               when SP_Symbols.return_statement | SP_Symbols.exit_statement | SP_Symbols.delay_statement | SP_Symbols.condition =>
                  Node := STree.NullNode;

               when SP_Symbols.if_statement | SP_Symbols.case_statement =>
                  Node     := STree.Child_Node (Current_Node => Node);
                  LastNode := Node;
                  Node     := STree.NullNode;

               when SP_Symbols.case_statement_alternative =>
                  Node := STree.Child_Node (Current_Node => Node);
                  Node := STree.Next_Sibling (Current_Node => Node);

               when SP_Symbols.others_part =>
                  if STree.Child_Node (Current_Node => Node) /= STree.NullNode then
                     Node := STree.Child_Node (Current_Node => Node);
                  else
                     Node := STree.NullNode;
                  end if;

               when SP_Symbols.loop_statement_opt =>
                  -- advance to iteration_scheme;
                  LocNode := STree.Child_Node (Current_Node => Node);
                  if LocNode /= STree.NullNode then
                     -- loop has an iteration_scheme
                     -- localnode is of type iteration_scheme
                     if STree.Next_Sibling (Current_Node => LocNode) /= STree.NullNode then
                        -- iteration_scheme has an invariant
                        foundAssert := True;
                     end if;
                  end if;
                  Node := STree.NullNode;

               when others =>
                  Node := STree.NullNode;
            end case;

            if not foundAssert and Node = STree.NullNode and LastNode /= StartNode then
               loop -----------------------up loop-----------------------
                  Node := STree.Next_Sibling (Current_Node => LastNode);
                  exit when Node /= STree.NullNode;
                  Node := STree.Parent_Node (Current_Node => LastNode);
                  exit when Node = STree.NullNode or Node = StartNode;
                  LastNode := Node;
               end loop;   ----------------------------up----------------
            end if;
            exit when foundAssert or Node = STree.NullNode or Node = StartNode;
         end loop;  ------------------down----------------------

         return foundAssert;
      end FindAssert;

      procedure CheckPlantAssert
      --# global in     CommandLineData.Content;
      --#        in     Dictionary.Dict;
      --#        in     ImportConstraints;
      --#        in     LexTokenManager.State;
      --#        in     LineNmbr;
      --#        in     LoopStack;
      --#        in     Node;
      --#        in     PreConstraints;
      --#        in     STree.Table;
      --#        in out ErrorHandler.Error_Context;
      --#        in out Graph.Table;
      --#        in out SPARK_IO.File_Sys;
      --#        in out Statistics.TableUsage;
      --#        in out StmtStack.S;
      --#        in out VCGHeap;
      --# derives ErrorHandler.Error_Context,
      --#         SPARK_IO.File_Sys          from CommandLineData.Content,
      --#                                         Dictionary.Dict,
      --#                                         ErrorHandler.Error_Context,
      --#                                         LexTokenManager.State,
      --#                                         LineNmbr,
      --#                                         Node,
      --#                                         SPARK_IO.File_Sys,
      --#                                         STree.Table &
      --#         Graph.Table,
      --#         StmtStack.S,
      --#         VCGHeap                    from Dictionary.Dict,
      --#                                         Graph.Table,
      --#                                         ImportConstraints,
      --#                                         LexTokenManager.State,
      --#                                         LineNmbr,
      --#                                         LoopStack,
      --#                                         Node,
      --#                                         PreConstraints,
      --#                                         StmtStack.S,
      --#                                         STree.Table,
      --#                                         VCGHeap &
      --#         Statistics.TableUsage      from *,
      --#                                         Dictionary.Dict,
      --#                                         Graph.Table,
      --#                                         ImportConstraints,
      --#                                         LexTokenManager.State,
      --#                                         LoopStack,
      --#                                         Node,
      --#                                         PreConstraints,
      --#                                         StmtStack.S,
      --#                                         STree.Table,
      --#                                         VCGHeap;
      is
         CpPreConstraints, InsertedAssert : Cells.Cell;

         procedure DebugPrintInvariant
         --# derives ;
         is
            --# hide DebugPrintInvariant;
         begin
            if CommandLineData.Content.Debug.Invariants then
               SPARK_IO.New_Line (SPARK_IO.Standard_Output, 1);
               SPARK_IO.Put_Line (SPARK_IO.Standard_Output, "Default loop invariant inserted: ", 0);
               SPARK_IO.Put_String (SPARK_IO.Standard_Output, "           ", 0);
               DAG_IO.PrintDag
                 (VCGHeap,
                  SPARK_IO.Standard_Output,
                  InsertedAssert,
                  Dictionary.Set_Visibility
                    (The_Visibility => Dictionary.Local,
                     The_Unit       => LoopContext.CurrentLoopSym (LoopStack, VCGHeap)),
                  DAG_IO.Default_Wrap_Limit);
               SPARK_IO.New_Line (SPARK_IO.Standard_Output, 1);
            end if;
         end DebugPrintInvariant;

      begin -- CheckPlantAssert
         if not FindAssert (Node) then
            ErrorHandler.Add_Cut_Point (At_Line => LexTokenManager.Line_Numbers (LineNmbr));

            ModelNullStmt (VCGHeap);
            Graph.Set_Proof_Context (X => Graph.Default_Assertion);
            Graph.Set_Text_Line_Nmbr (X => LineNmbr);

            if Cells.Is_Null_Cell (ImportConstraints) and Cells.Is_Null_Cell (PreConstraints) then
               CreateTrueCell (VCGHeap, InsertedAssert);
            elsif Cells.Is_Null_Cell (ImportConstraints) then
               Structures.CopyStructure (VCGHeap, PreConstraints, InsertedAssert);
            elsif Cells.Is_Null_Cell (PreConstraints) then
               Structures.CopyStructure (VCGHeap, ImportConstraints, InsertedAssert);
            else
               Structures.CopyStructure (VCGHeap, ImportConstraints, InsertedAssert);
               Structures.CopyStructure (VCGHeap, PreConstraints, CpPreConstraints);
               Cells.Utility.Conjoin (VCGHeap, CpPreConstraints, InsertedAssert);
            end if;
            -- if the loop being cut is a for a loop (including nested loops) then assert
            -- that the loop counter must be in its type
            AssertForLoopCounterProperties
              (Dictionary.Set_Visibility
                 (The_Visibility => Dictionary.Local,
                  The_Unit       => LoopContext.CurrentLoopSym (LoopStack, VCGHeap)),
               InsertedAssert);

            DebugPrintInvariant;

            Graph.Set_Assertion_Locn (X => InsertedAssert);
            ModelNullStmt (VCGHeap);
         end if;
      end CheckPlantAssert;

   begin -- StartLoopModel
      LoopHead := StmtStack.Top.StmtNmbr;
      -- push record holding nmbr of exit of loop-statement;
      Graph.Inc_Nmbr_Of_Stmts;
      R := StmtStack.StmtRecord'(Graph.Get_Nmbr_Of_Stmts, StmtStack.LoopExit);
      StmtStack.Push (R);

      Graph.Insert_Text_Line_Nmbr (Index => LoopHead,
                                   X     => LineNmbr);

      StartLoopBody;

      CheckPlantAssert;

      -- advance to iteration_scheme;
      LocalNode := STree.Child_Node (Current_Node => Node);
      if LocalNode /= STree.NullNode then
         -- loop has an iteration_scheme;
         -- localnode is of type iteration_scheme;
         LoopInvariantNode := STree.Next_Sibling (Current_Node => LocalNode);
         LocalNode         := STree.Child_Node (Current_Node => LocalNode);

         if LoopInvariantNode /= STree.NullNode then
            ModelAssertStmt
              (STree.Child_Node
                 (Current_Node => STree.Child_Node (Current_Node => STree.Child_Node (Current_Node => LoopInvariantNode))));
         end if;
         case STree.Syntax_Node_Type (Node => LocalNode) is
            when SP_Symbols.condition =>
               ModelWhile;
            when others =>
               null;
         end case;
      end if;
   end StartLoopModel;

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

   procedure ModelExit
   --# global in     CommandLineData.Content;
   --#        in     DoAssumeLocalRvalues;
   --#        in     LineNmbr;
   --#        in     LoopStack;
   --#        in     LScope;
   --#        in     Node;
   --#        in     Scope;
   --#        in     STree.Table;
   --#        in out CheckStack;
   --#        in out ContainsReals;
   --#        in out Dictionary.Dict;
   --#        in out ErrorHandler.Error_Context;
   --#        in out FlowHeap;
   --#        in out Graph.Table;
   --#        in out KindOfStackedCheck;
   --#        in out LexTokenManager.State;
   --#        in out ShortCircuitStack;
   --#        in out SPARK_IO.File_Sys;
   --#        in out Statistics.TableUsage;
   --#        in out StmtStack.S;
   --#        in out VCGFailure;
   --#        in out VCGHeap;
   --# derives CheckStack,
   --#         ContainsReals,
   --#         Dictionary.Dict,
   --#         FlowHeap,
   --#         Graph.Table,
   --#         KindOfStackedCheck,
   --#         LexTokenManager.State,
   --#         ShortCircuitStack,
   --#         Statistics.TableUsage,
   --#         StmtStack.S,
   --#         VCGFailure,
   --#         VCGHeap                    from *,
   --#                                         CheckStack,
   --#                                         CommandLineData.Content,
   --#                                         Dictionary.Dict,
   --#                                         DoAssumeLocalRvalues,
   --#                                         FlowHeap,
   --#                                         Graph.Table,
   --#                                         KindOfStackedCheck,
   --#                                         LexTokenManager.State,
   --#                                         LineNmbr,
   --#                                         LoopStack,
   --#                                         LScope,
   --#                                         Node,
   --#                                         Scope,
   --#                                         ShortCircuitStack,
   --#                                         StmtStack.S,
   --#                                         STree.Table,
   --#                                         VCGHeap &
   --#         ErrorHandler.Error_Context,
   --#         SPARK_IO.File_Sys          from CheckStack,
   --#                                         CommandLineData.Content,
   --#                                         Dictionary.Dict,
   --#                                         DoAssumeLocalRvalues,
   --#                                         ErrorHandler.Error_Context,
   --#                                         FlowHeap,
   --#                                         Graph.Table,
   --#                                         KindOfStackedCheck,
   --#                                         LexTokenManager.State,
   --#                                         LineNmbr,
   --#                                         LoopStack,
   --#                                         LScope,
   --#                                         Node,
   --#                                         Scope,
   --#                                         ShortCircuitStack,
   --#                                         SPARK_IO.File_Sys,
   --#                                         StmtStack.S,
   --#                                         STree.Table,
   --#                                         VCGHeap;
   is
      DAGRoot                                      : Cells.Cell;
      FalseBranchLabel, TrueBranchLabel, UnitLabel : Labels.Label;
      Q, R, S, T                                   : StmtStack.StmtRecord;
      IfTail, LoopTail, Switchnode                 : Graph.Matrix_Index;
   begin
      if Node /= STree.NullNode then
         -- exit occurs in a statement of the form "exit when ...";
         BuildExpnDAG
           (StartNode          => Node,
            ExpnScope          => LScope,
            Scope              => Scope,
            LineNmbr           => LineNmbr,
            DoRtc              => True,
            AssumeRvalues      => DoAssumeLocalRvalues,
            LoopStack          => LoopStack,
            FlowHeap           => FlowHeap,
            VCGHeap            => VCGHeap,
            ContainsReals      => ContainsReals,
            VCGFailure         => VCGFailure,
            ShortCircuitStack  => ShortCircuitStack,
            CheckStack         => CheckStack,
            KindOfStackedCheck => KindOfStackedCheck,
            DAGRoot            => DAGRoot);

         UnStackRtcs (LineNmbr, VCGHeap, CheckStack, KindOfStackedCheck);

         CreateSwitch (DAGRoot, FalseBranchLabel, TrueBranchLabel);
         Switchnode := StmtStack.Top.StmtNmbr;
         StmtStack.Pop;                         -- pop last statement in loop body,
         LoopTail := StmtStack.Top.StmtNmbr;
         Graph.Create_Coeff (Heap => VCGHeap,
                             I    => Switchnode,
                             J    => LoopTail,
                             K    => TrueBranchLabel);
         -- push False branch;
         Graph.Inc_Nmbr_Of_Stmts; --263
         Graph.Create_Coeff (Heap => VCGHeap,
                             I    => Switchnode,
                             J    => Graph.Get_Nmbr_Of_Stmts,
                             K    => FalseBranchLabel);
         R := StmtStack.StmtRecord'(Graph.Get_Nmbr_Of_Stmts, StmtStack.Elementary);
         StmtStack.Push (R);
      else
         -- exit occurs in a statement of the form if ... then ... exit;
         Q := StmtStack.Top; -- store if-branch record;
         StmtStack.Pop; -- pop if_branch record;
         IfTail := Q.StmtNmbr;
         -- store else-branch record;
         -- pop else_branch record; top of stack now holds if-statement tail;
         R := StmtStack.Top;
         StmtStack.Pop; -- pop else_branch record;

         -- top of stack now holds if-statement tail;
         S := StmtStack.Top; -- temporarily store and
         StmtStack.Pop; -- pop if-stmt tail;

         -- top of stack is now current first statement in loop body;
         T := StmtStack.Top; -- temporarily store and
         StmtStack.Pop; -- pop first stmt of loop body;
         LoopTail := StmtStack.Top.StmtNmbr;
         StmtStack.Push (T); -- restore loop stmt;
         StmtStack.Push (S); -- restore if-stmt tail;
         StmtStack.Push (R); -- restore else-branch;
         Q.Kind := StmtStack.LoopExit; -- prepare for StartElseModel;
         StmtStack.Push (Q); -- restore modified if-branch;
         CreateUnitLabel (UnitLabel, VCGHeap);
         Graph.Create_Coeff (Heap => VCGHeap,
                             I    => IfTail,
                             J    => LoopTail,
                             K    => UnitLabel);
      end if;
   end ModelExit;

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

   -- procedure to plant a notional "exit when false" at the end of any
   -- loop that does not have an exit statement or an iteration scheme.
   procedure ModelDefaultExit
   --# global in     Dictionary.Dict;
   --#        in out Graph.Table;
   --#        in out Statistics.TableUsage;
   --#        in out StmtStack.S;
   --#        in out VCGHeap;
   --# derives Graph.Table,
   --#         Statistics.TableUsage,
   --#         StmtStack.S,
   --#         VCGHeap               from *,
   --#                                    Dictionary.Dict,
   --#                                    Graph.Table,
   --#                                    StmtStack.S,
   --#                                    VCGHeap;
   is
      DAGRoot                           : Cells.Cell;
      FalseBranchLabel, TrueBranchLabel : Labels.Label;
      R                                 : StmtStack.StmtRecord;
      LoopTail, Switchnode              : Graph.Matrix_Index;
   begin -- ModelDefaultExit
         -- create False exit expression
      CreateNamedConstCell (DAGRoot, VCGHeap, Dictionary.GetFalse);
      -- build switch
      CreateSwitch (DAGRoot, FalseBranchLabel, TrueBranchLabel);
      Switchnode := StmtStack.Top.StmtNmbr;
      StmtStack.Pop;                         -- pop last statement in loop body,
      LoopTail := StmtStack.Top.StmtNmbr;
      Graph.Create_Coeff (Heap => VCGHeap,
                          I    => Switchnode,
                          J    => LoopTail,
                          K    => TrueBranchLabel);
      -- push False branch;
      Graph.Inc_Nmbr_Of_Stmts;
      Graph.Create_Coeff (Heap => VCGHeap,
                          I    => Switchnode,
                          J    => Graph.Get_Nmbr_Of_Stmts,
                          K    => FalseBranchLabel);
      R := StmtStack.StmtRecord'(Graph.Get_Nmbr_Of_Stmts, StmtStack.Elementary);
      StmtStack.Push (R);
   end ModelDefaultExit;

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

   procedure CloseIfStmt
   --# global in out Graph.Table;
   --#        in out Statistics.TableUsage;
   --#        in out StmtStack.S;
   --#        in out VCGHeap;
   --# derives Graph.Table,
   --#         VCGHeap               from Graph.Table,
   --#                                    StmtStack.S,
   --#                                    VCGHeap &
   --#         Statistics.TableUsage from *,
   --#                                    VCGHeap &
   --#         StmtStack.S           from *;
   is
      NullStmtLabel              : Labels.Label;
      ElsePartEndPoint, JoinNode : Graph.Matrix_Index;
   begin
      -- Here, the StmtStack is expected to have two entries
      -- at the top.
      --  The top-most entry represents the tail of the DAG for the final "else" part
      --  The next entry represents the node where the alternatives "join"
      --
      -- So...take a note of the statement numbers of these two entries, and
      -- pop them off:
      ElsePartEndPoint := StmtStack.Top.StmtNmbr;
      StmtStack.Pop;

      JoinNode := StmtStack.Top.StmtNmbr;    -- final node of if_statement;
      StmtStack.Pop;

      -- and then create a null arc from the end of the "else" part to the Join node
      CreateUnitLabel (NullStmtLabel, VCGHeap);
      Graph.Create_Coeff (Heap => VCGHeap,
                          I    => ElsePartEndPoint,
                          J    => JoinNode,
                          K    => NullStmtLabel);
      Advance (JoinNode);
   end CloseIfStmt;

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

   procedure CloseForStmtEnclosingIf
   --# global in out Graph.Table;
   --#        in out Statistics.TableUsage;
   --#        in out StmtStack.S;
   --#        in out VCGHeap;
   --# derives Graph.Table,
   --#         Statistics.TableUsage,
   --#         VCGHeap               from *,
   --#                                    Graph.Table,
   --#                                    StmtStack.S,
   --#                                    VCGHeap &
   --#         StmtStack.S           from *;
   is
      NullStmtLabel                                    : Labels.Label;
      NullStmtLabel2                                   : Labels.Label;
      ThenBranchEndPoint, ElseBranchEndPoint, JoinNode : Graph.Matrix_Index;
   begin
      -- Here, the StmtStack is expected to have three entries
      -- at the top.
      --  The top-most entry represents the tail of the DAG for the "then" part
      --    (the path that _does_ enter the loop)
      --  The next entry represents the tail of the DAG for the "else" part
      --    (the path that _doesn't_ enter the loop at all owing to a null range)
      --  The next entry represents the node where the these alternative "join"
      --
      -- So...take a note of the statement numbers of these three entries, and
      -- pop them off...
      ThenBranchEndPoint := StmtStack.Top.StmtNmbr;
      StmtStack.Pop;

      ElseBranchEndPoint := StmtStack.Top.StmtNmbr;
      StmtStack.Pop;

      JoinNode := StmtStack.Top.StmtNmbr;    -- final node of if_statement;
      StmtStack.Pop;

      -- ...then link both the ThenBranch and the ElseBranch to JoinNode
      CreateUnitLabel (NullStmtLabel, VCGHeap);
      CreateUnitLabel (NullStmtLabel2, VCGHeap);

      Graph.Create_Coeff (Heap => VCGHeap,
                          I    => ThenBranchEndPoint,
                          J    => JoinNode,
                          K    => NullStmtLabel);
      Graph.Create_Coeff (Heap => VCGHeap,
                          I    => ElseBranchEndPoint,
                          J    => JoinNode,
                          K    => NullStmtLabel2);

      Advance (JoinNode);
   end CloseForStmtEnclosingIf;

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

   procedure CombineCases
   --# global in out Graph.Table;
   --#        in out Statistics.TableUsage;
   --#        in out StmtStack.S;
   --#        in out VCGHeap;
   --# derives Graph.Table,
   --#         VCGHeap               from Graph.Table,
   --#                                    StmtStack.S,
   --#                                    VCGHeap &
   --#         Statistics.TableUsage from *,
   --#                                    VCGHeap &
   --#         StmtStack.S           from *;
   is
      UnitLabel : Labels.Label;
      R, S      : StmtStack.StmtRecord;
   begin
      R := StmtStack.Top;                 -- existing alternative branch, to be closed;
      StmtStack.Pop;                      -- remove record of alternative branch;
      StmtStack.Pop;                      -- remove record of fanout node;
      S := StmtStack.Top;                 -- top record holds tail of case_statement;
      StmtStack.Pop;
      CreateUnitLabel (UnitLabel, VCGHeap);
      Graph.Create_Coeff (Heap => VCGHeap,
                          I    => R.StmtNmbr,
                          J    => S.StmtNmbr,
                          K    => UnitLabel);
      Advance (S.StmtNmbr);
   end CombineCases;

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

   procedure CloseLoop
   --# global in out Graph.Table;
   --#        in out Statistics.TableUsage;
   --#        in out StmtStack.S;
   --#        in out VCGHeap;
   --# derives Graph.Table,
   --#         VCGHeap               from Graph.Table,
   --#                                    StmtStack.S,
   --#                                    VCGHeap &
   --#         Statistics.TableUsage from *,
   --#                                    VCGHeap &
   --#         StmtStack.S           from *;
   is
      BodyTail, LoopHead, LoopTail : Graph.Matrix_Index;
      NullStmtLabel                : Labels.Label;
   begin
      BodyTail := StmtStack.Top.StmtNmbr;
      StmtStack.Pop;                           -- pop last statement of loop body;
      LoopTail := StmtStack.Top.StmtNmbr;
      StmtStack.Pop;                           -- pop record of loop tail;
      LoopHead := StmtStack.Top.StmtNmbr;
      CreateUnitLabel (NullStmtLabel, VCGHeap);
      Graph.Create_Coeff (Heap => VCGHeap,
                          I    => BodyTail,
                          J    => LoopHead,
                          K    => NullStmtLabel);
      Advance (LoopTail);
   end CloseLoop;

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

   procedure ModelDelayStmt
   --# global in     CommandLineData.Content;
   --#        in     DoAssumeLocalRvalues;
   --#        in     LineNmbr;
   --#        in     LoopStack;
   --#        in     LScope;
   --#        in     Node;
   --#        in     Scope;
   --#        in     STree.Table;
   --#        in out CheckStack;
   --#        in out ContainsReals;
   --#        in out Dictionary.Dict;
   --#        in out ErrorHandler.Error_Context;
   --#        in out FlowHeap;
   --#        in out Graph.Table;
   --#        in out KindOfStackedCheck;
   --#        in out LexTokenManager.State;
   --#        in out ShortCircuitStack;
   --#        in out SPARK_IO.File_Sys;
   --#        in out Statistics.TableUsage;
   --#        in out StmtStack.S;
   --#        in out VCGFailure;
   --#        in out VCGHeap;
   --# derives CheckStack,
   --#         ContainsReals,
   --#         Dictionary.Dict,
   --#         FlowHeap,
   --#         Graph.Table,
   --#         KindOfStackedCheck,
   --#         LexTokenManager.State,
   --#         ShortCircuitStack,
   --#         Statistics.TableUsage,
   --#         StmtStack.S,
   --#         VCGFailure,
   --#         VCGHeap                    from *,
   --#                                         CheckStack,
   --#                                         CommandLineData.Content,
   --#                                         Dictionary.Dict,
   --#                                         DoAssumeLocalRvalues,
   --#                                         FlowHeap,
   --#                                         Graph.Table,
   --#                                         KindOfStackedCheck,
   --#                                         LexTokenManager.State,
   --#                                         LineNmbr,
   --#                                         LoopStack,
   --#                                         LScope,
   --#                                         Node,
   --#                                         Scope,
   --#                                         ShortCircuitStack,
   --#                                         StmtStack.S,
   --#                                         STree.Table,
   --#                                         VCGHeap &
   --#         ErrorHandler.Error_Context,
   --#         SPARK_IO.File_Sys          from CheckStack,
   --#                                         CommandLineData.Content,
   --#                                         Dictionary.Dict,
   --#                                         DoAssumeLocalRvalues,
   --#                                         ErrorHandler.Error_Context,
   --#                                         FlowHeap,
   --#                                         Graph.Table,
   --#                                         KindOfStackedCheck,
   --#                                         LexTokenManager.State,
   --#                                         LineNmbr,
   --#                                         LoopStack,
   --#                                         LScope,
   --#                                         Node,
   --#                                         Scope,
   --#                                         ShortCircuitStack,
   --#                                         SPARK_IO.File_Sys,
   --#                                         StmtStack.S,
   --#                                         STree.Table,
   --#                                         VCGHeap;
   is
      DAGRoot  : Cells.Cell;
      ExpnNode : STree.SyntaxNode;
   begin
      -- The delay statement itself is modelled like the null statement.
      ModelNullStmt (VCGHeap);
      ExpnNode := STree.Next_Sibling (Current_Node => STree.Child_Node (Current_Node => Node));

      -- Build expn DAG is called just to generate VCs for the delay expression.
      -- The Examiner will detect that assignment to DAGRoot is ineffective.
      --# accept F, 10, DAGRoot, "DAGRoot not used here" &
      --#        F, 33, DAGRoot, "DAGRoot not used here";
      BuildExpnDAG
        (StartNode          => ExpnNode,
         ExpnScope          => LScope,
         Scope              => Scope,
         LineNmbr           => LineNmbr,
         DoRtc              => True,
         AssumeRvalues      => DoAssumeLocalRvalues,
         LoopStack          => LoopStack,
         FlowHeap           => FlowHeap,
         VCGHeap            => VCGHeap,
         ContainsReals      => ContainsReals,
         VCGFailure         => VCGFailure,
         ShortCircuitStack  => ShortCircuitStack,
         CheckStack         => CheckStack,
         KindOfStackedCheck => KindOfStackedCheck,
         DAGRoot            => DAGRoot);

      UnStackRtcs (LineNmbr, VCGHeap, CheckStack, KindOfStackedCheck);
   end ModelDelayStmt; -- Expect flow error for DAGRoot unused

   ----------------------------------------------------------------------
   --                        For Loops
   ----------------------------------------------------------------------

   function RangeMayBeNull (RangeNode : STree.SyntaxNode) return Boolean
   --# global in Dictionary.Dict;
   --#        in STree.Table;
   is
      Result                       : Boolean;
      TypeSymbolPlantedAtRangeNode : Dictionary.Symbol;
   begin -- RangeMayBeNull
      Result := False;
      if (RangeNode /= STree.NullNode) then
         -- it is possible for the range to be null
         if STree.Syntax_Node_Type (Node => STree.Child_Node (Current_Node => RangeNode)) = SP_Symbols.simple_expression then
            -- we have an explicit range of
            --form lo .. hi and hi may be <
            --lo
            Result := True;

         else
            -- Otherwise range may be an 'range attribute which can only be empty if type is string (because
            -- the actual parameter might be the string literal "".
            -- We obtained type of the range constraint planted by the wellformation checker
            TypeSymbolPlantedAtRangeNode :=
              STree.NodeSymbol
              (STree.Next_Sibling
                 (Current_Node => STree.Child_Node (Current_Node => STree.Child_Node (Current_Node => RangeNode))));
            -- If the planted type is a special constraint type, indicating that the attribute is of an
            -- unconstrained array object then we check to see if the asociated parameter is a string.
            -- The loop may be empty if and only if that condition holds.
            if Dictionary.IsParameterConstraint (TypeSymbolPlantedAtRangeNode) then
               Result :=
                 Dictionary.IsPredefinedStringType
                 (Dictionary.GetType (Dictionary.GetParameterAssociatedWithParameterConstraint (TypeSymbolPlantedAtRangeNode)));
            else
               -- an ordinary index type has been planted and that can't be empty
               Result := False;
            end if;
         end if;
      end if;
      return Result;
   end RangeMayBeNull;

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

   procedure StartForStmtModel (Node, LoopNode : in STree.SyntaxNode)
   --# global in     CommandLineData.Content;
   --#        in     DoAssumeLocalRvalues;
   --#        in     ImportConstraints;
   --#        in     LineNmbr;
   --#        in     LoopStack;
   --#        in     LScope;
   --#        in     PreConstraints;
   --#        in     Scope;
   --#        in     STree.Table;
   --#        in out CheckStack;
   --#        in out ContainsReals;
   --#        in out Dictionary.Dict;
   --#        in out ErrorHandler.Error_Context;
   --#        in out FlowHeap;
   --#        in out Graph.Table;
   --#        in out KindOfStackedCheck;
   --#        in out LexTokenManager.State;
   --#        in out ShortCircuitStack;
   --#        in out SPARK_IO.File_Sys;
   --#        in out Statistics.TableUsage;
   --#        in out StmtStack.S;
   --#        in out VCGFailure;
   --#        in out VCGHeap;
   --# derives CheckStack,
   --#         ContainsReals,
   --#         Dictionary.Dict,
   --#         FlowHeap,
   --#         Graph.Table,
   --#         KindOfStackedCheck,
   --#         LexTokenManager.State,
   --#         ShortCircuitStack,
   --#         Statistics.TableUsage,
   --#         StmtStack.S,
   --#         VCGFailure,
   --#         VCGHeap                    from *,
   --#                                         CheckStack,
   --#                                         CommandLineData.Content,
   --#                                         Dictionary.Dict,
   --#                                         DoAssumeLocalRvalues,
   --#                                         FlowHeap,
   --#                                         Graph.Table,
   --#                                         ImportConstraints,
   --#                                         KindOfStackedCheck,
   --#                                         LexTokenManager.State,
   --#                                         LineNmbr,
   --#                                         LoopNode,
   --#                                         LoopStack,
   --#                                         LScope,
   --#                                         Node,
   --#                                         PreConstraints,
   --#                                         Scope,
   --#                                         ShortCircuitStack,
   --#                                         StmtStack.S,
   --#                                         STree.Table,
   --#                                         VCGHeap &
   --#         ErrorHandler.Error_Context,
   --#         SPARK_IO.File_Sys          from CheckStack,
   --#                                         CommandLineData.Content,
   --#                                         Dictionary.Dict,
   --#                                         DoAssumeLocalRvalues,
   --#                                         ErrorHandler.Error_Context,
   --#                                         FlowHeap,
   --#                                         Graph.Table,
   --#                                         ImportConstraints,
   --#                                         KindOfStackedCheck,
   --#                                         LexTokenManager.State,
   --#                                         LineNmbr,
   --#                                         LoopNode,
   --#                                         LoopStack,
   --#                                         LScope,
   --#                                         Node,
   --#                                         PreConstraints,
   --#                                         Scope,
   --#                                         ShortCircuitStack,
   --#                                         SPARK_IO.File_Sys,
   --#                                         StmtStack.S,
   --#                                         STree.Table,
   --#                                         VCGHeap;
   is
      ControlVarNode, DirectionNode, TypeNode, ArangeNode : STree.SyntaxNode;

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

      -- Called for all FOR loops.  Walks range boundary expression
      -- and assigns it to ExitBound local variable associated with current loop.  Where the
      -- range boundary expression contains variables, these are store in special "on_entry"
      -- copies and these copies substitted i nthe expression to "freeze" it.
      procedure AssignLoopBoundsToExitVariable (RangeNode : in STree.SyntaxNode)
      --# global in     CommandLineData.Content;
      --#        in     LineNmbr;
      --#        in     LoopStack;
      --#        in     LScope;
      --#        in     Scope;
      --#        in     STree.Table;
      --#        in out CheckStack;
      --#        in out ContainsReals;
      --#        in out Dictionary.Dict;
      --#        in out ErrorHandler.Error_Context;
      --#        in out FlowHeap;
      --#        in out Graph.Table;
      --#        in out KindOfStackedCheck;
      --#        in out LexTokenManager.State;
      --#        in out ShortCircuitStack;
      --#        in out SPARK_IO.File_Sys;
      --#        in out Statistics.TableUsage;
      --#        in out StmtStack.S;
      --#        in out VCGFailure;
      --#        in out VCGHeap;
      --# derives CheckStack,
      --#         ContainsReals,
      --#         Dictionary.Dict,
      --#         FlowHeap,
      --#         Graph.Table,
      --#         KindOfStackedCheck,
      --#         LexTokenManager.State,
      --#         ShortCircuitStack,
      --#         Statistics.TableUsage,
      --#         StmtStack.S,
      --#         VCGFailure,
      --#         VCGHeap                    from *,
      --#                                         CheckStack,
      --#                                         CommandLineData.Content,
      --#                                         Dictionary.Dict,
      --#                                         FlowHeap,
      --#                                         Graph.Table,
      --#                                         KindOfStackedCheck,
      --#                                         LexTokenManager.State,
      --#                                         LineNmbr,
      --#                                         LoopStack,
      --#                                         LScope,
      --#                                         RangeNode,
      --#                                         Scope,
      --#                                         ShortCircuitStack,
      --#                                         StmtStack.S,
      --#                                         STree.Table,
      --#                                         VCGHeap &
      --#         ErrorHandler.Error_Context,
      --#         SPARK_IO.File_Sys          from CheckStack,
      --#                                         CommandLineData.Content,
      --#                                         Dictionary.Dict,
      --#                                         ErrorHandler.Error_Context,
      --#                                         FlowHeap,
      --#                                         Graph.Table,
      --#                                         KindOfStackedCheck,
      --#                                         LexTokenManager.State,
      --#                                         LineNmbr,
      --#                                         LoopStack,
      --#                                         LScope,
      --#                                         RangeNode,
      --#                                         Scope,
      --#                                         ShortCircuitStack,
      --#                                         SPARK_IO.File_Sys,
      --#                                         StmtStack.S,
      --#                                         STree.Table,
      --#                                         VCGHeap;
      is
         ExitExpnDAG, CopyExitExpnDAG : Cells.Cell;

         procedure BuildExitExpn (DAGRoot : out Cells.Cell)
         --# global in     CommandLineData.Content;
         --#        in     LineNmbr;
         --#        in     LoopStack;
         --#        in     LScope;
         --#        in     RangeNode;
         --#        in     Scope;
         --#        in     STree.Table;
         --#        in out CheckStack;
         --#        in out ContainsReals;
         --#        in out Dictionary.Dict;
         --#        in out ErrorHandler.Error_Context;
         --#        in out FlowHeap;
         --#        in out Graph.Table;
         --#        in out KindOfStackedCheck;
         --#        in out LexTokenManager.State;
         --#        in out ShortCircuitStack;
         --#        in out SPARK_IO.File_Sys;
         --#        in out Statistics.TableUsage;
         --#        in out StmtStack.S;
         --#        in out VCGFailure;
         --#        in out VCGHeap;
         --# derives CheckStack,
         --#         ContainsReals,
         --#         Dictionary.Dict,
         --#         FlowHeap,
         --#         Graph.Table,
         --#         KindOfStackedCheck,
         --#         LexTokenManager.State,
         --#         ShortCircuitStack,
         --#         Statistics.TableUsage,
         --#         StmtStack.S,
         --#         VCGFailure,
         --#         VCGHeap                    from *,
         --#                                         CheckStack,
         --#                                         CommandLineData.Content,
         --#                                         Dictionary.Dict,
         --#                                         FlowHeap,
         --#                                         Graph.Table,
         --#                                         KindOfStackedCheck,
         --#                                         LexTokenManager.State,
         --#                                         LineNmbr,
         --#                                         LoopStack,
         --#                                         LScope,
         --#                                         RangeNode,
         --#                                         Scope,
         --#                                         ShortCircuitStack,
         --#                                         StmtStack.S,
         --#                                         STree.Table,
         --#                                         VCGHeap &
         --#         DAGRoot                    from CheckStack,
         --#                                         CommandLineData.Content,
         --#                                         Dictionary.Dict,
         --#                                         FlowHeap,
         --#                                         Graph.Table,
         --#                                         KindOfStackedCheck,
         --#                                         LexTokenManager.State,
         --#                                         LineNmbr,
         --#                                         LoopStack,
         --#                                         LScope,
         --#                                         RangeNode,
         --#                                         Scope,
         --#                                         ShortCircuitStack,
         --#                                         StmtStack.S,
         --#                                         STree.Table,
         --#                                         VCGHeap &
         --#         ErrorHandler.Error_Context,
         --#         SPARK_IO.File_Sys          from CheckStack,
         --#                                         CommandLineData.Content,
         --#                                         Dictionary.Dict,
         --#                                         ErrorHandler.Error_Context,
         --#                                         FlowHeap,
         --#                                         Graph.Table,
         --#                                         KindOfStackedCheck,
         --#                                         LexTokenManager.State,
         --#                                         LineNmbr,
         --#                                         LoopStack,
         --#                                         LScope,
         --#                                         RangeNode,
         --#                                         Scope,
         --#                                         ShortCircuitStack,
         --#                                         SPARK_IO.File_Sys,
         --#                                         StmtStack.S,
         --#                                         STree.Table,
         --#                                         VCGHeap;
         is
            ExitValueRoot          : Cells.Cell;
            LocalNode              : STree.SyntaxNode;
            TypeMarkCell, LASTCell : Cells.Cell;

         begin -- BuildExitExpn

            -- Handles ranges in the form of:
            -- (1) A type mark with no range constraint
            -- (2) A range in the form L .. R;
            -- (3) A range in the form of an attribute (e.g. for I in Index range A'Range)

            -- (1) ---------------------------------------------------------
            if RangeNode = STree.NullNode then
               -- statement is of form "for ControlVar in [reverse] ControlVarRange"
               CreateFixedVarCell
                 (TypeMarkCell,
                  VCGHeap,
                  Dictionary.GetType (LoopContext.CurrentLoopParameterSym (LoopStack, VCGHeap)));
               CreateCellKind (LASTCell, VCGHeap, Cell_Storage.Attrib_Value);
               if LoopContext.CurrentLoopMovesInReverse (LoopStack, VCGHeap) then
                  Cells.Set_Lex_Str (VCGHeap, LASTCell, LexTokenManager.First_Token);
               else
                  Cells.Set_Lex_Str (VCGHeap, LASTCell, LexTokenManager.Last_Token);
               end if;
               CreateOpCell (ExitValueRoot, VCGHeap, SP_Symbols.apostrophe);
               SetLeftArgument (ExitValueRoot, TypeMarkCell, VCGHeap);
               SetRightArgument (ExitValueRoot, LASTCell, VCGHeap);
            else
               LocalNode := STree.Child_Node (Current_Node => RangeNode);
               -- (2) ------------------------------------------------------------
               if STree.Syntax_Node_Type (Node => LocalNode) = SP_Symbols.simple_expression then
                  -- exit condition is given in terms of an expression;
                  if not LoopContext.CurrentLoopMovesInReverse (LoopStack, VCGHeap) then
                     -- move to RH side of L .. R
                     LocalNode := STree.Next_Sibling (Current_Node => LocalNode);
                  end if;

                  -- Do not generate checks
                  BuildExpnDAG
                    (StartNode          => LocalNode,
                     ExpnScope          => LScope,
                     Scope              => Scope,
                     LineNmbr           => LineNmbr,
                     DoRtc              => False,
                     AssumeRvalues      => False,
                     LoopStack          => LoopStack,
                     FlowHeap           => FlowHeap,
                     VCGHeap            => VCGHeap,
                     ContainsReals      => ContainsReals,
                     VCGFailure         => VCGFailure,
                     ShortCircuitStack  => ShortCircuitStack,
                     CheckStack         => CheckStack,
                     KindOfStackedCheck => KindOfStackedCheck,
                     DAGRoot            => ExitValueRoot);
               else
                  -- (3) ----------------------------------------------------------
                  -- exit condition is given in terms of an attribute;

                  -- This call to BuildExpnDAG will not create any checks.
                  BuildExpnDAG
                    (StartNode          => LocalNode,
                     ExpnScope          => LScope,
                     Scope              => Scope,
                     LineNmbr           => LineNmbr,
                     DoRtc              => False,
                     AssumeRvalues      => False,
                     LoopStack          => LoopStack,
                     FlowHeap           => FlowHeap,
                     VCGHeap            => VCGHeap,
                     ContainsReals      => ContainsReals,
                     VCGFailure         => VCGFailure,
                     ShortCircuitStack  => ShortCircuitStack,
                     CheckStack         => CheckStack,
                     KindOfStackedCheck => KindOfStackedCheck,
                     DAGRoot            => ExitValueRoot);

                  if LoopContext.CurrentLoopMovesInReverse (LoopStack, VCGHeap) then
                     ExitValueRoot := LeftPtr (VCGHeap, ExitValueRoot);
                  else
                     ExitValueRoot := RightPtr (VCGHeap, ExitValueRoot);
                  end if;
               end if;
            end if;
            DAGRoot := ExitValueRoot;
         end BuildExitExpn;

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

         procedure BuildAssignment (Destination, Source : in Cells.Cell)
         --# global in out Graph.Table;
         --#        in out Statistics.TableUsage;
         --#        in out StmtStack.S;
         --#        in out VCGHeap;
         --# derives Graph.Table,
         --#         StmtStack.S,
         --#         VCGHeap               from Destination,
         --#                                    Graph.Table,
         --#                                    Source,
         --#                                    StmtStack.S,
         --#                                    VCGHeap &
         --#         Statistics.TableUsage from *,
         --#                                    Destination,
         --#                                    Source,
         --#                                    VCGHeap;
         is
            StmtCell, ModList : Cells.Cell;
            StmtLabel         : Labels.Label;

         begin -- BuildAssignment
            PrepareLabel (VCGHeap, StmtLabel, StmtCell);
            Clists.CreateList (VCGHeap, ModList);
            Clists.AppendCell (VCGHeap, Destination, ModList);
            SetRightArgument (Destination, Source, VCGHeap);
            SetAuxPtr (StmtCell, ModList, VCGHeap);
            Chain (StmtLabel, VCGHeap);
         end BuildAssignment;

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

         procedure FreezeExitExpn
         --# global in     ExitExpnDAG;
         --#        in     LoopStack;
         --#        in out Dictionary.Dict;
         --#        in out Graph.Table;
         --#        in out Statistics.TableUsage;
         --#        in out StmtStack.S;
         --#        in out VCGHeap;
         --# derives Dictionary.Dict,
         --#         Graph.Table,
         --#         Statistics.TableUsage,
         --#         StmtStack.S,
         --#         VCGHeap               from *,
         --#                                    Dictionary.Dict,
         --#                                    ExitExpnDAG,
         --#                                    Graph.Table,
         --#                                    LoopStack,
         --#                                    StmtStack.S,
         --#                                    VCGHeap;
         is
            P               : Cells.Cell;
            S               : CStacks.Stack;
            VarSym          : Dictionary.Symbol;
            LoopEntryVarSym : Dictionary.Symbol;

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

            procedure SaveEntryValue (TheVariable, TheLoopEntryVariable : in Dictionary.Symbol)
            --# global in out Graph.Table;
            --#        in out Statistics.TableUsage;
            --#        in out StmtStack.S;
            --#        in out VCGHeap;
            --# derives Graph.Table,
            --#         StmtStack.S,
            --#         VCGHeap               from Graph.Table,
            --#                                    StmtStack.S,
            --#                                    TheLoopEntryVariable,
            --#                                    TheVariable,
            --#                                    VCGHeap &
            --#         Statistics.TableUsage from *,
            --#                                    TheLoopEntryVariable,
            --#                                    TheVariable,
            --#                                    VCGHeap;
            is
               Source, Dest : Cells.Cell;

            begin -- SaveEntryValue
               CreateModifiedCell (Dest, VCGHeap, TheLoopEntryVariable);
               CreateReferenceCell (Source, VCGHeap, TheVariable);
               BuildAssignment (Dest, Source);
            end SaveEntryValue;

         begin -- FreezeExitExpn;

            -- Traverse the loop exit expression.  For each variable found, create
            -- or get a special OnLoopEntryVariable.  Also, build an assignment from
            -- the original value of the variable to its special OnEntry equivalent.

            -- DAG traversal algorithm of D.E. Knuth, Fundamental
            -- Algorithms, p.317;
            CStacks.CreateStack (S);
            P := ExitExpnDAG;
            loop
               loop
                  exit when Cells.Is_Null_Cell (P);
                  CStacks.Push (VCGHeap, P, S);
                  if Is_Leaf (Node     => P,
                              VCG_Heap => VCGHeap) then
                     P := Cells.Null_Cell;
                  else
                     P := LeftPtr (VCGHeap, P);
                  end if;
               end loop;
               exit when CStacks.IsEmpty (S);
               P := CStacks.Top (VCGHeap, S);
               CStacks.Pop (VCGHeap, S);
               if Is_Leaf (Node     => P,
                           VCG_Heap => VCGHeap) then
                  if Cells.Get_Kind (VCGHeap, P) = Cell_Storage.Reference then
                     VarSym := Cells.Get_Symbol_Value (VCGHeap, P);
                     if Dictionary.Is_Variable (VarSym) then
                        -- We create a special variable in which to store the value
                        -- on entry into the loop and substitute this new var into
                        -- the exit expression DAG we are walking here
                        Dictionary.IdempotentCreateLoopOnEntryVariable
                          (OriginalVariable => VarSym,
                           TheLoop          => LoopContext.CurrentLoopSym (LoopStack, VCGHeap),
                           OnEntryVariable  => LoopEntryVarSym);
                        SaveEntryValue (VarSym, LoopEntryVarSym);
                        Cells.Set_Symbol_Value (VCGHeap, P, LoopEntryVarSym);
                     end if; -- IsVariable
                  end if; -- is RefCell
                  P := Cells.Null_Cell;
               else
                  P := RightPtr (VCGHeap, P);
               end if;
            end loop;
         end FreezeExitExpn;

      begin -- AssignLoopBoundsToExitVariable
         BuildExitExpn (DAGRoot => ExitExpnDAG);

         -- for each variable X in the exit expression:
         --   (1) construct the assignment X_on_entry := X;
         --   (2) substitute X_on_entry for X in exit expression
         FreezeExitExpn;

         -- Force exit expn cell into Dictionary so we can recover it when building loop invariants
         -- First deep copy expression
         Structures.CopyStructure (VCGHeap, ExitExpnDAG, CopyExitExpnDAG);
         -- Then save in Dictionary. associated with loop
         Dictionary.SetLoopExitExpn (LoopContext.CurrentLoopSym (LoopStack, VCGHeap), Natural (CopyExitExpnDAG));

      end AssignLoopBoundsToExitVariable;

      procedure AssignLoopCounterEntryValue (RangeNode : in STree.SyntaxNode)
      --# global in     CommandLineData.Content;
      --#        in     LineNmbr;
      --#        in     LoopStack;
      --#        in     LScope;
      --#        in     Scope;
      --#        in     STree.Table;
      --#        in out CheckStack;
      --#        in out ContainsReals;
      --#        in out Dictionary.Dict;
      --#        in out ErrorHandler.Error_Context;
      --#        in out FlowHeap;
      --#        in out Graph.Table;
      --#        in out KindOfStackedCheck;
      --#        in out LexTokenManager.State;
      --#        in out ShortCircuitStack;
      --#        in out SPARK_IO.File_Sys;
      --#        in out Statistics.TableUsage;
      --#        in out StmtStack.S;
      --#        in out VCGFailure;
      --#        in out VCGHeap;
      --# derives CheckStack,
      --#         ContainsReals,
      --#         Dictionary.Dict,
      --#         FlowHeap,
      --#         Graph.Table,
      --#         KindOfStackedCheck,
      --#         LexTokenManager.State,
      --#         ShortCircuitStack,
      --#         Statistics.TableUsage,
      --#         StmtStack.S,
      --#         VCGFailure,
      --#         VCGHeap                    from *,
      --#                                         CheckStack,
      --#                                         CommandLineData.Content,
      --#                                         Dictionary.Dict,
      --#                                         FlowHeap,
      --#                                         Graph.Table,
      --#                                         KindOfStackedCheck,
      --#                                         LexTokenManager.State,
      --#                                         LineNmbr,
      --#                                         LoopStack,
      --#                                         LScope,
      --#                                         RangeNode,
      --#                                         Scope,
      --#                                         ShortCircuitStack,
      --#                                         StmtStack.S,
      --#                                         STree.Table,
      --#                                         VCGHeap &
      --#         ErrorHandler.Error_Context,
      --#         SPARK_IO.File_Sys          from CheckStack,
      --#                                         CommandLineData.Content,
      --#                                         Dictionary.Dict,
      --#                                         ErrorHandler.Error_Context,
      --#                                         FlowHeap,
      --#                                         Graph.Table,
      --#                                         KindOfStackedCheck,
      --#                                         LexTokenManager.State,
      --#                                         LineNmbr,
      --#                                         LoopStack,
      --#                                         LScope,
      --#                                         RangeNode,
      --#                                         Scope,
      --#                                         ShortCircuitStack,
      --#                                         SPARK_IO.File_Sys,
      --#                                         StmtStack.S,
      --#                                         STree.Table,
      --#                                         VCGHeap;
      is
         EntryExpnDAG, CopyEntryExpnDAG : Cells.Cell;

         procedure BuildEntryExpn (DAGRoot : out Cells.Cell)
         --# global in     CommandLineData.Content;
         --#        in     LineNmbr;
         --#        in     LoopStack;
         --#        in     LScope;
         --#        in     RangeNode;
         --#        in     Scope;
         --#        in     STree.Table;
         --#        in out CheckStack;
         --#        in out ContainsReals;
         --#        in out Dictionary.Dict;
         --#        in out ErrorHandler.Error_Context;
         --#        in out FlowHeap;
         --#        in out Graph.Table;
         --#        in out KindOfStackedCheck;
         --#        in out LexTokenManager.State;
         --#        in out ShortCircuitStack;
         --#        in out SPARK_IO.File_Sys;
         --#        in out Statistics.TableUsage;
         --#        in out StmtStack.S;
         --#        in out VCGFailure;
         --#        in out VCGHeap;
         --# derives CheckStack,
         --#         ContainsReals,
         --#         Dictionary.Dict,
         --#         FlowHeap,
         --#         Graph.Table,
         --#         KindOfStackedCheck,
         --#         LexTokenManager.State,
         --#         ShortCircuitStack,
         --#         Statistics.TableUsage,
         --#         StmtStack.S,
         --#         VCGFailure,
         --#         VCGHeap                    from *,
         --#                                         CheckStack,
         --#                                         CommandLineData.Content,
         --#                                         Dictionary.Dict,
         --#                                         FlowHeap,
         --#                                         Graph.Table,
         --#                                         KindOfStackedCheck,
         --#                                         LexTokenManager.State,
         --#                                         LineNmbr,
         --#                                         LoopStack,
         --#                                         LScope,
         --#                                         RangeNode,
         --#                                         Scope,
         --#                                         ShortCircuitStack,
         --#                                         StmtStack.S,
         --#                                         STree.Table,
         --#                                         VCGHeap &
         --#         DAGRoot                    from CheckStack,
         --#                                         CommandLineData.Content,
         --#                                         Dictionary.Dict,
         --#                                         FlowHeap,
         --#                                         Graph.Table,
         --#                                         KindOfStackedCheck,
         --#                                         LexTokenManager.State,
         --#                                         LineNmbr,
         --#                                         LoopStack,
         --#                                         LScope,
         --#                                         RangeNode,
         --#                                         Scope,
         --#                                         ShortCircuitStack,
         --#                                         StmtStack.S,
         --#                                         STree.Table,
         --#                                         VCGHeap &
         --#         ErrorHandler.Error_Context,
         --#         SPARK_IO.File_Sys          from CheckStack,
         --#                                         CommandLineData.Content,
         --#                                         Dictionary.Dict,
         --#                                         ErrorHandler.Error_Context,
         --#                                         FlowHeap,
         --#                                         Graph.Table,
         --#                                         KindOfStackedCheck,
         --#                                         LexTokenManager.State,
         --#                                         LineNmbr,
         --#                                         LoopStack,
         --#                                         LScope,
         --#                                         RangeNode,
         --#                                         Scope,
         --#                                         ShortCircuitStack,
         --#                                         SPARK_IO.File_Sys,
         --#                                         StmtStack.S,
         --#                                         STree.Table,
         --#                                         VCGHeap;
         is
            EntryValueRoot         : Cells.Cell;
            LocalNode              : STree.SyntaxNode;
            TypeMarkCell, LASTCell : Cells.Cell;

         begin -- BuildEntryExpn

            -- Handles ranges in the form of:
            -- (1) A type mark with no range constraint
            -- (2) A range in the form L .. R;
            -- (3) A range in the form of an attribute (e.g. for I in Index range A'Range)

            -- (1) ---------------------------------------------------------
            if RangeNode = STree.NullNode then
               -- statement is of form "for ControlVar in [reverse] ControlVarRange"
               CreateFixedVarCell
                 (TypeMarkCell,
                  VCGHeap,
                  Dictionary.GetType (LoopContext.CurrentLoopParameterSym (LoopStack, VCGHeap)));
               CreateCellKind (LASTCell, VCGHeap, Cell_Storage.Attrib_Value);
               if LoopContext.CurrentLoopMovesInReverse (LoopStack, VCGHeap) then
                  Cells.Set_Lex_Str (VCGHeap, LASTCell, LexTokenManager.Last_Token);
               else
                  Cells.Set_Lex_Str (VCGHeap, LASTCell, LexTokenManager.First_Token);
               end if;
               CreateOpCell (EntryValueRoot, VCGHeap, SP_Symbols.apostrophe);
               SetLeftArgument (EntryValueRoot, TypeMarkCell, VCGHeap);
               SetRightArgument (EntryValueRoot, LASTCell, VCGHeap);
            else
               LocalNode := STree.Child_Node (Current_Node => RangeNode);

               -- (2) ------------------------------------------------------------
               if STree.Syntax_Node_Type (Node => LocalNode) = SP_Symbols.simple_expression then
                  -- entry value is given in terms of a simple_expression
                  if LoopContext.CurrentLoopMovesInReverse (LoopStack, VCGHeap) then
                     -- move to RH side of L .. R
                     LocalNode := STree.Next_Sibling (Current_Node => LocalNode);
                  end if;

                  -- Do not generate checks
                  BuildExpnDAG
                    (StartNode          => LocalNode,
                     ExpnScope          => LScope,
                     Scope              => Scope,
                     LineNmbr           => LineNmbr,
                     DoRtc              => False,
                     AssumeRvalues      => False,
                     LoopStack          => LoopStack,
                     FlowHeap           => FlowHeap,
                     VCGHeap            => VCGHeap,
                     ContainsReals      => ContainsReals,
                     VCGFailure         => VCGFailure,
                     ShortCircuitStack  => ShortCircuitStack,
                     CheckStack         => CheckStack,
                     KindOfStackedCheck => KindOfStackedCheck,
                     DAGRoot            => EntryValueRoot);
               else
                  -- (3) ----------------------------------------------------------
                  -- entry value is given in terms of a 'Range attribute;

                  -- This call to BuildExpnDAG will not create any checks.
                  BuildExpnDAG
                    (StartNode          => LocalNode,
                     ExpnScope          => LScope,
                     Scope              => Scope,
                     LineNmbr           => LineNmbr,
                     DoRtc              => False,
                     AssumeRvalues      => False,
                     LoopStack          => LoopStack,
                     FlowHeap           => FlowHeap,
                     VCGHeap            => VCGHeap,
                     ContainsReals      => ContainsReals,
                     VCGFailure         => VCGFailure,
                     ShortCircuitStack  => ShortCircuitStack,
                     CheckStack         => CheckStack,
                     KindOfStackedCheck => KindOfStackedCheck,
                     DAGRoot            => EntryValueRoot);

                  -- EntryValueRoot now points at "double_dot" Cell containing the
                  -- DAG for L .. R.  For a normal "for" loop, the initial value
                  -- of the loop counter is L, which is in the LeftPtr cell from
                  -- EntryValueRoot.
                  --
                  -- For a "reverse for" loop, R is the initial value, so...
                  if LoopContext.CurrentLoopMovesInReverse (LoopStack, VCGHeap) then
                     EntryValueRoot := RightPtr (VCGHeap, EntryValueRoot);
                  else
                     EntryValueRoot := LeftPtr (VCGHeap, EntryValueRoot);
                  end if;
               end if;
            end if;
            DAGRoot := EntryValueRoot;
         end BuildEntryExpn;

      begin
         BuildEntryExpn (DAGRoot => EntryExpnDAG);

         -- Force entry expn cell into Dictionary so we can recover it when building loop invariants
         -- First deep copy expression
         Structures.CopyStructure (VCGHeap, EntryExpnDAG, CopyEntryExpnDAG);
         -- Then save in Dictionary. associated with loop
         Dictionary.SetLoopEntryExpn (LoopContext.CurrentLoopSym (LoopStack, VCGHeap), Natural (CopyEntryExpnDAG));
      end AssignLoopCounterEntryValue;

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

      procedure StartForStmtEnclosingIf
      --# global in     ArangeNode;
      --#        in     CommandLineData.Content;
      --#        in     DoAssumeLocalRvalues;
      --#        in     LineNmbr;
      --#        in     LoopStack;
      --#        in     LScope;
      --#        in     Scope;
      --#        in     STree.Table;
      --#        in     TypeNode;
      --#        in out CheckStack;
      --#        in out ContainsReals;
      --#        in out Dictionary.Dict;
      --#        in out ErrorHandler.Error_Context;
      --#        in out FlowHeap;
      --#        in out Graph.Table;
      --#        in out KindOfStackedCheck;
      --#        in out LexTokenManager.State;
      --#        in out ShortCircuitStack;
      --#        in out SPARK_IO.File_Sys;
      --#        in out Statistics.TableUsage;
      --#        in out StmtStack.S;
      --#        in out VCGFailure;
      --#        in out VCGHeap;
      --# derives CheckStack,
      --#         Graph.Table,
      --#         KindOfStackedCheck,
      --#         Statistics.TableUsage,
      --#         StmtStack.S,
      --#         VCGHeap                    from *,
      --#                                         ArangeNode,
      --#                                         CheckStack,
      --#                                         CommandLineData.Content,
      --#                                         Dictionary.Dict,
      --#                                         DoAssumeLocalRvalues,
      --#                                         FlowHeap,
      --#                                         Graph.Table,
      --#                                         KindOfStackedCheck,
      --#                                         LexTokenManager.State,
      --#                                         LineNmbr,
      --#                                         LoopStack,
      --#                                         LScope,
      --#                                         Scope,
      --#                                         ShortCircuitStack,
      --#                                         StmtStack.S,
      --#                                         STree.Table,
      --#                                         TypeNode,
      --#                                         VCGHeap &
      --#         ContainsReals,
      --#         Dictionary.Dict,
      --#         FlowHeap,
      --#         LexTokenManager.State,
      --#         ShortCircuitStack,
      --#         VCGFailure                 from *,
      --#                                         ArangeNode,
      --#                                         CheckStack,
      --#                                         CommandLineData.Content,
      --#                                         Dictionary.Dict,
      --#                                         DoAssumeLocalRvalues,
      --#                                         FlowHeap,
      --#                                         Graph.Table,
      --#                                         KindOfStackedCheck,
      --#                                         LexTokenManager.State,
      --#                                         LineNmbr,
      --#                                         LoopStack,
      --#                                         LScope,
      --#                                         Scope,
      --#                                         ShortCircuitStack,
      --#                                         StmtStack.S,
      --#                                         STree.Table,
      --#                                         VCGHeap &
      --#         ErrorHandler.Error_Context,
      --#         SPARK_IO.File_Sys          from ArangeNode,
      --#                                         CheckStack,
      --#                                         CommandLineData.Content,
      --#                                         Dictionary.Dict,
      --#                                         DoAssumeLocalRvalues,
      --#                                         ErrorHandler.Error_Context,
      --#                                         FlowHeap,
      --#                                         Graph.Table,
      --#                                         KindOfStackedCheck,
      --#                                         LexTokenManager.State,
      --#                                         LineNmbr,
      --#                                         LoopStack,
      --#                                         LScope,
      --#                                         Scope,
      --#                                         ShortCircuitStack,
      --#                                         SPARK_IO.File_Sys,
      --#                                         StmtStack.S,
      --#                                         STree.Table,
      --#                                         VCGHeap;
      is
         DAGRoot                           : Cells.Cell;
         FalseBranchLabel, TrueBranchLabel : Labels.Label;
         R                                 : StmtStack.StmtRecord;
         Predecessor                       : Graph.Matrix_Index;

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

         procedure CreateSwitchExpn
         --# global in     ArangeNode;
         --#        in     CommandLineData.Content;
         --#        in     DoAssumeLocalRvalues;
         --#        in     LineNmbr;
         --#        in     LoopStack;
         --#        in     LScope;
         --#        in     Scope;
         --#        in     STree.Table;
         --#        in     TypeNode;
         --#        in out CheckStack;
         --#        in out ContainsReals;
         --#        in out Dictionary.Dict;
         --#        in out ErrorHandler.Error_Context;
         --#        in out FlowHeap;
         --#        in out Graph.Table;
         --#        in out KindOfStackedCheck;
         --#        in out LexTokenManager.State;
         --#        in out ShortCircuitStack;
         --#        in out SPARK_IO.File_Sys;
         --#        in out Statistics.TableUsage;
         --#        in out StmtStack.S;
         --#        in out VCGFailure;
         --#        in out VCGHeap;
         --#           out DAGRoot;
         --# derives CheckStack,
         --#         Graph.Table,
         --#         KindOfStackedCheck,
         --#         Statistics.TableUsage,
         --#         StmtStack.S,
         --#         VCGHeap                    from *,
         --#                                         ArangeNode,
         --#                                         CheckStack,
         --#                                         CommandLineData.Content,
         --#                                         Dictionary.Dict,
         --#                                         DoAssumeLocalRvalues,
         --#                                         FlowHeap,
         --#                                         Graph.Table,
         --#                                         KindOfStackedCheck,
         --#                                         LexTokenManager.State,
         --#                                         LineNmbr,
         --#                                         LoopStack,
         --#                                         LScope,
         --#                                         Scope,
         --#                                         ShortCircuitStack,
         --#                                         StmtStack.S,
         --#                                         STree.Table,
         --#                                         TypeNode,
         --#                                         VCGHeap &
         --#         ContainsReals,
         --#         Dictionary.Dict,
         --#         FlowHeap,
         --#         LexTokenManager.State,
         --#         ShortCircuitStack,
         --#         VCGFailure                 from *,
         --#                                         ArangeNode,
         --#                                         CheckStack,
         --#                                         CommandLineData.Content,
         --#                                         Dictionary.Dict,
         --#                                         DoAssumeLocalRvalues,
         --#                                         FlowHeap,
         --#                                         Graph.Table,
         --#                                         KindOfStackedCheck,
         --#                                         LexTokenManager.State,
         --#                                         LineNmbr,
         --#                                         LoopStack,
         --#                                         LScope,
         --#                                         Scope,
         --#                                         ShortCircuitStack,
         --#                                         StmtStack.S,
         --#                                         STree.Table,
         --#                                         VCGHeap &
         --#         DAGRoot                    from ArangeNode,
         --#                                         CheckStack,
         --#                                         CommandLineData.Content,
         --#                                         Dictionary.Dict,
         --#                                         DoAssumeLocalRvalues,
         --#                                         FlowHeap,
         --#                                         Graph.Table,
         --#                                         KindOfStackedCheck,
         --#                                         LexTokenManager.State,
         --#                                         LineNmbr,
         --#                                         LoopStack,
         --#                                         LScope,
         --#                                         Scope,
         --#                                         ShortCircuitStack,
         --#                                         StmtStack.S,
         --#                                         STree.Table,
         --#                                         TypeNode,
         --#                                         VCGHeap &
         --#         ErrorHandler.Error_Context,
         --#         SPARK_IO.File_Sys          from ArangeNode,
         --#                                         CheckStack,
         --#                                         CommandLineData.Content,
         --#                                         Dictionary.Dict,
         --#                                         DoAssumeLocalRvalues,
         --#                                         ErrorHandler.Error_Context,
         --#                                         FlowHeap,
         --#                                         Graph.Table,
         --#                                         KindOfStackedCheck,
         --#                                         LexTokenManager.State,
         --#                                         LineNmbr,
         --#                                         LoopStack,
         --#                                         LScope,
         --#                                         Scope,
         --#                                         ShortCircuitStack,
         --#                                         SPARK_IO.File_Sys,
         --#                                         StmtStack.S,
         --#                                         STree.Table,
         --#                                         VCGHeap;
         is
            NotCell                                   : Cells.Cell;
            AttributeExpression, ExpnRoot1, ExpnRoot2 : Cells.Cell;
            LocalNode                                 : STree.SyntaxNode;
         begin
            LocalNode := STree.Child_Node (Current_Node => ArangeNode);
            -- model simple expression or attribute as appropriate
            if STree.Syntax_Node_Type (Node => LocalNode) = SP_Symbols.simple_expression then
               -- range is of form simpexp .. simpexp
               BuildExpnDAG
                 (StartNode          => LocalNode,
                  ExpnScope          => LScope,
                  Scope              => Scope,
                  LineNmbr           => LineNmbr,
                  DoRtc              => False,
                  AssumeRvalues      => DoAssumeLocalRvalues,
                  LoopStack          => LoopStack,
                  FlowHeap           => FlowHeap,
                  VCGHeap            => VCGHeap,
                  ContainsReals      => ContainsReals,
                  VCGFailure         => VCGFailure,
                  ShortCircuitStack  => ShortCircuitStack,
                  CheckStack         => CheckStack,
                  KindOfStackedCheck => KindOfStackedCheck,
                  DAGRoot            => ExpnRoot1);

               LocalNode := STree.Next_Sibling (Current_Node => LocalNode);
               BuildExpnDAG
                 (StartNode          => LocalNode,
                  ExpnScope          => LScope,
                  Scope              => Scope,
                  LineNmbr           => LineNmbr,
                  DoRtc              => False,
                  AssumeRvalues      => DoAssumeLocalRvalues,
                  LoopStack          => LoopStack,
                  FlowHeap           => FlowHeap,
                  VCGHeap            => VCGHeap,
                  ContainsReals      => ContainsReals,
                  VCGFailure         => VCGFailure,
                  ShortCircuitStack  => ShortCircuitStack,
                  CheckStack         => CheckStack,
                  KindOfStackedCheck => KindOfStackedCheck,
                  DAGRoot            => ExpnRoot2);

            else -- attribute case
               BuildExpnDAG
                 (StartNode          => LocalNode,
                  ExpnScope          => LScope,
                  Scope              => Scope,
                  LineNmbr           => LineNmbr,
                  DoRtc              => False,
                  AssumeRvalues      => DoAssumeLocalRvalues,
                  LoopStack          => LoopStack,
                  FlowHeap           => FlowHeap,
                  VCGHeap            => VCGHeap,
                  ContainsReals      => ContainsReals,
                  VCGFailure         => VCGFailure,
                  ShortCircuitStack  => ShortCircuitStack,
                  CheckStack         => CheckStack,
                  KindOfStackedCheck => KindOfStackedCheck,
                  DAGRoot            => AttributeExpression);

               Structures.CopyStructure (VCGHeap, LeftPtr (VCGHeap, AttributeExpression), ExpnRoot1);
               Structures.CopyStructure (VCGHeap, RightPtr (VCGHeap, AttributeExpression), ExpnRoot2);
            end if;

            if Dictionary.TypeIsBoolean (STree.NodeSymbol (TypeNode)) then
               -- special expression needed to avoid Boolean inequalities
               -- Boolean equivalent of lower <= upper is
               -- not Lower or upper
               CreateOpCell (DAGRoot, VCGHeap, SP_Symbols.RWor);
               CreateOpCell (NotCell, VCGHeap, SP_Symbols.RWnot);
               SetRightArgument (NotCell, ExpnRoot1, VCGHeap);
               SetLeftArgument (DAGRoot, NotCell, VCGHeap);
               SetRightArgument (DAGRoot, ExpnRoot2, VCGHeap);
            else -- proceed as before
               CreateOpCell (DAGRoot, VCGHeap, SP_Symbols.less_or_equal);

               SetLeftArgument (DAGRoot, ExpnRoot1, VCGHeap);
               SetRightArgument (DAGRoot, ExpnRoot2, VCGHeap);
            end if;
            UnStackRtcs (LineNmbr, VCGHeap, CheckStack, KindOfStackedCheck);
         end CreateSwitchExpn;

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

      begin -- StartForStmtEnclosingIf
         CreateSwitchExpn;
         CreateSwitch (DAGRoot, FalseBranchLabel, TrueBranchLabel);
         Predecessor := StmtStack.Top.StmtNmbr;

         -- push record holding nmbr of tail (exit) of if-statement;
         Graph.Inc_Nmbr_Of_Stmts;
         R := StmtStack.StmtRecord'(Graph.Get_Nmbr_Of_Stmts, StmtStack.IfStart);
         StmtStack.Push (R);

         -- push False branch;
         Graph.Inc_Nmbr_Of_Stmts;
         Graph.Create_Coeff (Heap => VCGHeap,
                             I    => Predecessor,
                             J    => Graph.Get_Nmbr_Of_Stmts,
                             K    => FalseBranchLabel);
         R.StmtNmbr := Graph.Get_Nmbr_Of_Stmts;
         R.Kind     := StmtStack.IfFalseBranch;
         StmtStack.Push (R);

         -- push True branch;
         Graph.Inc_Nmbr_Of_Stmts;
         Graph.Create_Coeff (Heap => VCGHeap,
                             I    => Predecessor,
                             J    => Graph.Get_Nmbr_Of_Stmts,
                             K    => TrueBranchLabel);
         R.StmtNmbr := Graph.Get_Nmbr_Of_Stmts;
         R.Kind     := StmtStack.IfTrueBranch;
         StmtStack.Push (R);
      end StartForStmtEnclosingIf;

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

      procedure CheckRangeBounds (TypeNode, RangeNode : in STree.SyntaxNode)
      --# global in     CommandLineData.Content;
      --#        in     DoAssumeLocalRvalues;
      --#        in     LineNmbr;
      --#        in     LoopStack;
      --#        in     LScope;
      --#        in     Scope;
      --#        in     STree.Table;
      --#        in out CheckStack;
      --#        in out ContainsReals;
      --#        in out Dictionary.Dict;
      --#        in out ErrorHandler.Error_Context;
      --#        in out FlowHeap;
      --#        in out Graph.Table;
      --#        in out KindOfStackedCheck;
      --#        in out LexTokenManager.State;
      --#        in out ShortCircuitStack;
      --#        in out SPARK_IO.File_Sys;
      --#        in out Statistics.TableUsage;
      --#        in out StmtStack.S;
      --#        in out VCGFailure;
      --#        in out VCGHeap;
      --# derives CheckStack,
      --#         ContainsReals,
      --#         Dictionary.Dict,
      --#         FlowHeap,
      --#         Graph.Table,
      --#         KindOfStackedCheck,
      --#         LexTokenManager.State,
      --#         ShortCircuitStack,
      --#         Statistics.TableUsage,
      --#         StmtStack.S,
      --#         VCGFailure,
      --#         VCGHeap                    from *,
      --#                                         CheckStack,
      --#                                         CommandLineData.Content,
      --#                                         Dictionary.Dict,
      --#                                         DoAssumeLocalRvalues,
      --#                                         FlowHeap,
      --#                                         Graph.Table,
      --#                                         KindOfStackedCheck,
      --#                                         LexTokenManager.State,
      --#                                         LineNmbr,
      --#                                         LoopStack,
      --#                                         LScope,
      --#                                         RangeNode,
      --#                                         Scope,
      --#                                         ShortCircuitStack,
      --#                                         StmtStack.S,
      --#                                         STree.Table,
      --#                                         TypeNode,
      --#                                         VCGHeap &
      --#         ErrorHandler.Error_Context,
      --#         SPARK_IO.File_Sys          from CheckStack,
      --#                                         CommandLineData.Content,
      --#                                         Dictionary.Dict,
      --#                                         DoAssumeLocalRvalues,
      --#                                         ErrorHandler.Error_Context,
      --#                                         FlowHeap,
      --#                                         Graph.Table,
      --#                                         KindOfStackedCheck,
      --#                                         LexTokenManager.State,
      --#                                         LineNmbr,
      --#                                         LoopStack,
      --#                                         LScope,
      --#                                         RangeNode,
      --#                                         Scope,
      --#                                         ShortCircuitStack,
      --#                                         SPARK_IO.File_Sys,
      --#                                         StmtStack.S,
      --#                                         STree.Table,
      --#                                         TypeNode,
      --#                                         VCGHeap;
      is
         BaseTypeSym, TypeSym      : Dictionary.Symbol;
         LocalNode                 : STree.SyntaxNode;
         LowerBound, RangeBoundDAG : Cells.Cell;

         procedure BuildImpliedSubtypeCheck (Type_Sym          : in Dictionary.Symbol;
                                             LowExpr, HighExpr : in Cells.Cell)
         --# global in     Dictionary.Dict;
         --#        in out CheckStack;
         --#        in out ShortCircuitStack;
         --#        in out Statistics.TableUsage;
         --#        in out VCGHeap;
         --# derives CheckStack,
         --#         ShortCircuitStack,
         --#         Statistics.TableUsage,
         --#         VCGHeap               from *,
         --#                                    CheckStack,
         --#                                    Dictionary.Dict,
         --#                                    HighExpr,
         --#                                    LowExpr,
         --#                                    ShortCircuitStack,
         --#                                    Type_Sym,
         --#                                    VCGHeap;
         is
            Lhs, Rhs, Implies1, Implies2, LessThan, ImpliedExpression1, ImpliedExpression2 : Cells.Cell;
         begin -- BuildImpliedSubtypeCheck
               -- build lhs of implies expression (lower <= upper)
            Structures.CopyStructure (VCGHeap, LowExpr, Lhs);
            Structures.CopyStructure (VCGHeap, HighExpr, Rhs);
            CreateOpCell (LessThan, VCGHeap, SP_Symbols.less_or_equal);
            SetLeftArgument (LessThan, Lhs, VCGHeap);
            SetRightArgument (LessThan, Rhs, VCGHeap);

            -- create X in T model for LowExpr
            Type_Constraint.Process_Discrete
              (The_Type       => Type_Sym,
               The_Expression => LowExpr,
               The_Constraint => ImpliedExpression1,
               VCG_Heap       => VCGHeap);

            -- and for HighExpr
            Type_Constraint.Process_Discrete
              (The_Type       => Type_Sym,
               The_Expression => HighExpr,
               The_Constraint => ImpliedExpression2,
               VCG_Heap       => VCGHeap);

            -- make --> operators
            CreateOpCell (Implies1, VCGHeap, SP_Symbols.implies);
            CreateOpCell (Implies2, VCGHeap, SP_Symbols.implies);

            -- assemble entire X <= Y -> X in T expressions
            SetLeftArgument (Implies1, LessThan, VCGHeap);
            SetRightArgument (Implies1, ImpliedExpression1, VCGHeap);

            SetLeftArgument (Implies2, LessThan, VCGHeap);
            SetRightArgument (Implies2, ImpliedExpression2, VCGHeap);

            -- plant checks
            PlantCheckStatement (Implies1, VCGHeap, ShortCircuitStack, CheckStack);
            PlantCheckStatement (Implies2, VCGHeap, ShortCircuitStack, CheckStack);
         end BuildImpliedSubtypeCheck;

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

      begin -- CheckRangeBounds
         if RangeNode /= STree.NullNode then -- something to do
            TypeSym := STree.NodeSymbol (TypeNode); -- recover from wff planting

            -- Guard generation of checks so that they are not generated for Booleans
            if not Dictionary.TypeIsBoolean (TypeSym) then
               -- something to do
               BaseTypeSym := Dictionary.GetRootType (TypeSym);
               -- note that if TypeSym is not a subtype then TypeSym = BaseTypeSym

               -- we either have simpex .. simpex or an attribute to deal with
               LocalNode := STree.Child_Node (Current_Node => RangeNode);
               if STree.Syntax_Node_Type (Node => LocalNode) = SP_Symbols.simple_expression then
                  -- range is of form simpexp .. simpexp
                  -- LocalNode points at LHS of range at this point
                  -- first check that bounds are in base type
                  BuildExpnDAG
                    (StartNode          => LocalNode,
                     ExpnScope          => LScope,
                     Scope              => Scope,
                     LineNmbr           => LineNmbr,
                     DoRtc              => True,
                     AssumeRvalues      => DoAssumeLocalRvalues,
                     LoopStack          => LoopStack,
                     FlowHeap           => FlowHeap,
                     VCGHeap            => VCGHeap,
                     ContainsReals      => ContainsReals,
                     VCGFailure         => VCGFailure,
                     ShortCircuitStack  => ShortCircuitStack,
                     CheckStack         => CheckStack,
                     KindOfStackedCheck => KindOfStackedCheck,
                     DAGRoot            => RangeBoundDAG);

                  CheckConstraintRunTimeError
                    (BaseTypeSym,
                     RangeBoundDAG,
                     Scope,
                     VCGHeap,
                     ShortCircuitStack,
                     CheckStack,
                     ContainsReals);
                  LowerBound := RangeBoundDAG;
                  -- now do RHS of range
                  LocalNode := STree.Next_Sibling (Current_Node => LocalNode);
                  BuildExpnDAG
                    (StartNode          => LocalNode,
                     ExpnScope          => LScope,
                     Scope              => Scope,
                     LineNmbr           => LineNmbr,
                     DoRtc              => True,
                     AssumeRvalues      => DoAssumeLocalRvalues,
                     LoopStack          => LoopStack,
                     FlowHeap           => FlowHeap,
                     VCGHeap            => VCGHeap,
                     ContainsReals      => ContainsReals,
                     VCGFailure         => VCGFailure,
                     ShortCircuitStack  => ShortCircuitStack,
                     CheckStack         => CheckStack,
                     KindOfStackedCheck => KindOfStackedCheck,
                     DAGRoot            => RangeBoundDAG);
                  CheckConstraintRunTimeError
                    (BaseTypeSym,
                     RangeBoundDAG,
                     Scope,
                     VCGHeap,
                     ShortCircuitStack,
                     CheckStack,
                     ContainsReals);

                  -- generate separate VC for range bounds in base type before constructing implied check
                  UnStackRtcs (LineNmbr, VCGHeap, CheckStack, KindOfStackedCheck);

                  -- now construct implication check that range is in subtype
                  BuildImpliedSubtypeCheck (TypeSym, LowerBound, RangeBoundDAG);

               else -- range is in the form of an attribute

                  -- first check that bounds are in base type
                  BuildExpnDAG
                    (StartNode          => LocalNode,
                     ExpnScope          => LScope,
                     Scope              => Scope,
                     LineNmbr           => LineNmbr,
                     DoRtc              => False,
                     AssumeRvalues      => DoAssumeLocalRvalues,
                     LoopStack          => LoopStack,
                     FlowHeap           => FlowHeap,
                     VCGHeap            => VCGHeap,
                     ContainsReals      => ContainsReals,
                     VCGFailure         => VCGFailure,
                     ShortCircuitStack  => ShortCircuitStack,
                     CheckStack         => CheckStack,
                     KindOfStackedCheck => KindOfStackedCheck,
                     DAGRoot            => RangeBoundDAG);

                  CheckConstraintRunTimeError
                    (BaseTypeSym,
                     LeftPtr (VCGHeap, RangeBoundDAG),
                     Scope,
                     VCGHeap,
                     ShortCircuitStack,
                     CheckStack,
                     ContainsReals);
                  -- Upper bound
                  CheckConstraintRunTimeError
                    (BaseTypeSym,
                     RightPtr (VCGHeap, RangeBoundDAG),
                     Scope,
                     VCGHeap,
                     ShortCircuitStack,
                     CheckStack,
                     ContainsReals);

                  -- now construct implication check that range is in subtype
                  BuildImpliedSubtypeCheck (TypeSym, LeftPtr (VCGHeap, RangeBoundDAG), RightPtr (VCGHeap, RangeBoundDAG));

               end if;
               UnStackRtcs (LineNmbr, VCGHeap, CheckStack, KindOfStackedCheck);
            end if;
         end if;
      end CheckRangeBounds;

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

      procedure InitializeControlVar
      --# global in     ArangeNode;
      --#        in     CommandLineData.Content;
      --#        in     LineNmbr;
      --#        in     LoopStack;
      --#        in     LScope;
      --#        in     Scope;
      --#        in     STree.Table;
      --#        in out CheckStack;
      --#        in out ContainsReals;
      --#        in out Dictionary.Dict;
      --#        in out ErrorHandler.Error_Context;
      --#        in out FlowHeap;
      --#        in out Graph.Table;
      --#        in out KindOfStackedCheck;
      --#        in out LexTokenManager.State;
      --#        in out ShortCircuitStack;
      --#        in out SPARK_IO.File_Sys;
      --#        in out Statistics.TableUsage;
      --#        in out StmtStack.S;
      --#        in out VCGFailure;
      --#        in out VCGHeap;
      --# derives CheckStack,
      --#         ContainsReals,
      --#         Dictionary.Dict,
      --#         FlowHeap,
      --#         Graph.Table,
      --#         KindOfStackedCheck,
      --#         LexTokenManager.State,
      --#         ShortCircuitStack,
      --#         Statistics.TableUsage,
      --#         StmtStack.S,
      --#         VCGFailure,
      --#         VCGHeap                    from *,
      --#                                         ArangeNode,
      --#                                         CheckStack,
      --#                                         CommandLineData.Content,
      --#                                         Dictionary.Dict,
      --#                                         FlowHeap,
      --#                                         Graph.Table,
      --#                                         KindOfStackedCheck,
      --#                                         LexTokenManager.State,
      --#                                         LineNmbr,
      --#                                         LoopStack,
      --#                                         LScope,
      --#                                         Scope,
      --#                                         ShortCircuitStack,
      --#                                         StmtStack.S,
      --#                                         STree.Table,
      --#                                         VCGHeap &
      --#         ErrorHandler.Error_Context,
      --#         SPARK_IO.File_Sys          from ArangeNode,
      --#                                         CheckStack,
      --#                                         CommandLineData.Content,
      --#                                         Dictionary.Dict,
      --#                                         ErrorHandler.Error_Context,
      --#                                         FlowHeap,
      --#                                         Graph.Table,
      --#                                         KindOfStackedCheck,
      --#                                         LexTokenManager.State,
      --#                                         LineNmbr,
      --#                                         LoopStack,
      --#                                         LScope,
      --#                                         Scope,
      --#                                         ShortCircuitStack,
      --#                                         SPARK_IO.File_Sys,
      --#                                         StmtStack.S,
      --#                                         STree.Table,
      --#                                         VCGHeap;
      is
         AssignedVarCell, DAGRoot, StmtCell, ModList : Cells.Cell;
         StmtLabel                                   : Labels.Label;

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

         procedure CreateInitialExpn
         --# global in     ArangeNode;
         --#        in     CommandLineData.Content;
         --#        in     LineNmbr;
         --#        in     LoopStack;
         --#        in     LScope;
         --#        in     Scope;
         --#        in     STree.Table;
         --#        in out CheckStack;
         --#        in out ContainsReals;
         --#        in out Dictionary.Dict;
         --#        in out ErrorHandler.Error_Context;
         --#        in out FlowHeap;
         --#        in out Graph.Table;
         --#        in out KindOfStackedCheck;
         --#        in out LexTokenManager.State;
         --#        in out ShortCircuitStack;
         --#        in out SPARK_IO.File_Sys;
         --#        in out Statistics.TableUsage;
         --#        in out StmtStack.S;
         --#        in out VCGFailure;
         --#        in out VCGHeap;
         --#           out DAGRoot;
         --# derives CheckStack,
         --#         ContainsReals,
         --#         Dictionary.Dict,
         --#         FlowHeap,
         --#         Graph.Table,
         --#         KindOfStackedCheck,
         --#         LexTokenManager.State,
         --#         ShortCircuitStack,
         --#         Statistics.TableUsage,
         --#         StmtStack.S,
         --#         VCGFailure,
         --#         VCGHeap                    from *,
         --#                                         ArangeNode,
         --#                                         CheckStack,
         --#                                         CommandLineData.Content,
         --#                                         Dictionary.Dict,
         --#                                         FlowHeap,
         --#                                         Graph.Table,
         --#                                         KindOfStackedCheck,
         --#                                         LexTokenManager.State,
         --#                                         LineNmbr,
         --#                                         LoopStack,
         --#                                         LScope,
         --#                                         Scope,
         --#                                         ShortCircuitStack,
         --#                                         StmtStack.S,
         --#                                         STree.Table,
         --#                                         VCGHeap &
         --#         DAGRoot                    from ArangeNode,
         --#                                         CheckStack,
         --#                                         CommandLineData.Content,
         --#                                         Dictionary.Dict,
         --#                                         FlowHeap,
         --#                                         Graph.Table,
         --#                                         KindOfStackedCheck,
         --#                                         LexTokenManager.State,
         --#                                         LineNmbr,
         --#                                         LoopStack,
         --#                                         LScope,
         --#                                         Scope,
         --#                                         ShortCircuitStack,
         --#                                         StmtStack.S,
         --#                                         STree.Table,
         --#                                         VCGHeap &
         --#         ErrorHandler.Error_Context,
         --#         SPARK_IO.File_Sys          from ArangeNode,
         --#                                         CheckStack,
         --#                                         CommandLineData.Content,
         --#                                         Dictionary.Dict,
         --#                                         ErrorHandler.Error_Context,
         --#                                         FlowHeap,
         --#                                         Graph.Table,
         --#                                         KindOfStackedCheck,
         --#                                         LexTokenManager.State,
         --#                                         LineNmbr,
         --#                                         LoopStack,
         --#                                         LScope,
         --#                                         Scope,
         --#                                         ShortCircuitStack,
         --#                                         SPARK_IO.File_Sys,
         --#                                         StmtStack.S,
         --#                                         STree.Table,
         --#                                         VCGHeap;
         is
            LocalNode               : STree.SyntaxNode;
            TypeMarkCell, FIRSTCell : Cells.Cell;

         begin -- CreateInitialExpn
            if ArangeNode = STree.NullNode then
               -- statement is of form "for ControlVar in [reverse] ControlVarRange"
               CreateFixedVarCell
                 (TypeMarkCell,
                  VCGHeap,
                  Dictionary.GetType (LoopContext.CurrentLoopParameterSym (LoopStack, VCGHeap)));
               CreateCellKind (FIRSTCell, VCGHeap, Cell_Storage.Attrib_Value);
               if LoopContext.CurrentLoopMovesInReverse (LoopStack, VCGHeap) then
                  Cells.Set_Lex_Str (VCGHeap, FIRSTCell, LexTokenManager.Last_Token);
               else
                  Cells.Set_Lex_Str (VCGHeap, FIRSTCell, LexTokenManager.First_Token);
               end if;
               CreateOpCell (DAGRoot, VCGHeap, SP_Symbols.apostrophe);
               SetLeftArgument (DAGRoot, TypeMarkCell, VCGHeap);
               SetRightArgument (DAGRoot, FIRSTCell, VCGHeap);
            else
               LocalNode := STree.Child_Node (Current_Node => ArangeNode);
               if STree.Syntax_Node_Type (Node => LocalNode) = SP_Symbols.simple_expression then
                  -- range is of form simpexp .. simpexp
                  if LoopContext.CurrentLoopMovesInReverse (LoopStack, VCGHeap) then
                     LocalNode := STree.Next_Sibling (Current_Node => LocalNode);
                  end if;
                  -- Do not generate checks with this call
                  BuildExpnDAG
                    (StartNode          => LocalNode,
                     ExpnScope          => LScope,
                     Scope              => Scope,
                     LineNmbr           => LineNmbr,
                     DoRtc              => False,
                     AssumeRvalues      => False,
                     LoopStack          => LoopStack,
                     FlowHeap           => FlowHeap,
                     VCGHeap            => VCGHeap,
                     ContainsReals      => ContainsReals,
                     VCGFailure         => VCGFailure,
                     ShortCircuitStack  => ShortCircuitStack,
                     CheckStack         => CheckStack,
                     KindOfStackedCheck => KindOfStackedCheck,
                     DAGRoot            => DAGRoot);
               else
                  -- LocalNode is range attribute

                  -- This call to BuildExpnDAG will not generate any checks.
                  BuildExpnDAG
                    (StartNode          => LocalNode,
                     ExpnScope          => LScope,
                     Scope              => Scope,
                     LineNmbr           => LineNmbr,
                     DoRtc              => False,
                     AssumeRvalues      => False,
                     LoopStack          => LoopStack,
                     FlowHeap           => FlowHeap,
                     VCGHeap            => VCGHeap,
                     ContainsReals      => ContainsReals,
                     VCGFailure         => VCGFailure,
                     ShortCircuitStack  => ShortCircuitStack,
                     CheckStack         => CheckStack,
                     KindOfStackedCheck => KindOfStackedCheck,
                     DAGRoot            => DAGRoot);

                  if LoopContext.CurrentLoopMovesInReverse (LoopStack, VCGHeap) then
                     DAGRoot := RightPtr (VCGHeap, DAGRoot);
                  else
                     DAGRoot := LeftPtr (VCGHeap, DAGRoot);
                  end if;
               end if;
            end if;
         end CreateInitialExpn;

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

      begin -- InitializeControlVar
         PrepareLabel (VCGHeap, StmtLabel, StmtCell);
         Clists.CreateList (VCGHeap, ModList);
         CreateModifiedCell (AssignedVarCell, VCGHeap, LoopContext.CurrentLoopParameterSym (LoopStack, VCGHeap));
         Clists.AppendCell (VCGHeap, AssignedVarCell, ModList);

         CreateInitialExpn;

         SetRightArgument (AssignedVarCell, DAGRoot, VCGHeap);
         SetAuxPtr (StmtCell, ModList, VCGHeap);
         Chain (StmtLabel, VCGHeap);
      end InitializeControlVar;

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

   begin -- StartForStmtModel

      -- FOR statement is modelled as follows:
      --
      -- for I in Type range L .. R loop
      --    LoopBody;
      -- end loop;
      --
      -- Determine exit condition which is either L or R; or Type'First or Type'Last; or a range attribute
      -- depending on whether loop is forward or backward.
      -- Build an expression DAG for the exit expression
      -- For each variable X in the expression: save X in specially created X_On_Entry variable
      -- Substitute X_On_entry for X in the exit expression
      -- Store the exit expression in the Dictionary for use in loop invariant generation
      --
      -- Build model:
      --
      --                                          -- AssignLoopBoundsToExitVariable
      -- R_vars_on_entry := R_vars                -- as described above
      --                                          -- StartForStmtEnclosingIf
      -- if L <= R then                           -- omitted if loop must be entered
      --                                          -- InitializeControlVar
      --   I := L;
      --   loop                                   -- StartLoopModel
      --                                          -- AssertForLoopCounterProperties
      --     --# assert I <= R_with_on_entry_substitution
      --     BodyOfLoop;
      --     exit when I = R_with_on_entry_substitution -- ModelForExit
      --     I := I + 1;                          -- AdvanceControlVar
      --   end loop;                              -- CloseFor Stmt
      -- end if;

      -- Node is loop_parameter_specification;
      ControlVarNode := STree.Child_Node (Current_Node => Node);
      DirectionNode  := STree.Next_Sibling (Current_Node => ControlVarNode);
      TypeNode       := STree.Next_Sibling (Current_Node => DirectionNode);
      ArangeNode     := STree.Next_Sibling (Current_Node => TypeNode);

      -- Following call does two things (see description above):
      -- (1) It creates a model of the exit expression of the for loop in terms of the variables' state
      --     on entry to the loop and stores that expression in the dictionary so that we can use it
      --     when generating loop invariant.
      -- (2) It assigns that expression to the loop's exit variable which is also stored in the dictionary.
      --     Construction of the exit switch statement is made in terms of this variable rather than in terms
      --     of the exit expression.
      AssignLoopBoundsToExitVariable (ArangeNode);

      -- Now produce a DAG for the initial value of the loop counter,
      -- and save that in the Dictionary as well.  This is used later
      -- in producing the default loop invariant.
      AssignLoopCounterEntryValue (ArangeNode);

      -- check any explicit range is in control var subtype
      CheckRangeBounds (TypeNode, ArangeNode);

      -- test whether range could possibly be null (i.e. empty). If so,
      -- then we need to generate an "If" statement that encloses the loop
      if RangeMayBeNull (ArangeNode) then
         StartForStmtEnclosingIf;
      end if;

      InitializeControlVar;
      StartLoopModel (LoopNode);
   end StartForStmtModel;

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

   procedure CloseForStmt (Node : in STree.SyntaxNode)
   --# global in     Dictionary.Dict;
   --#        in     LoopStack;
   --#        in     STree.Table;
   --#        in out Graph.Table;
   --#        in out LexTokenManager.State;
   --#        in out Statistics.TableUsage;
   --#        in out StmtStack.S;
   --#        in out VCGHeap;
   --# derives Graph.Table,
   --#         Statistics.TableUsage,
   --#         StmtStack.S,
   --#         VCGHeap               from *,
   --#                                    Dictionary.Dict,
   --#                                    Graph.Table,
   --#                                    LexTokenManager.State,
   --#                                    LoopStack,
   --#                                    Node,
   --#                                    StmtStack.S,
   --#                                    STree.Table,
   --#                                    VCGHeap &
   --#         LexTokenManager.State from *,
   --#                                    Dictionary.Dict,
   --#                                    Graph.Table,
   --#                                    LoopStack,
   --#                                    StmtStack.S,
   --#                                    VCGHeap;
   is
      ControlVarNode, DirectionNode, ArangeNode : STree.SyntaxNode;

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

      procedure ModelForExit
      --# global in     Dictionary.Dict;
      --#        in     LoopStack;
      --#        in out Graph.Table;
      --#        in out Statistics.TableUsage;
      --#        in out StmtStack.S;
      --#        in out VCGHeap;
      --# derives Graph.Table,
      --#         Statistics.TableUsage,
      --#         StmtStack.S,
      --#         VCGHeap               from *,
      --#                                    Dictionary.Dict,
      --#                                    Graph.Table,
      --#                                    LoopStack,
      --#                                    StmtStack.S,
      --#                                    VCGHeap;
      is
         DAGRoot                           : Cells.Cell;
         FalseBranchLabel, TrueBranchLabel : Labels.Label;
         R                                 : StmtStack.StmtRecord;
         LoopTail, Predecessor             : Graph.Matrix_Index;

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

         procedure CreateExitExpn
         --# global in     Dictionary.Dict;
         --#        in     LoopStack;
         --#        in out Statistics.TableUsage;
         --#        in out VCGHeap;
         --#           out DAGRoot;
         --# derives DAGRoot,
         --#         VCGHeap               from Dictionary.Dict,
         --#                                    LoopStack,
         --#                                    VCGHeap &
         --#         Statistics.TableUsage from *,
         --#                                    Dictionary.Dict,
         --#                                    LoopStack,
         --#                                    VCGHeap;
         is
            ControlVarRefCell, ExitValueRoot : Cells.Cell;

         begin -- CreateExitExpn (e.g. I = <loop exit expression recoved from dict>)
            CreateReferenceCell (ControlVarRefCell, VCGHeap, LoopContext.CurrentLoopParameterSym (LoopStack, VCGHeap));
            -- select = or <-> as appropriate
            if Dictionary.TypeIsBoolean (Dictionary.GetType (LoopContext.CurrentLoopParameterSym (LoopStack, VCGHeap))) then
               CreateOpCell (DAGRoot, VCGHeap, SP_Symbols.is_equivalent_to);
            else
               CreateOpCell (DAGRoot, VCGHeap, SP_Symbols.equals);
            end if;

            SetLeftArgument (DAGRoot, ControlVarRefCell, VCGHeap);
            -- Recover exit expression put in Dict by AssignLoopBoundsToExitVariable
            ExitValueRoot := Cells.Cell (Dictionary.GetLoopExitExpn (LoopContext.CurrentLoopSym (LoopStack, VCGHeap)));
            -- There should always be an expression to get since it is planted by
            -- AssignLoopBoundsToExitVariable which is always called by StartForStmtModel.
            -- Therefore, the following assertion should never fail
            SystemErrors.RT_Assert
              (C       => not Cells.Is_Null_Cell (ExitValueRoot),
               Sys_Err => SystemErrors.Assertion_Failure,
               Msg     => "ExitExpn Null in CreateExitExpn");
            SetRightArgument (DAGRoot, ExitValueRoot, VCGHeap);
         end CreateExitExpn;

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

      begin   -- ModelForExit
         CreateExitExpn;
         CreateSwitch (DAGRoot, FalseBranchLabel, TrueBranchLabel);
         Predecessor := StmtStack.Top.StmtNmbr;
         StmtStack.Pop;                         -- pop last statement in loop body;
         LoopTail := StmtStack.Top.StmtNmbr;
         Graph.Create_Coeff (Heap => VCGHeap,
                             I    => Predecessor,
                             J    => LoopTail,
                             K    => TrueBranchLabel);
         -- push False branch;
         Graph.Inc_Nmbr_Of_Stmts;
         Graph.Create_Coeff (Heap => VCGHeap,
                             I    => Predecessor,
                             J    => Graph.Get_Nmbr_Of_Stmts,
                             K    => FalseBranchLabel);
         R := StmtStack.StmtRecord'(Graph.Get_Nmbr_Of_Stmts, StmtStack.Elementary);
         StmtStack.Push (R);
      end ModelForExit;

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

      procedure AdvanceControlVar
      --# global in     Dictionary.Dict;
      --#        in     LoopStack;
      --#        in out Graph.Table;
      --#        in out LexTokenManager.State;
      --#        in out Statistics.TableUsage;
      --#        in out StmtStack.S;
      --#        in out VCGHeap;
      --# derives Graph.Table,
      --#         StmtStack.S,
      --#         VCGHeap               from Dictionary.Dict,
      --#                                    Graph.Table,
      --#                                    LexTokenManager.State,
      --#                                    LoopStack,
      --#                                    StmtStack.S,
      --#                                    VCGHeap &
      --#         LexTokenManager.State,
      --#         Statistics.TableUsage from *,
      --#                                    Dictionary.Dict,
      --#                                    LexTokenManager.State,
      --#                                    LoopStack,
      --#                                    VCGHeap;
      is
         AssignedVarCell, DAGRoot, StmtCell, ModList : Cells.Cell;
         StmtLabel                                   : Labels.Label;

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

         procedure CreateAdvancingExpn
         --# global in     Dictionary.Dict;
         --#        in     LoopStack;
         --#        in out LexTokenManager.State;
         --#        in out Statistics.TableUsage;
         --#        in out VCGHeap;
         --#           out DAGRoot;
         --# derives DAGRoot               from Dictionary.Dict,
         --#                                    LoopStack,
         --#                                    VCGHeap &
         --#         LexTokenManager.State,
         --#         Statistics.TableUsage from *,
         --#                                    Dictionary.Dict,
         --#                                    LoopStack,
         --#                                    VCGHeap &
         --#         VCGHeap               from *,
         --#                                    Dictionary.Dict,
         --#                                    LexTokenManager.State,
         --#                                    LoopStack;
         is
            LexStr            : LexTokenManager.Lex_String;
            ControlVarRefCell : Cells.Cell;
            UnityCell         : Cells.Cell;
         begin
            CreateReferenceCell (ControlVarRefCell, VCGHeap, LoopContext.CurrentLoopParameterSym (LoopStack, VCGHeap));
            if Dictionary.TypeIsNumeric (Dictionary.GetType (LoopContext.CurrentLoopParameterSym (LoopStack, VCGHeap))) then
               -- define advance of control variable using plus or minus;
               if not LoopContext.CurrentLoopMovesInReverse (LoopStack, VCGHeap) then
                  CreateOpCell (DAGRoot, VCGHeap, SP_Symbols.plus);
               else
                  CreateOpCell (DAGRoot, VCGHeap, SP_Symbols.minus);
               end if;
               SetLeftArgument (DAGRoot, ControlVarRefCell, VCGHeap);
               LexTokenManager.Insert_Nat (N       => 1,
                                           Lex_Str => LexStr);
               CreateManifestConstCell (UnityCell, VCGHeap, LexStr);
               SetRightArgument (DAGRoot, UnityCell, VCGHeap);

               -- insertion to handle Boolean loop counters
            elsif Dictionary.TypeIsBoolean (Dictionary.GetType (LoopContext.CurrentLoopParameterSym (LoopStack, VCGHeap))) then
               -- for a well formed Boolean expression both Succ and Pred are the equivalent
               -- of "not"
               CreateOpCell (DAGRoot, VCGHeap, SP_Symbols.RWnot);
               SetRightArgument (DAGRoot, ControlVarRefCell, VCGHeap);
               --continue for non-Boolean enumerated types as before
            else
               -- define advance of control variable using succ or pred;
               Cells.Create_Cell (VCGHeap, DAGRoot);
               if not LoopContext.CurrentLoopMovesInReverse (LoopStack, VCGHeap) then
                  Cells.Set_Kind (VCGHeap, DAGRoot, Cell_Storage.Succ_Function);
               else
                  Cells.Set_Kind (VCGHeap, DAGRoot, Cell_Storage.Pred_Function);
               end if;
               SetRightArgument (DAGRoot, ControlVarRefCell, VCGHeap);
            end if;
         end CreateAdvancingExpn;

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

      begin -- AdvanceControlVar
         PrepareLabel (VCGHeap, StmtLabel, StmtCell);
         Clists.CreateList (VCGHeap, ModList);
         CreateModifiedCell (AssignedVarCell, VCGHeap, LoopContext.CurrentLoopParameterSym (LoopStack, VCGHeap));
         Clists.AppendCell (VCGHeap, AssignedVarCell, ModList);
         CreateAdvancingExpn;
         SetRightArgument (AssignedVarCell, DAGRoot, VCGHeap);
         SetAuxPtr (StmtCell, ModList, VCGHeap);
         Chain (StmtLabel, VCGHeap);
      end AdvanceControlVar;

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

   begin -- CloseForStmt
         -- Node is loop_parameter_specification;
      ControlVarNode := STree.Child_Node (Current_Node => Node);
      DirectionNode  := STree.Next_Sibling (Current_Node => ControlVarNode);
      ArangeNode     := STree.Next_Sibling (Current_Node => STree.Next_Sibling (Current_Node => DirectionNode));
      -- test whether control variable has reached limiting value;
      ModelForExit;
      AdvanceControlVar;
      CloseLoop;

      -- If we previously generated an enclosing "if" statement to
      -- deal with the possibility of a null range, then we need to
      -- close it here.
      if RangeMayBeNull (ArangeNode) then
         CloseForStmtEnclosingIf;
      end if;
   end CloseForStmt;

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

   procedure DefineTwiddledVars
   --# global in     Dictionary.Dict;
   --#        in     Scope;
   --#        in     SubprogSym;
   --#        in out Graph.Table;
   --#        in out Statistics.TableUsage;
   --#        in out StmtStack.S;
   --#        in out VCGHeap;
   --# derives Graph.Table,
   --#         StmtStack.S,
   --#         VCGHeap               from Dictionary.Dict,
   --#                                    Graph.Table,
   --#                                    Scope,
   --#                                    StmtStack.S,
   --#                                    SubprogSym,
   --#                                    VCGHeap &
   --#         Statistics.TableUsage from *,
   --#                                    Dictionary.Dict,
   --#                                    Scope,
   --#                                    SubprogSym,
   --#                                    VCGHeap;
   is
      Abstraction        : Dictionary.Abstractions;
      ExportIt           : Dictionary.Iterator;
      MappingStmtCreated : Boolean;
      StmtLabel          : Labels.Label;
      ModList            : Cells.Cell;

      procedure CreateMappingStmt
      --# global in out Statistics.TableUsage;
      --#        in out VCGHeap;
      --#           out ModList;
      --#           out StmtLabel;
      --# derives ModList,
      --#         StmtLabel,
      --#         VCGHeap               from VCGHeap &
      --#         Statistics.TableUsage from *,
      --#                                    VCGHeap;
      is
         StmtPair : Cells.Cell;
      begin
         PrepareLabel (VCGHeap, StmtLabel, StmtPair);
         Clists.CreateList (VCGHeap, ModList);
         SetAuxPtr (StmtPair, ModList, VCGHeap);
      end CreateMappingStmt;

      procedure TwiddledVarAssignment (Sym : Dictionary.Symbol)
      --# global in     ModList;
      --#        in out Statistics.TableUsage;
      --#        in out VCGHeap;
      --# derives Statistics.TableUsage,
      --#         VCGHeap               from *,
      --#                                    ModList,
      --#                                    Sym,
      --#                                    VCGHeap;
      is
         ImpExpVarCell, AssignedVarCell : Cells.Cell;
      begin
         CreateModifiedCell (AssignedVarCell, VCGHeap, Sym);
         SetTilde (AssignedVarCell, VCGHeap);
         Clists.AppendCell (VCGHeap, AssignedVarCell, ModList);
         CreateReferenceCell (ImpExpVarCell, VCGHeap, Sym);
         SetRightArgument (AssignedVarCell, ImpExpVarCell, VCGHeap);
      end TwiddledVarAssignment;

   begin -- DefineTwiddledVars

      -- Set up series of assignment of the form X~ = X; at the start of the sequence of statements model.
      -- These have the effect of preserving imported values thus allowing effective use of tilde.  We only
      -- do this for things that are imported AND exported (but that includes implicit exportation of "streams".

      ModList            := Cells.Null_Cell; -- initialized in case we bypass while loop that follows
      StmtLabel          := Labels.CellToLabel (Cells.Null_Cell); -- to avoid flow-sensitive DFA later
      MappingStmtCreated := False;
      Abstraction        := Dictionary.GetAbstraction (SubprogSym, Scope);

      -- For functions, we need to set up twiddles for any external var that the function references; this
      -- is because reading the external var will have an implicit side effect of removing the head from the
      -- external sequence and we may need to be able to refer to the initial value by using tilde
      if Dictionary.IsFunction (SubprogSym) then
         -- each function global is a potential "export"
         ExportIt := Dictionary.FirstGlobalVariable (Abstraction, SubprogSym);
         while not Dictionary.IsNullIterator (ExportIt) loop
            if Dictionary.IsOwnVariableOrConstituentWithMode (Dictionary.CurrentSymbol (ExportIt)) then
               -- it's an external variable the importation of which implies an export for modelling purposes
               if not MappingStmtCreated then
                  CreateMappingStmt;
                  MappingStmtCreated := True;
               end if;
               TwiddledVarAssignment (Dictionary.CurrentSymbol (ExportIt));
            end if;
            ExportIt := Dictionary.NextSymbol (ExportIt);
         end loop;

      else
         -- For procedures, we can use the import/export list to decide what twiddles need to be st up.  Note that
         -- the list work for streams as well as other import/exports because we patch the derives annotation
         -- appropriately when procedure reference or update streams.
         ExportIt := Dictionary.FirstExport (Abstraction, SubprogSym);
         while not Dictionary.IsNullIterator (ExportIt) loop
            if Dictionary.IsImport (Abstraction, SubprogSym, Dictionary.CurrentSymbol (ExportIt)) then
               if not MappingStmtCreated then
                  CreateMappingStmt;
                  MappingStmtCreated := True;
               end if;
               TwiddledVarAssignment (Dictionary.CurrentSymbol (ExportIt));
            end if;
            ExportIt := Dictionary.NextSymbol (ExportIt);
         end loop;
      end if;

      if MappingStmtCreated then
         Chain (StmtLabel, VCGHeap);
      else
         ModelNullStmt (VCGHeap); -- SIMPLIFY?
      end if;
   end DefineTwiddledVars;

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

   procedure IncorporateProofStmt
   --# global in     CommandLineData.Content;
   --#        in     ImportConstraints;
   --#        in     LineNmbr;
   --#        in     LoopStack;
   --#        in     LScope;
   --#        in     Node;
   --#        in     PreConstraints;
   --#        in     STree.Table;
   --#        in out ContainsReals;
   --#        in out Dictionary.Dict;
   --#        in out ErrorHandler.Error_Context;
   --#        in out Graph.Table;
   --#        in out LexTokenManager.State;
   --#        in out SPARK_IO.File_Sys;
   --#        in out Statistics.TableUsage;
   --#        in out StmtStack.S;
   --#        in out VCGFailure;
   --#        in out VCGHeap;
   --# derives ContainsReals,
   --#         Dictionary.Dict,
   --#         LexTokenManager.State,
   --#         VCGFailure                 from *,
   --#                                         CommandLineData.Content,
   --#                                         Dictionary.Dict,
   --#                                         LexTokenManager.State,
   --#                                         LoopStack,
   --#                                         LScope,
   --#                                         Node,
   --#                                         STree.Table,
   --#                                         VCGHeap &
   --#         ErrorHandler.Error_Context,
   --#         SPARK_IO.File_Sys          from CommandLineData.Content,
   --#                                         Dictionary.Dict,
   --#                                         ErrorHandler.Error_Context,
   --#                                         LexTokenManager.State,
   --#                                         LoopStack,
   --#                                         LScope,
   --#                                         Node,
   --#                                         SPARK_IO.File_Sys,
   --#                                         STree.Table,
   --#                                         VCGHeap &
   --#         Graph.Table,
   --#         Statistics.TableUsage,
   --#         StmtStack.S,
   --#         VCGHeap                    from *,
   --#                                         CommandLineData.Content,
   --#                                         Dictionary.Dict,
   --#                                         Graph.Table,
   --#                                         ImportConstraints,
   --#                                         LexTokenManager.State,
   --#                                         LineNmbr,
   --#                                         LoopStack,
   --#                                         LScope,
   --#                                         Node,
   --#                                         PreConstraints,
   --#                                         StmtStack.S,
   --#                                         STree.Table,
   --#                                         VCGHeap;
   is
      ExpnNode, LocalNode : STree.SyntaxNode;
      LocalNodeType       : SP_Symbols.SP_Symbol;
   begin
      LocalNode     := STree.Child_Node (Current_Node => Node);
      LocalNodeType := STree.Syntax_Node_Type (Node => LocalNode);
      case LocalNodeType is
         when SP_Symbols.assert_statement =>
            ExpnNode := STree.Child_Node (Current_Node => STree.Child_Node (Current_Node => LocalNode));
            ModelAssertStmt (ExpnNode);
         when SP_Symbols.assume_statement =>
            ExpnNode := STree.Child_Node (Current_Node => STree.Child_Node (Current_Node => LocalNode));
            Model_Assume_Statement (ExpnNode);
         when SP_Symbols.check_statement =>
            ExpnNode := STree.Child_Node (Current_Node => STree.Child_Node (Current_Node => LocalNode));
            ModelCheckStmt (ExpnNode);
         when others =>
            null;
      end case;
   end IncorporateProofStmt;

   procedure IncorporateConstraints
     (Semantic_Error_In_Subprogram : in Boolean;
      Type_Check_Exports           : in Boolean;
      Scope                        : in Dictionary.Scopes)
   --# global in     CommandLineData.Content;
   --#        in     DoAssumeLocalRvalues;
   --#        in     ImportConstraints;
   --#        in     LineNmbr;
   --#        in     LoopStack;
   --#        in     StartNode;
   --#        in     STree.Table;
   --#        in out CheckStack;
   --#        in out ContainsReals;
   --#        in out Dictionary.Dict;
   --#        in out ErrorHandler.Error_Context;
   --#        in out FlowHeap;
   --#        in out Graph.Table;
   --#        in out KindOfStackedCheck;
   --#        in out LexTokenManager.State;
   --#        in out ShortCircuitStack;
   --#        in out SPARK_IO.File_Sys;
   --#        in out Statistics.TableUsage;
   --#        in out StmtStack.S;
   --#        in out VCGFailure;
   --#        in out VCGHeap;
   --# derives CheckStack,
   --#         FlowHeap,
   --#         KindOfStackedCheck,
   --#         ShortCircuitStack,
   --#         StmtStack.S                from CheckStack,
   --#                                         CommandLineData.Content,
   --#                                         Dictionary.Dict,
   --#                                         DoAssumeLocalRvalues,
   --#                                         FlowHeap,
   --#                                         Graph.Table,
   --#                                         ImportConstraints,
   --#                                         KindOfStackedCheck,
   --#                                         LexTokenManager.State,
   --#                                         LineNmbr,
   --#                                         LoopStack,
   --#                                         Scope,
   --#                                         Semantic_Error_In_Subprogram,
   --#                                         ShortCircuitStack,
   --#                                         StartNode,
   --#                                         StmtStack.S,
   --#                                         STree.Table,
   --#                                         VCGHeap &
   --#         ContainsReals,
   --#         Dictionary.Dict,
   --#         Graph.Table,
   --#         LexTokenManager.State,
   --#         Statistics.TableUsage,
   --#         VCGFailure,
   --#         VCGHeap                    from *,
   --#                                         CheckStack,
   --#                                         CommandLineData.Content,
   --#                                         Dictionary.Dict,
   --#                                         DoAssumeLocalRvalues,
   --#                                         FlowHeap,
   --#                                         Graph.Table,
   --#                                         ImportConstraints,
   --#                                         KindOfStackedCheck,
   --#                                         LexTokenManager.State,
   --#                                         LineNmbr,
   --#                                         LoopStack,
   --#                                         Scope,
   --#                                         Semantic_Error_In_Subprogram,
   --#                                         ShortCircuitStack,
   --#                                         StartNode,
   --#                                         StmtStack.S,
   --#                                         STree.Table,
   --#                                         Type_Check_Exports,
   --#                                         VCGHeap &
   --#         ErrorHandler.Error_Context from *,
   --#                                         CheckStack,
   --#                                         CommandLineData.Content,
   --#                                         Dictionary.Dict,
   --#                                         DoAssumeLocalRvalues,
   --#                                         FlowHeap,
   --#                                         Graph.Table,
   --#                                         ImportConstraints,
   --#                                         KindOfStackedCheck,
   --#                                         LexTokenManager.State,
   --#                                         LineNmbr,
   --#                                         LoopStack,
   --#                                         Scope,
   --#                                         Semantic_Error_In_Subprogram,
   --#                                         ShortCircuitStack,
   --#                                         SPARK_IO.File_Sys,
   --#                                         StartNode,
   --#                                         StmtStack.S,
   --#                                         STree.Table,
   --#                                         VCGHeap &
   --#         SPARK_IO.File_Sys          from *,
   --#                                         CheckStack,
   --#                                         CommandLineData.Content,
   --#                                         Dictionary.Dict,
   --#                                         DoAssumeLocalRvalues,
   --#                                         ErrorHandler.Error_Context,
   --#                                         FlowHeap,
   --#                                         Graph.Table,
   --#                                         ImportConstraints,
   --#                                         KindOfStackedCheck,
   --#                                         LexTokenManager.State,
   --#                                         LineNmbr,
   --#                                         LoopStack,
   --#                                         Scope,
   --#                                         Semantic_Error_In_Subprogram,
   --#                                         ShortCircuitStack,
   --#                                         StartNode,
   --#                                         StmtStack.S,
   --#                                         STree.Table,
   --#                                         Type_Check_Exports,
   --#                                         VCGHeap;
      is separate;

   procedure CollectImportConstraints (Scope : in Dictionary.Scopes)
   --# global in     CommandLineData.Content;
   --#        in out ContainsReals;
   --#        in out Dictionary.Dict;
   --#        in out LexTokenManager.State;
   --#        in out SPARK_IO.File_Sys;
   --#        in out Statistics.TableUsage;
   --#        in out VCGFailure;
   --#        in out VCGHeap;
   --#           out ImportConstraints;
   --# derives ContainsReals,
   --#         Dictionary.Dict,
   --#         LexTokenManager.State,
   --#         SPARK_IO.File_Sys,
   --#         Statistics.TableUsage,
   --#         VCGFailure,
   --#         VCGHeap               from *,
   --#                                    CommandLineData.Content,
   --#                                    Dictionary.Dict,
   --#                                    LexTokenManager.State,
   --#                                    Scope,
   --#                                    VCGHeap &
   --#         ImportConstraints     from CommandLineData.Content,
   --#                                    Dictionary.Dict,
   --#                                    LexTokenManager.State,
   --#                                    Scope,
   --#                                    VCGHeap;
   is
      Abstraction : Dictionary.Abstractions;
      SubProg     : Dictionary.Symbol;
      BarrierCell : Cells.Cell;
   begin
      SubProg           := Dictionary.GetRegion (Scope);
      ImportConstraints := Cells.Null_Cell;

      if Dictionary.Is_Subprogram (SubProg) or else Dictionary.IsTaskType (SubProg) then
         Abstraction :=
           Dictionary.GetAbstraction
           (SubProg,
            Dictionary.Set_Visibility (The_Visibility => Dictionary.Local,
                                       The_Unit       => SubProg));
         -- Collect type constraints on imported parameters and globals
         AssumeTypesOfFormalImportParams (Abstraction, SubProg, Scope, ImportConstraints);
         AssumeTypesOfImportGlobals (Abstraction, SubProg, Scope, ImportConstraints);

         -- if the SubProg is an Entry we can also assert its Barrier is True
         if Dictionary.IsEntry (SubProg) then
            CreateModifiedCell (BarrierCell, VCGHeap, Dictionary.GetSubprogramEntryBarrier (SubProg));
            Cells.Utility.Conjoin (VCGHeap, BarrierCell, ImportConstraints);
         end if;
      end if;
   end CollectImportConstraints;

   procedure CollectPreConstraints
   --# global in     CommandLineData.Content;
   --#        in     LoopStack;
   --#        in     Scope;
   --#        in     STree.Table;
   --#        in out ContainsReals;
   --#        in out Dictionary.Dict;
   --#        in out ErrorHandler.Error_Context;
   --#        in out LexTokenManager.State;
   --#        in out SPARK_IO.File_Sys;
   --#        in out Statistics.TableUsage;
   --#        in out VCGFailure;
   --#        in out VCGHeap;
   --#           out PreConstraints;
   --# derives ContainsReals,
   --#         Dictionary.Dict,
   --#         LexTokenManager.State,
   --#         Statistics.TableUsage,
   --#         VCGFailure,
   --#         VCGHeap                    from *,
   --#                                         CommandLineData.Content,
   --#                                         Dictionary.Dict,
   --#                                         LexTokenManager.State,
   --#                                         LoopStack,
   --#                                         Scope,
   --#                                         STree.Table,
   --#                                         VCGHeap &
   --#         ErrorHandler.Error_Context,
   --#         SPARK_IO.File_Sys          from CommandLineData.Content,
   --#                                         Dictionary.Dict,
   --#                                         ErrorHandler.Error_Context,
   --#                                         LexTokenManager.State,
   --#                                         LoopStack,
   --#                                         Scope,
   --#                                         SPARK_IO.File_Sys,
   --#                                         STree.Table,
   --#                                         VCGHeap &
   --#         PreConstraints             from CommandLineData.Content,
   --#                                         Dictionary.Dict,
   --#                                         LexTokenManager.State,
   --#                                         LoopStack,
   --#                                         Scope,
   --#                                         STree.Table,
   --#                                         VCGHeap;
   is
      Precondition_Node      : STree.SyntaxNode;
      Abstraction            : Dictionary.Abstractions;
      Subprog                : Dictionary.Symbol;
      Function_Defs_Not_Used : CStacks.Stack;
   begin
      CStacks.CreateStack (Function_Defs_Not_Used);

      Subprog        := Dictionary.GetRegion (Scope);
      PreConstraints := Cells.Null_Cell;

      if Dictionary.Is_Subprogram (Subprog) then
         -- Build precondition DAG - only a subprogram can have one (not package elab. or task)
         Abstraction       :=
           Dictionary.GetConstraintAbstraction
           (Subprog,
            Dictionary.Set_Visibility (The_Visibility => Dictionary.Local,
                                       The_Unit       => Subprog));
         Precondition_Node := STree.RefToNode (Dictionary.GetPrecondition (Abstraction, Subprog));
         if Precondition_Node /= STree.NullNode then
            -- We do not need the function defs because they are regenerated each
            -- time that a function is applied within a proof context
            -- so Generate_Function_Instantiations is False
            --# accept F, 10, Function_Defs_Not_Used, "The function defs are needed here";
            Build_Annotation_Expression
              (Exp_Node                         => Precondition_Node,
               Instantiated_Subprogram          => Dictionary.NullSymbol,
               Scope                            => Scope,
               Calling_Scope                    => Scope,
               Force_Abstract                   => False,
               Loop_Stack                       => LoopStack,
               Generate_Function_Instantiations => False,
               VC_Failure                       => VCGFailure,
               VC_Contains_Reals                => ContainsReals,
               VCG_Heap                         => VCGHeap,
               DAG_Root                         => PreConstraints,
               Function_Defs                    => Function_Defs_Not_Used);
            --# end accept;
            -- substitute import-export variables by the twiddled version
            if Dictionary.IsProcedure (Subprog) then
               SubstituteTwiddled (Abstraction, Subprog, PreConstraints);
            end if;
         end if;
      end if;
   end CollectPreConstraints;

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

   procedure SetDoAssumeLocalRvalues
   --# global in     DataFlowErrorInSubprogram;
   --#        in     Dictionary.Dict;
   --#        in     Scope;
   --#           out DoAssumeLocalRvalues;
   --# derives DoAssumeLocalRvalues from DataFlowErrorInSubprogram,
   --#                                   Dictionary.Dict,
   --#                                   Scope;
   is

      function UsesUncheckedConversion return Boolean
      --# global in Dictionary.Dict;
      --#        in Scope;
      is
      begin
         return Dictionary.UsesUncheckedConversion (Dictionary.GetEnclosingCompilationUnit (Scope));
      end UsesUncheckedConversion;

      function AssignsFromExternal return Boolean
      --# global in Dictionary.Dict;
      --#        in Scope;
      is
      begin
         return Dictionary.AssignsFromExternal (Dictionary.GetEnclosingCompilationUnit (Scope));
      end AssignsFromExternal;

   begin -- SetDoAssumeLocalRvalues
      DoAssumeLocalRvalues := not (AssignsFromExternal or else UsesUncheckedConversion) and then not DataFlowErrorInSubprogram;
   end SetDoAssumeLocalRvalues;

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

begin -- BuildGraph

   LineNmbr        := 0;
   SubprogramCalls := 0;
   LScope          := Scope;

   CStacks.CreateStack (ShortCircuitStack);
   CStacks.CreateStack (CheckStack);
   ContainsReals := False;

   StmtStack.Clear;
   LoopContext.Initialize (LoopStack);
   SetDoAssumeLocalRvalues;
   CreateUnitLabel (StmtLabel, VCGHeap);
   Graph.Create_Coeff (Heap => VCGHeap,
                       I    => 1,
                       J    => 2,
                       K    => StmtLabel);
   InitialRecord := StmtStack.StmtRecord'(StmtNmbr => 2,
                                          Kind     => StmtStack.Elementary);
   StmtStack.Push (InitialRecord);
   Graph.Set_Nmbr_Of_Stmts (N => 2);

   -- Guard all statement syntax tree walking in case of semantic errors in the subprgoram being modelled
   -- Any graph model of invalid SPARK is useless to us so we don't do it.
   if not Semantic_Error_In_Subprogram then
      DefineTwiddledVars;

      -- collect import type constraints to be used in particular to
      -- propagate the information across assertions.
      CollectImportConstraints (Scope => Scope);
      CollectPreConstraints;

      ModelInitialisedVariables;  -- CheckStack always defined

      Node := StartNode;

      loop -- Down Loop -----------------------------------------------------

         LastNode := Node;
         NodeType := STree.Syntax_Node_Type (Node => Node);
         case NodeType is
            when SP_Symbols.sequence_of_statements |
              SP_Symbols.simple_statement       |
              SP_Symbols.compound_statement     |
              SP_Symbols.elsif_part             |
              SP_Symbols.loop_statement         |
              SP_Symbols.alternatives           =>
               Node := STree.Child_Node (Current_Node => Node);

            when SP_Symbols.statement =>
               LineNmbr := Integer (STree.Node_Position (Node => Node).Start_Line_No);
               Node     := STree.Child_Node (Current_Node => Node);

            when SP_Symbols.simple_name | SP_Symbols.sequence_of_labels | SP_Symbols.label =>

               Node := STree.NullNode; -- to ignore labels or optional loop labels

            when SP_Symbols.apragma | SP_Symbols.null_statement | SP_Symbols.justification_statement =>
               ModelNullStmt (VCGHeap);
               Node := STree.NullNode;

            when SP_Symbols.proof_statement =>
               IncorporateProofStmt;
               Node := STree.NullNode;

            when SP_Symbols.assignment_statement =>
               ModelAssignmentStmt; -- CheckStack always defined
               Node := STree.NullNode;

            when SP_Symbols.procedure_call_statement =>
               ModelProcedureCall; -- CheckStack always defined
               Node := STree.NullNode;

            when SP_Symbols.if_statement =>
               Node     := STree.Child_Node (Current_Node => Node);
               LastNode := Node;
               StartIfModel;   -- CheckStack always defined
               Node := STree.NullNode;

            when SP_Symbols.condition =>
               -- there is no Statement associated with the condition of the elsif so we need to get
               -- get the line number from the condition node rather than base it on whatever the
               -- last statement line number happend to be
               LineNmbr := Integer (STree.Node_Position (Node => Node).Start_Line_No);
               StartElsIfModel; -- CheckStack always defined
               Node := STree.NullNode;

            when SP_Symbols.else_part =>
               StartElseModel;
               Node := STree.Child_Node (Current_Node => Node);
               ModelNullStmt (VCGHeap);

            when SP_Symbols.case_statement =>
               Node     := STree.Child_Node (Current_Node => Node);
               LastNode := Node;
               StartCaseModel;  -- CheckStack always defined
               Node := STree.NullNode;

            when SP_Symbols.case_statement_alternative =>
               Node := STree.Child_Node (Current_Node => Node);
               ModelAlternative;  -- CheckStack always defined
               Node := STree.Next_Sibling (Current_Node => Node);

            when SP_Symbols.others_part =>
               if STree.Child_Node (Current_Node => Node) /= STree.NullNode then
                  ModelOthersPart;
                  Node := STree.Child_Node (Current_Node => Node);
               else
                  Node := STree.NullNode;
               end if;

            when SP_Symbols.return_statement =>
               Node := STree.NullNode;

            when SP_Symbols.loop_statement_opt =>
               LoopContext.EnterLoop (Scope, LoopStack, VCGHeap,
                                      -- to get
                                      LScope);
               -- advance to iteration_scheme;
               Local_Node := STree.Child_Node (Current_Node => Node);
               if Local_Node = STree.NullNode then
                  ModelNullStmt (VCGHeap);
                  StartLoopModel (Node);
               else
                  -- loop has an iteration_scheme;
                  -- localnode is of type iteration_scheme;
                  Local_Node := STree.Child_Node (Current_Node => Local_Node);
                  case STree.Syntax_Node_Type (Node => Local_Node) is
                     when SP_Symbols.loop_parameter_specification =>
                        StartForStmtModel (Local_Node, Node);
                     when others =>
                        ModelNullStmt (VCGHeap);
                        StartLoopModel (Node);
                  end case;
               end if;
               Node := STree.NullNode;

            when SP_Symbols.exit_statement =>
               Node := STree.Next_Sibling (Current_Node => STree.Child_Node (Current_Node => Node));

               if STree.Syntax_Node_Type (Node => Node) = SP_Symbols.simple_name then
                  -- Exit statement has a label, which we must skip
                  -- to get to the condition.
                  Node := STree.Next_Sibling (Current_Node => Node);
               end if;

               ModelExit; -- CheckStack is always defined
               Node := STree.NullNode;

            when SP_Symbols.end_of_loop =>
               Node := STree.NullNode;

            when SP_Symbols.delay_statement =>
               ModelDelayStmt; -- CheckStack is always defined
               Node := STree.NullNode;

            when others =>

               -- HTML Directives
               --! <NameFormat> <Name>
               --! <ErrorFormat> <Error>

               --! <Name> unexpected-node-kind-in-main-tree

               Node := STree.NullNode;
               SPARK_IO.New_Line (OutputFile, 1);
               SPARK_IO.Put_Line (OutputFile, "!!!        Unexpected node kind in main tree", 0);
               VCGFailure := True;
               --! <Error> !!! Unexpected node kind in main tree
               --! This message indicates corruption of the syntax tree being
               --! processed by the VC Generator. It should not be seen in normal
               --! operation.

         end case;
         if Node = STree.NullNode and LastNode /= StartNode then
            loop -- Up Loop ------------------------------------------
               Node := STree.Next_Sibling (Current_Node => LastNode);
               exit when Node /= STree.NullNode;
               Node := STree.Parent_Node (Current_Node => LastNode);
               exit when Node = STree.NullNode or Node = StartNode;
               NodeType := STree.Syntax_Node_Type (Node => Node);

               case NodeType is
                  when SP_Symbols.if_statement =>
                     CloseIfStmt;
                  when SP_Symbols.case_statement =>
                     CombineCases;
                  when SP_Symbols.loop_statement =>
                     Local_Node := STree.Child_Node (Current_Node => Node);
                     -- Local_Node is simple_name or loop_statement_opt;
                     if STree.Syntax_Node_Type (Node => Local_Node) = SP_Symbols.simple_name then
                        Local_Node := STree.Next_Sibling (Current_Node => Local_Node);
                     end if;
                     -- Local_Node is loop_statement_opt;
                     Local_Node := STree.Child_Node (Current_Node => Local_Node);
                     if Local_Node = STree.NullNode then
                        -- if the loop has no exits then add in a default "exit when false"
                        if not Dictionary.GetLoopHasExits (Dictionary.GetRegion (LScope)) then
                           ModelDefaultExit;
                        end if;
                        CloseLoop;
                     else
                        -- loop has an iteration_scheme;
                        -- Local_Node is of type iteration_scheme;
                        Local_Node := STree.Child_Node (Current_Node => Local_Node);
                        case STree.Syntax_Node_Type (Node => Local_Node) is
                           when SP_Symbols.loop_parameter_specification =>
                              CloseForStmt (Local_Node); -- CheckStack is always defined
                           when others =>
                              CloseLoop;
                        end case;
                     end if;
                     LoopContext.ExitLoop (LoopStack, VCGHeap, LScope);
                  when others =>
                     null;
               end case;
               LastNode := Node;
            end loop; -- Up ------------------------------------------
         end if;
         exit when Node = STree.NullNode or Node = StartNode;
      end loop; -- Down ------------------------------------
   end if;

   -- add "finish" node with arc to it;
   CreateUnitLabel (StmtLabel, VCGHeap);
   Graph.Inc_Nmbr_Of_Stmts;
   Graph.Create_Coeff (Heap => VCGHeap,
                       I    => StmtStack.Top.StmtNmbr,
                       J    => Graph.Get_Nmbr_Of_Stmts,
                       K    => StmtLabel);

   -- We pass Semantic_Error_In_Subprogram to IncorporateConstraints so that it can create a FALSE VC
   -- for malformed subprogram bodies.

   -- CheckStack is always defined
   -- ImportConstraints is defined if RedType.RTC
   -- Any last assignment to QuantNum, CheckStack and ShortCircuitStack
   -- within IncorporateConstraints will be reported as ineffective.
   --# accept F, 10, KindOfStackedCheck, "Ineffective assignment here OK" &
   --#        F, 10, CheckStack, "Ineffective assignment here OK" &
   --#        F, 10, ShortCircuitStack, "Ineffective assignment here OK";
   IncorporateConstraints
     (Semantic_Error_In_Subprogram => Semantic_Error_In_Subprogram,
      Type_Check_Exports           => Type_Check_Exports,
      Scope                        => Scope);
   --# end accept;

   if Semantic_Error_In_Subprogram then
      SPARK_IO.New_Line (OutputFile, 1);
      SPARK_IO.Put_Line (OutputFile, "/* False VC generated due to semantic errors in subprogram */", 0);
   end if;

   if ContainsReals then
      ErrorHandler.Semantic_Warning (Err_Num  => 405,
                                     Position => EndPosition,
                                     Id_Str   => LexTokenManager.Null_String);
   end if;
end BuildGraph;
