In article <6k27an$4mi at gap.cco.caltech.edu>, mathog at seqaxp.bio.caltech.edu writes:
>Hi,
>>Anybody else out there still running GCG 8.1 - on OpenVMS 7.1 (alpha)?
>>I've hit a very odd bug, not quite sure in what (GCG, compiler, linker, VMS?).
>Can anybody else verify this behavior?
>>$ for/Align/Extend_Source/NoList/Warning=All gensource:map.for
>$ sharelink map
>$ mmm:==$current_disk:[current_directory]map.exe
>
Ok folks, I tracked it down, and it is *ugly* and, unfortunately, pervasive.
In many places in MAP (and many other GCG 8.1 programs) one finds code like:
If ( .not.CLGetOldFName('INfile1', 1, SeqName) .and.
& .not.CLNoInteract() ) then
!* do something here
End If
The problem is that the Fortran standard apparently does not specify the
order in which the two functions will be evaluated, nor does it guarantee
that both will be evaluated, if after evaluating the first one, the result
of the second cannot change the result. (This from Steve Lionel, who is
pretty much the final word on these matters.) Older versions of Digital
Fortran on Alpha (and apparently every other Fortran compiler that GCG runs
on) did it in the left to right order, first CLGetOldFName, and then, if
necessary, CLNoInteract. Unfortunately, newer versions of Digital Fortran
are now doing it CLNoInteract, then, if necessary, CLGetOldFName.
So, if you put /DEFAULT on the command line, .not. CLNoInteract comes up
FALSE, and .FALSE. .AND. anything, is .FALSE., which the compiler
has allowed for, so the program never executes CLGetOldFName. Making the
/infile=whatever on the command line perfectly useless. /NOOPT doesn't
disable this optimization.
Unfortunately, the current version of the compiler cannot even issue
warnings about this, so all you can do is manually go through the code
searching for this sort of structure (and I found a lot of them) and
rewrite them the way they should have been in the first place, ie:
If ( .not.CLGetOldFName('INfile1', 1, SeqName)) then
If (.not.CLNoInteract() ) then
!* do something here
End If
End If
Note that the following is no better than the original:
isinter = .not. CLNointeract()
If ( .not.CLGetOldFName('INfile1', 1, SeqName) .and. isinter)then
!* do something here
End If
because the program will check isinter, and again bail before it executes
CLGetOldFName.
The good news is that this bug is only uncovered when you recompile any of
the Fortran modules - the older object files still work.
They may have cleaned this up in GCG 9.0 or later, but in that case it
would hardly matter, since you probably wouldn't have the source
code to modify.
Regards,
David Mathog
mathog at seqaxp.bio.caltech.edu
Manager, sequence analysis facility, biology division, Caltech