diff options
author | Richard Sandiford <richard.sandiford@arm.com> | 2015-02-23 23:02:50 +0000 |
---|---|---|
committer | Richard Sandiford <rsandifo@gcc.gnu.org> | 2015-02-23 23:02:50 +0000 |
commit | 025e5647099ed6387bd4d5f4a856c7cca77ca244 (patch) | |
tree | d45ea001d353538ed0b73bde01cbc59ecde404cd /gcc | |
parent | 8628d6e6502c436e94fecbcbe6770ea56757c18e (diff) | |
download | gcc-025e5647099ed6387bd4d5f4a856c7cca77ca244.zip gcc-025e5647099ed6387bd4d5f4a856c7cca77ca244.tar.gz gcc-025e5647099ed6387bd4d5f4a856c7cca77ca244.tar.bz2 |
re PR fortran/63427 (hwint.h:250:29: runtime error: shift exponent 64 is too large for 64-bit type 'long int')
gcc/
PR fortran/63427
* wide-int.cc (wi::from_mpz): Cope with unwrapped values that are
too big for a wide_int. Implement missing wrapping operation.
gcc/testsuite/
PR fortran/63427
* gfortran.dg/integer_exponentiation_6.F90: New test.
From-SVN: r220921
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 6 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/testsuite/gfortran.dg/integer_exponentiation_6.F90 | 4 | ||||
-rw-r--r-- | gcc/wide-int.cc | 20 |
4 files changed, 31 insertions, 4 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 5a652bc..0bc898e 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,9 @@ +2015-02-23 Richard Sandiford <richard.sandiford@arm.com> + + PR fortran/63427 + * wide-int.cc (wi::from_mpz): Cope with unwrapped values that are + too big for a wide_int. Implement missing wrapping operation. + 2015-02-23 Oleg Endo <olegendo@gcc.gnu.org> PR target/65163 diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index e695467..ff48d0a 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2015-02-23 Richard Sandiford <richard.sandiford@arm.com> + + PR fortran/63427 + * gfortran.dg/integer_exponentiation_6.F90: New test. + 2015-02-23 Martin Sebor <msebor@redhat.com> PR target/65109 diff --git a/gcc/testsuite/gfortran.dg/integer_exponentiation_6.F90 b/gcc/testsuite/gfortran.dg/integer_exponentiation_6.F90 new file mode 100644 index 0000000..55c2543 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/integer_exponentiation_6.F90 @@ -0,0 +1,4 @@ +! { dg-options "-fno-range-check" } +program test + write (*), (2_8 ** 64009999_8) / 2 +end program test diff --git a/gcc/wide-int.cc b/gcc/wide-int.cc index fd7cbb4..7662648 100644 --- a/gcc/wide-int.cc +++ b/gcc/wide-int.cc @@ -237,7 +237,7 @@ wide_int wi::from_mpz (const_tree type, mpz_t x, bool wrap) { size_t count, numb; - int prec = TYPE_PRECISION (type); + unsigned int prec = TYPE_PRECISION (type); wide_int res = wide_int::create (prec); if (!wrap) @@ -261,16 +261,28 @@ wi::from_mpz (const_tree type, mpz_t x, bool wrap) for representing the value. The code to calculate count is extracted from the GMP manual, section "Integer Import and Export": http://gmplib.org/manual/Integer-Import-and-Export.html */ - numb = 8 * sizeof(HOST_WIDE_INT); + numb = CHAR_BIT * sizeof (HOST_WIDE_INT); count = (mpz_sizeinbase (x, 2) + numb - 1) / numb; HOST_WIDE_INT *val = res.write_val (); - mpz_export (val, &count, -1, sizeof (HOST_WIDE_INT), 0, 0, x); + /* Write directly to the wide_int storage if possible, otherwise leave + GMP to allocate the memory for us. It might be slightly more efficient + to use mpz_tdiv_r_2exp for the latter case, but the situation is + pathological and it seems safer to operate on the original mpz value + in all cases. */ + void *valres = mpz_export (count <= WIDE_INT_MAX_ELTS ? val : 0, + &count, -1, sizeof (HOST_WIDE_INT), 0, 0, x); if (count < 1) { val[0] = 0; count = 1; } - res.set_len (count); + count = MIN (count, BLOCKS_NEEDED (prec)); + if (valres != val) + { + memcpy (val, valres, count * sizeof (HOST_WIDE_INT)); + free (valres); + } + res.set_len (canonize (val, count, prec)); if (mpz_sgn (x) < 0) res = -res; |