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  <tkoe...@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  <tkoe...@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
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

Reply via email to