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

Binding label restriction for submodule procedures

jwmwalrus
New Contributor I
574 Views

Hi.

The following code

module mod1
    use ISO_C_BINDING

    implicit none
    private

    interface
        module subroutine dummy()
        end subroutine
    end interface
end module

submodule (mod1) sm_callback
    implicit none

contains
    module procedure dummy
    end procedure

    function callback(arg) bind(C) result(res)
        type(C_PTR) :: res
        type(C_PTR), value :: arg
        res = C_NULL_PTR
    end function
end submodule

Fails to compile with

$ ifx -V -c /media/vmshare/submod-callback.f90 
Intel(R) Fortran Compiler for applications running on Intel(R) 64, Version 2025.0.1 Build 20241113
Copyright (C) 1985-2024 Intel Corporation. All rights reserved.

 Intel(R) Fortran 25.0-1205.1
/media/vmshare/submod-callback.f90(17): error #6117: A module procedure in a submodule that is not a separate module procedure cannot have a binding label.
    function callback(arg) bind(C) result(res)
---------------------------^
compilation aborted for /media/vmshare/submod-callback.f90 (code 1)

I know that the solutions is to just have an interface block for the "callback" function in the parent module, but why is that necessary?

Btw, gfortran 14 compiles the code without issue.

0 Kudos
1 Solution
Steve_Lionel
Honored Contributor III
423 Views

The only thing that occurs to me, is that there's probably another constraint that guarantees that the procedure name is not mangled only if its interface is declared in the parent module.

 


I think this is it.

View solution in original post

0 Kudos
7 Replies
andrew_4619
Honored Contributor III
545 Views

Well without the interface it has no external visibility and the whole point of bind(C) is to allow it to be called from C so to me that is a sound call by the compiler. As to what the standard chapter and verse says I have not looked.....

0 Kudos
jwmwalrus
New Contributor I
511 Views

@andrew_4619 wrote:

Well without the interface it has no external visibility and the whole point of bind(C) is to allow it to be called from C so to me that is a sound call by the compiler. As to what the standard chapter and verse says I have not looked.....


Isn't the visibility really a thing of the linker? Having the interface block doesn't seem to add much.

I have code that does this

module mod1
    use ISO_C_BINDING

    implicit none
    private

    interface
        module subroutine dummy()
        end subroutine
    end interface
end module

submodule (mod1) sm_callback
    implicit none

contains
    module procedure dummy
        ! invoke C function here, passing callback as an arg.
    contains
        function callback(arg) bind(C) result(res)
            type(C_PTR) :: res
            type(C_PTR), value :: arg
            res = C_NULL_PTR
        end function
    end procedure
end submodule

That is, the callback being passed is a contained procedure, and it works just fine. It was only when I tried to re-use that same callback from multiple places in the submodule, that the error was thrown.

0 Kudos
Steve_Lionel
Honored Contributor III
504 Views

C1807 A procedure defined in a submodule shall not have a binding label unless its interface is declared in the ancestor module.

NAG Fortran also doesn't like your code either. I played with this for a bit but couldn't figure out how to satisfy the standard - perhaps I'm just tired.

0 Kudos
jwmwalrus
New Contributor I
497 Views

Thanks for the pointer to the standard.

I still fail to see how passing a contained procedure is okay, but a non-contained one requires an interface in the parent module.

Do you mind expanding on the reasoning behind that constraint?

0 Kudos
andrew_4619
Honored Contributor III
456 Views

It isn't OK in my opinion. As to "Isn't the visibility really a thing of the linker?" , well no, I want procedures in a sub-module to have no external visibility, they are private and if they were not so it invalidates the purpose of a sub-module which is to separate interface and implementation to minimise build cascades. 

0 Kudos
jwmwalrus
New Contributor I
444 Views

@andrew_4619 wrote:

It isn't OK in my opinion. As to "Isn't the visibility really a thing of the linker?" , well no, I want procedures in a sub-module to have no external visibility, they are private and if they were not so it invalidates the purpose of a sub-module which is to separate interface and implementation to minimise build cascades. 


We're talking about C binding, so C doesn't really care about Fortran's PUBLIC|PRIVATE attributes. All that matters is whether the procedure name in the object file is either global (i.e., external) or local to the object. Since submodules can be in separate files (and might therefore be associated to separate object files), their procedure names have to be global.

(In fact, gfortran has a bug related submodules not seeing the parent module's private definitions because the generated object file for the module considers them local.)

The only thing that occurs to me, is that there's probably another constraint that guarantees that the procedure name is not mangled only if its interface is declared in the parent module.

 

0 Kudos
Steve_Lionel
Honored Contributor III
424 Views

The only thing that occurs to me, is that there's probably another constraint that guarantees that the procedure name is not mangled only if its interface is declared in the parent module.

 


I think this is it.

0 Kudos
Reply