From f2c255d4fa65514614d673a9e440dbe2b92b60b7 Mon Sep 17 00:00:00 2001 From: fxcoudert Date: Thu, 22 Mar 2007 22:51:50 +0000 Subject: [PATCH] PR fortran/31262 * trans-const.c (gfc_conv_mpz_to_tree): Allow integer constants larger than twice the width of a HOST_WIDE_INT. * gfortran.dg/no_range_check_1.f90: New test. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@123136 138bc75d-0d04-0410-961f-82ee72b054a4 --- gcc/fortran/ChangeLog | 6 ++++++ gcc/fortran/trans-const.c | 28 +++++++++++++++++--------- gcc/testsuite/ChangeLog | 5 +++++ gcc/testsuite/gfortran.dg/no_range_check_1.f90 | 16 +++++++++++++++ 4 files changed, 46 insertions(+), 9 deletions(-) create mode 100644 gcc/testsuite/gfortran.dg/no_range_check_1.f90 diff --git a/gcc/fortran/ChangeLog b/gcc/fortran/ChangeLog index 4e366aa..0cee9c8 100644 --- a/gcc/fortran/ChangeLog +++ b/gcc/fortran/ChangeLog @@ -1,3 +1,9 @@ +2007-03-22 Francois-Xavier Coudert + + PR fortran/31262 + * trans-const.c (gfc_conv_mpz_to_tree): Allow integer constants + larger than twice the width of a HOST_WIDE_INT. + 2006-03-22 Paul Thomas PR fortran/31193 diff --git a/gcc/fortran/trans-const.c b/gcc/fortran/trans-const.c index c1c9661..5e27134 100644 --- a/gcc/fortran/trans-const.c +++ b/gcc/fortran/trans-const.c @@ -165,23 +165,33 @@ gfc_conv_mpz_to_tree (mpz_t i, int kind) } else { - unsigned HOST_WIDE_INT words[2]; - size_t count; + unsigned HOST_WIDE_INT *words; + size_t count, numb; + + /* Determine the number of unsigned HOST_WIDE_INT that are required + for represent 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); + count = (mpz_sizeinbase (i, 2) + numb-1) / numb; + if (count < 2) + count = 2; + words = (unsigned HOST_WIDE_INT *) alloca (count * sizeof(HOST_WIDE_INT)); /* Since we know that the value is not zero (mpz_fits_slong_p), we know that at least one word will be written, but we don't know about the second. It's quicker to zero the second word before than conditionally clear it later. */ words[1] = 0; - + /* Extract the absolute value into words. */ - mpz_export (words, &count, -1, sizeof (HOST_WIDE_INT), 0, 0, i); - - /* We assume that all numbers are in range for its type, and that - we never create a type larger than 2*HWI, which is the largest - that the middle-end can handle. */ - gcc_assert (count == 1 || count == 2); + mpz_export (words, &count, -1, sizeof(HOST_WIDE_INT), 0, 0, i); + /* We don't assume that all numbers are in range for its type. + However, we never create a type larger than 2*HWI, which is the + largest that the middle-end can handle. So, we only take the + first two elements of words, which is equivalent to wrapping the + value if it's larger than the type range. */ low = words[0]; high = words[1]; diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 821fc01..936cebc 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2007-03-22 Francois-Xavier Coudert + + PR fortran/31262 + * gfortran.dg/no_range_check_1.f90: New test. + 2007-03-22 Dirk Mueller * g++.old-deja/g++.brendan/warnings2.C: Don't use -pedantic. diff --git a/gcc/testsuite/gfortran.dg/no_range_check_1.f90 b/gcc/testsuite/gfortran.dg/no_range_check_1.f90 new file mode 100644 index 0000000..3689086 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/no_range_check_1.f90 @@ -0,0 +1,16 @@ +! { dg-do run } +! { dg-options "-fno-range-check -O0" } +! +! This testcase arose from PR 31262 + integer :: a + integer(kind=8) :: b + a = -3 + b = -huge(b) / 7 + a = a ** 73 + b = 7894_8 * b - 78941_8 + if ((-3)**73 /= a) call abort + if (7894_8 * (-huge(b) / 7) - 78941_8 /= b) call abort + + a = 1234789786453123 + if (a - 1234789786453123 /= a - (-426244989)) call abort + end -- 2.7.4