aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Franke <franke.daniel@gmail.com>2010-06-09 15:40:58 -0400
committerDaniel Franke <dfranke@gcc.gnu.org>2010-06-09 15:40:58 -0400
commit33169a2285f10e2cfe0caf3f23628b074253e8cc (patch)
tree0965b0a5fbfcff0a37723936eadb74d0ab756673
parentb51789feb00890d5d4b0e9ec7e10fb0c140709d1 (diff)
downloadgcc-33169a2285f10e2cfe0caf3f23628b074253e8cc.zip
gcc-33169a2285f10e2cfe0caf3f23628b074253e8cc.tar.gz
gcc-33169a2285f10e2cfe0caf3f23628b074253e8cc.tar.bz2
re PR fortran/44359 (-Wall / -Wconversion: Too verbose warning for DATA BOZ conversions)
gcc/fortran/: 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. From-SVN: r160505
-rw-r--r--gcc/fortran/ChangeLog5
-rw-r--r--gcc/fortran/intrinsic.c113
-rw-r--r--gcc/testsuite/ChangeLog8
-rw-r--r--gcc/testsuite/gfortran.dg/warn_conversion.f901
-rw-r--r--gcc/testsuite/gfortran.dg/warn_conversion_2.f907
5 files changed, 80 insertions, 54 deletions
diff --git a/gcc/fortran/ChangeLog b/gcc/fortran/ChangeLog
index 05ec55d..cafbd31 100644
--- a/gcc/fortran/ChangeLog
+++ b/gcc/fortran/ChangeLog
@@ -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
diff --git a/gcc/fortran/intrinsic.c b/gcc/fortran/intrinsic.c
index 2d82f20..e5463a1 100644
--- a/gcc/fortran/intrinsic.c
+++ b/gcc/fortran/intrinsic.c
@@ -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. */
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 125b602..5dcee0f 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -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.
diff --git a/gcc/testsuite/gfortran.dg/warn_conversion.f90 b/gcc/testsuite/gfortran.dg/warn_conversion.f90
index f658b65..c8f0e23 100644
--- a/gcc/testsuite/gfortran.dg/warn_conversion.f90
+++ b/gcc/testsuite/gfortran.dg/warn_conversion.f90
@@ -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" }
diff --git a/gcc/testsuite/gfortran.dg/warn_conversion_2.f90 b/gcc/testsuite/gfortran.dg/warn_conversion_2.f90
index cb3b760..c022298 100644
--- a/gcc/testsuite/gfortran.dg/warn_conversion_2.f90
+++ b/gcc/testsuite/gfortran.dg/warn_conversion_2.f90
@@ -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