2

main.F90

program main
  use my_module

  real(8) :: a, b

  a = 1.3
  b = 2.4

  call my_subroutine1(a)
  !call my_subroutine2(a)

end program main

test.F90

module my_module
contains

  subroutine my_subroutine1(a, b)
    class(*), intent(in) :: a
    class(*), intent(in), optional :: b
  
    select type (a)
    type is (real(4))
      print*, 'real 4 a (my_subroutine1): ', a
    type is (real(8))
      print*, 'real 8 a (my_subroutine1): ', a
    end select

    if (present(b)) then
      print*, 'b is present in subroutine1'
      select type (b)
      type is (real(4))
        print*, 'real 4 b: ', b
      type is (real(8))
        print*, 'real 8 b: ', b
      end select
    else
    end if

    call my_subroutine3(a, b)

  end subroutine my_subroutine1

  subroutine my_subroutine2(a, b)
    real(8), intent(in) :: a
    real(8), intent(in), optional :: b

    print*, 'real 8 a (my_subroutine2): ', a
    if (present(b)) then
      print*, 'b is present in subroutine2'
      print*, 'real 8 b: ', b
    else
    end if

    call my_subroutine3(a, b)

  end subroutine my_subroutine2

  subroutine my_subroutine3(a, b)
    class(*), intent(in) :: a
    class(*), intent(in), optional :: b

    select type (a)
    type is (real(4))
      print*, 'real 4 a (my_subroutine3): ', a
    type is (real(8))
      print*, 'real 8 a (my_subroutine3): ', a
    end select

    if (present(b)) then
      print*, 'b is present in subroutine3'
      select type (b)
      type is (real(4))
        print*, 'real 4 b: ', b
      type is (real(8))
        print*, 'real 8 b: ', b
      end select
    end if

  end subroutine my_subroutine3

end module my_module

When main calls my_subroutine1(a), output is

 real 8 a (my_subroutine1):    1.29999995231628     
 real 8 a (my_subroutine3):    1.29999995231628 

However, when main calls my_subroutine2(a), output is

 real 8 a (my_subroutine2):    1.29999995231628     
 real 8 a (my_subroutine3):    1.29999995231628     
 b is present in subroutine3
forrtl: severe (408): fort: (7): Attempt to use pointer B when it is not associated with a target

Image              PC                Routine            Line        Source             
a.out              00000000004072A0  Unknown               Unknown  Unknown
a.out              0000000000404897  my_module_mp_my_s          62  test.F90
a.out              0000000000403CA2  my_module_mp_my_s          41  test.F90
a.out              0000000000404984  MAIN__                     10  main.F90
a.out              0000000000402B9E  Unknown               Unknown  Unknown
libc-2.17.so       00007F05EDED2555  __libc_start_main     Unknown  Unknown
a.out              0000000000402AA9  Unknown               Unknown  Unknown

In the second case (calling my_subroutine2), why does my_subroutine3 think the optional argument is present?

I understand that I can do something like this in my_subroutine2

if (present(b)) then
  call my_subroutine3(a,b)
else
  call my_subroutine3(a)
end if

but with all b's being an optional dummy argument in all 3 subroutines, this is not required as supported by my_subroutine1.

Is using class(*) variable as optional dummy argument causing this problem? If that's the case, why does main calling my_subroutine1 work without an error?

minsuk ji
  • 23
  • 4

0 Answers0