1

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
20
  • 1
    For what it's worth your code looks fine to me, but it's sufficiently niche that I wouldn't be surprised if it's forbidden by the standard or if the compilers can't handle it. One possible source of error is that Fortran procedure pointers don't have closure so if your default function is any more complex than add you may end up referencing undefined variables. Commented Jan 20, 2022 at 18:22
  • 1
    Does the code behave incorrectly for you? Is this piece of code supposed to show the mentioned compiler bug or not? It looks OK to me. Commented Jan 20, 2022 at 18:24
  • 1
    I don't spot anything non-standard about the code, but I see that NAG Fortran doesn't like it, complaining that add is multiply defined (which I don't understand and will ask about.) I wonder if the unspecified misbehavior is not due to a bug here, but something else. Commented Jan 20, 2022 at 18:41
  • 2
    There are constraints on using an initial pointer target (whether the procedure pointer is a component or not), but add here is valid. As others say, please expand on why you think there may be a problem. Commented Jan 20, 2022 at 18:47
  • 1
    @SteveLionel, which version of nagfor? I don't get a complaint. Commented Jan 20, 2022 at 18:47

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.