Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

CALL FOO when FOO is a function

419 views
Skip to first unread message

pmk

unread,
May 18, 2022, 11:40:00 AM5/18/22
to
Only one Fortran compiler can cope with this usage -- most crash hard with internal errors -- but I contend that it's conforming usage.

module m
contains
function foo()
procedure(bar), pointer :: foo
foo => bar
call foo ! <-- CALL of a function
end function
subroutine bar
print *, 'in bar'
end subroutine
end module

program demo
use m
procedure(bar), pointer :: p
p => foo()
call p
end

Thomas Koenig

unread,
May 18, 2022, 11:58:25 AM5/18/22
to
pmk <pmkla...@gmail.com> schrieb:

> Only one Fortran compiler can cope with this usage -- most crash
> hard with internal errors -- but I contend that it's conforming
> usage.

On what grounds?

> module m
> contains
> function foo()
> procedure(bar), pointer :: foo
> foo => bar
> call foo ! <-- CALL of a function
> end function
> subroutine bar
> print *, 'in bar'
> end subroutine
> end module
>
> program demo
> use m
> procedure(bar), pointer :: p
> p => foo()
> call p
> end

Sounds fishy, at least...

pmk

unread,
May 18, 2022, 12:07:14 PM5/18/22
to
> > Only one Fortran compiler can cope with this usage -- most crash
> > hard with internal errors -- but I contend that it's conforming
> > usage.
> On what grounds?

Within the body of the function FOO, the name FOO refers to its result variable. The result variable in this case is a procedure pointer to a subroutine. A CALL statement's procedure designator is allowed to be a procedure pointer.

gah4

unread,
May 18, 2022, 1:37:48 PM5/18/22
to
On Wednesday, May 18, 2022 at 9:07:14 AM UTC-7, pmk wrote:
> > > Only one Fortran compiler can cope with this usage -- most crash
> > > hard with internal errors -- but I contend that it's conforming
> > > usage.

> > On what grounds?

> Within the body of the function FOO, the name FOO refers to its
> result variable. The result variable in this case is a procedure pointer
> to a subroutine. A CALL statement's procedure designator is
> allowed to be a procedure pointer.

I suspect I believe that it should not be an internal compiler error, but otherwise
I might believe compilers could accept it. But there is no claim that the result
is actually executable.

Many systems have a different calling method for functions, depending
on the type, and other attributes, of a function.

A procedure pointer can point to either a function or subroutine,
but you can only call functions with it when it points to functions,
and subroutines when it points to subroutines.

And if the compiler believes that you are not doing that, it is allowed
to reject the program.



gah4

unread,
May 18, 2022, 1:53:45 PM5/18/22
to
On Wednesday, May 18, 2022 at 8:40:00 AM UTC-7, pmk wrote:
> Only one Fortran compiler can cope with this usage -- most crash hard with internal errors -- but I contend that it's conforming usage.

Some years ago, I tried one like this. gfortran didn't like it then,
and (the one I have here) doesn't like it now:

external fun, sub
call trythis(1,sub)
call trythis(2,fun)
stop
end
subroutine sub(i)
print *,'sub',i
return
end
integer function fun(i)
print *,'fun',i
fun=3*i
return
end
subroutine trythis(j, fs)
if(j.eq.1) call fs(5)
if(j.eq.2) k=fs(5)
return
end


If you comment out one of the IF statements, then it is fine.
Note that it never calls a function as a subroutine, or
subroutine as a function, but with both IF statements,
gfortran won't compile it.


Steve Lionel

unread,
May 18, 2022, 2:53:53 PM5/18/22
to
On 5/18/2022 12:07 PM, pmk wrote:
> Within the body of the function FOO, the name FOO refers to its result variable. The result variable in this case is a procedure pointer to a subroutine. A CALL statement's procedure designator is allowed to be a procedure pointer.

I agree with this.

--
Steve Lionel
ISO/IEC JTC1/SC22/WG5 (Fortran) Convenor
Retired Intel Fortran developer/support
Email: firstname at firstnamelastname dot com
Twitter: @DoctorFortran
LinkedIn: https://www.linkedin.com/in/stevelionel
Blog: https://stevelionel.com/drfortran
WG5: https://wg5-fortran.org

FortranFan

unread,
May 18, 2022, 8:35:57 PM5/18/22
to
On Wednesday, May 18, 2022 at 11:40:00 AM UTC-4, pmk wrote:

> Only one Fortran compiler can cope with this usage -- most crash hard with internal errors -- but I contend that it's conforming usage. ..

Yes, that appears correct based on the wording in the standard.

However the relevant wording is not part of any numbered constraint. And the processors then appear to miss out on coping with the semantics in such parts of the standard, especially with features introduced starting with Fortran 90. The "sleeping dogs lie" until an astute reader catches the omission and files support request(s) and the compiler developers find the resources to follow-up on the request(s).

Nonetheless the chances are more compilers can cope with this variant:

function foo() result(r)
procedure(bar), pointer :: r
r => bar
call r
end function

JRR

unread,
May 19, 2022, 10:07:42 AM5/19/22
to
Indeed, the compiler gets confused between the result of the function
foo (which should be the procedure pointer) and the function foo itself.
It works if the result is explicitly specified like by Vipul
(FortranFan), or if the function is defined as recursive. Then gfortran
and Nagfor can compile, Nagfor even the original code with the -f2018
flag (using the Fortran 2018 standard where every function is recursive).


--
Juergen Reuter
Theoretical Particle Physics
Deutsches Elektronen-Synchrotron
Hamburg, Germany
---------------------------------
invalid is desy .and. com is de

Dan Nagle

unread,
May 19, 2022, 12:08:54 PM5/19/22
to
Hi,

On May 18, 2022, Steve Lionel wrote
(in article <jektls...@mid.individual.net>):

> On 5/18/2022 12:07 PM, pmk wrote:
> > Within the body of the function FOO, the name FOO refers to its result
> > variable. The result variable in this case is a procedure pointer to a
> > subroutine. A CALL statement's procedure designator is allowed to be a
> > procedure pointer.
>
> I agree with this.

And I'll respectfully disagree.

I think the gremlin lies in the procedure pointer assignment 10.2.2.4.

