gcc/fortran/:
authordfranke <dfranke@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 9 Jun 2010 19:40:58 +0000 (19:40 +0000)
committerdfranke <dfranke@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 9 Jun 2010 19:40:58 +0000 (19:40 +0000)
2010-06-09  Daniel Franke  <franke.daniel@gmail.com>

PR fortran/44359
* intrinsic.c (gfc_convert_type_warn): Further improve -Wconversion.

gcc/testsuite/:
2010-06-09  Daniel Franke  <franke.daniel@gmail.com>

PR fortran/44359
* gfortran.dg/warn_conversion.f90: Removed check for redundant
warning.
* gfortran.dg/warn_conversion_2.f90: Use non-constant expression to
check for warning.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@160505 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/fortran/ChangeLog
gcc/fortran/intrinsic.c
gcc/testsuite/ChangeLog
gcc/testsuite/gfortran.dg/warn_conversion.f90
gcc/testsuite/gfortran.dg/warn_conversion_2.f90

index 05ec55d..cafbd31 100644 (file)
@@ -1,3 +1,8 @@
+2010-06-09  Daniel Franke  <franke.daniel@gmail.com>
+
+       PR fortran/44359
+       * intrinsic.c (gfc_convert_type_warn): Further improve -Wconversion.
+
 2010-06-09  Janus Weil  <janus@gcc.gnu.org>
 
        PR fortran/44430
index 2d82f20..e5463a1 100644 (file)
@@ -4022,58 +4022,67 @@ gfc_convert_type_warn (gfc_expr *expr, gfc_typespec *ts, int eflag, int wflag)
     }
   else if (wflag)
     {
-      /* Two modes of warning:
-         - gfc_option.warn_conversion tries to be more intelligent
-           about the warnings raised and omits those where smaller
-           kinds are promoted to larger ones without change in the
-           value
-         - gfc_option.warn_conversion_extra does not take the kinds
-           into account and also warns for coversions like
-           REAL(4) -> REAL(8)
-
-        NOTE: Possible enhancement for warn_conversion
-        If converting from a smaller to a larger kind, check if the
-        value is constant and if yes, whether the value still fits
-        in the smaller kind. If yes, omit the warning.
-      */
-
-      /* If the types are the same (but not LOGICAL), and if from-kind
-        is larger than to-kind, this may indicate a loss of precision.
-        The same holds for conversions from REAL to COMPLEX.  */
-      if (((from_ts.type == ts->type && from_ts.type != BT_LOGICAL)
-           && ((gfc_option.warn_conversion && from_ts.kind > ts->kind)
-              || gfc_option.warn_conversion_extra))
-         || ((from_ts.type == BT_REAL && ts->type == BT_COMPLEX)
-             && ((gfc_option.warn_conversion && from_ts.kind > ts->kind)
-                 || gfc_option.warn_conversion_extra)))
-       gfc_warning_now ("Possible change of value in conversion "
-                        "from %s to %s at %L", gfc_typename (&from_ts),
-                        gfc_typename (ts), &expr->where);
-
-      /* If INTEGER is converted to REAL/COMPLEX, this is generally ok if
-        the kind of the INTEGER value is less or equal to the kind of the
-        REAL/COMPLEX one. Otherwise the value may not fit.
-        Assignment of an overly large integer constant also generates
-        an overflow error with range checking. */
-      else if (from_ts.type == BT_INTEGER
-              && (ts->type == BT_REAL || ts->type == BT_COMPLEX)
-              && ((gfc_option.warn_conversion && from_ts.kind > ts->kind)
-                  || gfc_option.warn_conversion_extra))
-       gfc_warning_now ("Possible change of value in conversion "
-                        "from %s to %s at %L", gfc_typename (&from_ts),
-                        gfc_typename (ts), &expr->where);
-
-      /* If REAL/COMPLEX is converted to INTEGER, or COMPLEX is converted
-        to REAL we almost certainly have a loss of digits, regardless of
-        the respective kinds.  */
-      else if ((((from_ts.type == BT_REAL || from_ts.type == BT_COMPLEX)
-                 && ts->type == BT_INTEGER)
-               || (from_ts.type == BT_COMPLEX && ts->type == BT_REAL))
-              && (gfc_option.warn_conversion
-                  || gfc_option.warn_conversion_extra))
-       gfc_warning_now ("Possible change of value in conversion from "
-                       "%s to %s at %L", gfc_typename (&from_ts),
-                       gfc_typename (ts), &expr->where);
+      if (gfc_option.flag_range_check
+         && expr->expr_type == EXPR_CONSTANT
+         && from_ts.type == ts->type)
+       {
+         /* Do nothing. Constants of the same type are range-checked
+            elsewhere. If a value too large for the target type is
+            assigned, an error is generated. Not checking here avoids
+            duplications of warnings/errors.
+            If range checking was disabled, but -Wconversion enabled,
+            a non range checked warning is generated below.  */
+       }
+      else if (from_ts.type == BT_LOGICAL || ts->type == BT_LOGICAL)
+       {
+         /* Do nothing. This block exists only to simplify the other
+            else-if expressions.
+              LOGICAL <> LOGICAL    no warning, independent of kind values
+              LOGICAL <> INTEGER    extension, warned elsewhere
+              LOGICAL <> REAL       invalid, error generated elsewhere
+              LOGICAL <> COMPLEX    invalid, error generated elsewhere  */
+       }
+      else if (from_ts.type == ts->type
+              || (from_ts.type == BT_INTEGER && ts->type == BT_REAL)
+              || (from_ts.type == BT_INTEGER && ts->type == BT_COMPLEX)
+              || (from_ts.type == BT_REAL && ts->type == BT_COMPLEX))
+       {
+         /* Larger kinds can hold values of smaller kinds without problems.
+            Hence, only warn if target kind is smaller than the source
+            kind - or if -Wconversion-extra is specified.  */
+         if (gfc_option.warn_conversion_extra)
+           gfc_warning_now ("Conversion from %s to %s at %L",
+                            gfc_typename (&from_ts), gfc_typename (ts),
+                            &expr->where);
+         else if (gfc_option.warn_conversion
+                  && from_ts.kind > ts->kind)
+           gfc_warning_now ("Possible change of value in conversion "
+                            "from %s to %s at %L", gfc_typename (&from_ts),
+                            gfc_typename (ts), &expr->where);
+       }
+      else if ((from_ts.type == BT_REAL && ts->type == BT_INTEGER)
+              || (from_ts.type == BT_COMPLEX && ts->type == BT_INTEGER)
+              || (from_ts.type == BT_COMPLEX && ts->type == BT_REAL))
+       {
+         /* Conversion from REAL/COMPLEX to INTEGER or COMPLEX to REAL
+            usually comes with a loss of information, regardless of kinds.  */
+         if (gfc_option.warn_conversion_extra
+             || gfc_option.warn_conversion)
+           gfc_warning_now ("Possible change of value in conversion "
+                            "from %s to %s at %L", gfc_typename (&from_ts),
+                            gfc_typename (ts), &expr->where);
+       }
+      else if (from_ts.type == BT_HOLLERITH || ts->type == BT_HOLLERITH)
+       {
+         /* If HOLLERITH is involved, all bets are off.  */
+         if (gfc_option.warn_conversion_extra
+             || gfc_option.warn_conversion)
+           gfc_warning_now ("Conversion from %s to %s at %L",
+                            gfc_typename (&from_ts), gfc_typename (ts),
+                            &expr->where);
+       }
+      else
+        gcc_unreachable ();
     }
 
   /* Insert a pre-resolved function call to the right function.  */
