aboutsummaryrefslogtreecommitdiff
path: root/gcc/fortran/primary.c
diff options
context:
space:
mode:
authorThomas Koenig <tkoenig@netcologne.de>2015-06-06 16:12:39 +0000
committerThomas Koenig <tkoenig@gcc.gnu.org>2015-06-06 16:12:39 +0000
commitcbf560d708abe7f95490626d44f29d7c93650594 (patch)
tree795f1293f203f94163c691716e122d7f76b5c07b /gcc/fortran/primary.c
parent5a7929c86043933f5190154abc038dac4dbc122d (diff)
downloadgcc-cbf560d708abe7f95490626d44f29d7c93650594.zip
gcc-cbf560d708abe7f95490626d44f29d7c93650594.tar.gz
gcc-cbf560d708abe7f95490626d44f29d7c93650594.tar.bz2
re PR fortran/47359 (Recursive functions of intrinsic names generates invalid assembler)
2015-06-06 Thomas Koenig <tkoenig@netcologne.de> PR fortran/47359 * arith.c (eval_intrinsic_op): Set warn flag for gfc_type_convert_binary if -Wconversion or -Wconversion-extra are set. (wprecision_real_real): New function. (wprecision_int_real): New function. (gfc_int2int): If -fno-range-check and -Wconversion are specified and it is a narrowing conversion, warn. (gfc_int2real): If there is a change in value for the conversion, warn. (gfc_int2complex): Likewise. (gfc_real2int): If there is a fractional part to the real number, warn with -Wconversion, otherwise warn with -Wconversion-extra. (gfc_real2real): Emit warning if the constant was changed by conversion with either -Wconversion or -Wconversion-extra. With -Wconversion-extra, warn if no warning was issued earlier. (gfc_real2complex): Likewise. (gfc_complex2int): For -Wconversion or -Wconversion-extra, if there was an imaginary part, warn; otherwise, warn for change in value. Warn with -Wconversion-extra if no other warning was issued. (gfc_complex2real): For -Wconversion or -Wconversion-extra, if there was an imaginary part, warn; otherwise, warn for change in value. Warn with -Wconversion-extra if no other warning was issued. (gfc_complex2complex): For -Wconversion, warn if the value of either the real or the imaginary part was changed. Warn for -Wconversion-extra if no prior warning was issued. * expr.c (gfc_check_assign): Remove check for change in value. * primary.c (match_real_constant): For -Wconversion-extra, check against a number in which the last non-zero digit has been replaced with a zero. If the number compares equal, warn. * intrinsic.c (gfc_convert_type_warn): Do not warn about constant conversions. 2015-06-06 Thomas Koenig <tkoenig@netcologne.de> PR fortran/47359 * gfortran.dg/array_constructor_type_17.f03: Adjust error message. * gfortran.dg/warn_conversion.f90: Add warning for change in value for assignment. * gfortran.dg/warn_conversion_3.f90: Add warnings. * gfortran.dg/warn_conversion_5.f90: New test. * gfortran.dg/warn_conversion_6.f90: New test. * gfortran.dg/warn_conversion_7.f90: New test. From-SVN: r224190
Diffstat (limited to 'gcc/fortran/primary.c')
-rw-r--r--gcc/fortran/primary.c52
1 files changed, 52 insertions, 0 deletions
diff --git a/gcc/fortran/primary.c b/gcc/fortran/primary.c
index 7d2f9c7..e467e0b 100644
--- a/gcc/fortran/primary.c
+++ b/gcc/fortran/primary.c
@@ -736,6 +736,58 @@ done:
gfc_internal_error ("gfc_range_check() returned bad value");
}
+ /* Warn about trailing digits which suggest the user added too many
+ trailing digits, which may cause the appearance of higher pecision
+ than the kind kan support.
+
+ This is done by replacing the rightmost non-zero digit with zero
+ and comparing with the original value. If these are equal, we
+ assume the user supplied more digits than intended (or forgot to
+ convert to the correct kind).
+ */
+
+ if (warn_conversion_extra)
+ {
+ mpfr_t r;
+ char *c, *p;
+ bool did_break;
+
+ c = strchr (buffer, 'e');
+ if (c == NULL)
+ c = buffer + strlen(buffer);
+
+ did_break = false;
+ for (p = c - 1; p >= buffer; p--)
+ {
+ if (*p == '.')
+ continue;
+
+ if (*p != '0')
+ {
+ *p = '0';
+ did_break = true;
+ break;
+ }
+ }
+
+ if (did_break)
+ {
+ mpfr_init (r);
+ mpfr_set_str (r, buffer, 10, GFC_RND_MODE);
+ if (negate)
+ mpfr_neg (r, r, GFC_RND_MODE);
+
+ mpfr_sub (r, r, e->value.real, GFC_RND_MODE);
+
+ if (mpfr_cmp_ui (r, 0) == 0)
+ gfc_warning (OPT_Wconversion_extra, "Non-significant digits "
+ "in %qs number at %C, maybe incorrect KIND",
+ gfc_typename (&e->ts));
+
+ mpfr_clear (r);
+ }
+ }
+
*result = e;
return MATCH_YES;