These are all procedures in the same module so the interfaces are explicit
(as is required by the pointer-ness and the procedure-ness).
Since the interfaces are explicit, agreement is required of the
characteristics.
The characteristics include whether it is a subroutine or a function 15.3.1.
qed

(I'm reading 22-007r1)

--
Cheers!

Dan Nagle

pmk

unread,
May 19, 2022, 1:17:15 PM5/19/22
to
On Thursday, May 19, 2022 at 9:08:54 AM UTC-7, Dan Nagle wrote:
> I think the gremlin lies in the procedure pointer assignment 10.2.2.4.
>
> These are all procedures in the same module so the interfaces are explicit
> (as is required by the pointer-ness and the procedure-ness).
> Since the interfaces are explicit, agreement is required of the
> characteristics.
> The characteristics include whether it is a subroutine or a function 15.3.1.
> qed

The procedure pointer is assigned to the same procedure used to define its interface.

pmk

unread,
May 19, 2022, 1:22:01 PM5/19/22
to
On Thursday, May 19, 2022 at 7:07:42 AM UTC-7, JRR wrote:
> It works if the result is explicitly specified like by Vipul
> (FortranFan), or if the function is defined as recursive. Then gfortran
> and Nagfor can compile, Nagfor even the original code with the -f2018
> flag (using the Fortran 2018 standard where every function is recursive).

The recursive attribute (defaulted or not) is not relevant to the interpretation of names in a program.

FortranFan

unread,
May 19, 2022, 2:26:25 PM5/19/22
to
On Thursday, May 19, 2022 at 12:08:54 PM UTC-4, Dan Nagle wrote:

> ..
> And I'll respectfully disagree.
>
> I think the gremlin lies in the procedure pointer assignment 10.2.2.4.
>
> These are all procedures in the same module so the interfaces are explicit
> (as is required by the pointer-ness and the procedure-ness).
> Since the interfaces are explicit, agreement is required of the
> characteristics.
> The characteristics include whether it is a subroutine or a function 15.3.1.
> qed
>
> (I'm reading 22-007r1) ..

@Dan Nagle,

Are you reading much into OP' s comment in the code in the original post, "CALL of a function"? There is no "call of a function" there, `FOO` is not a function on that line of instruction!

Anyways, the characteristics with the function result which is FOO in the execution-part of the function match with the interface, there are no issues with this.

The only problem here appears to be that several compilers as well as human readers overlook the text of the standard that states, "If RESULT does not appear, the name of the function result is function-name and all occurrences of the function name in execution-part statements in its scope are references to the function result."

FortranFan

unread,
May 19, 2022, 2:32:27 PM5/19/22
to
On Thursday, May 19, 2022 at 10:07:42 AM UTC-4, JRR wrote:

> .. if the function is defined as recursive. Then gfortran
> and Nagfor can compile, Nagfor even the original code with the -f2018
> flag (using the Fortran 2018 standard where every function is recursive). ..

@Juergen Reuter,

No recursion is involved here, the 2 compilers you have tried might be confused if they are bringing up anything recursion: they both appear to be treating occurrences of `FOO` in the `execution-part` of the function as `function-name`, instead of as function result, the latter being the semantics as stipulated by the standard. Both those compilers will then be non-conforming.

Dan Nagle

unread,
May 19, 2022, 3:25:14 PM5/19/22
to
On May 19, 2022, pmk wrote
(in article<8c2cbb6d-7f18-4cdc...@googlegroups.com>):
The function statement declares foo to be a function.
The explicit interface for bar declares bar to be a subroutine.
Hence, the mismatch.

--
Cheers!

Dan Nagle

FortranFan

unread,
May 19, 2022, 4:36:17 PM5/19/22
to
On Thursday, May 19, 2022 at 3:25:14 PM UTC-4, Dan Nagle wrote:

> ..
> The function statement declares foo to be a function.
> The explicit interface for bar declares bar to be a subroutine.
> Hence, the mismatch...

That is not the case.

See R1532 and note what is said about function statement versus execution-part and J3/22-007r1, page 336, lines 27 thru' 29.

pmk

unread,
May 19, 2022, 5:39:18 PM5/19/22
to
On Thursday, May 19, 2022 at 12:25:14 PM UTC-7, Dan Nagle wrote:
> The function statement declares foo to be a function.
> The explicit interface for bar declares bar to be a subroutine.
> Hence, the mismatch.

I think you're saying that a function returning a procedure pointer can only return a pointer to a function, but not a pointer to a subroutine.

That turns out to not be the case.

gah4

unread,
May 19, 2022, 8:43:37 PM5/19/22
to
On Thursday, May 19, 2022 at 12:25:14 PM UTC-7, Dan Nagle wrote:

(snip)

> The function statement declares foo to be a function.
> The explicit interface for bar declares bar to be a subroutine.
> Hence, the mismatch.

Does that explain why my program doesn't work?

Note that it only calls a function as function, and subroutine as subroutine,
but still it won't compile with gfortran.

FortranFan

unread,
May 19, 2022, 10:19:44 PM5/19/22
to
On Thursday, May 19, 2022 at 8:43:37 PM UTC-4, gah4 wrote:

@gah4,

>
> Does that explain why my program doesn't work?

No, your code has genuine mismatch in the scope of your `trythis` subprogram.

> but still it won't compile with gfortran.

If you have a Fortran 2018 compiler, here's a variant of your code the processor should accept: with "gfortran", you can replace the "generic" statement with an INTERFACE block.

module m
generic :: trythis => trythis1, trythis2
contains
subroutine trythis1(fs)
procedure(sub) :: fs
call fs(5)
end subroutine
subroutine trythis2(fs)
procedure(fun) :: fs
print *, "fs returns: ", fs(5)
end subroutine
subroutine sub(i)
print *,'sub',i
return
end
integer function fun(i)
print *,'fun',i
fun=3*i
return
end
end module
use m
call trythis(sub)
call trythis(fun)
end

--- console output ---
C:\temp>ifort /standard-semantics p.f90
Intel(R) Fortran Intel(R) 64 Compiler Classic for applications running on Intel(R) 64, Version 2021.5.0 Build 20211109_000000
Copyright (C) 1985-2021 Intel Corporation. All rights reserved.

Microsoft (R) Incremental Linker Version 14.31.31105.0
Copyright (C) Microsoft Corporation. All rights reserved.

-out:p.exe
-subsystem:console
p.obj

C:\temp>p.exe
sub 5
fun 5
15

gah4

unread,
May 19, 2022, 10:46:36 PM5/19/22
to
On Thursday, May 19, 2022 at 7:19:44 PM UTC-7, FortranFan wrote:

(snip, I wrote)

> > Does that explain why my program doesn't work?

> No, your code has genuine mismatch in the scope of your `trythis` subprogram.
> > but still it won't compile with gfortran.

> If you have a Fortran 2018 compiler, here's a variant of your code the processor
> should accept: with "gfortran", you can replace the "generic" statement with an INTERFACE block.

I actually wrote a program like this some years ago, when a similar question
came up. I then had to recreate it. As far as I know, it uses only Fortran 66
features, but the only compiler I tried it on was gfortran.

Much of Fortran 66 trusts users to do things right, such as argument
type matching. Even so, as far as I know, Fortran 66 doesn't have a
different type for subroutine names and function names.

But okay, the way you write it sub and fun have to be in the module,
which is less convenient than it could be. It is especially inconvenient
if you want to separately compile each of them.




Dan Nagle

unread,
May 20, 2022, 12:00:28 PM5/20/22
to
On May 19, 2022, FortranFan wrote
(in article<ca164c05-4151-451d...@googlegroups.com>):
And at line 25 the function result variable has all the characteristics of
the function.

--
Cheers!

Dan Nagle

Dan Nagle

unread,
May 20, 2022, 12:05:53 PM5/20/22
to
Hi,

On May 19, 2022, pmk wrote
(in article<b62af7de-49fd-420a...@googlegroups.com>):
If you write a result-name in foo,
and you use a local variable with the subroutine characteristic in bar.

--
Cheers!

Dan Nagle

FortranFan

unread,
May 20, 2022, 1:27:52 PM5/20/22
to
On Friday, May 20, 2022 at 12:00:28 PM UTC-4, Dan Nagle wrote:
> ..
> And at line 25 the function result variable has all the characteristics of
> the function. ..
and
On Friday, May 20, 2022 at 12:05:53 PM UTC-4, Dan Nagle wrote:
> ..
> If you write a result-name in foo,
> and you use a local variable with the subroutine characteristic in bar.

@Dan Nagle,

I fail to see how your first point, "the function result variable has all the characteristics of the function" of any relevance to the original post. A function can *indeed* have a function-result that is a procedure pointer to a subroutine, there are no doubts it. The following is a conforming program:

module m
contains
function foo() result(r)
procedure(bar), pointer :: r
r => bar
end function
subroutine bar
print *, 'in bar'
end subroutine
end module

The question implied by OP is
1. If RESULT clause does NOT appear and
2. There is a reference to the function-name in the execution-part of the function,
what does the standard and the compilers have to "say" about that?

Well with the code in the original post, it conforms.

The compilers appear to "fall over" at the line "CALL foo" only because the function-name itself is FOO.

But the standard makes it clear, "If RESULT does not appear, the name of the function result is function-name and all occurrences of the function name in execution-part statements in its scope are references to the function result."

Thus "CALL foo" does not involved a reference to the function-name per the standard, instead it is a reference to a procedure pointer associated with `bar`. One can see it as though the "offending" line were `CALL bar` and there is nothing non-conformant when viewed as such.

Robin Vowels

unread,
May 21, 2022, 5:56:05 AM5/21/22
to
.
Why do you want to do this?
.
Just CALL a subroutine, and invoke a function with a function reference,
in the traditional way.

Dan Nagle

unread,
May 21, 2022, 11:26:43 AM5/21/22
to
Hi,

On May 20, 2022, FortranFan wrote
(in article<46eb9bc5-af40-43fe...@googlegroups.com>):

> On Friday, May 20, 2022 at 12:00:28 PM UTC-4, Dan Nagle wrote:
> > ..
> > And at line 25 the function result variable has all the characteristics of
> > the function. ..
> and
> On Friday, May 20, 2022 at 12:05:53 PM UTC-4, Dan Nagle wrote:
> > ..
> > If you write a result-name in foo,
> > and you use a local variable with the subroutine characteristic in bar.
>
> @Dan Nagle,
>
> I fail to see how your first point, "the function result variable has all the
> characteristics of the function" of any relevance to the original post.

The relevance is that, once the function statement gives the name foo the
function characteristic,
the declaration of the local result variable cannot change it. The
declaration can set other
attributes, but cannot change whether a name refers to an entity that is a
function or a subroutine.
That is determined by whether the name appears in a function statement
or a subroutine statement.

> A
> function can *indeed* have a function-result that is a procedure pointer to a
> subroutine, there are no doubts it. The following is a conforming program:
>
> module m
> contains
> function foo() result(r)
> procedure(bar), pointer :: r
> r => bar
> end function
> subroutine bar
> print *, 'in bar'
> end subroutine
> end module

I agree that this is conforming code.
But that is due to the use of a result variable with a different name.
This allows declaration of the function characteristics separately
from the result value characteristics.

That is, the above code never tells me that foo is a function and a
subroutine.

>
>
> The question implied by OP is
> 1. If RESULT clause does NOT appear and
> 2. There is a reference to the function-name in the execution-part of the
> function,
> what does the standard and the compilers have to "say" about that?

It says the result variable has all the characteristics of the function name,
and that whether something is a function or a subroutine is a characteristic.

>
>
> Well with the code in the original post, it conforms.

It does not. The original code confuses whether foo is a function or a
subroutine.
This it cannot do and be standard-conforming.

I believe that another local variable is needed where foo is called,
again to separate the function (value-producing) aspect from the subroutine
aspect
(target of pointer).

>
>
> The compilers appear to "fall over" at the line "CALL foo" only because the
> function-name itself is FOO.

And the compiler can't guess whether you mean foo is a function or a
subroutine.
There are contradictory declarations.

>
>
> But the standard makes it clear, "If RESULT does not appear, the name of the
> function result is function-name and all occurrences of the function name in
> execution-part statements in its scope are references to the function result."

Can you read the paragraph just before the above?
You cannot specify the type of a function both on the function statement
and within the function. Yet that is what you want to do.

You must separate the declaration of the function from the declaration
of the function's value. Do this by using another name, as in your result
example
(which I agree is conforming).

"
>
>
> Thus "CALL foo" does not involved a reference to the function-name per the
> standard, instead it is a reference to a procedure pointer associated with
> `bar`. One can see it as though the "offending" line were `CALL bar` and
> there is nothing non-conformant when viewed as such.

Not so. C1525 disagrees. The name appearing in a call statement must
designate
a subroutine. foo is the name of a function (whose value is a pointer to
subroutine).

Again, this can be cured by using a local variable to hold the value
returned from the function foo, the which can then be called.

The theme is that one must distinguish the function-ness of foo
from the subroutine-ness of foo's result value. An extra variable does the
trick.

--
Cheers!

Dan Nagle

Ron Shepard

unread,
May 21, 2022, 1:33:50 PM5/21/22
to
On 5/21/22 10:26 AM, Dan Nagle wrote:
[...]
>> Thus "CALL foo" does not involved a reference to the function-name per the
>> standard, instead it is a reference to a procedure pointer associated with
>> `bar`. One can see it as though the "offending" line were `CALL bar` and
>> there is nothing non-conformant when viewed as such.
>
> Not so. C1525 disagrees. The name appearing in a call statement must
> designate
> a subroutine.

In that call statement, foo is a procedure pointer to a subroutine, so
does that not qualify as designating a subroutine?

> foo is the name of a function (whose value is a pointer to
> subroutine).

Without the result() clause, foo is the value of the function within the
function body, which is a pointer to a procedure. A procedure pointer
can point to either subroutines or functions, without restriction. There
are not separate pointers for functions and for subroutines, they all
share the same type declaration.

Furthermore, after the pointer assignment, it would be illegal to
reference foo as a function within the body of the function. It is
REQUIRED to reference it only as a subroutine and with the interface
that is consistent with that of the target subroutine.

>
> Again, this can be cured by using a local variable to hold the value
> returned from the function foo, the which can then be called.

The result() clause was added to the language in order to allow direct
recursion to the function from within the body of the function. Of
course, the recursive attribute is required, either explicitly (f90) or
implicitly (f2003), in this case. After result(r) is added, then any
references to foo are to the function, while references to r are to the
value. It is even allowed to do indirect recursion without the result()
clause, it is only direct recursion from foo to itself that requires the
result() clause. However, in this example, there is no recursion
involved anywhere, direct nor indirect. If recursion is not involved
then it seems like result() should not be necessary.

Without result(), there is no ambiguity that within the body of the
function that references to foo are references to the value.

>
> The theme is that one must distinguish the function-ness of foo
> from the subroutine-ness of foo's result value. An extra variable does the
> trick.

Those two "-ness" are already distinguished. Without the result(), all
references to foo within the body are to its value. With the result()
clause, all references to foo are recursive references to the function
itself. It follows that since no recursive references to foo are
invoked, then result() is unnecessary. It is like declaring a variable
and then not referencing it. Of course, in this case, that might not be
a bad idea for human readers of the code, but it seems unnecessary for
the compiler which knows all of this because there is no ambiguity in
the language in this respect.

There is also the question of the argument list. If foo() and/or bar()
had arguments, then all references to the foo function would require
that argument list while references to the procedure pointer value would
require the absence of an argument list. The associated code would then
look like

! no result() code
foo => bar ! no argument list.
call bar(arg1,...) ! with argument list
call foo(arg1,...) ! with argument list, through the pointer value.

! with result(r)
r => bar ! no argument list.
x=....foo(arg1,...) ! expression with direct recursion to foo()
call bar(arg1,...) ! with argument list.
call r(arg1,...) ! with argument list, through the pointer value.

$.02 -Ron Shepard




FortranFan

unread,
May 21, 2022, 6:49:23 PM5/21/22
to
On Saturday, May 21, 2022 at 11:26:43 AM UTC-4, Dan Nagle wrote:

> ..
> The relevance is that, once the function statement gives the name foo the
> function characteristic,
> the declaration of the local result variable cannot change it. The
> declaration can set other
> attributes, but cannot change whether a name refers to an entity that is a
> function or a subroutine.
> That is determined by whether the name appears in a function statement
> or a subroutine statement.

@Dan Nagle,

Re: your comment "The relevance is that, once the function statement gives the name foo the function characteristic, the declaration of the local result variable cannot change it,"

* are you saying a function statement `foo` prevents the name `foo` from it from being treated as a function result variable that is a procedure pointer to a subroutine whereas it can have other characteristics?

The following is a conforming program per my read of the Fortran 90 standard, chances are rather high every Fortran 90 and later compiler you can try will process the program ok:

print *, foo(1)
contains
function foo(a)
integer, intent(in) :: a
integer :: foo(2)
foo(1) = a
foo(2) = foo(1) + 1
end function
end

Do you think in this case once the function statement gives the name foo the function characteristic, the declaration of the local result variable cannot change it to an array of rank-1?


Dan Nagle

unread,
May 22, 2022, 11:22:57 AM5/22/22
to
Hi,

You can't change a characteristic with a type statement. Full stop.
You can create a characteristic with a type statement, but you cannot
change an existing characteristic.

On May 21, 2022, Ron Shepard wrote
(in article <_n9iK.4090$Dr6....@fx06.iad>):

> On 5/21/22 10:26 AM, Dan Nagle wrote:
> [...]
> > > Thus "CALL foo" does not involved a reference to the function-name per the
> > > standard, instead it is a reference to a procedure pointer associated with
> > > `bar`. One can see it as though the "offending" line were `CALL bar` and
> > > there is nothing non-conformant when viewed as such.
> >
> > Not so. C1525 disagrees. The name appearing in a call statement must
> > designate
> > a subroutine.
>
> In that call statement, foo is a procedure pointer to a subroutine, so
> does that not qualify as designating a subroutine?

No. The name foo appears in a function statement,
which makes it a function.

The value of foo is a pointer to subroutine.
But foo is a function.

>
>
> > foo is the name of a function (whose value is a pointer to
> > subroutine).
>
> Without the result() clause, foo is the value of the function within the
> function body, which is a pointer to a procedure. A procedure pointer
> can point to either subroutines or functions, without restriction. There
> are not separate pointers for functions and for subroutines, they all
> share the same type declaration.

The use must be consistent with the declarations of pointer and target.
For example, the use must be consistent with the interface.

>
>
> Furthermore, after the pointer assignment, it would be illegal to
> reference foo as a function within the body of the function. It is
> REQUIRED to reference it only as a subroutine and with the interface
> that is consistent with that of the target subroutine.

The function result variable inherits all the characteristics
of the function name.

The statement declaring foo to be a pointer to subroutine
is invalid because it attempts to change the characteristics of foo.

The function statement declares two characteristics of foo:
1. foo is a function, and
2. foo has no arguments.

Neither can be contradicted and be standard-conforming.

(aside- this is real nitpicking)

In the above paragraph, shouldn't the prohibition on foo-as-function
start with the declaration of foo-as-pointer-to-subroutine?
So how do you assign a value at all?
What is the function result variable of a subroutine?

(end aside)

>
>
> >
> > Again, this can be cured by using a local variable to hold the value
> > returned from the function foo, the which can then be called.
>
> The result() clause was added to the language in order to allow direct
> recursion to the function from within the body of the function. Of
> course, the recursive attribute is required, either explicitly (f90) or
> implicitly (f2003), in this case. After result(r) is added, then any
> references to foo are to the function, while references to r are to the
> value. It is even allowed to do indirect recursion without the result()
> clause, it is only direct recursion from foo to itself that requires the
> result() clause. However, in this example, there is no recursion
> involved anywhere, direct nor indirect. If recursion is not involved
> then it seems like result() should not be necessary.

result was also added to allow the function value to be an array.
(This is one reason why result variables inherit all characteristics
of the function name- you want the array to have the correct shape.)

>
>
> Without result(), there is no ambiguity that within the body of the
> function that references to foo are references to the value.
>
> >
> > The theme is that one must distinguish the function-ness of foo
> > from the subroutine-ness of foo's result value. An extra variable does the
> > trick.
>
> Those two "-ness" are already distinguished. Without the result(), all
> references to foo within the body are to its value. With the result()
> clause, all references to foo are recursive references to the function
> itself. It follows that since no recursive references to foo are
> invoked, then result() is unnecessary. It is like declaring a variable
> and then not referencing it. Of course, in this case, that might not be
> a bad idea for human readers of the code, but it seems unnecessary for
> the compiler which knows all of this because there is no ambiguity in
> the language in this respect.

The ambiguity is that you want some references to foo to be a function,
and some references to foo to be a subroutine.

Whether foo is a function or a subroutine is a characteristic
that cannot change.

foo is a function because it is the name in a function statement.
The type of foo is irrelevant.

foo is not a subroutine because its name does not appear in a subroutine
statement.
Attempting to do so by setting the type of the result is not conforming.

<snip>

>
> $.02 -Ron Shepard

--
Cheers!

Dan Nagle

Ron Shepard

unread,
May 22, 2022, 2:06:30 PM5/22/22
to
On 5/22/22 10:22 AM, Dan Nagle wrote:
[...]
> The function result variable inherits all the characteristics
> of the function name.

Your claim would seem to apply to both cases, with and without the
result() clause. Yet you have already stated that it doesn't, that it
only applies to the case without the result() clause.

Or are you claiming that with result(r), the entity r is not the result
variable? Or that the entity r does not inherit all the characteristics
of foo, the function name.

Either way, it seems like a contradiction to the above statement?

>
> The statement declaring foo to be a pointer to subroutine
> is invalid because it attempts to change the characteristics of foo.

Yet, with the result() clause you claim that the same thing is allowed.
Isn't this inconsistent with your above argument?

>
> The function statement declares two characteristics of foo:
> 1. foo is a function, and
> 2. foo has no arguments.

Within the body of the function, and without the result() clause,
references to foo are to the result value, not recursive references to
the function. This is the same as if it were say, an integer function.
References within the body would be to the integer value, not recursive
references to the function with no arguments. Here is another example of
this, which I think is conforming:

program func
write(*,*) foo(3)
contains
function foo(n)
integer :: foo(2) ! return an integer array.
integer, intent(in) :: n
foo(1) = -n
foo(2) = n
return
end function foo
end program func

Note that there is no result() clause. The result of the function is an
integer array, so result() is not necessary simply to declare an array
valued function. Also, within the function body, the references to
foo(1) and foo(2) are to the elements of the integer array, they are not
recursive references to the function with its single integer argument.

Is this small program conforming?

[...]
> result was also added to allow the function value to be an array.

The example above shows that result() is not required for this purpose.

> (This is one reason why result variables inherit all characteristics
> of the function name- you want the array to have the correct shape.)

See the above example which contradicts this statement.

>> Without result(), there is no ambiguity that within the body of the
>> function that references to foo are references to the value.

This is demonstrated with the above example. There is no result()
clause, and there is no ambiguity, even though foo(1) looks the same
with either interpretation.


>>> The theme is that one must distinguish the function-ness of foo
>>> from the subroutine-ness of foo's result value. An extra variable does the
>>> trick.
>>
>> Those two "-ness" are already distinguished.

This is demonstrated with the above code for the case of an integer
array. The language already distinguishes between foo(1) as a recursive
function reference and foo(1) as an array reference. The same occurs for
other types, including I believe procedure pointers.


> The ambiguity is that you want some references to foo to be a function,
> and some references to foo to be a subroutine.

There is no ambiguity. Without the result() clause, all references to
foo within the function body are to its value as an integer array in the
above example, and to a procedure pointer in the example being discussed.

>
> Whether foo is a function or a subroutine is a characteristic
> that cannot change.

foo is a function, and its value is a procedure pointer.

> foo is a function because it is the name in a function statement.
> The type of foo is irrelevant.

This statement is not consistent with the above example. There foo is a
function, and the type of its value is an integer array. References such
as foo(1) within the body of the function are to the integer array, not
recursive references to the function.

> foo is not a subroutine because its name does not appear in a subroutine
> statement.
> Attempting to do so by setting the type of the result is not conforming.

Are you claiming that the value of foo cannot be a procedure pointer
that is assigned to a subroutine either with or without the result() clause?

I remember Richard Maine saying that one should never write a function
that returns a pointer value. I'm not sure this is what he had in mind,
but perhaps this discussion reflects the wisdom of his warning.

However, having said that, if I were to write a function that returns a
procedure pointer, I would always use the result() clause to make it
easier for a human to understand, although I think the language is
unambiguous in either the result() or the no result() case.

$.02 -Ron Shepard

James Van Buskirk

unread,
May 22, 2022, 2:44:31 PM5/22/22
to
"Ron Shepard" wrote in message news:CYuiK.16679$wIO9...@fx12.iad...

> Within the body of the function, and without the result() clause,
> references to foo are to the result value, not recursive references to
> the function. This is the same as if it were say, an integer function.
> References within the body would be to the integer value, not recursive
> references to the function with no arguments. Here is another example of
> this, which I think is conforming:

> program func
> write(*,*) foo(3)
> contains
> function foo(n)
> integer :: foo(2) ! return an integer array.
> integer, intent(in) :: n
> foo(1) = -n
> foo(2) = n
> return
> end function foo
> end program func

> Note that there is no result() clause. The result of the function is an
> integer array, so result() is not necessary simply to declare an array
> valued function. Also, within the function body, the references to
> foo(1) and foo(2) are to the elements of the integer array, they are not
> recursive references to the function with its single integer argument.

This was an issue that Steve Lionel was certainly familiar with because
the Digital compiler had an extension that allowed for recursive
functions. When the standard itself expanded to allow recursive
procedures one could create standard-conforming programs where
the Digital extension led to a result inconsistent with what the
standard dictates, and the above example might be one such.

Of course, Digital had to follow the standard but yet not require
its user base to throw out all of their code at the same time. It's
kind of mind-bending to think about the function foo and the
result variable foo as different things with the same name in
the seminal example of this thread, but different things can indeed
have the same name. If you google my name the first thing it comes
up with is some pervert from the West Coast. Another thing about
names with which we are all familiar:
https://en.wikipedia.org/wiki/Haddocks%27_Eyes

I note that the title of this thread is intentionally provocative. If
it were something like "CALL the target of FOO when FOO is a
result variable that is a pointer to a subroutine" the thread would
not have been nearly as entertaining.

Cyrmag

unread,
May 22, 2022, 10:17:01 PM5/22/22
to
On 5/22/2022 1:44 PM, James Van Buskirk wrote:
<--SNIP-->

> It's kind of mind-bending to think about the function foo and the
> result variable foo as different things with the same name in
> the seminal example of this thread, but different things can indeed
> have the same name. If you google my name the first thing it comes
> up with is some pervert from the West Coast. Another thing about
> names with which we are all familiar:
> https://en.wikipedia.org/wiki/Haddocks%27_Eyes
>
Not only the same name, as James writes, but sometimes we use the same
notation but with different meanings.

Indeed, having multiple purposes/meanings of parentheses -- to hold a
sequence of subprogram arguments, and also to hold subscripts -- is the
cause of so many complicated and confusing rules. Had we used the
notation of other programming languages, "foo(n)" would be a function
invocation and "foo[n]" would be the n-th or (n+1)th element of array
"foo". As things stand in Fortran, we are burdened with mind-bending
stuff such as the following in F2008:

"If RESULT appears, the name of the result variable of the function is
result-name and all occurrences of the function name in execution-part
statements in its scope refer to the function itself. If RESULT does not
appear, the name of the result variable is function-name and all
occurrences of the function name in execution-part statements in its
scope are references to the result variable."

One could comically restate this quotation as "If RESULT appears, the
result is RESULT and the function is FUNCTION. If RESULT does not
appear, result is FUNCTION and function is RESULT".

-- CyrMag

jfh

unread,
May 23, 2022, 12:41:25 AM5/23/22
to
On Monday, May 23, 2022 at 2:17:01 PM UTC+12, CyrMag wrote:
> On 5/22/2022 1:44 PM, James Van Buskirk wrote:
> <--SNIP-->
> > It's kind of mind-bending to think about the function foo and the
> > result variable foo as different things with the same name in
> > the seminal example of this thread, but different things can indeed
> > have the same name. If you google my name the first thing it comes
> > up with is some pervert from the West Coast. Another thing about
> > names with which we are all familiar:
> > https://en.wikipedia.org/wiki/Haddocks%27_Eyes
>
> Not only the same name, as James writes, but sometimes we use the same
> notation but with different meanings.
>
> Indeed, having multiple purposes/meanings of parentheses -- to hold a
> sequence of subprogram arguments, and also to hold subscripts -- is the
> cause of so many complicated and confusing rules. Had we used the
> notation of other programming languages, "foo(n)" would be a function
> invocation and "foo[n]" would be the n-th or (n+1)th element of array
> "foo".
> <-SNIP->

That would give [ ] multiple meanings. If you think parentheses have too many meanings in Fortran, what about the asterisk? It had 20 the last time I looked, and many of them are not obsolescent.

Dan Nagle

unread,
May 23, 2022, 12:41:48 PM5/23/22
to
Hi,

On May 22, 2022, Ron Shepard wrote
(in article <CYuiK.16679$wIO9...@fx12.iad>):

> On 5/22/22 10:22 AM, Dan Nagle wrote:
> [...]
> > The function result variable inherits all the characteristics
> > of the function name.
>
> Your claim would seem to apply to both cases, with and without the
> result() clause. Yet you have already stated that it doesn't, that it
> only applies to the case without the result() clause.

Because that is the same name in the result variable and the function.
I have posted that I believe the code is valid, provided a differently-named
result variable is used.

I claim (again) that declarations may not contradict each other.

>
>
> Or are you claiming that with result(r), the entity r is not the result
> variable? Or that the entity r does not inherit all the characteristics
> of foo, the function name.
>
> Either way, it seems like a contradiction to the above statement?
>
> >
> > The statement declaring foo to be a pointer to subroutine
> > is invalid because it attempts to change the characteristics of foo.
>
> Yet, with the result() clause you claim that the same thing is allowed.
> Isn't this inconsistent with your above argument?

No, because with a result clause, the same name in the same scope
is not being given contradictory characteristics.

<snip>

> Here is another example of
> this, which I think is conforming:
>
> program func
> write(*,*) foo(3)
> contains
> function foo(n)
> integer :: foo(2) ! return an integer array.
> integer, intent(in) :: n
> foo(1) = -n
> foo(2) = n
> return
> end function foo
> end program func
>
> Note that there is no result() clause. The result of the function is an
> integer array, so result() is not necessary simply to declare an array
> valued function. Also, within the function body, the references to
> foo(1) and foo(2) are to the elements of the integer array, they are not
> recursive references to the function with its single integer argument.
>
> Is this small program conforming?

Where does a declaration contradict another declaration?

>
>
> [...]
> > result was also added to allow the function value to be an array.
>
> The example above shows that result() is not required for this purpose.
>
> > (This is one reason why result variables inherit all characteristics
> > of the function name- you want the array to have the correct shape.)
>
> See the above example which contradicts this statement.

Again, where are the contradictory declarations?

<snip>

>
> There is no ambiguity. Without the result() clause, all references to
> foo within the function body are to its value as an integer array in the
> above example, and to a procedure pointer in the example being discussed.

But your example declaration (integer function) the later declaration
does not contradict the earlier one.

Look, the statement "function foo" declares foo to be a function.
Declaring foo's return value to be a pointer-to-subroutine contradicts that,
if you try to use the same name. Declaring foo to return an integer array
does not contradict foo being a function.

>
>
> >
> > Whether foo is a function or a subroutine is a characteristic
> > that cannot change.
>
> foo is a function, and its value is a procedure pointer.

Correct. Which is why, in the same scope, they both cannot
be declared using the same name.

>
>
> > foo is a function because it is the name in a function statement.
> > The type of foo is irrelevant.
>
> This statement is not consistent with the above example. There foo is a
> function, and the type of its value is an integer array. References such
> as foo(1) within the body of the function are to the integer array, not
> recursive references to the function.

Note that "subsequent declaration" and "contradictory declaration" are
different cases.

Please.

Comment

A code is not standard-conforming unless the standard says what it means.

Fortran allows declarations of one name in one scope to be spread across
several statements. But the incremental declarations must all be consistent.

Recall that the OP asked why so many compilers "crash hard with internal
errors".
My answer is that many compilers have not seen a lot of code with procedure
pointers,
and they do not yet catch all the errors they might (and possibly will
someday).

--
Cheers!

Dan Nagle

Steve Lionel

unread,
May 23, 2022, 7:29:31 PM5/23/22
to
On 5/18/2022 11:39 AM, pmk wrote:
> Only one Fortran compiler can cope with this usage -- most crash hard with internal errors -- but I contend that it's conforming usage.
>
> module m
> contains
> function foo()
> procedure(bar), pointer :: foo
> foo => bar
> call foo ! <-- CALL of a function
> end function
> subroutine bar
> print *, 'in bar'
> end subroutine
> end module
>
> program demo
> use m
> procedure(bar), pointer :: p
> p => foo()
> call p
> end
>

I respectfully disagree with Dan Nagle here.

Referencing Fortran 2018, 15.6.2.2 (Function subprogram), paragraph 3, says:

"The type and type parameters (if any) of the result of the function
defined by a function subprogram may be specified by a type
specification in the FUNCTION statement or by the name of the function
result appearing in a type declaration statement in the specification
part of the function subprogram. They shall not be specified both ways.
If they are not specified either way, they are determined by the
implicit typing rules in effect within the function subprogram. If the
function result is an array, allocatable, or a pointer, this shall be
specified by specifications of the name of the function result within
the function body. The specifications of the function result attributes,
the specification of dummy argument attributes, and the information in
the procedure heading collectively define the characteristics of the
function (15.3.1)"

P4 then says, in part, "If RESULT does not appear, the name of the
function result is function-name and all occurrences of the function
name in execution-part statements in its scope are references to the
function result."

NOTE 1 then says, "The function result is similar to any other entity
(variable or procedure pointer) local to a function sub program. Its
existence begins when execution of the function is initiated and ends
when execution of the
function is terminated."

Within the function, FOO is not a function, it is a local variable that
is the function result. Its characteristics are those declared in the
specification section as a procedure pointer with interface (BAR), which
happens to be a subroutine. This is fine, and there is no conflict or
duplicate declaration.

If we were to accept Dan's position that the FUNCTION statement causes
the function result to be a function, a function such as:

function BAZ ()
REAL :: BAZ
BAZ = 3.0
end function BAZ

would be invalid, since you can't assign 3.0 to a function.

This case is confusing, I'll admit. I note that NAG Fortran 7.1 rejects
it, complaining of a recursive reference to FOO. I'm going to run this
by the committee and see what they think. (I'll also report the ICE to
Intel, though not before I get an answer as to what it is supposed to do.)

--
Steve Lionel
ISO/IEC JTC1/SC22/WG5 (Fortran) Convenor
Retired Intel Fortran developer/support
Email: firstname at firstnamelastname dot com
Twitter: @DoctorFortran
LinkedIn: https://www.linkedin.com/in/stevelionel
Blog: https://stevelionel.com/drfortran
WG5: https://wg5-fortran.org

gah4

unread,
May 23, 2022, 10:55:58 PM5/23/22
to
On Monday, May 23, 2022 at 4:29:31 PM UTC-7, Steve Lionel wrote:

(snip)

> This case is confusing, I'll admit. I note that NAG Fortran 7.1 rejects
> it, complaining of a recursive reference to FOO. I'm going to run this
> by the committee and see what they think. (I'll also report the ICE to
> Intel, though not before I get an answer as to what it is supposed to do.)

Much of this can be confusing to humans, if not the compiler.

Since you can't call integers, or add functions, we know the difference
between an integer variable and procedure pointer.

I know it slightly better in C, and maybe it is a little less confusing.

In C you can declare a function:

double fun();

or a function pointer:

double (*fp)();

Also, in C () is the function call operator, similar to the way [] is the
array reference operator. (It isn't quite as easy in Fortran.)

You can assign to a function pointer:

fp=sqrt; // no () operator

and call a function using a dereferenced function pointer:

x=(*fp)(2.0);

However, it seems that C lets you get away with calling a function
pointer instead of a function:

x=fp(2.0);
even though maybe it shouldn't.

But now, consider a function that returns a function pointer.

Here is one place where the difference between C and Fortran appears.
In C, you can reference an array element of an array (actually
a pointer) returned by a function:

double *af();
x = af()[0];

while Fortran requires assigning the function value to an array.

But now, consider a function returning a function pointer,
a function pointer to such function, and reference using it.
and then a call to the function from the returned pointer.

Declare function pointer to function returning a function pointer:
double (*(*fpp)())();

Declare function returning a function pointer:
double (*ffp())();

ffp=fpp; // point to the function

Call the function, and then the returned function:

printf("%f\n", (*fpp())(3.14));

or call it this way:

printf("%f\n", (fpp())(3.14));

I don't know how to write or call functions returning function pointers,
or pointers to them in Fortran. Here is the whole C program:


#include <stdio.h>
#include <math.h>
int main() {
double (*fp)();
double (*(*fpp)())();
double (*ffp())();
fp=sqrt;
printf("%f\n", (*fp)(2.0));
printf("%f\n", fp(2.0));
fpp = ffp;
printf("%f\n", (*fpp())(3.14));
printf("%f\n", (fpp())(3.14));
}

double (*ffp())() {
return cos;
}






FortranFan

unread,
May 23, 2022, 11:15:26 PM5/23/22
to
On Monday, May 23, 2022 at 7:29:31 PM UTC-4, Steve Lionel wrote:

> ..
> This case is confusing, I'll admit. I note that NAG Fortran 7.1 rejects
> it, complaining of a recursive reference to FOO. I'm going to run this
> by the committee and see what they think.

Given OP's first line, "Only one Fortran compiler can cope with this usage," I had been wondering whether NAG Fortran was the one that managed to "cope with this usage". Your note that "NAG Fortran 7.1 rejects it, complaining of a recursive reference to FOO" is interesting. The note by @Juergen Reuter upthread, ".. if the function is defined as recursive. Then gfortran and Nagfor can compile, Nagfor even the original code with the -f2018 flag (using the Fortran 2018 standard where every function is recursive)" had indicated the same.

Given the situation, your plan that "I'm going to run this by the committee and see what they think" is perfect. Thank you, it will be very helpful to learn of the committee feedback.

Steve Lionel

unread,
May 24, 2022, 9:17:49 AM5/24/22
to
On 5/23/2022 7:29 PM, Steve Lionel wrote:
> This case is confusing, I'll admit. I note that NAG Fortran 7.1 rejects
> it, complaining of a recursive reference to FOO. I'm going to run this
> by the committee and see what they think. (I'll also report the ICE to
> Intel, though not before I get an answer as to what it is supposed to do.)

Malcolm Cohen (NAG Fortran, standard editor) said, "There is no doubt
that within FOO, FOO is the eponymous result name, not the name of the
subprogram. This is similar to functions returning arrays – within an
array function F with no RESULT clause, F(I,J) is an array element of
the result, not a recursive self-reference."

CyrMag

unread,
May 24, 2022, 7:39:43 PM5/24/22
to
On Tuesday, May 24, 2022 at 8:17:49 AM UTC-5, Steve Lionel wrote:
> On 5/23/2022 7:29 PM, Steve Lionel wrote:
> > This case is confusing, I'll admit. I note that NAG Fortran 7.1 rejects
> > it, complaining of a recursive reference to FOO. I'm going to run this
> > by the committee and see what they think. (I'll also report the ICE to
> > Intel, though not before I get an answer as to what it is supposed to do.)
> Malcolm Cohen (NAG Fortran, standard editor) said, "There is no doubt
> that within FOO, FOO is the eponymous result name, not the name of the
> subprogram. This is similar to functions returning arrays – within an
> array function F with no RESULT clause, F(I,J) is an array element of
> the result, not a recursive self-reference."
> --
> Steve Lionel

In that case, the comment by PMK in the code fragment in the leading post:

call foo ! <-- CALL of a function

is incorrect, and perhaps misleading. On this line, "foo" is not the function FOO, but a pointer that is associated with a subroutine, and it is that subroutine that is being called through the pointer, and there is no the function itself being (recursively or otherwise) "called", as the comment suggests.

Do you agree, Steve L.?

-- Cyrmag

FortranFan

unread,
May 24, 2022, 9:26:56 PM5/24/22
to
On Tuesday, May 24, 2022 at 9:17:49 AM UTC-4, Steve Lionel wrote:
> ..
> Malcolm Cohen (NAG Fortran, standard editor) said, "There is no doubt
> that within FOO, FOO is the eponymous result name, not the name of the
> subprogram. This is similar to functions returning arrays – within an
> array function F with no RESULT clause, F(I,J) is an array element of
> the result, not a recursive self-reference." ..

Thank you for the follow-up, that is very useful to know. I wonder whether NAG Fortran team will open up a support incident on this.

gah4

unread,
May 25, 2022, 7:43:26 AM5/25/22
to
On Monday, May 23, 2022 at 4:29:31 PM UTC-7, Steve Lionel wrote:

(snip)

> If we were to accept Dan's position that the FUNCTION statement causes
> the function result to be a function, a function such as:

> function BAZ ()
> REAL :: BAZ
> BAZ = 3.0
> end function BAZ

> would be invalid, since you can't assign 3.0 to a function.

It seems to me that isn't quite right. Variables can have different
attributes, depending on where they are used.

My first thought is that I should be able to use an array as a DO
variable, since I can assign one in an assignment statement.

integer i(10)
do i=1,10
print *,i
enddo

I expect this not to work, even though there is nothing wrong
with assigning to i.

But yes, in an assignment statement BAZ is an integer variable,
and not a function, so the assignment works.

Steve Lionel

unread,
May 25, 2022, 5:55:21 PM5/25/22
to
On 5/24/2022 9:26 PM, FortranFan wrote:
> Thank you for the follow-up, that is very useful to know. I wonder whether NAG Fortran team will open up a support incident on this.

Yes, Malcolm filed one. I have also reported the ICE to Intel.

Steve Lionel

unread,
May 25, 2022, 5:55:42 PM5/25/22
to
On 5/24/2022 7:39 PM, CyrMag wrote:
> In that case, the comment by PMK in the code fragment in the leading post:
>
> call foo ! <-- CALL of a function
>
> is incorrect, and perhaps misleading.

Yes.
0 new messages