Frontend bug: Illegal number or type of arguments

Originally this bug can be triggered in the following example using OpenMPI:

module provider_m
  use iso_c_binding
  interface
    subroutine callback(userdata)
      import
      type(c_ptr), intent(in) :: userdata(:)
    end
  end interface
contains
  subroutine go(prec)
    procedure(callback) prec
  end
end
module consumer_m
  use mpi_f08 ! <-- remove this to make the error disappear
  use provider_m
contains
  subroutine process
    call go(op)
  end
  subroutine op(userdata)
    type(c_ptr), intent(in) :: userdata(:)
  end
end

This was actually quite hard to reduce, because it doesn’t trigger reliably. The smallest dependency-free example I could make is 164 lines and has five modules. Any little variation to this example, e.g. deleting a seemingly unused variable in one of the modules makes the bug disappear.

Live example on Compiler Explorer

minimal.f90
module mpi_types
  type MPI_Status
  end type
  type MPI_Comm
  end type
  type MPI_Datatype
    integer :: MPI_VAL
  end type
  type MPI_Errhandler
    integer :: MPI_VAL
  end type
  type MPI_VAL
  end type
  type MPI_Group
    integer :: MPI_VAL
  end type
  type MPI_Info
    integer :: MPI_VAL
  end type
  type MPI_Message
    integer :: MPI_VAL
  end type
  type MPI_Op
    integer :: MPI_VAL
  end type
  type MPI_Request
  end type
  type MPI_Session
  end type
  type MPI_Win
  end type
