Example of illegal code:

```ada
procedure P is
   Max : Integer := 42;
   subtype Int is Natural range 0 .. Max; -- error: Max is not constant

   type Int_Arr is array (Positive range <>) of Integer;
   A  : Int_Arr (1 .. 100) := (others => 0);

   type Int_Acc is access Integer;
   Ptr : Int_Acc := new Integer'(42);
begin
   declare
     I : Positive := 42;
     V : Integer renames A (I); -- error: I is not constant
   begin
     V := 1;
   end;

   declare
     V : Integer renames Ptr.all; -- error: Ptr is not constant
   begin
     V := 1;
   end;
end P;
```

This error is issued on direct reads of variables, or indirect reads of
variables through function calls, in specific expressions which should only
read constants in SPARK. Such a read violates legality rule 2 of [section 4.4 of
SPARK Reference Manual].

This is the case for type constraints, such as the bounds of subtype `Int`
above, which is not allowed to depend on the value of variable `Max`, as well
as array indexes and pointer dereferences occurring in renamed expressions like
`V1` and `V2`.

The fix is to introduce constants to capture the value of variables, that can
then be used in these specific expressions. For prefixes of dereferences, using
an anonymous access type like `constant access Integer` for `B` avoids
the need of copying the pointer back at the end of the scope of the renaming:

```ada
procedure P is
   Max : constant Integer := 42;
   subtype Int is Natural range 0 .. Max;

   type Int_Arr is array (Positive range <>) of Integer;
   A  : Int_Arr (1 .. 100) := (others => 0);

   type Int_Acc is access Integer;
   Ptr : Int_Acc := new Integer'(42);
begin
   declare
     I : constant Positive := 42;
     V : Integer renames A (I);
   begin
     V := 1;
   end;

   declare
     B : constant access Integer := Ptr;
     V : Integer renames B.all;
   begin
     V := 1;
   end;
end P;
```

[section 4.4 of SPARK Reference Manual]:
https://docs.adacore.com/live/wave/spark2014/html/spark2014_rm/names-and-expressions.html#expressions
