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

Passing a procedure with upoly argument as an argument

Dharma
Beginner
805 Views
Hello,
I am not sure if this is legal to do. I get a seg fault in the following code where i use a procedure, say A, passed as an argument to another procedure, say B. Procedure A has a argument which is an unlimited polymorphic argument.
Here is the test case:
[fortran]module DTCompontentPointer
 implicit none
 type A
  integer numB
  procedure(),pointer,nopass :: f=>null()
  contains
  procedure :: init => init
 end type A
 contains
 subroutine init(this,numB,foo)
 class(A),intent(inout),target :: this
 integer, intent(in) :: numB
 external :: foo
 this%numB = numB
 this%f => foo
 end subroutine init
end module DTCompontentPointer
module Temp
 implicit none
 contains
  subroutine foo1(val)
  integer :: val
  integer :: ival
  !real :: upoly
  print*,'Value=',val
  print*,'ThisWorks'

 end subroutine foo1
 subroutine foo2(val,upoly)
  integer :: val
  class(*):: upoly
  !real :: upoly
  print*,'Value=',val
  print*,'This seg faults on Next Line'
  select type(upoly)
   type is(integer)
    print*,'upoly is integer with value=',upoly
   type is(real)
   print*,'upoly is real with value=',upoly
   end select
 end subroutine foo2
end module Temp
program Test
use DTCompontentPointer
use Temp
 type(A):: C
 integer :: ival
 real :: rval
 call C%init(5,foo1)
  ival=10
  call C%f(ival)
 call C%init(6,foo2)
 rval=8.0
  call C%f(ival,rval)
end program Test[/fortran]
0 Kudos
5 Replies
Steven_L_Intel1
Employee
805 Views
I have taken a quick look at this. The fundamental issue is that foo2 accepts an unlimited polymoprphic but there is no explicit interface visible to the caller saying so. You then pass it a REAL, which doesn't include the information needed to resolve the CLASS(*). Since you have gone to some lengths to hide the interface of the pointer procedure, the compiler can't validate this for you.

If you're going to be calling a procedure that requires an explicit interface, then you must provide one.
0 Kudos
Dharma
Beginner
805 Views
So, how is foo differenet from foo2. Both of them do not have explicit interface. I even tried passing a CLASS(*) object as a second argument to the foo2. I still get segfault. Have a look at this code
[fortran]module DTCompontentPointer
 implicit none
 type A
  integer numB
  procedure(),pointer,nopass :: f=>null()
  contains
  procedure :: init => init
 end type A
 contains
 subroutine init(this,numB,foo)
 class(A),intent(inout),target :: this
 integer, intent(in) :: numB
 external :: foo
 this%numB = numB
 this%f => foo
 end subroutine init
end module DTCompontentPointer
module Temp
 implicit none
 contains
  subroutine foo1(val)
  integer :: val
  integer :: ival
  !real :: upoly
  print*,'Value=',val
  print*,'ThisWorks'

 end subroutine foo1
 subroutine foo2(val,upoly)
  integer :: val
  class(*):: upoly
  !real :: upoly
  print*,'Value=',val
  print*,'This seg faults on Next Line'
  select type(upoly)
   type is(integer)
    print*,'upoly is integer with value=',upoly
   type is(real)
   print*,'upoly is real with value=',upoly
   end select
 end subroutine foo2
end module Temp
program Test
use DTCompontentPointer
use Temp
 type(A):: C
 integer :: ival
 class(*),pointer :: rvalupoly
 real :: rval
 call C%init(5,foo1)
  ival=10
  call C%f(ival)
 call C%init(6,foo2)
 rval=8.0
  allocate(rvalupoly,source=rval)
    select type(rvalupoly)
   type is(integer)
    print*,'rvalupoly is integer with value=',rvalupoly
   type is(real)
   print*,'rvalupolyis real with value=',rvalupoly
   end select
  call C%f(ival,rvalupoly)
end program Test[/fortran]
0 Kudos
Steven_L_Intel1
Employee
805 Views
foo doesn't have a upoly argument and doesn't require an explicit interface. It doesn't matter that you pass a upoly - what matters is that the compiler can see, at the point of the call, that the called procedure is expecting a polymorphic argument. This is one of the cases that requires an explicit interface to be visible to the caller.

You can't fudge this with the approach you are taking. The procedure pointer f has no interface, so it is treated as if it was just an ordinary external routine. There's no information the compiler can use to pass what foo2 wants.
0 Kudos
Dharma
Beginner
805 Views
Thanks. I got it. I was using an explicit interface. I was experimenting with this other appraoch. Did not knew that explicit interface is needed in case of polymorphic arguments.
0 Kudos
Steven_L_Intel1
Employee
805 Views
Here is what the standard now says about this:

19 1 A procedure other than a statement function shall have an explicit interface if it is referenced and
20 (1) a reference to the procedure appears
21 (a) with an argument keyword (12.5.2), or
22 (b) in a context that requires it to be pure,
23 (2) the procedure has a dummy argument that
24 (a) has the ALLOCATABLE, ASYNCHRONOUS, OPTIONAL, POINTER, TARGET, VALUE,
25 or VOLATILE attribute,
26 (b) is an assumed-shape array,
27 (c) is a coarray,
28 (d) is of a parameterized derived type, or
29 (e) is polymorphic,
30 (3) the procedure has a result that
31 (a) is an array,
32 (b) is a pointer or is allocatable, or
33 (c) has a nonassumed type parameter value that is not a constant expression,
34 (4) the procedure is elemental, or
35 (5) the procedure has the BIND attribute.
0 Kudos
Reply