I just want to know for sure if this is valid Fortran or if I've misunderstood some usage. Is the following code valid?
Module MathFxns
implicit none
Type A_T
procedure(DoStuff_F), nopass, pointer :: method => add
contains
End Type A_T
Abstract Interface
Function DoStuff_F(a, b) result(c)
integer, intent(in) :: a, b
integer :: c
End Function DoStuff_F
End Interface
contains
function add(a, b) result(c)
integer, intent(in) :: a, b
integer :: c
c = a + b
end function add
End Module MathFxns
program Main
use MathFxns
implicit none
type(A_T) :: math
print *, math%method(2, 5)
end program Main
I just had to track down a compiler bug, that was being caused by something I think is valid Fortran. I'd submit to the compiler team, but I don't have a way to replicate as it's buried pretty far down in the stack and down multiple libraries before it caused a compiler bug and it doesn't happen in every program that uses it.
Edit: I didn't mention it before because it is complicated to explain, but since there was some curiosity, I'll try.
The production code does work in some executables, but recently I implemented it in another project which caused a compiler bug. I'll try to make a pseudo code example to illustrate, but first is a description. In the production code I have a type that has a default procedure pointer to a function (just like above). An instance of that type is a field of an abstract type. That abstract type is extended by another abstract type, then in a subsequent library that type is extended by another abstract type, which is then extended by a concrete type in another library. Finally an executable makes use of that concrete type. The module that has an instance of the concrete type throws a compiler error.
In the production code, it is an ODE Solver, with functionality wrapped into an entity type that gets extended a few times before being implemented.
It took me 6 hours, but after commenting and uncommenting line after line, the cause of the error was shown to be the default procedure pointer in the type. Whether that is the actual error or not, I can't know, but removing the default pointer (and pointing in the construction subroutine) made the project work again.
!this is in the first static library project
Module Library1
implicit none
Type A_T
!more stuff
procedure(DoStuff_F), nopass, pointer :: method => add
contains
!more procedures
End Type A_T
Type, abstract :: B1_A
type(A_T) :: a
!more stuff and procedures
End Type B1_A
Type, extends(B1_A), abstract :: B2_A
!more stuff and procedures
End Type B2_A
Abstract Interface
Function DoStuff_F(a, b) result(c)
integer, intent(in) :: a, b
integer :: c
End Function DoStuff_F
End Interface
contains
function add(a, b) result(c)
integer, intent(in) :: a, b
integer :: c
c = a + b
end function add
End Module Library1
! this is in the second static library project
Module Library2
use Library1
implicit none
Type, extends(B2_A), abstract :: B3_A
!more stuff and procedures
End Type B3_A
End Module Library2
! this is in the third static library project
Module Library3
use Library2
implicit none
Type, extends(B3_A) :: C_T
!more stuff and procedures
End Type C_T
End Module Library3
!this is in a fourth executable project
program Main
use Library3
implicit none
type(C_T) :: math
print *, math%a%method(2, 5)
end program Main