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

Procedure target in structure constructor

ivanp
New Contributor I
333 Views

I would like to build a table of procedures. The program (copied below) fails to compile with the following error:

ifx: remark #10440: Note that use of a debug option without any optimization-level option will turnoff most compiler optimizations similar to use of '-O0'
/app/example.f90(39): error #6592: This symbol must be a defined parameter, an enumerator, or an argument of an inquiry function that evaluates to a compile-time constant.   [A]
type(pc), parameter :: table(3) = [pc(a),pc(b),pc(c)]  ! Doesn't work
--------------------------------------^
I believe the program is legal. According to section 7.5.10 of J3/24-007, a procedure target is a valid component data source of a procedure pointer component of the derived type `pc`. Furthermore, a named procedure is a valid pointer initialization target in a constant expression, according to 10.1.12, bullet 3b. 

Full program:
! dispatch_test.f90 --
!   Dispatch table using procedure pointers

module funcs
abstract interface
    function retchar()
       character(len=1) :: retchar
    end function
end interface
contains
    function a()
        character(len=1) :: a
        a = 'a'
    end function
    function b()
        character(len=1) :: b
        b = 'b'
    end function
    function c()
        character(len=1) :: c
        c = 'c'
    end function
end module

module dispatch_table
use funcs
implicit none
private

public :: table
public :: build_table, pc

! Procedure container
type :: pc
    procedure(retchar), pointer, nopass :: rc => null()
end type

! Static dispatch table
type(pc), parameter :: table(3) = [pc(a),pc(b),pc(c)]  ! Doesn't work

! According to J3/24-007, section 7.5.10, a procedure target
! can be used in the structure constructor.

contains

    ! Dynamic dispatch table
    function build_table() result(table)
        type(pc) :: table(3)
        table = [pc(a),pc(b),pc(c)]  ! This works
    end function

end module

program test
    use dispatch_table, only: pc, build_table
    implicit none
    type(pc) :: table(3)
    table = build_table() ! Dynamic table
    associate(abc => &
        table(1)%rc()//table(2)%rc()//table(3)%rc())
        if (abc /= 'abc') stop 1
    end associate

    block
        use dispatch_table, only: table ! Static table
        associate(abc => &
            table(1)%rc()//table(2)%rc()//table(3)%rc())
            if (abc /= 'abc') stop 2
        end associate
    end block

    print *, 'PASS'
end program

Both the NAG Fortran compiler and flang accept this program.

Labels (2)
0 Kudos
4 Replies
ivanp
New Contributor I
230 Views

Any opinions on this issue? 

As I've tried to illustrate, the initialization of the (dynamic) dispatch table with:

        table = [pc(a),pc(b),pc(c)]

is legal. The question is whether this statement is also valid as a constant expression in the initialization of a parameter variable. 

 

 

0 Kudos
Mark_Lewy
Valued Contributor I
188 Views

This is one for the language lawyers

But, I note that compiling with gfortran 13.1.0 gives:

dispatch_test.f90:39:38:

39 | type(pc), parameter :: table(3) = [pc(a),pc(b),pc(c)] ! Doesn't work
| 1
Error: Parameter ‘a’ at (1) has not been declared or is a variable, which does not reduce to a constant expression
dispatch_test.f90:30:15:

30 | public :: table
| 1
Error: Symbol ‘table’ at (1) has no IMPLICIT type
dispatch_test.f90:55:9:

55 | use dispatch_table, only: pc, build_table
| 1
Fatal Error: Cannot open module file ‘dispatch_table.mod’ for reading at (1): No such file or directory
compilation terminated

 

Also, looking in John Reid's summary of the new features in Fortran 2023 (N2212.pdf), there doesn't appear to have been any relaxation on what you can have in initialisation expressions.

ivanp
New Contributor I
169 Views

I also asked the GNU contributors and they sent me here to ask for an opinion: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=117070

For the record, also the tickets that saw this behavior fixed/introduced in NAG Fortran and LLVM flang were opened by me. For the Nvidia Fortran compiler (formerly PGI) I was recommended to use a dynamic dispatch table as a workaround. 


It would be great if language lawyers could reach a verdict. Otherwise it is just one more unportable behavior.

 

0 Kudos
Steve_Lionel
Honored Contributor III
138 Views

My take is that this is valid usage, though it does not astonish me that compilers get this wrong. Here's my logic:

R758 allows a proc-target as a component-data-source. 
C7109 says "a proc-target shall correspond to a procedure pointer component.", which it does here.
R1041 says that proc-target can be a procedure-name
C1033 includes a module procedure in the list of allowed uses of a proc-target here

Reply