Intel® Fortran Compiler
Build applications that can scale for the future with optimized code designed for Intel® Xeon® and compatible processors.

Non-scalar pass-object dummy arguments

FlyingHermes
New Contributor I
622 Views

Hi,

I am trying to use type-bound procedures (TBP) with non-scalar pass-object dummy arguments. Although not valid from the standard (C461: "The passed-object dummy argument shall be a scalar, nonpointer, nonallocatable dummy data object..."), it seems to be supported by ifort version 14.0.4 (the version I'm using here) as shown by the following code:

Module MyModule
  implicit none
  Type          ::      MyType
    integer     ::      Val
  contains
    procedure   ::      ScaProc
    procedure   ::      VecProc
  End Type
  contains
Subroutine ScaProc( This, Inp, Out )
  class(MyType)                 ,intent(in)     ::      This
  integer                       ,intent(in)     ::      Inp
  integer                       ,intent(out)    ::      Out
  Out   =       Inp     +       This%Val
End Subroutine
Subroutine VecProc( Those, Inp, Out )
  class(MyType) ,dimension(:)   ,intent(in)     ::      Those
  integer                       ,intent(in)     ::      Inp
  integer                       ,intent(out)    ::      Out
  Out   =       Inp     +       sum(Those%Val)
End Subroutine
End Module

Program Main
  use MyModule  ,only:  MyType
  implicit none
  type(MyType)                  ::      Sca
  type(MyType)  ,dimension(10)  ::      Vec
  integer                       ::      i
  integer       ,parameter      ::      Inp = 1000
  integer                       ::      Out
  write(*,"(/,a)") 'Calling a TBP with a scalar passed-object dummy argument:'
  Sca        =       MyType(Val=100)
  call Sca%ScaProc( Inp, Out )
  write(*,"(a,g0)")       'Sca%Val = ', Sca%Val
  write(*,"(a,g0)")       'Inp     = ', Inp
  write(*,"(a,g0)")       'Out     = ', Out
  write(*,"(/,a)") 'Calling a TBP with a non-scalar passed-object dummy argument:'
  Vec        =       [ (MyType(Val=i),i=1,size(Vec)) ]
  call Vec%VecProc( Inp, Out )
  write(*,"(a,*(i3,1x))") 'Vec%Val = ', Vec(:)%Val
  write(*,"(a,g0)")       'Inp     = ', Inp
  write(*,"(a,g0)")       'Out     = ', Out
End Program

Using ifort version 14.0.4, I am getting the following output:

$ ifort main.F90; ./a.out

Calling a TBP with a scalar passed-object dummy argument:
Sca%Val = 100
Inp     = 1000
Out     = 1100

Calling a TBP with a non-scalar passed-object dummy argument:
Vec%Val =   1   2   3   4   5   6   7   8   9  10
Inp     = 1000
Out     = 1055

while gfortran (version 4.8.3 20140911) do not compile this code:

$ gfortran main.F90
main.F90:10.13:

    procedure   ::      VecProc
             1
Error: Passed-object dummy argument of 'vecproc' at (1) must be scalar

Note that if I had a generic TBP, I get an ICE.

Module MyModule
  implicit none
  Type          ::      MyType
    integer     ::      Val
  contains
    generic     ::      Proc => ScaProc, VecProc
    procedure   ::      ScaProc
    procedure   ::      VecProc
  End Type
  contains
Subroutine ScaProc( This, Inp, Out )
  class(MyType)                 ,intent(in)     ::      This
  integer                       ,intent(in)     ::      Inp
  integer                       ,intent(out)    ::      Out
  Out   =       Inp     +       This%Val
End Subroutine
Subroutine VecProc( Those, Inp, Out )
  class(MyType) ,dimension(:)   ,intent(in)     ::      Those
  integer                       ,intent(in)     ::      Inp
  integer                       ,intent(out)    ::      Out
  Out   =       Inp     +       sum(Those%Val)
End Subroutine
End Module

Program Main
  use MyModule  ,only:  MyType
  implicit none
  type(MyType)                  ::      Sca
  type(MyType)  ,dimension(10)  ::      Vec
  integer                       ::      i
  integer       ,parameter      ::      Inp = 1000
  integer                       ::      Out
  write(*,"(/,a)") 'Calling a TBP with a scalar passed-object dummy argument:'
  Sca        =       MyType(Val=100)
  call Sca%Proc( Inp, Out )
  write(*,"(a,g0)")       'Sca%Val = ', Sca%Val
  write(*,"(a,g0)")       'Inp     = ', Inp
  write(*,"(a,g0)")       'Out     = ', Out
  write(*,"(/,a)") 'Calling a TBP with a non-scalar passed-object dummy argument:'
  Vec        =       [ (MyType(Val=i),i=1,size(Vec)) ]
  call Vec%Proc( Inp, Out )
  write(*,"(a,*(i3,1x))") 'Vec%Val = ', Vec(:)%Val
  write(*,"(a,g0)")       'Inp     = ', Inp
  write(*,"(a,g0)")       'Out     = ', Out
End Program

which produce

main_ICE.F90(44): catastrophic error: **Internal compiler error: internal abort** Please report this error along with the circumstances in which it occurred in a Software Problem Report.  Note: File and line given may not be explicit cause of this error.
compilation aborted for main_ICE.F90 (code 1)

So, here are my questions:

  1. Is the "non-scalar pass-object dummy arguments" capability an non-standard extension from intel or just a bug that somehow passes through the compiler checks and happens to gives the correct results ?
  2. Is this "scalar pass-object dummy arguments" restriction on TBP is likely to be relaxed in the standard ?

 

Thanks

0 Kudos
4 Replies
reinhold-bader
New Contributor II
622 Views

Ad 1: I think this is a compiler bug. Because the requirement that the passed-object be a scalar is a constraint of the language, I don't think it is permissible to have this functionality as a compiler extension.

Ad 2: I think this particular constraint is unlikely to be relaxed. There would be too many side effects in the standard, not least with the combination of polymorphic (run-time) and generic (compile-time) resolution.

Note that array processing via ELEMENTAL type-bound procedures is possible; for your scenario which desires a reduction across array elements this however does not appear to be an option. On the other hand, you are not obliged to make your subroutine, which operates on a component of the base type only anyway, a type-bound procedure. And even if this were not the case, you could process the various dynamic types inside your subroutine with SELECT TYPE.

Cheers

Reinhold

0 Kudos
FortranFan
Honored Contributor III
622 Views

FWIW, the issue is present in the latest compiler version too: Compiler 15, Update 1.  And -stand f08 compiler option generates no warnings either, so this aspect is possibly an oversight in the TBP implementation in Intel Fortran.

I agree: it wouldn't make sense to relax the scalar passed-object constraint in the standard.  Coders should look to ELEMENTAL procedures or a non-TBP approach, etc. for their needs.

0 Kudos
Steven_L_Intel1
Employee
622 Views

Missing error escalated as issue DPD200365611.

0 Kudos
Steven_L_Intel1
Employee
622 Views

Fixed for a release later this year.

0 Kudos
Reply