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

Pointer function as type-bound procedure - valid?

Arjen_Markus
명예로운 기여자 II
2,578 조회수

Hello, I posted a small program the other day on Fortran Discourse to illustrate how to use pointer function to implement a simple dictionary. PierU followed up on my suggestion that this can be made more flexible by putting everything in a type with type-bound procedures. The resulting code is:

module container_m
    implicit none

    type container_t
        real, pointer :: a(:)
    contains
        procedure :: v
    end type

contains

    function v(this,i)
        class(container_t), target, intent(inout) :: this
        integer, intent(in) :: i
        real, pointer :: v
        v => this%a(i)
    end function

    function w(this,i)
        type(container_t), target :: this
        integer, intent(in) :: i
        real, pointer :: w
        w => this%a(i)
    end function

end module

program container
    use container_m
    implicit none

    type(container_t), target :: x
    integer :: i

    do i = 1, 10, 2
        x%v(i) = i
    end do
    do i = 2, 10, 2
        w(x,i) = i
    end do

    do i = 1, 10
        print*, i, ' : ', x%v(i), w(x,i)
    end do

end

gfortran is happy to compile this program but ifx (I am using 2025.0.0 at the moment) is not:

ifx chk_p.f90 -standard-semantics
Intel(R) Fortran Compiler for applications running on Intel(R) 64, Version 2025.0.0 Build 20241008
Copyright (C) 1985-2024 Intel Corporation. All rights reserved.

chk_p.f90(38): error #6515: This function, which is specified as the left side of an assignment statement, is invalid.   [V]
        x%v(i) = i
----------^
compilation aborted for chk_p.f90 (code 1)

So the question now is: is this legal or not? And if it is not legal, what is the rationale?

 

 

0 포인트
1 솔루션
andrew_4619
명예로운 기여자 III
2,339 조회수

has to be a bug. The workaround does not fail  but in reality that should make no difference, the fact that it does the opposite is a bug one way or the other.

 

원본 게시물의 솔루션 보기

0 포인트
11 응답
andrew_4619
명예로운 기여자 III
2,570 조회수

I have not a clue what the intended outcome of this program is meant to be, I just can't see how a function call can be on the LHS of an assignment. I am interested so see how this thread develops as there may be a hole in my understanding which may lead to an existential crisis! Just for the record could you take me through what the intended outcome should be of x%v(i) = i  please.

0 포인트
Arjen_Markus
명예로운 기여자 II
2,543 조회수

The (plain) feature is described in MFE (version for 2023), paragraph 8.7 and figure 8.5. The output from the program built with gfortran is:

           1  :    1.00000000       1.00000000
           2  :    2.00000000       2.00000000
           3  :    3.00000000       3.00000000
           4  :    4.00000000       4.00000000
           5  :    5.00000000       5.00000000
           6  :    6.00000000       6.00000000
           7  :    7.00000000       7.00000000
           8  :    8.00000000       8.00000000
           9  :    9.00000000       9.00000000
          10  :    10.0000000       10.0000000

You see two ways of getting a pointer to an element of the array x%a. The feature "simply" allows the pointer result of a function to be used on the left-hand side of an assignment. So, the first loop uses a type-bound procedure to set the odd-numbered elements and the second loop uses a "loose" function to set the even-numbered elements.

If I leave out the first loop (so x%v(i) = ...) then ifx accepts the program.

0 포인트
andrew_4619
명예로운 기여자 III
2,527 조회수

OK thanks I get what  your are trying to do, but it seems  counter intuitive to how a function assignment would work in the rest of the Fortran universe. You are effectively saying x=y and defining what x actual is  at the same time. I will be interested to see authoratative responses, I hope there are some.  

 

.... But it seems " Fortran standard (since F08) supports referencing a function which returns a pointer in variable-definition contexts"

 

0 포인트
MarcGrodent
새로운 기여자 II
2,502 조회수

I tested several things:

  • With gfortran (14.2.0)

The compilation is OK, but there is a segmentation fault at run time: "invalid memory reference"

I think you need to allocate "a" first in the program with, for example:

allocate (x%a(10))

Then, the code provides the results you are showing.

 

  • With IFX 2025.3.0

With your code, I get the same compilation error as you (error #6515 ...)

Leaving out the first loop, the compilation is OK. 

But at run time, there is an access violation at the first assignment "w(x,i) = i"

After allocating "a" as with gfortran, the result is as follows (which I think is what we are expecting):

1  :   0.000

2 :   2.000

3 :  0.000

4 : 4.000

...

 

So I think there is definitely a problem with IFX when it comes to the assignments involving x%v(i) = i, but I think that you must  allocate "a" in all cases.

 

 

0 포인트
Arjen_Markus
명예로운 기여자 II
2,495 조회수

You're right about that. I apparently did not correct some of the variations I tried. The original code by PierU had a non-allocatable array of 10 elements. I experimented with a array pointer, assuming that might solve it, but that was not the case. Since the "w" version does work, I do believe ifx is in error.

0 포인트
MarcGrodent
새로운 기여자 II
2,410 조회수

The solution with IFX is to modify the function "v" as follows:

    function v(this,i) result(res)
        class(container_t), target, intent(inout) :: this
        integer, intent(in) :: i
        real, pointer :: res
        res => this%a(i)
    end function

The key element seems to be distinguishing the function name from the value returned by that function.

After this modification, the code compiles and runs as expected with IFX.

However, I don't fully understand why this modification is not necessary for the 'w' function. Maybe because it is not a procedure of the container_t type ...

0 포인트
Arjen_Markus
명예로운 기여자 II
2,402 조회수

Oh, thanks a lot for this workaround, This does show it is an error in the compiler, as there should be no need for defining a separate name for the return value. But I will pass this on. 

0 포인트
Mark_Lewy
소중한 기여자 I
2,390 조회수

I think the code is legal, following the rules down to R1522 in the Fortran 2023 Interpretation document:

R1033 (10.2.1.1) defines assignment-stmt is variable = expr

In R902 (9.2) variable can be a function-reference

In R1520 (15.5.1) function-reference is a procedure-designator with its argument list

In R1522 (15.5.1) procedure-designator can be data-ref % binding-name (i.e. a TBP call)

I can't see anything in the constraints here disallowing a TBP from use as an accessor function.

 

0 포인트
MarcGrodent
새로운 기여자 II
2,385 조회수

Yes, we all agree that the code is legal, I think this is not the issue.

But IFX triggers a compilation error with the initial version of the code. The workaround is to use different names for the function and the returned value. Unsure whether this is a bug or not...

0 포인트
Mark_Lewy
소중한 기여자 I
2,378 조회수

Yes, I think your post hadn't appeared when I was writing my reply to the OP.  That's a good workaround, I normally put a result clause on any functions I write.

0 포인트
andrew_4619
명예로운 기여자 III
2,340 조회수

has to be a bug. The workaround does not fail  but in reality that should make no difference, the fact that it does the opposite is a bug one way or the other.

 

0 포인트
응답