aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/fortran/ChangeLog9
-rw-r--r--gcc/fortran/gfortran.texi8
-rw-r--r--gcc/fortran/invoke.texi13
-rw-r--r--gcc/fortran/trans-decl.c9
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/gfortran.dg/int_range_io_1.f9034
-rw-r--r--libgfortran/ChangeLog17
-rw-r--r--libgfortran/io/io.h4
-rw-r--r--libgfortran/io/list_read.c18
-rw-r--r--libgfortran/io/read.c51
-rw-r--r--libgfortran/libgfortran.h1
-rw-r--r--libgfortran/runtime/compile_options.c7
12 files changed, 117 insertions, 59 deletions
diff --git a/gcc/fortran/ChangeLog b/gcc/fortran/ChangeLog
index 5e1dba9..59cfa32 100644
--- a/gcc/fortran/ChangeLog
+++ b/gcc/fortran/ChangeLog
@@ -1,3 +1,12 @@
+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.
+
2012-05-14 Tobias Burnus <burnus@net-b.de>
PR fortran/49110
diff --git a/gcc/fortran/gfortran.texi b/gcc/fortran/gfortran.texi
index 96662c4..ffcd3ec 100644
--- a/gcc/fortran/gfortran.texi
+++ b/gcc/fortran/gfortran.texi
@@ -2740,15 +2740,13 @@ Default: enabled.
are (bitwise or-ed): GFC_RTCHECK_BOUNDS (1), GFC_RTCHECK_ARRAY_TEMPS (2),
GFC_RTCHECK_RECURSION (4), GFC_RTCHECK_DO (16), GFC_RTCHECK_POINTER (32).
Default: disabled.
-@item @var{option}[7] @tab If non zero, range checking is enabled.
-Default: enabled. See -frange-check (@pxref{Code Gen Options}).
@end multitable
@item @emph{Example}:
@smallexample
- /* Use gfortran 4.7 default options. */
- static int options[] = @{68, 511, 0, 0, 1, 1, 0, 1@};
- _gfortran_set_options (8, &options);
+ /* Use gfortran 4.8 default options. */
+ static int options[] = @{68, 511, 0, 0, 1, 1, 0@};
+ _gfortran_set_options (7, &options);
@end smallexample
@end table
diff --git a/gcc/fortran/invoke.texi b/gcc/fortran/invoke.texi
index 8db869b..658ed23 100644
--- a/gcc/fortran/invoke.texi
+++ b/gcc/fortran/invoke.texi
@@ -166,8 +166,7 @@ and warnings}.
@item Runtime Options
@xref{Runtime Options,,Options for influencing runtime behavior}.
-@gccoptlist{-fconvert=@var{conversion} -fmax-subrecord-length=@var{length}
--fno-range-check @gol
+@gccoptlist{-fconvert=@var{conversion} -fmax-subrecord-length=@var{length} @gol
-frecord-marker=@var{length} -fsign-zero
}
@@ -1116,16 +1115,6 @@ representation for unformatted files.
The @code{CONVERT} specifier and the GFORTRAN_CONVERT_UNIT environment
variable override the default specified by @option{-fconvert}.}
-
-@item -fno-range-check
-@opindex @code{fno-range-check}
-Disable range checking of input values during integer @code{READ} operations.
-For example, GNU Fortran will give an error if an input value is
-outside of the relevant range of [@code{-HUGE()}:@code{HUGE()}]. In other words,
-with @code{INTEGER (kind=4) :: i} , attempting to read @math{-2147483648} will
-give an error unless @option{-fno-range-check} is given.
-
-
@item -frecord-marker=@var{length}
@opindex @code{frecord-marker=}@var{length}
Specify the length of record markers for unformatted files.
diff --git a/gcc/fortran/trans-decl.c b/gcc/fortran/trans-decl.c
index 1354ad0..0480f95 100644
--- a/gcc/fortran/trans-decl.c
+++ b/gcc/fortran/trans-decl.c
@@ -5039,12 +5039,17 @@ create_main_function (tree fndecl)
build_int_cst (integer_type_node,
(gfc_option.rtcheck
& GFC_RTCHECK_BOUNDS)));
+ /* TODO: This is the -frange-check option, which no longer affects
+ library behavior; when bumping the library ABI this slot can be
+ reused for something else. As it is the last element in the
+ array, we can instead leave it out altogether.
CONSTRUCTOR_APPEND_ELT (v, NULL_TREE,
build_int_cst (integer_type_node,
gfc_option.flag_range_check));
+ */
array_type = build_array_type (integer_type_node,
- build_index_type (size_int (7)));
+ build_index_type (size_int (6)));
array = build_constructor (array_type, v);
TREE_CONSTANT (array) = 1;
TREE_STATIC (array) = 1;
@@ -5059,7 +5064,7 @@ create_main_function (tree fndecl)
tmp = build_call_expr_loc (input_location,
gfor_fndecl_set_options, 2,
- build_int_cst (integer_type_node, 8), var);
+ build_int_cst (integer_type_node, 7), var);
gfc_add_expr_to_block (&body, tmp);
}
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index c160fae..d6a2adf 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,8 @@
+2012-05-14 Janne Blomqvist <jb@gcc.gnu.org>
+
+ PR fortran/52428
+ * gfortran.dg/int_range_io_1.f90: New test.
+
2012-05-14 Andi Kleen <ak@linux.intel.com>
Jakub Jelinek <jakub@redhat.com>
diff --git a/gcc/testsuite/gfortran.dg/int_range_io_1.f90 b/gcc/testsuite/gfortran.dg/int_range_io_1.f90
new file mode 100644
index 0000000..de1fdb8
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/int_range_io_1.f90
@@ -0,0 +1,34 @@
+! { dg-do run }
+! { dg-options "-fno-range-check" }
+! PR 52428 Read IO of integers near the end of range. Note that we
+! support the two's complement representation even though the Fortran
+! numerical model has a symmetric range. (The -fno-range-check option
+! is needed to allow the -2147483648 literal.)
+program int_range
+ implicit none
+ character(25) :: inputline = "-2147483648"
+ integer(4) :: test
+ integer :: st
+
+ read(inputline,100) test
+100 format(1i11)
+ if (test /= -2147483648) call abort
+ inputline(1:1) = " "
+ read(inputline, 100, iostat=st) test
+ if (st == 0) call abort
+ inputline(11:11) = "7"
+ read(inputline, 100) test
+ if (test /= 2147483647) call abort
+
+ ! Same as above but with list-formatted IO
+ inputline = "-2147483648"
+ read(inputline, *) test
+ if (test /= -2147483648) call abort
+ inputline(1:1) = " "
+ read(inputline, *, iostat=st) test
+ if (st == 0) call abort
+ inputline(11:11) = "7"
+ read(inputline, *) test
+ if (test /= 2147483647) call abort
+
+end program int_range
diff --git a/libgfortran/ChangeLog b/libgfortran/ChangeLog
index a6223fc..088d517 100644
--- a/libgfortran/ChangeLog
+++ b/libgfortran/ChangeLog
@@ -1,3 +1,20 @@
+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.
+
2012-05-11 Tobias Burnus <burnus@net-b.de>
PR fortran/53310
diff --git a/libgfortran/io/io.h b/libgfortran/io/io.h
index 06364e1..6b54af1 100644
--- a/libgfortran/io/io.h
+++ b/libgfortran/io/io.h
@@ -661,8 +661,8 @@ internal_proto(hit_eof);
extern void set_integer (void *, GFC_INTEGER_LARGEST, int);
internal_proto(set_integer);
-extern GFC_UINTEGER_LARGEST max_value (int, int);
-internal_proto(max_value);
+extern GFC_UINTEGER_LARGEST si_max (int);
+internal_proto(si_max);
extern int convert_real (st_parameter_dt *, void *, const char *, int);
internal_proto(convert_real);
diff --git a/libgfortran/io/list_read.c b/libgfortran/io/list_read.c
index 4d2ce79..b0c4e5f 100644
--- a/libgfortran/io/list_read.c
+++ b/libgfortran/io/list_read.c
@@ -461,12 +461,20 @@ convert_integer (st_parameter_dt *dtp, int length, int negative)
{
char c, *buffer, message[MSGLEN];
int m;
- GFC_INTEGER_LARGEST v, max, max10;
+ GFC_UINTEGER_LARGEST v, max, max10;
+ GFC_INTEGER_LARGEST value;
buffer = dtp->u.p.saved_string;
v = 0;
- max = (length == -1) ? MAX_REPEAT : max_value (length, 1);
+ if (length == -1)
+ max = MAX_REPEAT;
+ else
+ {
+ max = si_max (length);
+ if (negative)
+ max++;
+ }
max10 = max / 10;
for (;;)
@@ -490,8 +498,10 @@ convert_integer (st_parameter_dt *dtp, int length, int negative)
if (length != -1)
{
if (negative)
- v = -v;
- set_integer (dtp->u.p.value, v, length);
+ value = -v;
+ else
+ value = v;
+ set_integer (dtp->u.p.value, value, length);
}
else
{
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;
diff --git a/libgfortran/libgfortran.h b/libgfortran/libgfortran.h
index 051e2e8..7dafd94 100644
--- a/libgfortran/libgfortran.h
+++ b/libgfortran/libgfortran.h
@@ -535,7 +535,6 @@ typedef struct
size_t record_marker;
int max_subrecord_length;
int bounds_check;
- int range_check;
}
compile_options_t;
diff --git a/libgfortran/runtime/compile_options.c b/libgfortran/runtime/compile_options.c
index 0e657f7..2ba1aed 100644
--- a/libgfortran/runtime/compile_options.c
+++ b/libgfortran/runtime/compile_options.c
@@ -169,8 +169,10 @@ set_options (int num, int options[])
compile_options.sign_zero = options[5];
if (num >= 7)
compile_options.bounds_check = options[6];
- if (num >= 8)
- compile_options.range_check = options[7];
+ /* options[7] is the -frange-check option, which no longer affects
+ the library behavior; range checking is now always done when
+ parsing integers. It's place in the options array is retained due
+ to ABI compatibility. Remove when bumping the library ABI. */
/* If backtrace is required, we set signal handlers on the POSIX
2001 signals with core action. */
@@ -223,7 +225,6 @@ init_compile_options (void)
compile_options.pedantic = 0;
compile_options.backtrace = 0;
compile_options.sign_zero = 1;
- compile_options.range_check = 1;
}
/* Function called by the front-end to tell us the