Patchwork [fortran] PR 47659 - extend conversion warnings to assignments

login
register
mail settings
Submitter Thomas Koenig
Date Aug. 21, 2011, 11:21 a.m.
Message ID <4E50EA33.3040400@netcologne.de>
Download mbox | patch
Permalink /patch/110827/
State New
Headers show

Comments

Thomas Koenig - Aug. 21, 2011, 11:21 a.m.
Hello everybody,

now that I have found a little time, here is an updated version of
the patch, which incorporates Tobias' suggestions.  Regression-tested.

OK for trunk?

	Thomas

2011-08-21  Thomas Koenig  <tkoenig@gcc.gnu.org>

         PR fortran/47659
         * expr.c (gfc_check_assign): Check for type conversions when the
         right-hand side is a constant REAL/COMPLEX contstant the left-hand
         side is also REAL/COMPLEX.  Don't warn when a narrowing conversion
         for REAL does not change the value of the constant.

2011-08-21  Thomas Koenig  <tkoenig@gcc.gnu.org>

         PR fortran/47659
         * gfortran.dg/warn_conversion_2.f90:  Also warn about conversion
         of a constant resulting from simplification.
         * gfortran.dg/warn_conversion_3.f90:  New test.
! { dg-do compile }
! { dg-options "-Wconversion -Wconversion-extra" }
! PR 47659 - warning about conversions on assignment
! Based on test cases by Thomas Henlich and Tobias Burnus.
program main
  double precision d1, d2
  complex(8), parameter :: z = cmplx (0.5, 0.5)  ! { dg-warning "Conversion" }
  real :: r1, r2
  r1 = 2.3d0 ! { dg-warning "Change of value in conversion" }
  r2 = 2.5d0 ! No warning because the value does not change
  d1 = .13 ! { dg-warning "Conversion" }
  d2 = .13d0
  d1 = z     ! { dg-warning "change of value in conversion" }
end program main
Tobias Burnus - Aug. 21, 2011, 3:01 p.m.
Thomas Koenig wrote:
> now that I have found a little time, here is an updated version of
> the patch, which incorporates Tobias' suggestions.  Regression-tested.
>
> OK for trunk?

OK. Thanks for the patch!

Tobias

> 2011-08-21  Thomas Koenig <tkoenig@gcc.gnu.org>
>
>         PR fortran/47659
>         * expr.c (gfc_check_assign): Check for type conversions when the
>         right-hand side is a constant REAL/COMPLEX contstant the 
> left-hand
>         side is also REAL/COMPLEX.  Don't warn when a narrowing 
> conversion
>         for REAL does not change the value of the constant.
>
> 2011-08-21  Thomas Koenig <tkoenig@gcc.gnu.org>
>
>         PR fortran/47659
>         * gfortran.dg/warn_conversion_2.f90:  Also warn about conversion
>         of a constant resulting from simplification.
>         * gfortran.dg/warn_conversion_3.f90:  New test.
Thomas Koenig - Aug. 21, 2011, 4:36 p.m.
Hello Tobias,

>
> OK. Thanks for the patch!

Sende          fortran/ChangeLog
Sende          fortran/expr.c
Sende          testsuite/ChangeLog
Sende          testsuite/gfortran.dg/warn_conversion_2.f90
Hinzufügen     testsuite/gfortran.dg/warn_conversion_3.f90
Übertrage Daten .....
Revision 177942 übertragen.

Thanks for the comments and the review!

	Thomas

Patch

Index: fortran/expr.c
===================================================================
--- fortran/expr.c	(Revision 177746)
+++ fortran/expr.c	(Arbeitskopie)
@@ -3190,6 +3190,53 @@ 
 	}
     }
 
+  /*  Warn about type-changing conversions for REAL or COMPLEX constants.
+      If lvalue and rvalue are mixed REAL and complex, gfc_compare_types
+      will warn anyway, so there is no need to to so here.  */
+
+  if (rvalue->expr_type == EXPR_CONSTANT && lvalue->ts.type == rvalue->ts.type
+      && (lvalue->ts.type == BT_REAL || lvalue->ts.type == BT_COMPLEX))
+    {
+      if (lvalue->ts.kind < rvalue->ts.kind && gfc_option.gfc_warn_conversion)
+	{
+	  /* As a special bonus, don't warn about REAL rvalues which are not
+	     changed by the conversion if -Wconversion is specified.  */
+	  if (rvalue->ts.type == BT_REAL && mpfr_number_p (rvalue->value.real))
+	    {
+	      /* Calculate the difference between the constant and the rounded
+		 value and check it against zero.  */
+	      mpfr_t rv, diff;
+	      gfc_set_model_kind (lvalue->ts.kind);
+	      mpfr_init (rv);
+	      gfc_set_model_kind (rvalue->ts.kind);
+	      mpfr_init (diff);
+	      
+	      mpfr_set (rv, rvalue->value.real, GFC_RND_MODE);
+	      mpfr_sub (diff, rv, rvalue->value.real, GFC_RND_MODE);
+	  
+	      if (!mpfr_zero_p (diff))
+		gfc_warning ("Change of value in conversion from "
+			     " %s to %s at %L", gfc_typename (&rvalue->ts),
+			     gfc_typename (&lvalue->ts), &rvalue->where);
+	      
+	      mpfr_clear (rv);
+	      mpfr_clear (diff);
+	    }
+	  else
+	    gfc_warning ("Possible change of value in conversion from %s "
+			 "to %s at %L",gfc_typename (&rvalue->ts),
+			 gfc_typename (&lvalue->ts), &rvalue->where);
+
+	}
+      else if (gfc_option.warn_conversion_extra
+	       && lvalue->ts.kind > rvalue->ts.kind)
+	{
+	  gfc_warning ("Conversion from %s to %s at %L",
+		       gfc_typename (&rvalue->ts),
+		       gfc_typename (&lvalue->ts), &rvalue->where);
+	}
+    }
+
   if (gfc_compare_types (&lvalue->ts, &rvalue->ts))
     return SUCCESS;
 
Index: testsuite/gfortran.dg/warn_conversion_2.f90
===================================================================
--- testsuite/gfortran.dg/warn_conversion_2.f90	(Revision 177746)
+++ testsuite/gfortran.dg/warn_conversion_2.f90	(Arbeitskopie)
@@ -7,5 +7,5 @@ 
   x = 2.0
   sqrt2 = sqrt(x)      ! { dg-warning "Conversion" }
 
-  sqrt2 = sqrt(2.0)    ! no warning; simplified to a constant and range checked
+  sqrt2 = sqrt(2.0)    ! { dg-warning "Conversion" }
 end