[Bug fortran/59604] Constant comparisons with -fno-range-check and int(z'...')

2014-04-27 Thread tkoenig at gcc dot gnu.org
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'...')

2014-04-27 Thread tkoenig at gcc dot gnu.org
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'...')

2013-12-29 Thread dominiq at lps dot ens.fr
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'...')

2013-12-28 Thread tkoenig at gcc dot gnu.org
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'...')

2013-12-28 Thread tkoenig at gcc dot gnu.org
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'...')

2013-12-27 Thread tkoenig at gcc dot gnu.org
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'...')

2013-12-27 Thread kargl at gcc dot gnu.org
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'...')

2013-12-27 Thread sgk at troutmask dot apl.washington.edu
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'...')

2013-12-27 Thread tkoenig at gcc dot gnu.org
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'...')

2013-12-27 Thread sgk at troutmask dot apl.washington.edu
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