2

I'm modernizing some old Fortran code and I cannot get rid of an equivalence statement somewhere (long story short: it's mixed use is so convoluted it'd take too much work to convert everything).

I need the length of the EQUIVALENCEd arrays to depend on some input, like the following code:

program test_equivalence                                                
      implicit none                                                     

      type :: t1                                                        
          integer :: len = 10                                           
      end type t1                                                       

      type(t1) :: o1                                                    


      call eqv_int(o1%len)                                              
      call eqv(o1)                                                      

      return                                                 

      contains                                                          
          subroutine eqv_int(len)                                       
             integer, intent(in) :: len                                 
             integer :: iwork(len*2)                                    
             real(8) :: rwork(len)                                      
             equivalence(iwork,rwork)                                   

             print *, 'LEN = ',len                                      
             print *, 'SIZE(IWORK) = ',size(iwork)                      
             print *, 'SIZE(RWORK) = ',size(rwork)                      
          end subroutine eqv_int                                        

          subroutine eqv(o1)                                            
             type(t1), intent(in) :: o1                                 

             integer :: iwork(o1%len*2)                                 
             real(8) :: rwork(o1%len)                                   
             equivalence(iwork,rwork)                                   

             print *, 'LEN = ',o1%len                                   
             print *, 'SIZE(IWORK) = ',size(iwork)                      
             print *, 'SIZE(RWORK) = ',size(rwork)                      
          end subroutine eqv                                            
end program test_equivalence                                            

This program will create 0-length arrays with gfortran 9.2.0. This is the output:

 LEN =           10
 SIZE(IWORK) =            0
 SIZE(RWORK) =            0

 LEN =           10
 SIZE(IWORK) =            0
 SIZE(RWORK) =            0

The same code will return Array 'rwork' at (1) with non-constant bounds cannot be an EQUIVALENCE object when compiled with gfortran 5.3.0, the warning disappears since gfortran 6.2.0, but the size of the arrays is always 0. So maybe compiler bug?

Federico Perini
  • 1,414
  • 8
  • 13
  • Edit: the same code will return ```Array 'rwork' at (1) with non-constant bounds cannot be an EQUIVALENCE object``` when compiled with gfortran 5.3.0, the warning disappears since gfortran 6.2.0, but the size of the arrays is always 0. So maybe compiler bug? – Federico Perini Mar 25 '20 at 09:46
  • Please [edit] your question, do not leave important information in the comments. – Vladimir F Героям слава Mar 25 '20 at 09:52
  • @VladimirF gotcha, thanks – Federico Perini Mar 25 '20 at 10:00
  • 1
    @FedericoPerini Please note RETURN in the main program is not standard Fortran and should be deleted - this is not C! Also please read https://stackoverflow.com/questions/838310/fortran-90-kind-parameter and understand why real( 8 ) is not good practice – Ian Bush Mar 25 '20 at 11:56

1 Answers1

0

The source code is indeed not a valid Fortran program. To be specific, it violates the numbered constraint C8106 of Fortran 2018:

An equivalence-object shall not be a designator with a base object that is .. an automatic data object ..

Being a numbered constraint, the compiler must be capable of detecting this violation. If hasn't such a capability this is a deficiency in the compiler (a bug). Being "capable" doesn't mean doing so by default, so please look carefully to see whether there are options which do lead to this detection. Someone familiar with the internals of GCC can give further detail here.

As the source isn't a valid Fortran program, the compiler is allowed to consider the arrays of size zero if it has skipped the violation detection.

francescalus
  • 30,576
  • 16
  • 61
  • 96
  • Thanks, so I need to find another way to accomplish what I need. I have a routine whose interface is like this: ```subroutine sub(iwork,rwork)``` where ```integer :: iwork(*)``` and ```real(8) :: rwork(*)``` . Since these arrays are equivalenced and their usage is mixed integer/real inside ```sub```, somewhere else in the code there is only a unique real workspace, and sub is called as ```call sub(rwork,rwork)```. My only other option besides equivalencing the arrays is to do something like ```call sub(rwork,transfer(rwork,[0]))```, but it does not pass the contents of transfer by reference... – Federico Perini Mar 25 '20 at 10:29
  • BTW - the issue is that the compiler will not compile ```call sub(rwork,rwork)``` inside the same module, because it is imposing type checking. – Federico Perini Mar 25 '20 at 10:33
  • 2
    A 40 year old program using equivalence of real/integer workspaces is likely doing it just to save memory: you can now probably afford to just have separate variables. – francescalus Mar 25 '20 at 10:55
  • Hmmmm, looking for an option in gfortran that picks this up but can't find one - I would expect -std= at the very least to detect it. Time for a bug report methinks! – Ian Bush Mar 25 '20 at 11:57
  • It's a bug in gfortran. My version of gfortran gives a few errors of the form: _Error: Array 'iwork' at (1) with non-constant bounds cannot be an EQUIVALENCE object_ – evets Mar 25 '20 at 18:31
  • @evets What version is that and what flags are you using? – Ian Bush Mar 25 '20 at 20:23
  • @IanBush, it's my personal development copy of gcc. I saw this discussion and then looked at gfortran source code. The error message has been in gfortran forever; it however, seems that the condition to raise the error is broken. I fixed that problem and posted a patch on the fortran@gcc.gnu.org list. Don't know if anyone will commit the change. – evets Mar 25 '20 at 20:39
  • 1
    @evets If you can add to you report it looks like a regression problem between versions 5.5 and 6.5, on my laptop it fails to compile with the former, but incorrectly compiles with 6.5, 7.4 and 8.3 (and 10.0 (experimental) downloaded a couple of weeks ago – Ian Bush Mar 25 '20 at 20:59
  • @evets, I seem to recall another question where a gfortran check no longer functioned. I can't remember the details, but I'll look for that question. – francescalus Mar 25 '20 at 23:35
  • It would be a surprise to change the constraint being reported on by default intentionally without it being obvious why the "extension" is desirable. – francescalus Mar 25 '20 at 23:37
  • AFAICT, there isn't a test in the gfortran testsuite for this constraint. The function that should trigger the error has changed numerous times to accommodate newer standards, which I think inverted the logic. – evets Mar 26 '20 at 00:57