summaryrefslogtreecommitdiffstats
path: root/gcc/ada/sem_ch3.adb
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/ada/sem_ch3.adb')
-rw-r--r--gcc/ada/sem_ch3.adb75
1 files changed, 75 insertions, 0 deletions
diff --git a/gcc/ada/sem_ch3.adb b/gcc/ada/sem_ch3.adb
index fad454e5ec3..653d9dfa328 100644
--- a/gcc/ada/sem_ch3.adb
+++ b/gcc/ada/sem_ch3.adb
@@ -19678,6 +19678,81 @@ package body Sem_Ch3 is
Set_Ekind (T, E_Signed_Integer_Subtype);
Set_Etype (T, Implicit_Base);
+ -- In formal verification mode, override partially the decisions above
+ -- to restrict base type's range to the minimum allowed by RM 3.5.4,
+ -- namely the smallest symmetric range around zero with a possible extra
+ -- negative value that contains the subtype range. Keep Size, RM_Size
+ -- and First_Rep_Item info, which should not be relied upon in formal
+ -- verification.
+
+ if ALFA_Mode then
+
+ -- If the range of the type is already symmetric with a possible
+ -- extra negative value, just make the type its own base type.
+
+ if UI_Le (Lo_Val, Hi_Val)
+ and then (UI_Eq (Lo_Val, UI_Negate (Hi_Val))
+ or else
+ UI_Eq (Lo_Val, UI_Sub (UI_Negate (Hi_Val), Uint_1)))
+ then
+ Set_Etype (T, T);
+
+ else
+ declare
+ Sym_Hi_Val : Uint;
+ Sym_Lo_Val : Uint;
+ Decl : Node_Id;
+ Dloc : constant Source_Ptr := Sloc (Def);
+ Lbound : Node_Id;
+ Ubound : Node_Id;
+
+ begin
+ -- If the subtype range is empty, the smallest base type range
+ -- is the symmetric range around zero containing Lo_Val and
+ -- Hi_Val.
+
+ if UI_Gt (Lo_Val, Hi_Val) then
+ Sym_Hi_Val := UI_Max (UI_Abs (Lo_Val), UI_Abs (Hi_Val));
+ Sym_Lo_Val := UI_Negate (Sym_Hi_Val);
+
+ -- Otherwise, if the subtype range is not empty and Hi_Val has
+ -- the largest absolute value, Hi_Val is non negative and the
+ -- smallest base type range is the symmetric range around zero
+ -- containing Hi_Val.
+
+ elsif UI_Le (UI_Abs (Lo_Val), UI_Abs (Hi_Val)) then
+ Sym_Hi_Val := Hi_Val;
+ Sym_Lo_Val := UI_Negate (Hi_Val);
+
+ -- Otherwise, the subtype range is not empty, Lo_Val has the
+ -- strictly largest absolute value, Lo_Val is negative and the
+ -- smallest base type range is the symmetric range around zero
+ -- with an extra negative value Lo_Val.
+
+ else
+ Sym_Lo_Val := Lo_Val;
+ Sym_Hi_Val := UI_Sub (UI_Negate (Lo_Val), Uint_1);
+ end if;
+
+ Lbound := Make_Integer_Literal (Dloc, Sym_Lo_Val);
+ Ubound := Make_Integer_Literal (Dloc, Sym_Hi_Val);
+ Set_Is_Static_Expression (Lbound);
+ Set_Is_Static_Expression (Ubound);
+
+ Decl := Make_Full_Type_Declaration (Dloc,
+ Defining_Identifier => Implicit_Base,
+ Type_Definition =>
+ Make_Signed_Integer_Type_Definition (Dloc,
+ Low_Bound => Lbound,
+ High_Bound => Ubound));
+
+ Analyze (Decl);
+ Set_Etype (Implicit_Base, Implicit_Base);
+ Insert_Before (Parent (Def), Decl);
+ end;
+ end if;
+ end if;
+
Set_Size_Info (T, (Implicit_Base));
Set_First_Rep_Item (T, First_Rep_Item (Implicit_Base));
Set_Scalar_Range (T, Def);
OpenPOWER on IntegriCloud