aboutsummaryrefslogtreecommitdiff
path: root/libgfortran/io/read.c
diff options
context:
space:
mode:
authorJanne Blomqvist <jb@gcc.gnu.org>2012-05-14 22:39:23 +0300
committerJanne Blomqvist <jb@gcc.gnu.org>2012-05-14 22:39:23 +0300
commit80b91c0b39e7d65e3d89e49b5bf2ec40927f5a33 (patch)
tree1b4a3a8d4b65ec8d0a88de4f00b90d28ce493090 /libgfortran/io/read.c
parentf62866740b93747b2d3f1dd4d4637e6890e0fa22 (diff)
downloadgcc-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.c51
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;