Lcheck : Compare_Result;
Ucheck : Compare_Result;
- Warn1 : constant Boolean :=
+ Warn : constant Boolean :=
Constant_Condition_Warnings
and then Comes_From_Source (N)
and then not In_Instance;
-- also skip these warnings in an instance since it may be the
-- case that different instantiations have different ranges.
- Warn2 : constant Boolean :=
- Warn1
- and then Nkind (Original_Node (Rop)) = N_Range
- and then Is_Integer_Type (Etype (Lo));
- -- For the case where only one bound warning is elided, we also
- -- insist on an explicit range and an integer type. The reason is
- -- that the use of enumeration ranges including an end point is
- -- common, as is the use of a subtype name, one of whose bounds is
- -- the same as the type of the expression.
-
begin
-- If test is explicit x'First .. x'Last, replace by valid check
-- legality checks, because we are constant-folding beyond RM 4.9.
if Lcheck = LT or else Ucheck = GT then
- if Warn1 then
+ if Warn then
Error_Msg_N ("?c?range test optimized away", N);
Error_Msg_N ("\?c?value is known to be out of range", N);
end if;
-- since we know we are in range.
elsif Lcheck in Compare_GE and then Ucheck in Compare_LE then
- if Warn1 then
+ if Warn then
Error_Msg_N ("?c?range test optimized away", N);
Error_Msg_N ("\?c?value is known to be in range", N);
end if;
-- a comparison against the upper bound.
elsif Lcheck in Compare_GE then
- if Warn2 and then not In_Instance then
- Error_Msg_N ("??lower bound test optimized away", Lo);
- Error_Msg_N ("\??value is known to be in range", Lo);
- end if;
-
Rewrite (N,
Make_Op_Le (Loc,
Left_Opnd => Lop,
Analyze_And_Resolve (N, Restyp);
goto Leave;
- -- If upper bound check succeeds and lower bound check is not
- -- known to succeed or fail, then replace the range check with
- -- a comparison against the lower bound.
+ -- Inverse of previous case.
elsif Ucheck in Compare_LE then
- if Warn2 and then not In_Instance then
- Error_Msg_N ("??upper bound test optimized away", Hi);
- Error_Msg_N ("\??value is known to be in range", Hi);
- end if;
-
Rewrite (N,
Make_Op_Ge (Loc,
Left_Opnd => Lop,
-- see if we can determine the outcome assuming everything is
-- valid, and if so give an appropriate warning.
- if Warn1 and then not Assume_No_Invalid_Values then
+ if Warn and then not Assume_No_Invalid_Values then
Lcheck := Compile_Time_Compare (Lop, Lo, Assume_Valid => True);
Ucheck := Compile_Time_Compare (Lop, Hi, Assume_Valid => True);
elsif Lcheck in Compare_GE and then Ucheck in Compare_LE then
Error_Msg_N
("?c?value can only be out of range if it is invalid", N);
-
- -- Lower bound check succeeds if value is valid
-
- elsif Warn2 and then Lcheck in Compare_GE then
- Error_Msg_N
- ("?c?lower bound check only fails if it is invalid", Lo);
-
- -- Upper bound check succeeds if value is valid
-
- elsif Warn2 and then Ucheck in Compare_LE then
- Error_Msg_N
- ("?c?upper bound check only fails for invalid values", Hi);
end if;
end if;
end;
Assume_No_Invalid_Values : Boolean := False;
-- GNAT Normally, in accordance with (RM 13.9.1 (9-11)) the front end
-- assumes that values could have invalid representations, unless it can
- -- clearly prove that the values are valid. If this switch is set (by
+ -- prove that the values are valid. If this switch is set (by -gnatB or
-- pragma Assume_No_Invalid_Values (On)), then the compiler assumes values
- -- are valid and in range of their representations. This feature is now
- -- fully enabled in the compiler.
-
- -- WARNING: There is a matching C declaration of this variable in fe.h
+ -- are valid and in range of their representations.
Back_Annotate_Rep_Info : Boolean := False;
-- GNAT