diff options
author | fxcoudert <fxcoudert@138bc75d-0d04-0410-961f-82ee72b054a4> | 2007-03-22 22:51:50 +0000 |
---|---|---|
committer | fxcoudert <fxcoudert@138bc75d-0d04-0410-961f-82ee72b054a4> | 2007-03-22 22:51:50 +0000 |
commit | f2c255d4fa65514614d673a9e440dbe2b92b60b7 (patch) | |
tree | 0a5617457fdf2cbc258625c013283ae7a6b8e6b8 /gcc/fortran/trans-const.c | |
parent | 63c68695947927f83f1182fb22cb6a272780e1d3 (diff) | |
download | gcc-f2c255d4fa65514614d673a9e440dbe2b92b60b7.tar.gz |
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
Diffstat (limited to 'gcc/fortran/trans-const.c')
-rw-r--r-- | gcc/fortran/trans-const.c | 28 |
1 files changed, 19 insertions, 9 deletions
diff --git a/gcc/fortran/trans-const.c b/gcc/fortran/trans-const.c index c1c96619715..5e27134b006 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]; |