[Bug fortran/59604] Constant comparisons with -fno-range-check and int(z'...')
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=59604 --- Comment #8 from Thomas Koenig tkoenig at gcc dot gnu.org --- Author: tkoenig Date: Sun Apr 27 10:48:56 2014 New Revision: 209836 URL: http://gcc.gnu.org/viewcvs?rev=209836root=gccview=rev Log: 2014-03-27 Thomas Koenig tkoe...@gcc.gnu.org PR fortran/59604 PR fortran/58003 * gfortran.h (gfc_convert_mpz_to_signed): Add prototype. * arith.c (gfc_int2int): Convert number to signed if arithmetic overflow is not checked. * simplify.c (convert_mpz_to_unsigned): Only trigger assert for size if range checking is in force. (convert_mpz_to_signed): Make non-static, rename to (gfc_convert_mpz_to_signed). (simplify_dshift): Use gfc_convert_mpz_to_signed. (gfc_simplify_ibclr): Likewise. (gfc_simplify_ibits): Likewise. (gfc_simplify_ibset): Likewise. (simplify_shift): Likewise. (gfc_simplify_ishiftc): Likewise. (gfc_simplify_maskr): Likewise. (gfc_simplify_maskl): Likewise. 2014-03-27 Thomas Koenig tkoe...@gcc.gnu.org PR fortran/59604 PR fortran/58003 * gfortran.dg/no_range_check_3.f90: New test. Added: trunk/gcc/testsuite/gfortran.dg/no_range_check_3.f90 Modified: trunk/gcc/fortran/ChangeLog trunk/gcc/fortran/arith.c trunk/gcc/fortran/gfortran.h trunk/gcc/fortran/simplify.c trunk/gcc/testsuite/ChangeLog
[Bug fortran/59604] Constant comparisons with -fno-range-check and int(z'...')
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=59604 Thomas Koenig tkoenig at gcc dot gnu.org changed: What|Removed |Added Status|NEW |RESOLVED Resolution|--- |FIXED --- Comment #9 from Thomas Koenig tkoenig at gcc dot gnu.org --- Fixed on trunk, closing. I don't think this is bad enough for a backport.
[Bug fortran/59604] Constant comparisons with -fno-range-check and int(z'...')
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=59604 Dominique d'Humieres dominiq at lps dot ens.fr changed: What|Removed |Added Status|UNCONFIRMED |NEW Last reconfirmed|2013-12-28 00:00:00 |2013-12-29 Ever confirmed|0 |1
[Bug fortran/59604] Constant comparisons with -fno-range-check and int(z'...')
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=59604 Thomas Koenig tkoenig at gcc dot gnu.org changed: What|Removed |Added Status|UNCONFIRMED |ASSIGNED Last reconfirmed||2013-12-28 Assignee|unassigned at gcc dot gnu.org |tkoenig at gcc dot gnu.org Ever confirmed|0 |1 --- Comment #6 from Thomas Koenig tkoenig at gcc dot gnu.org --- I have a patch.
[Bug fortran/59604] Constant comparisons with -fno-range-check and int(z'...')
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=59604 Thomas Koenig tkoenig at gcc dot gnu.org changed: What|Removed |Added Status|ASSIGNED|UNCONFIRMED Ever confirmed|1 |0 --- Comment #7 from Thomas Koenig tkoenig at gcc dot gnu.org --- (In reply to Steve Kargl from comment #5) On Fri, Dec 27, 2013 at 07:53:00PM +, tkoenig at gcc dot gnu.org wrote: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=59604 Thomas Koenig tkoenig at gcc dot gnu.org changed: What|Removed |Added Blocks||58003 --- Comment #4 from Thomas Koenig tkoenig at gcc dot gnu.org --- (In reply to kargl from comment #2) (In reply to Thomas Koenig from comment #1) TRANSFER gets this right. It is unclear what you mean here. What I mean is that program test if (transfer(z'',1) /= -1) call abort end program test does not call abort. I suspect that the above is not portable as transfer() simply copies bits. z'FFF' is an integer(8) (or integer(16)) entity. Transfer() is copying 32-bits from that entity. It is clear from the -fdump-tree-original that middle-end is converting the resulting 32-bit thing into -1. So, you're relying on twos-complement wrap around semantics. As gcc supports only twos complement arithmetic, I think this is OK.
[Bug fortran/59604] Constant comparisons with -fno-range-check and int(z'...')
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=59604 --- Comment #1 from Thomas Koenig tkoenig at gcc dot gnu.org --- TRANSFER gets this right.
[Bug fortran/59604] Constant comparisons with -fno-range-check and int(z'...')
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=59604 kargl at gcc dot gnu.org changed: What|Removed |Added CC||kargl at gcc dot gnu.org --- Comment #2 from kargl at gcc dot gnu.org --- (In reply to Thomas Koenig from comment #1) TRANSFER gets this right. It is unclear what you mean here. A simplified program that removes the complication of the IO and ISO C binding is program test if (int(z'') /= -1) call abort end program test % gfc4x -o z -fno-range-check -fdump-tree-original a.f90 % ./z Program aborted. Backtrace: #0 0x4807A01C #1 0x4807B8CF #2 0x48134C17 #3 0x8048792 in MAIN__ at a.f90:0 Abort (core dumped) %cat a.f90.003t.orginal test () { _gfortran_abort (); L.1:; } main (integer(kind=4) argc, character(kind=1) * * argv) { static integer(kind=4) options.0[9] = {68, 1023, 0, 0, 1, 1, 0, 0, 31}; _gfortran_set_args (argc, argv); _gfortran_set_options (9, options.0[0]); test (); return 0; } I believe the problem lies in gfc_simplify_int. From what I can tell, there is never a conversion of a boz to an integer, until we reach code generation. The call chain is gfc_simplify_int - simplify-intconv - gfc_convert_constant - gfc_int2int. By the time we reach gfc_int2int, the boz should have been converted to the integer, but isn't. Now, if we compare gfc_simplify_int to gfc_simplify_real, we see in gfc_simplify_real, if (convert_boz (e, kind) == gfc_bad_expr) return gfc_bad_expr; where convert_boz will do an explicit conversion of a boz to a real type. There isn't a similar functionality for integer.
[Bug fortran/59604] Constant comparisons with -fno-range-check and int(z'...')
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=59604 --- Comment #3 from Steve Kargl sgk at troutmask dot apl.washington.edu --- On Fri, Dec 27, 2013 at 06:10:23PM +, kargl at gcc dot gnu.org wrote: By the time we reach gfc_int2int, the boz should have been converted to the integer, but isn't. Now, if we compare gfc_simplify_int to gfc_simplify_real, we see in gfc_simplify_real, if (convert_boz (e, kind) == gfc_bad_expr) return gfc_bad_expr; where convert_boz will do an explicit conversion of a boz to a real type. There isn't a similar functionality for integer. I forgot to mention that gfortran may be delaying the conversion under the translation to the middle-end, so tit can rely on the middle-end for wrap-around semantics of twos-complement signed integer arithmetic.
[Bug fortran/59604] Constant comparisons with -fno-range-check and int(z'...')
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=59604 Thomas Koenig tkoenig at gcc dot gnu.org changed: What|Removed |Added Blocks||58003 --- Comment #4 from Thomas Koenig tkoenig at gcc dot gnu.org --- (In reply to kargl from comment #2) (In reply to Thomas Koenig from comment #1) TRANSFER gets this right. It is unclear what you mean here. What I mean is that program test if (transfer(z'',1) /= -1) call abort end program test does not call abort. Also setting this as blocking 58003, because an obvious fix to that bug would replace an ICE with a wrong-code bug for some corner cases (not preferable :-)
[Bug fortran/59604] Constant comparisons with -fno-range-check and int(z'...')
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=59604 --- Comment #5 from Steve Kargl sgk at troutmask dot apl.washington.edu --- On Fri, Dec 27, 2013 at 07:53:00PM +, tkoenig at gcc dot gnu.org wrote: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=59604 Thomas Koenig tkoenig at gcc dot gnu.org changed: What|Removed |Added Blocks||58003 --- Comment #4 from Thomas Koenig tkoenig at gcc dot gnu.org --- (In reply to kargl from comment #2) (In reply to Thomas Koenig from comment #1) TRANSFER gets this right. It is unclear what you mean here. What I mean is that program test if (transfer(z'',1) /= -1) call abort end program test does not call abort. I suspect that the above is not portable as transfer() simply copies bits. z'FFF' is an integer(8) (or integer(16)) entity. Transfer() is copying 32-bits from that entity. It is clear from the -fdump-tree-original that middle-end is converting the resulting 32-bit thing into -1. So, you're relying on twos-complement wrap around semantics. Also setting this as blocking 58003, because an obvious fix to that bug would replace an ICE with a wrong-code bug for some corner cases (not preferable :-) This isn't blocking 58003 as the code in 59604 is invalid. As gfortran provides popcnt() as an intrinsics procedure, it follows that popcnt() should follow the Fortran standard (see below quote). Now, if you want to chase a real bug in gfortran, try this little program program test integer(8) :: i = 4294967295_8 integer(8) :: j = z'' ! ! The following two lines should call abort, but don't! In addition, ! these lines do not require -fno-range-check to compile, so gfortran ! violates the quote from the F95 standard (p.228) below. ! if (int(i) /= -1) call abort if (int(j) /= -1) call abort ! ! On a 2-complement system, the next statement is optimized away. ! I haven't decided yet, whether transfer() violates the standard ! because it only copies bits and the 32-bits copied from the boz ! fit into an integer(4). ! if (transfer(z'',1) /= -1) call abort ! ! Both of these require -fno-range-check to compile, and they violate ! !A program is prohibited from invoking an intrinsic procedure !under circumstances where a value to be returned in a subroutine !argument or function result is outside the range of values !representable by objects of the specified type and type parameters. ! ! 4294967295_8 is well outside of the range [-huge()-1:huge()] of a ! twos-complement 32-bit integer(4) ! if (int(z'') /= -1) call abort if (int(4294967295_8) /= -1) call abort end program test