This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [patch,fortran] Fix PR19310 unnecessary error for overflowing results


:REVIEWMAIL:

Here is another try. The attached revised patch implements -frange-check, allowing the negative -fno-range-check.

Also, I have added handling of NaN and Inf to trans-const.c and this takes care of PR19904 as well.

See also the attached test case.

Regression tested OK. Documentation checked.

OK for Trunk and 4.1 branch?

2006-06-08 Jerry DeLisle <jvdelisle@gcc.gnu.org>

	PR fortran/19310
	PR fortran/19904
	* 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): Return result if -frange-check not set.
	Add error messages for overflow, underflow, and other errors.
	* trans-const.c (gfc_conv_mpfr_to_tree): Build NaN and Inf.
Index: gfortran.h
===================================================================
*** gfortran.h	(revision 114499)
--- gfortran.h	(working copy)
*************** typedef struct
*** 1627,1632 ****
--- 1627,1633 ----
    int flag_max_stack_var_size;
    int flag_module_access_private;
    int flag_no_backend;
+   int flag_range_check;
    int flag_pack_derived;
    int flag_repack_arrays;
    int flag_preprocessed;
Index: lang.opt
===================================================================
*** lang.opt	(revision 114499)
--- lang.opt	(working copy)
*************** fno-backend
*** 181,186 ****
--- 181,190 ----
  Fortran RejectNegative
  Don't generate code, just do syntax and semantics checking
  
+ frange-check
+ Fortran
+ Enable range checking during compilation
+ 
  fpack-derived
  Fortran
  Try to layout derived types as compact as possible
Index: trans-const.c
===================================================================
*** trans-const.c	(revision 114499)
--- trans-const.c	(working copy)
*************** gfc_conv_mpfr_to_tree (mpfr_t f, int kin
*** 209,219 ****
--- 209,239 ----
    mp_exp_t exp;
    char *p, *q;
    int n;
+   REAL_VALUE_TYPE real;
  
    n = gfc_validate_kind (BT_REAL, kind, false);
  
    gcc_assert (gfc_real_kinds[n].radix == 2);
  
+   type = gfc_get_real_type (kind);
+ 
+   /* Take care of Infinity and NaN.  */
+   if (mpfr_inf_p (f))
+     {
+       real_inf (&real);
+       if (mpfr_sgn (f) < 0)
+ 	real.sign = 1;
+       res = build_real (type , real);
+       return res;
+     }
+ 
+   if (mpfr_nan_p (f))
+     {
+       real_nan (&real, "", 0, TYPE_MODE (type));
+       res = build_real (type , real);
+       return res;
+     }
+ 
    /* mpfr chooses too small a number of hexadecimal digits if the
       number of binary digits is not divisible by four, therefore we
       have to explicitly request a sufficient number of digits here.  */
*************** gfc_conv_mpfr_to_tree (mpfr_t f, int kin
*** 234,240 ****
    else
      sprintf (q, "0x.%sp%d", p, (int) exp);
  
-   type = gfc_get_real_type (kind);
    res = build_real (type, REAL_VALUE_ATOF (q, TYPE_MODE (type)));
  
    gfc_free (q);
--- 254,259 ----
Index: invoke.texi
===================================================================
*** invoke.texi	(revision 114499)
--- invoke.texi	(working copy)
*************** by type.  Explanations are in the follow
*** 122,128 ****
  -ffixed-line-length-@var{n}  -ffixed-line-length-none @gol
  -ffree-line-length-@var{n}  -ffree-line-length-none @gol
  -fdefault-double-8  -fdefault-integer-8  -fdefault-real-8 @gol
! -fcray-pointer  -fopenmp }
  
  @item Warning Options
  @xref{Warning Options,,Options to Request or Suppress Warnings}.
--- 122,128 ----
  -ffixed-line-length-@var{n}  -ffixed-line-length-none @gol
  -ffree-line-length-@var{n}  -ffree-line-length-none @gol
  -fdefault-double-8  -fdefault-integer-8  -fdefault-real-8 @gol
! -fcray-pointer  -fopenmp  -frange-check }
  
  @item Warning Options
  @xref{Warning Options,,Options to Request or Suppress Warnings}.
*************** and @code{c$}, @code{*$} and @code{!$} s
*** 308,313 ****
--- 308,322 ----
  and when linking arranges for the OpenMP runtime library to be linked
  in.
  
