Hello world,

the attached patch extends conversion warnings to assignments.

OK for trunk?

        Thomas

011-08-14  Thomas Koenig  <tkoe...@gcc.gnu.org>

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

2011-08-14  Thomas Koenig  <tkoe...@gcc.gnu.org>

        PR fortran/46659
        * gfortran.dg/warn_conversion_2.f90:  Also warn about conversion
        of a constant resulting from simplification.
        * gfortran.dg/warn_conversion_3.f90:  New test.
Index: fortran/expr.c
===================================================================
--- fortran/expr.c	(Revision 177746)
+++ fortran/expr.c	(Arbeitskopie)
@@ -3190,6 +3190,53 @@ gfc_check_assign (gfc_expr *lvalue, gfc_expr *rval
 	}
     }
 
+  /*  If lvalue is REAL and rvalue is a REAL constant with different,
+      warn about possible errors the user may have done during conversion.  */
+
+  if (rvalue->expr_type == EXPR_CONSTANT
+      && (lvalue->ts.type == BT_REAL || lvalue->ts.type == BT_COMPLEX)
+      && (rvalue->ts.type == BT_REAL || rvalue->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
! { dg-do compile }
! { dg-options "-Wconversion -Wconversion-extra" }
! PR 47659 - warning about conversions on assignment
! Based on a test case by Thomas Henlich
program main
  double precision d1, d2
  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
end program main

Reply via email to