3

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
francescalus
  • 30,576
  • 16
  • 61
  • 96
Stef1611
  • 1,978
  • 2
  • 11
  • 30
  • 2
    "internal compiler error" means you have a bug in the _compiler_ (as well possibly as in your code). You resolve this by reporting the bug, upgrading your compiler, using another compiler, or working around the issue. You have a workaround already identified, so do you still want formal advice on whether your code is allowed (even if correct it doesn't do you much good if you can't use it)? As you've noticed, the newer compiler version accepts the code, so there's perhaps little more left to say – francescalus Aug 26 '22 at 10:31
  • @francescalus. I asked for an advice because, perhaps, my code does not conform to the standard. That is why I have an error. Other points, I could not upgrade the version compiler or use another compiler on the computer where there is the problem. I have a workaround. Do you think it is a bug in the compiler ? How can I report the bug ? But it is solved in the last version. – Stef1611 Aug 26 '22 at 10:37
  • 4
    Compilers shouldn't crash, and "internal compiler error" means the compiler detected a failure in it's own compilation processes and aborted. This says nothing about the (Fortran) validity of your code. As you've seen GCC 10 fails and GCC 12 works, you probably won't benefit from reporting this particular compiler bug. Asking whether your code is valid is appropriate, but we'd ideally have more focused concerns about it than a compiler bug (lots of valid code can crash compilers). – francescalus Aug 26 '22 at 10:45
  • @francescalus. Ok. I try to do my first bug report – Stef1611 Aug 26 '22 at 10:46
  • 4
    This was already fixed at https://gcc.gnu.org/g:c0134b7383992aab5c1a91440dbdd8fbb747169c so there's not much point reporting a bug. I added a comment with your code to https://gcc.gnu.org/PR104430 – Jonathan Wakely Aug 26 '22 at 11:00
  • @JonathanWakely. Thanks for answer and to add a comment with my code. I made an edit2 in my question to be sure that even with this code the bug is fixed. – Stef1611 Aug 26 '22 at 11:28
  • @JonathanWakely. Following the answer of Francescalus, I am not sure that this edit2 is appropriate. I will remove `forall` statement/construct and replace them with `do` loops. – Stef1611 Aug 26 '22 at 11:47

1 Answers1

3

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.

francescalus
  • 30,576
  • 16
  • 61
  • 96
  • Thanks a lot. I did not know that `forall (integer :: i=1:4, j=1:4, k=1:4)` was allowed. I will change my code. – Stef1611 Aug 26 '22 at 11:33
  • I think GCC (even 12) doesn't support that form of FORALL (but please do try). I've added a note to my answer that the best way to have your code work with GCC 10 is to rewrite the FORALLs as DOs. – francescalus Aug 26 '22 at 11:37
  • `forall ( integer :: iix=1:4, iiy=1:4 )` : syntax error with GCC 12. I was thinking that FORALL was good for optimisation. But, as it is obsolescent, I will remove them. – Stef1611 Aug 26 '22 at 11:40
  • 1
    @Stef1611 It turned out that FORALL was somewhat poorly designed and thus optimizing it wasn't as straightforward as hoped for, hence later standards marked it as obsolescent. If you want to tell the compiler there are no loop-carried dependencies, see the DO CONCURRENT construct (FORALL done right, in a sense). – janneb Aug 26 '22 at 13:47