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

--- Comment #8 from Tobias Burnus <burnus at gcc dot gnu.org> ---
(In reply to Jakub Jelinek from comment #5)
>   common /a/ i(10)
> subroutine foo (j)
>   common /a/ i(1)
> Is that valid Fortran at all?

No. Fortran 2008 (in 5.7.2.5) has: "Named common blocks of the same name shall
be of the same size in all scoping units of a program in which they appear"

That's not new as FORTRAN 77 (in 8.3.3) had: "Within an executable program, all
named common blocks that have the same name must be the same size".

The example has a named common block with name "A". Admittedly, that's not
really the issue for the wrong code here - as one could simply turn it into a
blank common: "but blocks of the same name shall be of the same size in at
blank common blocks may be of different sizes." [continuation of F2008 quote].


>   call foo (10)
> end
> subroutine foo (j)
>   common /a/ i(1)
...
>   do k = 1, j
>     l = l + i(k)
>
> Is that valid Fortran at all? 

In terms of the standard: No. Fortran 2008 explicitly states: "The value of a
subscript in an array element shall be within the bounds for its dimension."
(F2008, 6.5.3.)

For Fortran 77, I could only find something less explicit: "The first  element 
of  the  array has a subscript value of one; the second element has a subscript
value  of  two; the  last  element  has  a subscript value equal to the size of
the array." and "The size of an array is equal to the  product  of  the  sizes 
of  the dimensions  specified  by the array declarator for that array name."

Hence, I'd claim that anything but 1 is already invalid in Fortran 77. (Storage
associations in general allows some tricks, such as with using EQUIVALENCE (cf.
C/C++'s union) but this does not apply here.)


In Fortran 66/77, it was alledgedly not uncommon to write "dimension(1)" for
dummy/formal arguments - instead of using dimension(*) - and then to access
array elements beyond the first one. (Also invalid back then.) However, for
COMMON, that's new to me. (Not that I have much experience with pre-Fortran-90
code.)


> If Fortran as language allows this, either everywhere, or for compatibility
> in some mode, it would be better if such common blocks were modeled similarly
> to C99 flexible array members with GNU extension of initializing that;

Hmm, the big problem is where to draw a boundary and what to support. As such
things were never allowed by the standard, it is difficult to decide what to
support and using which flag. In real-world code, one can find tons of code
which was invalid but worked - often for years and with different compilers -
until it suddenly stopped doing so. It seems as if GCC/gfortran is in
particular successful in doing so (judging from bug reports) - which implies
that it seems to be better at exploiting optimization opportunities given by
the language.

A similar use to the one above would be:

integer A
integer B
COMMON /foo/ A(5), B(7)

and accessing A(8). That memory reference matches B(3) and is a valid memory
address. (Fortran's storage association rules guarantee this.) Still, it
exceeds "A" and is hence invalid according to the Fortran standard - and I
assume also the middle end does not like A(8).

I think for that memory access, the VLA trick wouldn't work. I try to avoid
such legacy extensions as they are ill-defined.


In any case, gfortran with -fcheck=bounds should reject this at run time - and
using a compile-time array index it should do so already at compile time. 


> From the comments in unport.F, it looks like 416.gamess has commented out
> even far uglier hacks, in particular using the COMMON /FPCOM / X(1) and then
> when accessing it biasing index by some variable, which is initialized as a
> difference between a heap region and the array in the common block.  That
> would be even worse for the middle-end and C semantics, dunno what Fortran
> as language ever allowed and what needs to be (optionally?) tolerated to get
> badly written code working.

Well, I think in may cases, the early versions of the language - like the
Fortran manuals from IBM - simply didn't state what would happen in that case.
But back in the old days, for many the standard matched what their compiler
did.

For instance a loop like "do i = 5, 3": How often is it executed? (Fortran 66
didn't permit it - but one can still write it.) Answer: With some vendors once,
with other vendors zero times. I think already Fortran 77 standardized this to
execute zero times. As the execute-once version was common, several compilers
(including Intel's current one, g77 and others) had a compile-time flag to
permit this.

(Actually, if I look at the code gfortran generates for a loop, it is written
such that once-trip loops could be simply enabled, even though no flag exists
to turn it on.)


(In reply to Vladimir Makarov from comment #6)
> Some SPEC benchmarks contain questionable code.  It is true for SPEC2000
> and true for SPEC2006.  So the PR is not a surprise for me.
> 
>  Unfortunately, nobody from GCC community participates in SPEC org

I think it would be useful if they could run the code before inclusion with all
checking turned on (gfortran's -fcheck=all -fsanitize=*, Intel's "-check all").
I think some of the issues would then be found before.

With a small test program, mimicing the code Jakub has posted, Intel's ifort
-CB gives: "Subscript #1 of the array I has value 2 which is greater than the
upper bound of 1"

Reply via email to