Problem with impure elemental subroutine in interface with gfortran

Compiling and running the code below, also at Compiler Explorer,

module m1_mod
implicit none
interface foo
   module procedure foo_mat
end interface foo
contains

subroutine foo_mat(x, nacf, label)
real, intent(in) :: x(:,:)
integer, intent(in) :: nacf
character (len=*), intent(in), optional :: label
end subroutine foo_mat

end module m1_mod

module m2_mod
use m1_mod, only: foo
implicit none
interface foo
  module procedure foo_df
end interface foo
contains

impure elemental subroutine foo_df(nacf, outu, xstr)
integer          , intent(in) :: nacf
integer          , intent(in), optional :: outu
character (len=*), intent(in), optional :: xstr
if (present(xstr)) print*,"in foo_df, xstr = '" // trim(xstr) // "'"
end subroutine foo_df

impure elemental subroutine bar(nacf, outu, xstr)
integer          , intent(in) :: nacf
integer          , intent(in), optional :: outu
character (len=*), intent(in), optional :: xstr
if (present(xstr)) print*,"in bar, xstr = '" // trim(xstr) // "'"
end subroutine bar

end module m2_mod

program main
use m2_mod, only: foo, bar
implicit none
call bar(nacf = 5, xstr="ab")
call foo(nacf = 5, xstr="ab")
end program main

with gfortran 15.0.0 20241215 from equation.com

gives

 in bar, xstr = 'ab'
 in foo_df, xstr = ''

With ifx it gives

 in bar, xstr = 'ab'
 in foo_df, xstr = 'ab'

as I think it should. The program works with gfortran if any of the changes

  1. remove impure elemental attribute
  2. remove the line use m1_mod, only: foo
  3. remove the label argument from foo_mat

are made.

Yeah, IFX behaviour is correct (I believe?). Probably a bug in GNU’s compiler? I reproduced this with gfortran 13.2. Have you tried other compilers?

Ps. How do you find examples of these behaviours so often?

Just lucky, I guess :slight_smile: . I have not tried other compilers.

Impure elemental is a recent and obscure addition to Fortran, so there may be more bugs in its implementation than that of more commonly used language features. It can be convenient, though. With a single line

call print_acf(df_ret**[1,2], nacf=5, title=["ret   ","ret**2"])

where print_acf is impure elemental I can display the autocorrelations of both the original time series in df_ret (stored in a derived type) and its squares, with output such as

ret   
           SPY     EFA     EEM     TLT
ACF_01 -0.1009 -0.1111 -0.1130 -0.0295
ACF_02 -0.0188  0.0026 -0.0374 -0.0510
ACF_03  0.0122  0.0126  0.0328 -0.0289
ACF_04 -0.0321 -0.0201 -0.0402  0.0093
ACF_05 -0.0184 -0.0090 -0.0103 -0.0019

ret**2
           SPY     EFA     EEM     TLT
ACF_01  0.2611  0.2465  0.1934  0.3715
ACF_02  0.4603  0.3810  0.4481  0.2937
ACF_03  0.2326  0.2187  0.1583  0.2968
ACF_04  0.2775  0.2383  0.2806  0.3285
ACF_05  0.3076  0.3101  0.3020  0.2382
1 Like

that’s pretty neat, I would then raise a bug report for the GNU people.

1 Like

Someone else did:

Bug 119656 - [12/13/14/15 Regression] Wrong code with impure elemental subroutine and interface. Their test case works in gfortran 11.5.0 but fails in gfortran 12+.

1 Like

open source is amazing :slight_smile: thanks for your help