+ @cindex -frange-check
+ @cindex options, -frange-check
+ @item -frange-check
+ Enable range checking on results of simplification of constant expressions
+ during compilation.  For example, by default, @command{gfortran} will give
+ an overflow error at compile time when simplifying @code{a = EXP(1000)}.
+ With @samp{-fno-range-check}, no error will be given and the variable @code{a}
+ will be assigned the value @code{+Infinity}.
+ 
  @cindex -std=@var{std} option
  @cindex option, -std=@var{std}
  @item -std=@var{std}
Index: arith.c
===================================================================
*** arith.c	(revision 114499)
--- arith.c	(working copy)
*************** gfc_range_check (gfc_expr * e)
*** 555,560 ****
--- 555,563 ----
  {
    arith rc;
  
+   if (gfc_option.flag_range_check == 0)
+     return ARITH_OK;
+ 
    switch (e->ts.type)
      {
      case BT_INTEGER:
*************** gfc_arith_divide (gfc_expr * op1, gfc_ex
*** 813,820 ****
        break;
  
      case BT_REAL:
!       /* FIXME: MPFR correctly generates NaN.  This may not be needed.  */
!       if (mpfr_sgn (op2->value.real) == 0)
  	{
  	  rc = ARITH_DIV0;
  	  break;
--- 816,823 ----
        break;
  
      case BT_REAL:
!       if (mpfr_sgn (op2->value.real) == 0
! 	  && gfc_option.flag_range_check == 1)
  	{
  	  rc = ARITH_DIV0;
  	  break;
*************** gfc_arith_divide (gfc_expr * op1, gfc_ex
*** 825,833 ****
        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)
  	{
  	  rc = ARITH_DIV0;
  	  break;
--- 828,836 ----
        break;
  
      case BT_COMPLEX:
        if (mpfr_sgn (op2->value.complex.r) == 0
! 	  && mpfr_sgn (op2->value.complex.i) == 0
! 	  && gfc_option.flag_range_check == 1)
  	{
  	  rc = ARITH_DIV0;
  	  break;
Index: options.c
===================================================================
*** options.c	(revision 114499)
--- options.c	(working copy)
*************** gfc_init_options (unsigned int argc ATTR
*** 73,78 ****
--- 73,79 ----
    gfc_option.flag_max_stack_var_size = 32768;
    gfc_option.flag_module_access_private = 0;
    gfc_option.flag_no_backend = 0;
+   gfc_option.flag_range_check = 1;
    gfc_option.flag_pack_derived = 0;
    gfc_option.flag_repack_arrays = 0;
    gfc_option.flag_preprocessed = 0;
*************** gfc_handle_option (size_t scode, const c
*** 519,524 ****
--- 520,529 ----
        gfc_option.flag_no_backend = value;
        break;
  
+     case OPT_frange_check:
+       gfc_option.flag_range_check = value;
+       break;
+ 
      case OPT_fpack_derived:
        gfc_option.flag_pack_derived = value;
        break;
Index: simplify.c
===================================================================
*** simplify.c	(revision 114499)
--- simplify.c	(working copy)
*************** static int xascii_table[256];
*** 90,104 ****
  
  
  /* Range checks an expression node.  If all goes well, returns the
!    node, otherwise returns &gfc_bad_expr and frees the node.  */
  
  static gfc_expr *
  range_check (gfc_expr * result, const char *name)
  {
!   if (gfc_range_check (result) == ARITH_OK)
      return result;
  
!   gfc_error ("Result of %s overflows its kind at %L", name, &result->where);
    gfc_free_expr (result);
    return &gfc_bad_expr;
  }
--- 90,122 ----
  
  
  /* Range checks an expression node.  If all goes well, returns the
!    node, otherwise returns &gfc_bad_expr and frees the node.  Just
!    returns the result if -fno-range-check was given.  */
  
  static gfc_expr *
  range_check (gfc_expr * result, const char *name)
  {
!   if (gfc_option.flag_range_check == 0)
      return result;
  
!   switch (gfc_range_check (result))
!     {
!       case ARITH_OK:
! 	return result;
!  
!       case ARITH_OVERFLOW:
! 	gfc_error ("Result of %s overflows its kind at %L", name, &result->where);
! 	break;
! 
!       case ARITH_UNDERFLOW:
! 	gfc_error ("Result of %s underflows its kind at %L", name, &result->where);
! 	break;
! 
!       default:
! 	gfc_error ("Result of %s gives range error for its kind at %L", name, &result->where);
! 	break;
!     }
! 
    gfc_free_expr (result);
    return &gfc_bad_expr;
  }

Attachment: real_const_3.f90
Description: application/extension-f90


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]