https://gcc.gnu.org/bugzilla/show_bug.cgi?id=95631

            Bug ID: 95631
           Summary: Unable to redefine a literal with `-std=legacy'
           Product: gcc
           Version: 11.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: fortran
          Assignee: unassigned at gcc dot gnu.org
          Reporter: ma...@linux-mips.org
  Target Milestone: ---

This is an interesting one.  This was mentioned by Eric Korpela here:
<http://www.classiccmp.org/pipermail/cctalk/2020-May/053704.html> as a
language peculiarity of up to at least FORTRAN 77.  Which is given the
following program:

C
C     CHANGE THE VALUE OF 4
C

      CALL INC(4)
      WRITE (*, 30) 4
30    FORMAT ('2+2=',I4)
      END

      SUBROUTINE INC(I)
      I = I + 1
      END

the supposed output is:

2+2=   5

Eric says:

'Most languages will give you some way to shoot yourself in the foot.  The
question is how much work do you need to do?  In FORTRAN the easiest method
was changing the value of a literal in a subroutine call.  It is standard
compliant behavior that goes back to at least FORTRAN IV.   Current
compliers and converters go to pains to make sure it still happens.  Not
sure if it is still present in f90 and beyond.  At least modern compilers
for other languages will give you a "potential foot shooting warning",
although in C++ that warning statement could take 200 kB.'

However when this program is built with GCC like this and run on an
`x86_64-linux-gnu' system, it causes SIGSEGV at the incrementation:

$ gfortran -Wall -W -Wextra -pedantic -std=legacy -O2 -g -o four four.f
$ ./four

Program received signal SIGSEGV: Segmentation fault - invalid memory reference.

Backtrace for this error:
#0  0x7f0e8c9f5b90 in ???
#1  0x7f0e8c9f4dc5 in ???
#2  0x7f0e8c66683f in ???
#3  0x4011b1 in inc_
        at /home/macro/src/four.f:11
#4  0x4011b1 in MAIN__
        at /home/macro/src/four.f:5
#5  0x40109c in main
        at /home/macro/src/four.f:8
$ 

The reason is the literal to be incremented (4) has been assigned to
`.rodata'.  There is no warning issued with the compilation either.
Conversely with the `riscv64-linux-gnu' target the literal gets assigned
to `.sdata' and the program executes as expected:

$ ./four
2+2=   5
$ 

but I take it it is by chance rather than design (no `.srodata' has been
defined, for obvious reasons).

My Fortran experience is so-so, but I did some language standard
examination and indeed it says something like:

"INTENT (INOUT) is not equivalent to omitting the INTENT attribute.  The
argument corresponding to an INTENT (INOUT) dummy argument always shall
be definable, while an argument corresponding to a dummy argument without
an INTENT attribute need be definable only if the dummy argument is
actually redefined."

which essentially means that the actual argument associated with I in the
call to INC here has to be a variable rather than a literal.

My understanding however is we still intend to support peculiar old
programs if built with the `-std=legacy' level.  If not, then perhaps we
ought to at least give that "potential foot shooting warning" Eric talks
about?

Reply via email to