Loop variable reaching integer `huge` causes infinite loop

the index overflow. I’ve just ran this on godbolt:

    do i=-huge(i),huge(i)
       print "('i=',i10,' b=',b8.8)", i,i
    end do
    print *, 'i=',i

and both ifx and ifort run the prescribed loop and then return

i= -128

So I thought that - while still having to be warned about the index overflow - this would be more expected behavior than getting caught in an infinite loop.
It’s crystal clear that gfortran is doing the right thing per standard i.e. warning of this behavior.
Now though, I was asking because I don’t have the expertise to assess if such a fix is easily doable and/or if it could potentially backfire, but my guess is it would be a relatively straightforward extension?.

Right now, you can’t basically run loops through the whole integer range, so at least loops whose range is known at compile time may be useful. For example, I ended up doing this test because I wanted to map all possible values of an integer(int8) into a parameter:

integer(int8) :: i
real, parameter :: my_var(-huge(i):huge(i)) = [(something, i=-huge(i),huge(i))]

As explained above, that array range does NOT map all possible values on a twos-complement machine. It misses the -128 value. It would be correct on a ones-complement or a sign-magnitude machine.

Since fortran has defined the value of the do loop index upon exit since f77, many programs rely on that value after loop exit. If that definition were removed or changed, it would make those formerly conforming codes nonconforming. Then there would be some mishmash of compiler options so that programmers could continue to keep their old codes working with the new standard convention. Within a large program, some do loops would need the old convention while others could use the new convention, so build systems would all get complicated because of that change, and if the wrong compiler options were used on the wrong files, then the code would simply break. These are the types of problems that arise when backward incompatible changes are made to the language.

In your example, there is an easy solution, just use an integer with a different KIND as the loop index. And if the compiler tells you at compile time that there is a problem, then you can fix it in a few seconds and that fix will always be there. You would not need to know which compiler options to use to compile your codes, and if other programmers use your codes, you don’t need to tell them the magical incantations that are required to compile and run your program. So in this case, that seems like the best approach overall.

You are focusing on the index overflow problem. What about the trip count problem? The fortran standard does not require your loop to cycle 255 times, which is probably what you intend. What if it cycles zero times, which I think is what the trip count expression will give you if the overflows are ignored: (127_int8+127_int8+1_int8) evaluates to -1. Do you want the compiler to recognize that and warn you, or should it just remain silent and expect that the programmer knows what he is doing?

1 Like

Along the lines of previous suggestions, borrowing syntax from other Fortran constructs I could
picture a new syntax being allowed such as

program testit
implicit none
do (integer :: I = (-1-huge(0):huge(0))
   write(*,*)i
enddo
end program testit

where the counter only has scope within the loop and so could have different rules to avoid the overindexing and possible range limit. This alternate syntax could also allow “I” to be altered within the loop, eliminating another constraint of the current DO construct; albeit probably at the cost of some optimizations a current DO loop construct can achieve because of those very limitations.

Allowing the new construct would avoid backward compatibility issues.

Although FORALL did not quite pan out; allowing multiple declarations in the DO header like a FORALL that, like a BLOCK structure, had scope limited to the loop might also be useful, as that can be clearer than the current syntax.

So it would require allowing a new syntax, but could allow for handling these dusty corners while remaining backward-compatible. Maybe there are other limitations to a DO that could be allowed(?).

1 Like

I forgot to mention, also use -fcheck=all

At runtime for the test case given, it detects the infinite loop and throws an error.
.
.
.
i= 122 b=01111010
i= 123 b=01111011
i= 124 b=01111100
i= 125 b=01111101
i= 126 b=01111110
At line 4 of file looper.f90
Fortran runtime error: Loop iterates infinitely

gfortran is a very good compiler. It is not perfect. We have not implemented the -fwrite-my-code-for-me option yet.

Cheers

2 Likes

For “DO i = i1,i2” to function correctly, we need that 0 < i2-i1+1 < huge(i). ( I understand i2-i1+1 is the trip count )
If i2 > i1, but we don’t have 0 < i2-i1+1 < huge(i) then we have an overflow condition.
If the trip count is in range, all is ok and the code can continue.

But, should the compiler automatically provide additional checks if the trip count is out of range, without the need for special compile options ?

I think it should, as the DO loop is valid Fortran.

1 Like

This is inaccurate - it’s a fantastic compiler!

@JohnCampbell @urbanjost @RonShepard Here’s some ideas I laid out earlier last year to further extend Fortran’s array/loop handling, which I believe is it’s major strength:

Fortran proposals

If anyone here would be interested in joining the gfortran developers team, send an email to gfortran@gcc.gnu.org or myself at jvdelisle@gcc.gnu.org. We have set up a gfortran workspace on MatterMost cloud to facilitate chat, patch discussions, mentoring new folks, etc. We just started this up a few weeks ago. I like that it has live chat via phone, web browser interface and a desktop version. I run on Linux and do a little on Windows operating systems.

As an administrator I can send you an invitation to join.

All support is greatly appreciated.

5 Likes

@JerryD ,

This is great. Perhaps you will join the Fortran Monthly Call the next time and go over the gfortran workspace?

3 Likes