I am working with a source code that might have been written before the most recent version of gfortran. I'm aware that the way DO, END DO, and CONTINUE has changed so that there can not be shared loop termination. There's a handy link here. The thing is, I don't know what the explanation really is telling me to do on that page. If I set up a really basic DO loop in a new script, it compiles with no error. I'm not sure how to reverse engineer this to find what the problem is.
Here is one part of the code that returns an error message.
DO 20 II = I1, I2
IW = ICN(II)
! Has node iw been on stack already?
IF (NUMB(IW)==0) GOTO 70
! Update value of LOWL(IV) if necessary.
20 LOWL(IV) = MIN(LOWL(IV),LOWL(IW))
! There are no more edges leaving node IV.
ARP(IV) = -1
! Is node IV the root of a block.
30 IF (LOWL(IV)<NUMB(IV)) GOTO 60
! Order nodes in a block.
NUM = NUM + 1
IST1 = N + 1 - IST
LCNT = ICNT + 1
! Peel block off the top of the stack starting at the
! top and working down to the root of the block.
DO STP = IST1, N
IW = IB(STP)
LOWL(IW) = N + 1
ICNT = ICNT + 1
NUMB(IW) = ICNT
IF (IW==IV) GOTO 50
END DO
The error looks like this. Basically the same error repeats for any outdated DO loops that come up and is the only type of error that comes up when compiling.
dvode_f90_m.f90:15865:45:
15865 | 20 LOWL(IV) = MIN(LOWL(IV),LOWL(IW))
| 1
Warning: Fortran 2018 deleted feature: DO termination statement which is not END DO or CONTINUE with label 20 at (1)
I would like to know how to rework the DO loops in this code chunk so that I can go through and update this source code. If it's relevant, I'm running GFortran9.3.0 on Cygwin.
Fortran - Do Loop Construct. The do loop construct enables a statement, or a series of statements, to be carried out iteratively, while a given condition is true.
Indeed, the labelled form is obsolescent in Fortran 2018. For non-block DO constructs where the terminating action statement was also the target of a go to we rewrite such that the go to points to the (labelled) statement pulled in to the loop. We can also rewrite non-block DO constructs which share the terminating action statement.
The DO construct in Fortran 2018 (the block DO construct in previous language standards) requires the terminating statement to be either an end do statement or a (labelled) continue statement. (The end do statement must be labelled if the DO construct is a labelled DO construct such as do 1....)
where x and y are real and i is integer, FORTRAN computes the result in stages: First it calculates (2**i)/3 and evaluates it as an integer number, then multiplies the result by x and evaluates it as real.
As the warning message says, all DO
loops should terminate with END DO
or CONTINUE
, for instance:
DO 20 IV = 1, 100
LOWL(IV) = MIN(LOWL(IV),LOWL(IW))
20 CONTINUE
Old versions of Fortran allowed the programmer to drop the terminating line, resulting in the shorter
DO 20 IV = 1, 100
20 LOWL(IV) = MIN(LOWL(IV),LOWL(IW))
However, these two codes are functionally equivalent. You can test it on your own with some trivial loops.
Before Fortran 2018 there were two forms of the DO construct: the block DO construct and the non-block DO construct. Fortran 2018 deleted the non-block DO construct and the warning from your compiler relates to using this deleted form. Shared termination is a slightly different issue.
The DO construct in Fortran 2018 (the block DO construct in previous language standards) requires the terminating statement to be either an end do
statement or a (labelled) continue
statement. (The end do
statement must be labelled if the DO construct is a labelled DO construct such as do 1 ...
.)
A non-block DO construct was much less restrictive and allowed many other statements (action statements) to be the labelled end of a DO construct. However, the labelled termination statement was always within the scope of the DO construct (so would be executed in every iteration). An assignment statement (such as in the question) is an action statement.
This means that you can modernize the (Fortran 2008 non-block) DO construct of the question (removing comments and changing to free-form source for clarity)
DO 20 II = I1, I2
IW = ICN(II)
IF (NUMB(IW)==0) GOTO 70
20 LOWL(IV) = MIN(LOWL(IV),LOWL(IW))
with the unlabelled form
DO II = I1, I2
IW = ICN(II)
IF (NUMB(IW)==0) GOTO 70
LOWL(IV) = MIN(LOWL(IV),LOWL(IW))
END DO
or the labelled form
DO 20 II = I1, I2
IW = ICN(II)
IF (NUMB(IW)==0) GOTO 70
LOWL(IV) = MIN(LOWL(IV),LOWL(IW))
20 END DO ! OR CONTINUE
I'm sure many people would prefer the unlabelled form. Indeed, the labelled form is obsolescent in Fortran 2018.
For non-block DO constructs where the terminating action statement was also the target of a go to
we rewrite such that the go to
points to the (labelled) statement pulled in to the loop. We can also rewrite non-block DO constructs which share the terminating action statement.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With