aboutsummaryrefslogtreecommitdiff
path: root/gcc/fortran/arith.c
diff options
context:
space:
mode:
authorJerry DeLisle <jvdelisle@gcc.gnu.org>2006-06-18 06:36:45 +0000
committerJerry DeLisle <jvdelisle@gcc.gnu.org>2006-06-18 06:36:45 +0000
commit545548257d8ad0c0663f70c61a1fd189eaf896b8 (patch)
tree9f73b7afa27dd254cb18534c5d1ceda6349bf744 /gcc/fortran/arith.c
parent37b4da102f718345282ca7f9b5c7bf9be857fd47 (diff)
downloadgcc-545548257d8ad0c0663f70c61a1fd189eaf896b8.zip
gcc-545548257d8ad0c0663f70c61a1fd189eaf896b8.tar.gz
gcc-545548257d8ad0c0663f70c61a1fd189eaf896b8.tar.bz2
re PR fortran/19310 ([4.1 Only] unnecessary error for overflowing results)
2006-06-18 Jerry DeLisle <jvdelisle@gcc.gnu.org> PR fortran/19310 * arith.c (gfc_range_check): Return ARITH_OK if -fno-range-check. Add return of ARITH_NAN, ARITH_UNDERFLOW, and ARITH_OVERFLOW. (gfc_arith_divide): If -fno-range-check allow mpfr to divide by zero. * gfortran.h (gfc_option_t): Add new flag. * invoke.texi: Document new flag. * lang.opt: Add option -frange-check. * options.c (gfc_init_options): Initialize new flag. (gfc_handle_options): Set flag if invoked. * simplify.c (range_check): Add error messages for overflow, underflow, and other errors. * trans-const.c (gfc_conv_mpfr_to_tree): Build NaN and Inf from mpfr result. From-SVN: r114752
Diffstat (limited to 'gcc/fortran/arith.c')
-rw-r--r--gcc/fortran/arith.c64
1 files changed, 49 insertions, 15 deletions
diff --git a/gcc/fortran/arith.c b/gcc/fortran/arith.c
index 348b87f..55289b4 100644
--- a/gcc/fortran/arith.c
+++ b/gcc/fortran/arith.c
@@ -379,12 +379,36 @@ gfc_check_real_range (mpfr_t p, int kind)
mpfr_init (q);
mpfr_abs (q, p, GFC_RND_MODE);
- if (mpfr_sgn (q) == 0)
+ if (mpfr_inf_p (p))
+ {
+ if (gfc_option.flag_range_check == 0)
+ retval = ARITH_OK;
+ else
+ retval = ARITH_OVERFLOW;
+ }
+ else if (mpfr_nan_p (p))
+ {
+ if (gfc_option.flag_range_check == 0)
+ retval = ARITH_OK;
+ else
+ retval = ARITH_NAN;
+ }
+ else if (mpfr_sgn (q) == 0)
retval = ARITH_OK;
else if (mpfr_cmp (q, gfc_real_kinds[i].huge) > 0)
- retval = ARITH_OVERFLOW;
+ {
+ if (gfc_option.flag_range_check == 0)
+ retval = ARITH_OK;
+ else
+ retval = ARITH_OVERFLOW;
+ }
else if (mpfr_cmp (q, gfc_real_kinds[i].subnormal) < 0)
- retval = ARITH_UNDERFLOW;
+ {
+ if (gfc_option.flag_range_check == 0)
+ retval = ARITH_OK;
+ else
+ retval = ARITH_UNDERFLOW;
+ }
else if (mpfr_cmp (q, gfc_real_kinds[i].tiny) < 0)
{
/* MPFR operates on a numbers with a given precision and enormous
@@ -564,19 +588,29 @@ gfc_range_check (gfc_expr * e)
case BT_REAL:
rc = gfc_check_real_range (e->value.real, e->ts.kind);
if (rc == ARITH_UNDERFLOW)
- mpfr_set_ui (e->value.real, 0, GFC_RND_MODE);
+ mpfr_set_ui (e->value.real, 0, GFC_RND_MODE);
+ if (rc == ARITH_OVERFLOW)
+ mpfr_set_inf (e->value.real, mpfr_sgn (e->value.real));
+ if (rc == ARITH_NAN)
+ mpfr_set_nan (e->value.real);
break;
case BT_COMPLEX:
rc = gfc_check_real_range (e->value.complex.r, e->ts.kind);
if (rc == ARITH_UNDERFLOW)
- mpfr_set_ui (e->value.complex.r, 0, GFC_RND_MODE);
- if (rc == ARITH_OK || rc == ARITH_UNDERFLOW)
- {
- rc = gfc_check_real_range (e->value.complex.i, e->ts.kind);
- if (rc == ARITH_UNDERFLOW)
- mpfr_set_ui (e->value.complex.i, 0, GFC_RND_MODE);
- }
+ mpfr_set_ui (e->value.complex.r, 0, GFC_RND_MODE);
+ if (rc == ARITH_OVERFLOW)
+ mpfr_set_inf (e->value.complex.r, mpfr_sgn (e->value.complex.r));
+ if (rc == ARITH_NAN)
+ mpfr_set_nan (e->value.complex.r);
+
+ rc = gfc_check_real_range (e->value.complex.i, e->ts.kind);
+ if (rc == ARITH_UNDERFLOW)
+ mpfr_set_ui (e->value.complex.i, 0, GFC_RND_MODE);
+ if (rc == ARITH_OVERFLOW)
+ mpfr_set_inf (e->value.complex.i, mpfr_sgn (e->value.complex.i));
+ if (rc == ARITH_NAN)
+ mpfr_set_nan (e->value.complex.i);
break;
@@ -813,8 +847,8 @@ gfc_arith_divide (gfc_expr * op1, gfc_expr * op2, gfc_expr ** resultp)
break;
case BT_REAL:
- /* FIXME: MPFR correctly generates NaN. This may not be needed. */
- if (mpfr_sgn (op2->value.real) == 0)
+ if (mpfr_sgn (op2->value.real) == 0
+ && gfc_option.flag_range_check == 1)
{
rc = ARITH_DIV0;
break;
@@ -825,9 +859,9 @@ gfc_arith_divide (gfc_expr * op1, gfc_expr * op2, gfc_expr ** resultp)
break;
case BT_COMPLEX:
- /* FIXME: MPFR correctly generates NaN. This may not be needed. */
if (mpfr_sgn (op2->value.complex.r) == 0
- && mpfr_sgn (op2->value.complex.i) == 0)
+ && mpfr_sgn (op2->value.complex.i) == 0
+ && gfc_option.flag_range_check == 1)
{
rc = ARITH_DIV0;
break;