end
module mpi_f08_types
  use mpi_types
  logical :: MPI_COMM_WORLD(1)
  type(MPI_Message) :: MPI_MESSAGE_NO_PROC(1)
  type(MPI_Info) :: MPI_INFO_ENV(1)
  type(MPI_Op) :: MPI_MAX(1)
  type(MPI_Op) :: MPI_MIN(1)
  type(MPI_Op) :: MPI_SUM(1)
  type(MPI_Op) :: MPI_PROD(1)
  type(MPI_Op) :: MPI_LAND(1)
  type(MPI_Op) :: MPI_BAND(1)
  type(MPI_Op) :: MPI_LOR(1)
  type(MPI_Op) :: MPI_BOR(1)
  type(MPI_Op) :: MPI_LXOR(1)
  type(MPI_Op) :: MPI_BXOR(1)
  type(MPI_Op) :: MPI_MAXLOC(1)
  type(MPI_Op) :: MPI_COMM_NULL(1)
  type(MPI_Datatype) :: MPI_DATATYPE_NULL(1)
  type(MPI_Errhandler) :: MPI_ERRHANDLER_NULL(1)
  type(MPI_Group) :: MPI_GROUP_NULL(1)
  type(MPI_Info) :: MPI_INFO_NULL(1)
  type(MPI_Message) :: MPI_MESSAGE_NULL(1)
  type(MPI_Op) :: MPI_SESSION_NULL(1)
  type(MPI_Datatype) :: MPI_AINT(1)
  type(MPI_Datatype) :: MPI_BYTE(1)
  type(MPI_Datatype) :: MPI_PACKED(1)
  type(MPI_Datatype) :: MPI_UB(1)
  type(MPI_Datatype) :: MPI_LB(1)
  type(MPI_Datatype) :: MPI_CHAR(1)
  type(MPI_Datatype) :: MPI_SIGNED_CHAR(1)
  type(MPI_Datatype) :: MPI_UNSIGNED_CHAR(1)
  type(MPI_Datatype) :: MPI_WCHAR(1)
  type(MPI_Datatype) :: MPI_CHARACTER(1)
  type(MPI_Datatype) :: MPI_LOGICAL(1)
  type(MPI_Datatype) :: MPI_INT(1)
  type(MPI_Datatype) :: MPI_INT16_T(1)
  type(MPI_Datatype) :: MPI_INT32_T(1)
  type(MPI_Datatype) :: MPI_INT64_T(1)
  type(MPI_Datatype) :: MPI_INT8_T(1)
  type(MPI_Datatype) :: MPI_UINT16_T(1)
  type(MPI_Datatype) :: MPI_UINT32_T(1)
  type(MPI_Datatype) :: MPI_UINT64_T(1)
  type(MPI_Datatype) :: MPI_UINT8_T(1)
  type(MPI_Datatype) :: MPI_SHORT(1)
  type(MPI_Datatype) :: MPI_UNSIGNED_SHORT(1)
  type(MPI_Datatype) :: MPI_UNSIGNED(1)
  type(MPI_Datatype) :: MPI_LONG(1)
  type(MPI_Datatype) :: MPI_UNSIGNED_LONG(1)
  type(MPI_Datatype) :: MPI_LONG_LONG(1)
  type(MPI_Datatype) :: MPI_UNSIGNED_LONG_LONG(1)
  type(MPI_Datatype) :: MPI_LONG_LONG_INT(1)
  type(MPI_Datatype) :: MPI_INTEGER(1)
  type(MPI_Datatype) :: MPI_INTEGER1(1)
  type(MPI_Datatype) :: MPI_INTEGER2(1)
  type(MPI_Datatype) :: MPI_INTEGER4(1)
  type(MPI_Datatype) :: MPI_INTEGER8(1)
  type(MPI_Datatype) :: MPI_INTEGER16(1)
  type(MPI_Datatype) :: MPI_FLOAT(1)
  type(MPI_Datatype) :: MPI_DOUBLE(1)
  type(MPI_Datatype) :: MPI_LONG_DOUBLE(1)
  type(MPI_Datatype) :: MPI_REAL(1)
  type(MPI_Datatype) :: MPI_REAL4(1)
  type(MPI_Datatype) :: MPI_REAL8(1)
  type(MPI_Datatype) :: MPI_REAL16(1)
  type(MPI_Datatype) :: MPI_DOUBLE_PRECISION(1)
  type(MPI_Datatype) :: MPI_C_COMPLEX(1)
  type(MPI_Datatype) :: MPI_C_FLOAT_COMPLEX(1)
  type(MPI_Datatype) :: MPI_C_DOUBLE_COMPLEX(1)
  type(MPI_Datatype) :: MPI_C_LONG_DOUBLE_COMPLEX(1)
  type(MPI_Datatype) :: MPI_CXX_COMPLEX(1)
  type(MPI_Datatype) :: MPI_CXX_FLOAT_COMPLEX(1)
  type(MPI_Datatype) :: MPI_CXX_DOUBLE_COMPLEX(1)
  type(MPI_Datatype) :: MPI_CXX_LONG_DOUBLE_COMPLEX(1)
  type(MPI_Datatype) :: MPI_COMPLEX(1)
  type(MPI_Datatype) :: MPI_COMPLEX8(1)
  type(MPI_Datatype) :: MPI_COMPLEX16(1)
  type(MPI_Datatype) :: MPI_COMPLEX32(1)
  type(MPI_Datatype) :: MPI_DOUBLE_COMPLEX(1)
  type(MPI_Datatype) :: MPI_FLOAT_INT(1)
  type(MPI_Datatype) :: MPI_DOUBLE_INT(1)
  type(MPI_Datatype) :: MPI_2REAL(1)
  type(MPI_Datatype) :: MPI_2DOUBLE_PRECISION(1)
  type(MPI_Datatype) :: MPI_2INT(1)
  type(MPI_Datatype) :: MPI_SHORT_INT(1)
  type(MPI_Datatype) :: MPI_LONG_INT(1)
  type(MPI_Datatype) :: MPI_LONG_DOUBLE_INT(1)
  type(MPI_Datatype) :: MPI_2INTEGER(1)
  type(MPI_Datatype) :: MPI_2COMPLEX(1)
  type(MPI_Datatype) :: MPI_2DOUBLE_COMPLEX(1)
  type(MPI_Datatype) :: MPI_REAL2(1)
  type(MPI_Datatype) :: MPI_LOGICAL1(1)
  type(MPI_Datatype) :: MPI_LOGICAL2(1)
  type(MPI_Datatype) :: MPI_LOGICAL4(1)
  type(MPI_Datatype) :: MPI_LOGICAL8(1)
  type(MPI_Datatype) :: MPI_C_BOOL(1)
  type(MPI_Datatype) :: MPI_CXX_BOOL(1)
  type(MPI_Datatype) :: MPI_COUNT(1)
  type(MPI_Datatype) :: MPI_OFFSET(1)
  type(MPI_Datatype), parameter :: MPI_COMPLEX4 = MPI_Datatype(0)
end
module pmpi_f08_interfaces
  interface
    subroutine PMPI_Neighbor_alltoallw_init_f08
      use mpi_f08_types
      use ISO_C_BINDING
    end
  end interface
end
module provider_m
  use iso_c_binding
  interface
    subroutine callback(userdata)
      import
      type(c_ptr), intent(in) :: userdata(:)
    end
  end interface
contains
  subroutine go(prec)
    procedure(callback) prec
  end
end
module consumer_m
  use pmpi_f08_interfaces
  use provider_m
contains
  subroutine process
    call go(op)
  end
  subroutine op(userdata)
    type(c_ptr), intent(in) :: userdata(:)
  end
end

Since this is so hard to trigger it makes me think that this might have something to do with the internal state of the parser.

Here I would also be really interested in a workaround for my part of the code, because I can’t easily edit OpenMPI.

Hi herni.menke,

I filed a report, TPR #38322, and sent it to engineering for investigation.

I found that if I reverse the order of the modules, i.e. put “use provider_m” before “use mpi_f90”, then it works.

If that’s not a viable work around for you, I also tried it with our new Fortran compiler that were working on with the LLVM Community, and it worked without issue. While the new nvfortran is still a bit away, you can download the open source version from: llvm-project/flang at main · llvm/llvm-project · GitHub, if you want to give it try.

-Mat