[comp.lang.fortran] fortran problem

AER7101@TECHNION.BITNET (Zvika Bar-Deroma) (06/11/88)

Hello,
I have some questions concerning a bug (or  as I call it, when it
bares the name of a big manufacturer, an undocumented feature..).
I ran the following program on several machines. There is "some problem"
with the program, as in the subroutine, an attempt is made to redefine
a constant.
Naively enough, I expected to get a reasonably clear message in English,
(not HEX location of unknown registers..), just as the following will:
* this produces "clear" message:
      PARAMETER ( I=5)
      I=1
      END
The message you get follows:
*ERR* EQ-02 line 2, column 7, cannot assign value to expression
(That's WATFOR77's compiler, one could think of something better like:
"trying to redefine a constant", which I saw somewhere, but even that's
good enough..).

Now try to run the following program. Do NOT allocate files (if possible
with your system) and check the following:
     1. On which unit it printed 'THIS SHOULD BE PRINTED ON UNIT 1' ?
     2. What is the value of I printed on the default output unit ?

      CALL TRY ( 1 )
      WRITE (1,*) 'THIS SHOULD BE PRINTED ON UNIT 1'
      I=1
      WRITE (*,*) ' I (SHOULD BE 1) = ',I
      STOP
      END

      SUBROUTINE TRY ( KUKU )
      KUKU = 8
      RETURN
      END

Following are the results of some compilers (refer to the questions):

    compiler/machine           unit #    I    comments
************************       ******    *    ********
IBM VS FORTRAN 2.2.0             8       1    OPT(2) causes I to be 8 ..

IBM VS FORTRAN 1.4.1             8       8

WATFOR77  2.5                    1       1

CDC/NOS FTN5                     8       1

CDC/ NOS/VE FORTRAN                            runtime err: "ACCESS VIOLATION"
                                               + HEX location
 (when run with full debug causes the cursor to point at the "KUKU=8"
  line, in addition to the ACCESS VIOLATION error msg. )

VAX/VMS FORTRAN                                runtime err: "ACCESS VIOLATION"
                                               + HEX location

WATFIV                                        err. msg.:
***ERROR*** SUBPROGRAM TRY   REDEFINES A CONSTANT, EXPRESSION, DO-PARAMETER OR
ASSIGNED GOTO INDEX ( ARGUMENT NUMBER   1)
PROGRAM WAS EXECUTING LINE  1 IN ROUTINE M/PROG WHEN TERMINATION OCCURED

Unfortunately, WATFIV is FORTRAN 4 ....

How does your compiler execute this program ?
Can anyone tell me if/what the ANSI standard "says" to such a situation?
How about the 8x draft ?

(Of course, my program is a small demonstration of a problem that can
be serious, as happened to a user here with a program a few thousand
statements long, producing inexplicable results).

Regards,

Zvika Bar-Deroma
dept. of Aeronautical eng.
Technion, Haifa, Israel

BITNET        :   AER7101@TECHNION
INTERNET      :   AER7101%TECHNION.BITNET@cunyvm.cuny.EDU
DOMAIN NAMING :   AER7101@TECHNION.TECH.AC.IL
UUCP          :   .....!ucbvax!aer7101@technion.bitnet
CSNET         :   aer7101@technion.bitnet

mcdonald@uxe.cso.uiuc.edu (06/12/88)

>      CALL TRY ( 1 )
>      WRITE (1,*) 'THIS SHOULD BE PRINTED ON UNIT 1'
>      I=1
>      WRITE (*,*) ' I (SHOULD BE 1) = ',I
>      STOP
>      END

>      SUBROUTINE TRY ( KUKU )
>      KUKU = 8
>      RETURN
>      END
This is the classic expression of a common stupid Fortran bug. It is
not legal Fortran for a subroutine to redefine the value of a constant
or expression. It doesn't matter WHAT a given compiler does with it:
it is an illegal construct. It is up to the programmer to write correct
programs. Fortran compilers are required to give correct output
with correct programs. If you feed them a program with a bug in it,
the resulting output is "undefined" , which means essentially anything
is "correct" behaviour of the compiler.

smryan@garth.UUCP (Steven Ryan) (06/13/88)

This is a long standing feature of Fortran. All parameters are passed
by reference, so the address of the constant 1 is passed. The subroutine
does not know this is constant--it is considerred the programmer's
responsibilty.

In some systems the constant is in a readonly page so that attempts to
store into it cause an access violation.

In some systems the io is translated into calls with the unit being passed by
value (hidden protocols need not be conforming).

In some systems constants used in expressions are handled by load immediate
instructions so that each use of a constant is distinct. In other systems
all uses of a constant map into the same memory location.

                                 Make it simple--not simplistic.
                                                         sm ryan

bill@hcx2.SSD.HARRIS.COM (06/13/88)

/* Written  8:22 am  Jun 11, 1988 by AER7101@TECHNION.BITNET.UUCP in hcx2:comp.lang.fortran */
/* ---------- "fortran problem" ---------- */

> Hello,
> I have some questions concerning a bug (or  as I call it, when it
> bares the name of a big manufacturer, an undocumented feature..).
> I ran the following program on several machines. There is "some problem"
> with the program, as in the subroutine, an attempt is made to redefine
> a constant.
> Naively enough, I expected to get a reasonably clear message in English,
> 
> Can anyone tell me if/what the ANSI standard "says" to such a situation?
> How about the 8x draft ?
/* End of text from hcx2:comp.lang.fortran */

The Standard says (Section 15.9.2), "Actual arguments may be constants,
symbolic names of constants, function references, expressions involving
operators, and expressions enclosed in parentheses if and only if the
associated dummy argument is a variable that is not defined during
execution of the referenced external procedure."

