OSDN Git Service

2008-08-01 Ed Schonberg <schonberg@adacore.com>
authorcharlet <charlet@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 1 Aug 2008 09:02:44 +0000 (09:02 +0000)
committercharlet <charlet@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 1 Aug 2008 09:02:44 +0000 (09:02 +0000)
* checks.adb (Apply_Float_Conversion_Check): If the expression to be
converted is a real literal and the target type has static bounds,
perform the conversion exactly to prevent floating-point anomalies on
some targets.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@138486 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ada/checks.adb

index 6eb7ebb..f55bd7c 100644 (file)
@@ -1633,11 +1633,36 @@ package body Checks is
          end;
       end if;
 
-      --  Get the bounds of the target type
+      --  Get the (static) bounds of the target type
 
       Ifirst := Expr_Value (LB);
       Ilast  := Expr_Value (HB);
 
+      --  A simple optimization: if the expression is a universal literal,
+      --  we can do the comparison with the bounds and the conversion to
+      --  an integer type statically. The range checks are unchanged.
+
+      if Nkind (Ck_Node) = N_Real_Literal
+        and then Etype (Ck_Node) = Universal_Real
+        and then Is_Integer_Type (Target_Typ)
+        and then Nkind (Parent (Ck_Node)) = N_Type_Conversion
+      then
+         declare
+            Int_Val : constant Uint := UR_To_Uint (Realval (Ck_Node));
+
+         begin
+            if Int_Val <= Ilast and then Int_Val >= Ifirst then
+
+               --  Conversion is safe.
+
+               Rewrite (Parent (Ck_Node),
+                 Make_Integer_Literal (Loc, UI_To_Int (Int_Val)));
+               Analyze_And_Resolve (Parent (Ck_Node), Target_Typ);
+               return;
+            end if;
+         end;
+      end if;
+
       --  Check against lower bound
 
       if Truncate and then Ifirst > 0 then