aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorEd Schonberg <schonberg@adacore.com>2008-08-01 11:02:44 +0200
committerArnaud Charlet <charlet@gcc.gnu.org>2008-08-01 11:02:44 +0200
commit44114dff15f7dd78e05b31920beee7d56a7dc03c (patch)
treed764922d7874c29d0afee9da316ce2c0ab88b390 /gcc
parentb43112145089bb0bc42ac48dfb0900a73d47aef4 (diff)
downloadgcc-44114dff15f7dd78e05b31920beee7d56a7dc03c.zip
gcc-44114dff15f7dd78e05b31920beee7d56a7dc03c.tar.gz
gcc-44114dff15f7dd78e05b31920beee7d56a7dc03c.tar.bz2
checks.adb (Apply_Float_Conversion_Check): If the expression to be converted is a real literal and the target type has...
2008-08-01 Ed Schonberg <schonberg@adacore.com> * 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. From-SVN: r138486
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ada/checks.adb27
1 files changed, 26 insertions, 1 deletions
diff --git a/gcc/ada/checks.adb b/gcc/ada/checks.adb
index 6eb7ebb..f55bd7c 100644
--- a/gcc/ada/checks.adb
+++ b/gcc/ada/checks.adb
@@ -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