The 8x draft says essentially the same thing, in quite a different way,
but it also (at least, at the moment) provides you with INTERFACE blocks
that can declare the INTENT of each argument, giving the compiler the
opportunity of giving a more meaningful error message in this situation.
If you choose not to use INTERFACE, though, you're back to F77.

As has been pointed out about a zillion times, the Standard says
absolutely nothing about what errors the FORTRAN processor (compiler,
linker, loader, et al.) must give for programs that violate some
restriction other than a syntax rule.  It says only what is a
standard-conforming program; non-conforming programs may or may not
be detected.  If they are detected, the Standard says nothing about
what the error message (if any) must say.

Bill Leonard (member, X3J3)
Harris Computer Systems Division
2101 W. Cypress Creek Road
Fort Lauderdale, FL  33309
bill@ssd.harris.com or bill%ssd.harris.com@eddie.mit.edu

cdb@hpclcdb.HP.COM (Carl Burch) (06/14/88)

Unfortunately, any such program is not standard-conforming, and the standard
therefore says exactly nothing about its required behavior.  The relevant
passage of the F77 standard is paragraph 15.9.2 on page 15-16 :

     "Actual arguments may be constants ... if and only if the associated
      dummy argument is a variable that is not defined during execution of
      the referenced external procedure."

The Fortran 8x draft standard has similar words, and is quite likely to
retain them in light of the F8x Prime Directive - to be 100% F77 compatible.

There are some tools that try to find such problems - see the previous
notestrings on Fortran lint.  I don't know if they mentioned MAT from SAIC,
or flint from Programming Research Ltd in England.  I haven't used either
one, but they're both made by nice guys that know more about the problem
than I do.

As for your general implication on the quality of compilers that cause
this sort of problem, I wish you hadn't mentioned the specific companies
you compared - I could be somewhat more candid in the abstract.  As it is,
I will just report that the problem you cite was used as a horror story
in the compiler-writing class I took at Purdue in 1981 - with the professor's
opinion that this story is so famous that nobody would ever do it "wrong"
again.  Silly him.  Actually, after a similar conversation with a couple HP
customers at a users group conference I found to my dismay that HP still
has one compiler (F7x on the HP1000) that also allows constants to change
value this way.  So (as the saying goes) "Let's be CAREFUL out there!"

						- Carl Burch
						  cdb%hpda@hplabs.HP.COM
						  HP Fortran Team

hirchert@uxe.cso.uiuc.edu (06/16/88)

I'd like to make a few more observations on the issue of changing constants
in Fortran:
1. In the most general case, detection _requires_ run-time checks.  Consider
   the following procedure:
      SUBROUTINE SUB(X,ICODE)
      SAVE XX
      IF(ICODE.EQ.0)THEN
         XX=X
      ELSE
         X=XX
      ENDIF
      END
   This routine is correct (according to the rules of Fortran), as long as
   ICODE has the value 0 for each call to SUB where the actual argument
   corresponding to X is not something that can be assigned to.  In general,
   we will not know the value of ICODE until run-time (e.g. it may be read in),
   so no static analysis (whether by the compiler, the linker, or a separate
   "lint" program) can say definitely whether or not this program is correct.
   This is not to say that static analysis is useless.  Static analysis can
   recognize that there is the possibility for error in this procedure and
   can recognize when the erroneous statement is unconditional.
2. Thus, in the general case, checking for this error (or protecting a program
   from the effects of this error) is never entirely without run-time cost.
   The closest one can come to no cost is when the hardware does the checking 
   (as when constants are stored in write-protected memory).  Unfortunately, the
   error messages for hardware detected errors are often cryptic and/or 
   difficult to relate to one's Fortran error.  If hardware detection is either
   unavailable or undesirable, then the compiler must generate extra code,
   either to check for the occurrence of this error or to copy constants to
   storage that can be modified without hurting anything.
3. In turn, this means that it is not necessarily "wrong" to allow programs
   to commit this error.  It depends on whether it is more important to you
   (and your customers) to detect (or protect the program from) errors or to
   achieve maximum performance on correct programs.  (Of course, if you're
   really generous, you can give your customers a choice, just as is usually
   done for subscript bounds checking.)

Kurt W. Hirchert     hirchert@ncsa.uiuc.edu
National Center for Supercomputing Applications

chpf127@ut-emx.UUCP (J. Eaton) (06/17/88)

In article <50500056@uxe.cso.uiuc.edu>, hirchert@uxe.cso.uiuc.edu writes:
> 
> I'd like to make a few more observations on the issue of changing constants
> in Fortran:

    [ stuff deleted about changing constants ]

> 3. In turn, this means that it is not necessarily "wrong" to allow programs
>    to commit this error.  It depends on whether it is more important to you
>    (and your customers) to detect (or protect the program from) errors or to
>    achieve maximum performance on correct programs.  (Of course, if you're
>    really generous, you can give your customers a choice, just as is usually
>    done for subscript bounds checking.)

    How about just writing correct programs from the start, or if you are
    unsure about what variables in the argument list may be modified,
    don't use constants -- use a temporary variable instead and avoid this
    whole problem.  This can also make your code easier to read.

    Consider the following:

      CALL SUB ( X, 5, 3, 2, IER )

    Who can possibly tell, without looking at SUB, what 5, 3, and 2 mean?
    Isn't it better to write:

      LDX  = 5
      NROW = 3
      NCOL = 2

      CALL SUB ( X, LDX, NROW, NCOL, IER )

    I think this is a lot better.  Anyone else?
   
> Kurt W. Hirchert     hirchert@ncsa.uiuc.edu
> National Center for Supercomputing Applications

    J. Eaton
    UT Austin Dept of Chemical Engineering

    Still not speaking for my employer, even if he does pay me.