Search code examples
fortrangfortran

forall index an associating entity?


I tried to compile this program with two different versions of gfortran:

program main

    integer, dimension(1:2) :: iii
    real, dimension(1:4,1:4,1:2) :: myArray
    
    associate(iix => iii(1), iiy=> iii(2) )
    forall( iix=1:4, iiy=1:4 )
        myArray(iix,iiy,1) = iix + iiy
        myArray(iix,iiy,2) = (iix + iiy)*10
    endforall
    end associate

    print *, myArray(:,:,1)
    print *, myArray(:,:,2)
    
end program main

There is no problem with GNU Fortran (GCC) 12.1.1 20220507 (Red Hat 12.1.1-1) version

But with GNU Fortran (Debian 10.2.1-6) 10.2.1 20210110 version, I get a compilation error

7 |  forall( iix=1:4, iiy=1:4 )
  |                           1 internal compiler error: Segmentation fault

This version is not so old (2021/01/10)

From which gfortran version, is it possible to use associate in a forall statement? And does this program conform to the standard?

It works with do loops

integer, dimension(1:2) :: iii
real, dimension(1:4,1:4,1:2) :: myArray

    associate(iix => iii(1), iiy=> iii(2) )
    do iix = 1,4
        do iiy = 1,4
            myArray(iix,iiy,1) = iix + iiy
            myArray(iix,iiy,2) = (iix + iiy)*10
        enddo
    enddo
    end associate

    print *, myArray(:,:,1)
    print *, myArray(:,:,2)
    
end program main

Following the comment of Jonathan Wakely, I sum up. In my initial code, there is also a do loop between the associate line and the forall line.

program main

integer, dimension(1:2) :: iii
real, dimension(1:4,1:4,1:2) :: myArray
integer :: i

myArray = 0.0

associate( iix => iii(1), iiy => iii(2) )
do i=1,2
    forall( iix=1:4, iiy=1:4 )
        myArray(iix,iiy,i) = (iix+iiy)*10*i
    endforall
enddo
end associate

print *, myArray(:,:,1)
print *, myArray(:,:,2)

end program main

Solution

  • In comments we've addressed that the failure to compile with GCC 10 is a compiler bug which has been fixed in/by GCC 12. You offered to report this bug, but Jonathan Wakely has identified where this was fixed: there's little point reporting.

    That said, there's still something we can say about code validity and workarounds.

    Actually, I won't comment on validity, because what I'll say about the code itself makes that concept redundant.

    Based on previous questions you've asked, you're using the ASSOCIATE with the FORALL to allow you to use an array element as the index. Something like

    integer :: i(2)
    forall (i(1)=1:4) ...
    

    isn't allowed, so like with DO constructs and arrays you're associating a scalar variable with the element.

    With FORALLs, though, that's entirely unhelpful.

    The scope of an index in a FORALL statement/construct is that statement/construct. There's no connection between the array iii (in the question example) outside the FORALL and inside. There's simply no point associating the arrays elements with scalars to use those scalars in the FORALL.1

    Note that you can2 "create" a new name specific to the FORALL itself, so you don't need to re-use names:

    forall (integer :: iix=1:4, iiy=1:4, iiz=1:4) ...
    

    instead of

    integer iii(3)
    associate (iix=>iii(1), iiy=>iii(2), iiz=>iii(3)
       forall (iix=1:4, iiy=1:4, iiz=1:4) ...
    end associate
    

    FORALLs and DOs are very different things.

    Some Fortran developers would say that the appropriate workaround for GCC 10 is to simply avoid using FORALLs at all. FORALLs are obsolescent in the Fortran standard and may be removed in the future. It's a reasonable position to hold that they should be avoided in new code.


    1 If you don't have compiler support for what I mention next, then there is a (weak) point in using an ASSOCIATE to tidy up the number of declared scalar variables - in this case use a BLOCK construct to at least keep them local. It's hard to see the ASSOCIATE example above as any tidier than

    block
      integer iix, iiy, iiz
      forall (iix=1:4, iiy=1:4, iiz1:4) ...
    end block 
    

    Or avoid the obsolescent FORALL altogether.

    2 If you have compiler support for this Fortran 2008 feature. GCC at the time of answering is missing this support.