This change removes some unnecessary range checks. The following test
compiled with -gnatdt -gnatc:

     1. procedure RCInteger (X : Integer) is
     2.    type YT is new Integer;
     3.    Y : constant YT := YT(X) * YT(X);
     4. begin
     5.    null;
     6. end;

generates a tree file that has no instances of the Do_Range_Check flag
being set (the multiplication in line 3 needs an overflow check, but
not a subsequent range check).

This test, also compiled with -gnatdt -gnatc:

     1. procedure Assign_Int (X : in out Integer) is
     2.    Tmp : Integer := X + 1;
     3.    Pos : Positive := X + 2;
     4. begin
     5.    X := X + 3;
     6. end Assign_Int;

Generates a tree file with one instance of Do_Range_Check being set.
Line 3 needs a range check, but line 2 does not.

Tested on x86_64-pc-linux-gnu, committed on trunk

2014-08-04  Robert Dewar  <de...@adacore.com>

        * sem_eval.adb (Test_In_Range): Always in range for
        Is_Known_Valid target type, where input type has smaller or
        equal size and does not have biased rep.

Index: sem_eval.adb
===================================================================
--- sem_eval.adb        (revision 213530)
+++ sem_eval.adb        (working copy)
@@ -6193,6 +6193,18 @@
       then
          return In_Range;
 
+      --  Another special case. For signed integer types, if the target type
+      --  has Is_Known_Valid set, and the source type does not have a larger
+      --  size, then the source value must be in range. We exclude biased
+      --  types, because they bizarrely can generate out of range values.
+
+      elsif Is_Signed_Integer_Type (Etype (N))
+        and then Is_Known_Valid (Typ)
+        and then Esize (Etype (N)) <= Esize (Typ)
+        and then not Has_Biased_Representation (Etype (N))
+      then
+         return In_Range;
+
       --  For all other cases, result is unknown
 
       else

Reply via email to