aboutsummaryrefslogtreecommitdiff
path: root/gcc/ada/libgnat/s-valueu.adb
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/ada/libgnat/s-valueu.adb')
-rw-r--r--gcc/ada/libgnat/s-valueu.adb333
1 files changed, 9 insertions, 324 deletions
diff --git a/gcc/ada/libgnat/s-valueu.adb b/gcc/ada/libgnat/s-valueu.adb
index e6f1d5e..a27e00f 100644
--- a/gcc/ada/libgnat/s-valueu.adb
+++ b/gcc/ada/libgnat/s-valueu.adb
@@ -29,78 +29,10 @@
-- --
------------------------------------------------------------------------------
-with System.SPARK.Cut_Operations; use System.SPARK.Cut_Operations;
with System.Val_Util; use System.Val_Util;
package body System.Value_U is
- -- Ghost code, loop invariants and assertions in this unit are meant for
- -- analysis only, not for run-time checking, as it would be too costly
- -- otherwise. This is enforced by setting the assertion policy to Ignore.
-
- pragma Assertion_Policy (Ghost => Ignore,
- Loop_Invariant => Ignore,
- Assert => Ignore,
- Assert_And_Cut => Ignore,
- Subprogram_Variant => Ignore);
-
- use type Spec.Uns_Option;
- use type Spec.Split_Value_Ghost;
-
- -- Local lemmas
-
- procedure Lemma_Digit_Not_Last
- (Str : String;
- P : Integer;
- From : Integer;
- To : Integer)
- with Ghost,
- Pre => Str'Last /= Positive'Last
- and then From in Str'Range
- and then To in From .. Str'Last
- and then Str (From) in '0' .. '9' | 'a' .. 'f' | 'A' .. 'F'
- and then P in From .. To
- and then P <= Spec.Last_Hexa_Ghost (Str (From .. To)) + 1
- and then Spec.Is_Based_Format_Ghost (Str (From .. To)),
- Post =>
- (if Str (P) in '0' .. '9' | 'a' .. 'f' | 'A' .. 'F'
- then P <= Spec.Last_Hexa_Ghost (Str (From .. To)));
-
- procedure Lemma_Underscore_Not_Last
- (Str : String;
- P : Integer;
- From : Integer;
- To : Integer)
- with Ghost,
- Pre => Str'Last /= Positive'Last
- and then From in Str'Range
- and then To in From .. Str'Last
- and then Str (From) in '0' .. '9' | 'a' .. 'f' | 'A' .. 'F'
- and then P in From .. To
- and then Str (P) = '_'
- and then P <= Spec.Last_Hexa_Ghost (Str (From .. To)) + 1
- and then Spec.Is_Based_Format_Ghost (Str (From .. To)),
- Post => P + 1 <= Spec.Last_Hexa_Ghost (Str (From .. To))
- and then Str (P + 1) in '0' .. '9' | 'a' .. 'f' | 'A' .. 'F';
-
- -----------------------------
- -- Local lemma null bodies --
- -----------------------------
-
- procedure Lemma_Digit_Not_Last
- (Str : String;
- P : Integer;
- From : Integer;
- To : Integer)
- is null;
-
- procedure Lemma_Underscore_Not_Last
- (Str : String;
- P : Integer;
- From : Integer;
- To : Integer)
- is null;
-
-----------------------
-- Scan_Raw_Unsigned --
-----------------------
@@ -132,36 +64,6 @@ package body System.Value_U is
Digit : Uns;
-- Digit value
- Ptr_Old : constant Integer := Ptr.all
- with Ghost;
- Last_Num_Init : constant Integer :=
- Last_Number_Ghost (Str (Ptr.all .. Max))
- with Ghost;
- Init_Val : constant Spec.Uns_Option :=
- Spec.Scan_Based_Number_Ghost (Str, Ptr.all, Last_Num_Init)
- with Ghost;
- Starts_As_Based : constant Boolean :=
- Spec.Raw_Unsigned_Starts_As_Based_Ghost (Str, Last_Num_Init, Max)
- with Ghost;
- Last_Num_Based : constant Integer :=
- (if Starts_As_Based
- then Spec.Last_Hexa_Ghost (Str (Last_Num_Init + 2 .. Max))
- else Last_Num_Init)
- with Ghost;
- Is_Based : constant Boolean :=
- Spec.Raw_Unsigned_Is_Based_Ghost
- (Str, Last_Num_Init, Last_Num_Based, Max)
- with Ghost;
- Based_Val : constant Spec.Uns_Option :=
- (if Starts_As_Based and then not Init_Val.Overflow
- then Spec.Scan_Based_Number_Ghost
- (Str, Last_Num_Init + 2, Last_Num_Based, Init_Val.Value)
- else Init_Val)
- with Ghost;
- First_Exp : constant Integer :=
- (if Is_Based then Last_Num_Based + 2 else Last_Num_Init + 1)
- with Ghost;
-
begin
-- We do not tolerate strings with Str'Last = Positive'Last
@@ -171,7 +73,15 @@ package body System.Value_U is
end if;
P := Ptr.all;
- Spec.Lemma_Scan_Based_Number_Ghost_Step (Str, P, Last_Num_Init);
+
+ -- Exit when the initial string to parse is empty
+
+ if Max < P then
+ raise Program_Error with
+ "Scan end Max=" & Max'Img &
+ " is smaller than scan end Ptr=" & P'Img;
+ end if;
+
Uval := Character'Pos (Str (P)) - Character'Pos ('0');
pragma Assert (Str (P) in '0' .. '9');
P := P + 1;
@@ -189,14 +99,6 @@ package body System.Value_U is
begin
-- Loop through decimal digits
loop
- pragma Loop_Invariant (P in P'Loop_Entry .. Last_Num_Init + 1);
- pragma Loop_Invariant
- (if Overflow then Init_Val.Overflow);
- pragma Loop_Invariant
- (if not Overflow
- then Init_Val = Spec.Scan_Based_Number_Ghost
- (Str, P, Last_Num_Init, Acc => Uval));
-
exit when P > Max;
Digit := Character'Pos (Str (P)) - Character'Pos ('0');
@@ -205,8 +107,6 @@ package body System.Value_U is
if Digit > 9 then
if Str (P) = '_' then
- Spec.Lemma_Scan_Based_Number_Ghost_Underscore
- (Str, P, Last_Num_Init, Acc => Uval);
Scan_Underscore (Str, P, Ptr, Max, False);
else
exit;
@@ -215,55 +115,23 @@ package body System.Value_U is
-- Accumulate result, checking for overflow
else
- pragma Assert
- (By
- (Str (P) in '0' .. '9',
- By
- (Character'Pos (Str (P)) >= Character'Pos ('0'),
- Uns '(Character'Pos (Str (P))) >=
- Character'Pos ('0'))));
- Spec.Lemma_Scan_Based_Number_Ghost_Step
- (Str, P, Last_Num_Init, Acc => Uval);
- Spec.Lemma_Scan_Based_Number_Ghost_Overflow
- (Str, P, Last_Num_Init, Acc => Uval);
-
if Uval <= Umax then
Uval := 10 * Uval + Digit;
- pragma Assert
- (if not Overflow
- then Init_Val = Spec.Scan_Based_Number_Ghost
- (Str, P + 1, Last_Num_Init, Acc => Uval));
-
elsif Uval > Umax10 then
Overflow := True;
-
else
Uval := 10 * Uval + Digit;
if Uval < Umax10 then
Overflow := True;
end if;
- pragma Assert
- (if not Overflow
- then Init_Val = Spec.Scan_Based_Number_Ghost
- (Str, P + 1, Last_Num_Init, Acc => Uval));
-
end if;
P := P + 1;
end if;
end loop;
- Spec.Lemma_Scan_Based_Number_Ghost_Base
- (Str, P, Last_Num_Init, Acc => Uval);
end;
- pragma Assert_And_Cut
- (By
- (P = Last_Num_Init + 1,
- P > Max or else Str (P) not in '_' | '0' .. '9')
- and then Overflow = Init_Val.Overflow
- and then (if not Overflow then Init_Val.Value = Uval));
-
Ptr.all := P;
-- Deal with based case. We recognize either the standard '#' or the
@@ -295,10 +163,6 @@ package body System.Value_U is
-- Numbers bigger than UmaxB overflow if multiplied by base
begin
- pragma Assert
- (if Str (P) in '0' .. '9' | 'A' .. 'F' | 'a' .. 'f'
- then Spec.Is_Based_Format_Ghost (Str (P .. Max)));
-
-- Loop to scan out based integer value
loop
@@ -321,49 +185,11 @@ package body System.Value_U is
-- already stored in Ptr.all.
else
- pragma Assert
- (By
- (Spec.Only_Hexa_Ghost (Str, P, Last_Num_Based),
- P > Last_Num_Init + 1
- and Spec.Only_Hexa_Ghost
- (Str, Last_Num_Init + 2, Last_Num_Based)));
- Spec.Lemma_Scan_Based_Number_Ghost_Base
- (Str, P, Last_Num_Based, Base, Uval);
Uval := Base;
Base := 10;
- pragma Assert (Ptr.all = Last_Num_Init + 1);
- pragma Assert
- (if Starts_As_Based
- then By
- (P = Last_Num_Based + 1,
- P <= Last_Num_Based + 1
- and Str (P) not in
- '0' .. '9' | 'a' .. 'f' | 'A' .. 'F' | '_'));
- pragma Assert (not Is_Based);
- pragma Assert (if not Overflow then Uval = Init_Val.Value);
exit;
end if;
- pragma Loop_Invariant (P in P'Loop_Entry .. Last_Num_Based);
- pragma Loop_Invariant
- (Str (P) in '0' .. '9' | 'a' .. 'f' | 'A' .. 'F'
- and then Digit = Spec.Hexa_To_Unsigned_Ghost (Str (P)));
- pragma Loop_Invariant
- (if Overflow'Loop_Entry then Overflow);
- pragma Loop_Invariant
- (if Overflow then
- (Overflow'Loop_Entry or else Based_Val.Overflow));
- pragma Loop_Invariant
- (if not Overflow
- then Based_Val = Spec.Scan_Based_Number_Ghost
- (Str, P, Last_Num_Based, Base, Uval));
- pragma Loop_Invariant (Ptr.all = Last_Num_Init + 1);
-
- Spec.Lemma_Scan_Based_Number_Ghost_Step
- (Str, P, Last_Num_Based, Base, Uval);
- Spec.Lemma_Scan_Based_Number_Ghost_Overflow
- (Str, P, Last_Num_Based, Base, Uval);
-
-- If digit is too large, just signal overflow and continue.
-- The idea here is to keep scanning as long as the input is
-- syntactically valid, even if we have detected overflow
@@ -375,24 +201,14 @@ package body System.Value_U is
elsif Uval <= Umax then
Uval := Base * Uval + Digit;
- pragma Assert
- (if not Overflow
- then Based_Val = Spec.Scan_Based_Number_Ghost
- (Str, P + 1, Last_Num_Based, Base, Uval));
-
elsif Uval > UmaxB then
Overflow := True;
-
else
Uval := Base * Uval + Digit;
if Uval < UmaxB then
Overflow := True;
end if;
- pragma Assert
- (if not Overflow
- then Based_Val = Spec.Scan_Based_Number_Ghost
- (Str, P + 1, Last_Num_Based, Base, Uval));
end if;
-- If at end of string with no base char, not a based number
@@ -411,86 +227,22 @@ package body System.Value_U is
if Str (P) = Base_Char then
Ptr.all := P + 1;
- pragma Assert (P = Last_Num_Based + 1);
- pragma Assert (Ptr.all = Last_Num_Based + 2);
- pragma Assert
- (By
- (Is_Based,
- So
- (Starts_As_Based,
- So
- (Last_Num_Based < Max,
- Str (Last_Num_Based + 1) = Base_Char
- and Base_Char = Str (Last_Num_Init + 1)))));
- Spec.Lemma_Scan_Based_Number_Ghost_Base
- (Str, P, Last_Num_Based, Base, Uval);
exit;
-- Deal with underscore
elsif Str (P) = '_' then
- Lemma_Underscore_Not_Last (Str, P, Last_Num_Init + 2, Max);
- Spec.Lemma_Scan_Based_Number_Ghost_Underscore
- (Str, P, Last_Num_Based, Base, Uval);
Scan_Underscore (Str, P, Ptr, Max, True);
- pragma Assert
- (if not Overflow
- then Based_Val = Spec.Scan_Based_Number_Ghost
- (Str, P, Last_Num_Based, Base, Uval));
- pragma Assert (Str (P) not in '_' | Base_Char);
end if;
-
- Lemma_Digit_Not_Last (Str, P, Last_Num_Init + 2, Max);
- pragma Assert (Str (P) not in '_' | Base_Char);
end loop;
end;
- pragma Assert
- (if Starts_As_Based then P = Last_Num_Based + 1
- else P = Last_Num_Init + 2);
- pragma Assert
- (By
- (Overflow /= Spec.Scan_Split_No_Overflow_Ghost
- (Str, Ptr_Old, Max),
- So
- (Last_Num_Init < Max - 1
- and then Str (Last_Num_Init + 1) in '#' | ':',
- Overflow =
- (Init_Val.Overflow
- or else Init_Val.Value not in 2 .. 16
- or else (Starts_As_Based and Based_Val.Overflow)))));
end if;
- pragma Assert_And_Cut
- (Overflow /= Spec.Scan_Split_No_Overflow_Ghost (Str, Ptr_Old, Max)
- and then Ptr.all = First_Exp
- and then Base in 2 .. 16
- and then
- (if not Overflow then
- (if Is_Based then Base = Init_Val.Value else Base = 10))
- and then
- (if not Overflow then
- (if Is_Based then Uval = Based_Val.Value
- else Uval = Init_Val.Value)));
-
-- Come here with scanned unsigned value in Uval. The only remaining
-- required step is to deal with exponent if one is present.
Scan_Exponent (Str, Ptr, Max, Expon);
- pragma Assert
- (By
- (Ptr.all = Spec.Raw_Unsigned_Last_Ghost (Str, Ptr_Old, Max),
- Ptr.all =
- (if not Starts_As_Exponent_Format_Ghost (Str (First_Exp .. Max))
- then First_Exp
- elsif Str (First_Exp + 1) in '-' | '+' then
- Last_Number_Ghost (Str (First_Exp + 2 .. Max)) + 1
- else Last_Number_Ghost (Str (First_Exp + 1 .. Max)) + 1)));
- pragma Assert
- (if not Overflow
- then Spec.Scan_Split_Value_Ghost (Str, Ptr_Old, Max) =
- (Uval, Base, Expon));
-
if Expon /= 0 and then Uval /= 0 then
-- For non-zero value, scale by exponent value. No need to do this
@@ -500,66 +252,22 @@ package body System.Value_U is
declare
UmaxB : constant Uns := Uns'Last / Base;
-- Numbers bigger than UmaxB overflow if multiplied by base
-
- Res_Val : constant Spec.Uns_Option :=
- Spec.Exponent_Unsigned_Ghost (Uval, Expon, Base)
- with Ghost;
begin
for J in 1 .. Expon loop
- pragma Loop_Invariant
- (if Overflow'Loop_Entry then Overflow);
- pragma Loop_Invariant
- (if Overflow
- then Overflow'Loop_Entry or else Res_Val.Overflow);
- pragma Loop_Invariant (Uval /= 0);
- pragma Loop_Invariant
- (if not Overflow
- then Res_Val = Spec.Exponent_Unsigned_Ghost
- (Uval, Expon - J + 1, Base));
-
- pragma Assert
- ((Uval > UmaxB) = Spec.Scan_Overflows_Ghost (0, Base, Uval));
-
if Uval > UmaxB then
- Spec.Lemma_Exponent_Unsigned_Ghost_Overflow
- (Uval, Expon - J + 1, Base);
Overflow := True;
exit;
end if;
- Spec.Lemma_Exponent_Unsigned_Ghost_Step
- (Uval, Expon - J + 1, Base);
-
Uval := Uval * Base;
end loop;
- Spec.Lemma_Exponent_Unsigned_Ghost_Base (Uval, 0, Base);
-
- pragma Assert
- (Overflow /=
- Spec.Raw_Unsigned_No_Overflow_Ghost (Str, Ptr_Old, Max));
- pragma Assert (if not Overflow then Res_Val = (False, Uval));
end;
end if;
- Spec.Lemma_Exponent_Unsigned_Ghost_Base (Uval, Expon, Base);
- pragma Assert
- (if Expon = 0 or else Uval = 0 then
- Spec.Exponent_Unsigned_Ghost (Uval, Expon, Base) = (False, Uval));
- pragma Assert
- (Overflow /=
- Spec.Raw_Unsigned_No_Overflow_Ghost (Str, Ptr_Old, Max));
- pragma Assert
- (if not Overflow then
- Uval = Spec.Scan_Raw_Unsigned_Ghost (Str, Ptr_Old, Max));
-- Return result, dealing with overflow
if Overflow then
Bad_Value (Str);
- pragma Annotate
- (GNATprove, Intentional,
- "call to nonreturning subprogram might be executed",
- "it is expected that Constraint_Error is raised in case of"
- & " overflow");
else
Res := Uval;
end if;
@@ -608,15 +316,7 @@ package body System.Value_U is
if Str'Last = Positive'Last then
declare
subtype NT is String (1 .. Str'Length);
- procedure Prove_Is_Unsigned_Ghost with
- Ghost,
- Pre => Str'Length < Natural'Last
- and then not Only_Space_Ghost (Str, Str'First, Str'Last)
- and then Spec.Is_Unsigned_Ghost (Spec.Slide_To_1 (Str)),
- Post => Spec.Is_Unsigned_Ghost (NT (Str));
- procedure Prove_Is_Unsigned_Ghost is null;
begin
- Prove_Is_Unsigned_Ghost;
return Value_Unsigned (NT (Str));
end;
@@ -626,12 +326,6 @@ package body System.Value_U is
declare
V : Uns;
P : aliased Integer := Str'First;
- Non_Blank : constant Positive := First_Non_Space_Ghost
- (Str, Str'First, Str'Last)
- with Ghost;
- Fst_Num : constant Positive :=
- (if Str (Non_Blank) = '+' then Non_Blank + 1 else Non_Blank)
- with Ghost;
begin
declare
P_Acc : constant not null access Integer := P'Access;
@@ -639,16 +333,7 @@ package body System.Value_U is
Scan_Unsigned (Str, P_Acc, Str'Last, V);
end;
- pragma Assert
- (P = Spec.Raw_Unsigned_Last_Ghost (Str, Fst_Num, Str'Last));
- pragma Assert
- (V = Spec.Scan_Raw_Unsigned_Ghost (Str, Fst_Num, Str'Last));
-
Scan_Trailing_Blanks (Str, P);
-
- pragma Assert
- (Spec.Is_Value_Unsigned_Ghost
- (Spec.Slide_If_Necessary (Str), V));
return V;
end;
end if;