index 125b602..5dcee0f 100644 (file)
@@ -1,3 +1,11 @@
+2010-06-09  Daniel Franke  <franke.daniel@gmail.com>
+
+       PR fortran/44359
+       * gfortran.dg/warn_conversion.f90: Removed check for redundant
+       warning.
+       * gfortran.dg/warn_conversion_2.f90: Use non-constant expression to
+       check for warning.
+
 2010-06-09  Steven G. Kargl  <kargl@gcc.gnu.org>
 
        * gfortran.dg/data_namelist_conflict.f90: New test.
index f658b65..c8f0e23 100644 (file)
@@ -18,7 +18,6 @@ SUBROUTINE pr27866c4
   integer(kind=4) :: i4
   i4 = 2.3              ! { dg-warning "conversion" }
   i1 = 500              ! { dg-error "overflow" }
-                        ! { dg-warning "conversion" "" { target *-*-* } 20 }
   a = 2**26-1           ! assignment INTEGER(4) to REAL(4) - no warning
   b = 1d999             ! { dg-error "overflow" }
 
index cb3b760..c022298 100644 (file)
@@ -2,5 +2,10 @@
 ! { dg-options "-Wconversion-extra" }
 
   real(8) :: sqrt2
-  sqrt2 = sqrt(2.0)      ! { dg-warning "conversion" }
+  real x
+
+  x = 2.0
+  sqrt2 = sqrt(x)      ! { dg-warning "Conversion" }
+
+  sqrt2 = sqrt(2.0)    ! no warning; simplified to a constant and range checked
 end