diff options
author | Janne Blomqvist <jb@gcc.gnu.org> | 2012-05-14 22:39:23 +0300 |
---|---|---|
committer | Janne Blomqvist <jb@gcc.gnu.org> | 2012-05-14 22:39:23 +0300 |
commit | 80b91c0b39e7d65e3d89e49b5bf2ec40927f5a33 (patch) | |
tree | 1b4a3a8d4b65ec8d0a88de4f00b90d28ce493090 /libgfortran/io/read.c | |
parent | f62866740b93747b2d3f1dd4d4637e6890e0fa22 (diff) | |
download | gcc-80b91c0b39e7d65e3d89e49b5bf2ec40927f5a33.zip gcc-80b91c0b39e7d65e3d89e49b5bf2ec40927f5a33.tar.gz gcc-80b91c0b39e7d65e3d89e49b5bf2ec40927f5a33.tar.bz2 |
PR 52428 Range checking when reading integer values.
gcc/fortran ChangeLog:
2012-05-14 Janne Blomqvist <jb@gcc.gnu.org>
PR fortran/52428
* gfortran.texi: Update _gfortran_set_options documentation.
* invoke.texi: Remove runtime behavior description of
-fno-range-check.
* trans-decl.c (create_main_function): Don't pass the range-check
setting to the library.
libgfortran ChangeLog:
2012-05-14 Janne Blomqvist <jb@gcc.gnu.org>
PR fortran/52428
* io/io.h (max_value): Rename to si_max, remove second argument.
* io/list_read.c (convert_integer): Use unsigned types when
parsing the digits, set max value depending on the sign.
* io/read.c (max_value): Rename to si_max, remove second argument,
simplify.
(read_decimal): Set max value depending on sign, always check
overflow.
(read_radix): Calculate max unsigned value directly.
* libgfortran.h (struct compile_options_t): Remove range_check
field.
* runtime/compile_options.c (set_options): Skip handling
options[7].
(init_compile_options): Don't set removed field.
gcc/testsuite ChangeLog:
2012-05-14 Janne Blomqvist <jb@gcc.gnu.org>
PR fortran/52428
* gfortran.dg/int_range_io_1.f90: New test.
From-SVN: r187478
Diffstat (limited to 'libgfortran/io/read.c')
-rw-r--r-- | libgfortran/io/read.c | 51 |
1 files changed, 21 insertions, 30 deletions
diff --git a/libgfortran/io/read.c b/libgfortran/io/read.c index 32c8b32..c493d5a 100644 --- a/libgfortran/io/read.c +++ b/libgfortran/io/read.c @@ -87,46 +87,34 @@ set_integer (void *dest, GFC_INTEGER_LARGEST value, int length) } -/* max_value()-- Given a length (kind), return the maximum signed or - * unsigned value */ +/* Max signed value of size give by length argument. */ GFC_UINTEGER_LARGEST -max_value (int length, int signed_flag) +si_max (int length) { GFC_UINTEGER_LARGEST value; -#if defined HAVE_GFC_REAL_16 || defined HAVE_GFC_REAL_10 - int n; -#endif switch (length) - { + { #if defined HAVE_GFC_REAL_16 || defined HAVE_GFC_REAL_10 case 16: case 10: value = 1; - for (n = 1; n < 4 * length; n++) + for (int n = 1; n < 4 * length; n++) value = (value << 2) + 3; - if (! signed_flag) - value = 2*value+1; - break; + return value; #endif case 8: - value = signed_flag ? 0x7fffffffffffffff : 0xffffffffffffffff; - break; + return GFC_INTEGER_8_HUGE; case 4: - value = signed_flag ? 0x7fffffff : 0xffffffff; - break; + return GFC_INTEGER_4_HUGE; case 2: - value = signed_flag ? 0x7fff : 0xffff; - break; + return GFC_INTEGER_2_HUGE; case 1: - value = signed_flag ? 0x7f : 0xff; - break; + return GFC_INTEGER_1_HUGE; default: internal_error (NULL, "Bad integer kind"); } - - return value; } @@ -634,11 +622,7 @@ read_decimal (st_parameter_dt *dtp, const fnode *f, char *dest, int length) return; } - maxv = max_value (length, 1); - maxv_10 = maxv / 10; - negative = 0; - value = 0; switch (*p) { @@ -656,6 +640,11 @@ read_decimal (st_parameter_dt *dtp, const fnode *f, char *dest, int length) break; } + maxv = si_max (length); + if (negative) + maxv++; + maxv_10 = maxv / 10; + /* At this point we have a digit-string */ value = 0; @@ -674,20 +663,21 @@ read_decimal (st_parameter_dt *dtp, const fnode *f, char *dest, int length) if (c < '0' || c > '9') goto bad; - if (value > maxv_10 && compile_options.range_check == 1) + if (value > maxv_10) goto overflow; c -= '0'; value = 10 * value; - if (value > maxv - c && compile_options.range_check == 1) + if (value > maxv - c) goto overflow; value += c; } - v = value; if (negative) - v = -v; + v = -value; + else + v = value; set_integer (dest, v, length); return; @@ -734,7 +724,8 @@ read_radix (st_parameter_dt *dtp, const fnode *f, char *dest, int length, return; } - maxv = max_value (length, 0); + /* Maximum unsigned value, assuming two's complement. */ + maxv = 2 * si_max (length) + 1; maxv_r = maxv / radix; negative = 0; |