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

subroutines as arguments

16 views
Skip to first unread message

david....@comcast.net

unread,
Oct 8, 2008, 5:44:49 PM10/8/08
to
Hi all,

First, I have read through some old postings, but haven't been able to
find this specific situation.
To wit, is the following "legal" per the Fortran standard?

subroutine foo(x)
real, intent(in) :: x

call bar(x,foo)

return
end subroutine foo

On some machines, with some compilers, the appearance of "foo" as a
formal argument to
"bar" generates errors messages. On some machines, with some
compilers, the errors can
be eliminated by using "recursive":

recursive subroutine foo(x)

On those machines/compilers where the above doesn't help, changing
"foo" from a
subroutine to a function eliminates the errors.

I've tried adding a module wrapper with an interface block, to more
tightly "type" the
subroutine name "foo", but to no avail.

So, is this a compiler bug I'm running into, or is this not legal
Fortran? More details about
machines and compilers upon request. Thanks!

dt

Richard Maine

unread,
Oct 8, 2008, 6:21:11 PM10/8/08
to
<david....@comcast.net> wrote:

> To wit, is the following "legal" per the Fortran standard?

> subroutine foo(x)
...
> call bar(x,foo)

No.... Well... I suppose there might be an obscure technicality that
might make it legal in an obscure case, but the case would, by
definition, be completely useless and thus only of academic interest.
That would be the case where bar never ended up invoking the subroutine
passed to it. But in that case, there wasn't much point in passing it.
I'm not entirely sure of that particular nitpicky point without spending
more time than I want to in digging. Even if it is arguably technically
legal, a compiler would certainly be well justified in warning that it
was highly suspect. But absolutely for sure it is not legal if bar ever
ends up invoking foo.

This is exactly what recursive is about - foo getting called while an
instance of foo is already active. It does not matter that the second
call to foo would occur indirectly from bar instead of directly from
foo. It is still recursive and thus needs the recursive attribute.

Compilers are not required to catch illegal recursive calls. Indeed,
some cases would be impractical to detect at compile time. Also, some
compilers might have extensions that allow nonstandard recursive calls.
Other compilers might not have it as a deliberate extension, but might
just happen to work. Also, sucessful compilation does not guarantee
sucessfull execution. The short version of all that is that all bets are
off when you have this particular nonstandard practice.

It has nothing in particular to do with being a subroutine. All the same
things apply to functions. But one feature of functions is quite likely
to be confusing you.

> On those machines/compilers where the above doesn't help,
> changing "foo" from a subroutine to a function eliminates the errors.

It might have eliminated the compilation errors, but did you try to
actually run it? You might be in for a bit of a surprise because I bet
it does nothing even close to what you think it does. If you do

function foo(...)
...
call bar(foo)

then what gets passed to bar is not the function foo. What gets passed
to bar is instead the result variable, which is also named foo, but is
just a variable instead of the function. If foo isn't resursive, that's
the only potentially useful thing of that name that could be passed
anyway. If foo is recursive, then it could make sense to pass either the
function or the result variable. But if foo is recursive, then it is
required to have a RESULT clause to give the result variable a different
name from the function, thus eliminating any such ambiguity.

> So, is this a compiler bug I'm running into, or is this not legal
> Fortran? More details about machines and compilers upon
> request.

It is just not legal Fortran. No, compiler details aren't interesting in
this case. As I said above, all bets are off with this code; a compiler
can do anything it like with it, and need not even be consistent.

The correct fix is to add the recursive attribute.

Well... I suppose the one set of compiler details that might be helpful
would be the compilers where adding recursive did *NOT* fix it. Those
are the compilers that might merit suspicion, except that...

Well, if they are f77 compilers, then that's very different. F77 doesn't
allow recursion at all. You appear to have a few f90-isms in the code,
but it is at least possible that you are using an f77 compiler that has
those f90 features.

I would also want to see the exact code and exact error message before
too stringly suspecting a compiler bug. Describing that you added
recursive isn't enough. I'd want to see exactly how you did it. And I'd
want to see the error message and the exact code that produced it to
make sure that you didn't hit some different error.

--
Richard Maine | Good judgement comes from experience;
email: last name at domain . net | experience comes from bad judgement.
domain: summertriangle | -- Mark Twain

glen herrmannsfeldt

unread,
Oct 8, 2008, 7:22:00 PM10/8/08
to
david....@comcast.net wrote:

> First, I have read through some old postings, but haven't been able to
> find this specific situation.
> To wit, is the following "legal" per the Fortran standard?

> subroutine foo(x)
> real, intent(in) :: x

> call bar(x,foo)

> return
> end subroutine foo

> On some machines, with some compilers, the appearance of "foo" as a
> formal argument to "bar" generates errors messages.
> On some machines, with some compilers, the errors can
> be eliminated by using "recursive":

Yes, it is only legal if foo is declared RECURSIVE.
Recursion wasn't allowed in Fortran 66 and 77, so older compiler
won't accept it.

> recursive subroutine foo(x)

> On those machines/compilers where the above doesn't help, changing
> "foo" from a subroutine to a function eliminates the errors.

Then it is legal, but doesn't do what you think. Inside a function,
the function name is a variable which can be passed to other
subroutines or functions. You need the RESULT keyword on the
FUNCTION statement such that the function name is not a variable,
and can be referred to inside the function. Then you also need
the RECURSIVE attribute to make it legal.

(I presume this is the reason why RESULT was added.)

-- glen

James Van Buskirk

unread,
Oct 8, 2008, 10:04:25 PM10/8/08
to
"Richard Maine" <nos...@see.signature> wrote in message
news:1iohyok.1nq1w621nv8j1cN%nos...@see.signature...

> <david....@comcast.net> wrote:

>> To wit, is the following "legal" per the Fortran standard?

>> subroutine foo(x)
> ...
>> call bar(x,foo)

> No.... Well... I suppose there might be an obscure technicality that
> might make it legal in an obscure case, but the case would, by
> definition, be completely useless and thus only of academic interest.
> That would be the case where bar never ended up invoking the subroutine
> passed to it. But in that case, there wasn't much point in passing it.
> I'm not entirely sure of that particular nitpicky point without spending
> more time than I want to in digging. Even if it is arguably technically
> legal, a compiler would certainly be well justified in warning that it
> was highly suspect. But absolutely for sure it is not legal if bar ever
> ends up invoking foo.

Well, it's possible that bar wants to point a C_FUNPTR or a procedure
pointer at foo. If the affected entity is visible outside the scope
of bar something meaningful could be done with it.

> This is exactly what recursive is about - foo getting called while an
> instance of foo is already active. It does not matter that the second
> call to foo would occur indirectly from bar instead of directly from
> foo. It is still recursive and thus needs the recursive attribute.

> Compilers are not required to catch illegal recursive calls. Indeed,
> some cases would be impractical to detect at compile time. Also, some
> compilers might have extensions that allow nonstandard recursive calls.
> Other compilers might not have it as a deliberate extension, but might
> just happen to work. Also, sucessful compilation does not guarantee
> sucessfull execution. The short version of all that is that all bets are
> off when you have this particular nonstandard practice.

The difference with RECURSIVE is that the interface to foo is explicit
within foo if foo is RECURSIVE, but not for an external, non-RECURSIVE
procedure. This could be fixed by adding the statement

EXTERNAL foo

to the specification-part of subroutine foo, or by making foo a module
procedure. In f08, maybe even by making foo an internal procedure.
So I think you are missing the aspect of RECURSIVE procedures that
makes the difference in this case.

> It has nothing in particular to do with being a subroutine. All the same
> things apply to functions. But one feature of functions is quite likely
> to be confusing you.

>> On those machines/compilers where the above doesn't help,
>> changing "foo" from a subroutine to a function eliminates the errors.

> It might have eliminated the compilation errors, but did you try to
> actually run it? You might be in for a bit of a surprise because I bet
> it does nothing even close to what you think it does. If you do

> function foo(...)
> ...
> call bar(foo)

> then what gets passed to bar is not the function foo. What gets passed
> to bar is instead the result variable, which is also named foo, but is
> just a variable instead of the function. If foo isn't resursive, that's
> the only potentially useful thing of that name that could be passed
> anyway. If foo is recursive, then it could make sense to pass either the
> function or the result variable. But if foo is recursive, then it is
> required to have a RESULT clause to give the result variable a different
> name from the function, thus eliminating any such ambiguity.

Good catch on the result variable aspect, although I consider the last
sentence above to be rather awkwardly worded in that a naive reader
might come to the conclusion that the RESULT clause is always required
for a RECURSIVE function whereas that's only true if the function
directly invokes itself or points a pointer at itself.

>> So, is this a compiler bug I'm running into, or is this not legal
>> Fortran? More details about machines and compilers upon
>> request.

> It is just not legal Fortran. No, compiler details aren't interesting in
> this case. As I said above, all bets are off with this code; a compiler
> can do anything it like with it, and need not even be consistent.

It is possibly legal Fortran provided subroutine foo is a module
procedure, or maybe an internal procedure in f08.

> The correct fix is to add the recursive attribute.

As mentioned, declaring foo to have the external attribute within
itself should also work. How about an interface block for foo
among foo's declarations? Illegal for a RECURSIVE subroutine, I
know, but what if foo is an external, non-RECURSIVE subroutine?

> Well... I suppose the one set of compiler details that might be helpful
> would be the compilers where adding recursive did *NOT* fix it. Those
> are the compilers that might merit suspicion, except that...

> Well, if they are f77 compilers, then that's very different. F77 doesn't
> allow recursion at all. You appear to have a few f90-isms in the code,
> but it is at least possible that you are using an f77 compiler that has
> those f90 features.

f77 also didn't have INTENT. I was trying to create some examples,
but gfortran of 20080921 didn't have procedure pointers implemented
to the extent that it was possible to do anything with them.

--
write(*,*) transfer((/17.392111325966148d0,6.5794487871554595D-85, &
6.0134700243160014d-154/),(/'x'/)); end


Richard Maine

unread,
Oct 9, 2008, 12:39:35 AM10/9/08
to
James Van Buskirk <not_...@comcast.net> wrote:

> "Richard Maine" <nos...@see.signature> wrote in message
> news:1iohyok.1nq1w621nv8j1cN%nos...@see.signature...

> > Compilers are not required to catch illegal recursive calls....

> The difference with RECURSIVE is that the interface to foo is explicit
> within foo if foo is RECURSIVE, but not for an external, non-RECURSIVE
> procedure. This could be fixed by adding the statement
>
> EXTERNAL foo
>
> to the specification-part of subroutine foo, or by making foo a module
> procedure. In f08, maybe even by making foo an internal procedure.
> So I think you are missing the aspect of RECURSIVE procedures that
> makes the difference in this case.

I'm not sure I understand your point. My para above was all about how
compilers are not required to catch illegal recursive calls. If this
bears on that, it is passing me by (which is certainly possible).

> > But if foo is recursive, then it is
> > required to have a RESULT clause to give the result variable a different
> > name from the function, thus eliminating any such ambiguity.
>

> ...I consider the last


> sentence above to be rather awkwardly worded in that a naive reader
> might come to the conclusion that the RESULT clause is always required
> for a RECURSIVE function whereas that's only true if the function
> directly invokes itself or points a pointer at itself.

The reason that sentence could be read that way was that I was thinking
it to be the case that recursive always required result. But on quickly
skimming the standard, I can't find that requirement, so I you are
probably right.

James Van Buskirk

unread,
Oct 9, 2008, 2:20:46 AM10/9/08
to
"Richard Maine" <nos...@see.signature> wrote in message
news:1ioih8d.1w6exw3138uqomN%nos...@see.signature...

> James Van Buskirk <not_...@comcast.net> wrote:

>> "Richard Maine" <nos...@see.signature> wrote in message
>> news:1iohyok.1nq1w621nv8j1cN%nos...@see.signature...

>> > Compilers are not required to catch illegal recursive calls....

>> The difference with RECURSIVE is that the interface to foo is explicit
>> within foo if foo is RECURSIVE, but not for an external, non-RECURSIVE
>> procedure. This could be fixed by adding the statement

>> EXTERNAL foo

>> to the specification-part of subroutine foo, or by making foo a module
>> procedure. In f08, maybe even by making foo an internal procedure.
>> So I think you are missing the aspect of RECURSIVE procedures that
>> makes the difference in this case.

> I'm not sure I understand your point. My para above was all about how
> compilers are not required to catch illegal recursive calls. If this
> bears on that, it is passing me by (which is certainly possible).

The point is that in f77,

subroutine x(y)
integer i
call y(i)
write(*,*) i
end

subroutine y(i)
integer i
i = 42
end

was legal, but


subroutine x(y)
integer i
call z(y,i)
end

subroutine y(i)
integer i
i = 42
end

subroutine z(y,i)
integer i
call y(i)
end

was not the reason being that it was illegal to pass the external
subroutine y as an actual argument to subroutine z in subroutine x
without declaring y as EXTERNAL in subroutine x. This could be
fixed by adding the line

external y

to the declarations of subroutine x. Similarly subroutine foo
was passed as an actual argument (in subroutine foo) to
subroutine bar in the original example. This was illegal only
because the was no line

external foo

among the declarations of subroutine foo. Now, in f90 and
subsequent there are more ways to tell the compiler that a
procedure has the external attribute. Anything that makes the
interface to foo explicit within subroutine foo will give it the
external attribute so the external statement would not be required
and indeed would be illegal in such a case. Declaring foo as
recursive is one of these ways to make the interface explicit
and another would be to make foo a module procedure.

Looking around in N1601.pdf, I see that "In an external subprogram,
an EXTERNAL statement shall not specify the name of a procedure
defined by the subprogram." (Section 12.3.2.2) As well, "An
interface-block in a subprogram shall not contain an interface-body
for a procedure defined by that subprogram." (C1201) So my
suggestions of using an EXTERNAL statement or an interface block
were invalid. Making foo a module procedure should still work
however, so I still don't think it necessary to declare foo
RECURSIVE to give it the external attribute within its own scope.
I am not sure whether the restriction on the EXTERNAL statement
was present in f77.

Before f90, DEC Fortran had an extension where procedures were
allowed to be used recursively given an appropriate command-line
switch. I'm not sure if the subroutine in the original example
of the thread would be legal in that context. Certainly there
were usages that had a different interpretation (compiled to
different code) under the old extension compared to what would
be the case with a procedure declared RECURSIVE. I think the
extension was changed in those instances to be consistent with
RECURSIVE procedures, potentially resulting in orphan code, but
my recollection is foggy on this point. I would have to look
through my old bug reports to be sure.

Richard Maine

unread,
Oct 9, 2008, 2:48:48 AM10/9/08
to
James Van Buskirk <not_...@comcast.net> wrote:

> "Richard Maine" <nos...@see.signature> wrote in message

> news:1ioih8d.1w6exw3138uqomN%nos...@see.signature...

> > I'm not sure I understand your point. My para above was all about how
> > compilers are not required to catch illegal recursive calls. If this
> > bears on that, it is passing me by (which is certainly possible).
>
> The point is that in f77,

[elided]
> was legal, but
[elided]
> was not...

Ah. Ok. I understand that. You just threw me by putting it after a para
of mine that it didn't have much to do with.

> Similarly subroutine foo
> was passed as an actual argument (in subroutine foo) to
> subroutine bar in the original example. This was illegal only
> because the was no line
>
> external foo
>
> among the declarations of subroutine foo.

Well, except that an "external foo" statement is illegal in subroutine
foo, independent of issues of recursion. I think it counts as an illegal
duplicate specification or some such thing. I seem to recall an interp
about that somewhere.

> Looking around in N1601.pdf, I see that "In an external subprogram,
> an EXTERNAL statement shall not specify the name of a procedure
> defined by the subprogram."

Ok, you found it. That's the restriction I was thinking of. And I don't
think I buy your whole argument. The basic reason that such an external
statement is invalid is that it is duplicative. The subroutine name
already has the external attribute within itself. So no, I don't buy
that the lack of an external statement is a reason for this being
invalid, since that's just a lack of duplicate information. I also don't
think explicit interfaces have anything in particular to do with the
question.

In fact, I think I'm coming to the conclusion that the original code
shown actually is technically valid, but of very limitted use. The
subroutine does have the external attribute within itself, so that
doesn't make it invalid. I think the fact that it sort of implies a
recursive call is the only problem, and if it isn't actually called,
that isn't actually a problem. As you note, one might use a procedure
pointer (or a C equivalent) to do something useful with it. Those would
require f2003, though. I can't come up with a way it can ever be useful
in standard-conforming f95.

> Before f90, DEC Fortran had an extension where procedures were
> allowed to be used recursively given an appropriate command-line
> switch.

Yes. There were various f77 extensions for recursion. I was sticking
solely to the standard.

robert....@sun.com

unread,
Oct 9, 2008, 4:54:29 AM10/9/08
to
On Oct 8, 11:48 pm, nos...@see.signature (Richard Maine) wrote:
> shown actually is technically valid, but of very limited use. The

> subroutine does have the external attribute within itself, so that
> doesn't make it invalid. I think the fact that it sort of implies a
> recursive call is the only problem, and if it isn't actually called,
> that isn't actually a problem. As you note, one might use a procedure
> pointer (or a C equivalent) to do something useful with it. Those would
> require f2003, though. I can't come up with a way it can ever be useful
> in standard-conforming f95.

The different Fortran standards have had different
requirements in this area, but none of them allow
the OP's example. An external procedure does not
have the EXTERNAL attribute within itself. As
James Van Buskirk and Glen Herrmannsfeldt pointed
out, an external procedure might (or might not)
have explicit interface within itself. A procedure
that has explicit interface should work the same as
one with the EXTERNAL attribute in so far as argument
passing is concerned. The committee effectively said
they should work the same in the committee's response
to public comment J32028. The committee's response
referred to meeting paper 08-156r2. I should take a
look at that paper.

Bob Corbett

robert....@sun.com

unread,
Oct 9, 2008, 5:29:33 AM10/9/08
to
On Oct 9, 1:54 am, robert.corb...@sun.com wrote:

> The committee's response
> referred to meeting paper 08-156r2. I should take a
> look at that paper.

I have now read the paper, and it is relevant to this
thread. If the paper is accepted, it will make the
OP's exmaple standard-conforming.

Bob Corbett

Richard Maine

unread,
Oct 9, 2008, 1:01:38 PM10/9/08
to
<robert....@sun.com> wrote:

> As
> James Van Buskirk and Glen Herrmannsfeldt pointed
> out, an external procedure might (or might not)
> have explicit interface within itself.

That's what I'm not convinced of. Admitedly the point is subtle, but I
think that it always does have the external attribute within itself. See
below.

> A procedure
> that has explicit interface should work the same as
> one with the EXTERNAL attribute in so far as argument
> passing is concerned. The committee effectively said
> they should work the same in the committee's response
> to public comment J32028.

Agree on that one. In fact, I could have sworn that the standard already
explicitly said that an explicit interface confered the EXTERNAL
attribute. Not worth me checking in detail, as I'm agreeing.

> The committee's response
> referred to meeting paper 08-156r2. I should take a
> look at that paper.

I hadn't seen that paper before, but it seems to be making points
simillar to mine. In psrticular, from that paper

"once we say that external subprograms have the EXTERNAL
attribute in their own definition, it is covered by the general
prohibition against duplicate specification"

Of course, it is proposed edits to the f2008 draft and thus doesn't
necessarily give a definitive answer for earlier standards, even if it
ends up that way in f2008. One might possibly take it as a guess about
how an interp against an earlier standard would be answered, but it
would only be a guess and not a definitive answer; it would also be
possible for the committee to say that the answer was different for the
old version and that allowing this was a new feature. I've seen both of
those kinds of approaches to things in the past - the approach of "this
fix is to clarify what was meant all along" and the approach of "even if
this might have been a good idea before, it wasn't that way, but we'll
fix it in the new standard."

robert....@sun.com

unread,
Oct 9, 2008, 9:46:23 PM10/9/08
to
On Oct 9, 10:01 am, nos...@see.signature (Richard Maine) wrote:

The part of the paper that you say supports your position
is marked as a TECHNICAL CHANGE. The comment following the
proposed change to the text of the standard is

Saying that an external procedure has the EXTERNAL
attribute in its own definition simplifies several
other places where we needed special wording to
cover that case, specifically C538 and the places
where we said "have explicit interface or the
EXTERNAL attribute".

That comment makes no sense if external procedures already
had the EXTERNAL attribute within their own definitions.

Bob Corbett

david....@comcast.net

unread,
Oct 20, 2008, 7:55:01 PM10/20/08
to
OP here. Interesting discussion. I'd like to focus on just the
"recursive" part.

On Oct 8, 3:21 pm, nos...@see.signature (Richard Maine) wrote:
> > So, is this a compiler bug I'm running into, or is this not legal
> > Fortran? More details about machines and compilers upon
> > request.
>
> It is just not legal Fortran. No, compiler details aren't interesting in
> this case. As I said above, all bets are off with this code; a compiler
> can do anything it like with it, and need not even be consistent.
>
> The correct fix is to add the recursive attribute.
>
> Well... I suppose the one set of compiler details that might be helpful
> would be the compilers where adding recursive did *NOT* fix it. Those
> are the compilers that might merit suspicion, except that...

...


> I would also want to see the exact code and exact error message before
> too stringly suspecting a compiler bug. Describing that you added
> recursive isn't enough. I'd want to see exactly how you did it. And I'd
> want to see the error message and the exact code that produced it to
> make sure that you didn't hit some different error.

Here are some details:

% cat test.F
subroutine foo(x)
implicit none
real, intent(in) :: x

call bar(x,foo)

return
end subroutine foo
% cat test_recursive.F
recursive subroutine foo(x)
implicit none
real, intent(in) :: x

call bar(x,foo)

return
end subroutine foo

The machine of interest here is a Cray XT4. The default Fortran
compiler is a Cray-wrapped version of the PGI compiler. I get the
same result whether using the wrapped or the unwrapped version, so
here it is unwrapped:

% pgf90 -c test.F
PGF90-S-0084-Illegal use of symbol foo (test.F: 5)
0 inform, 0 warnings, 1 severes, 0 fatal for foo
% pgf90 -c test_recursive.F
PGF90-S-0084-Illegal use of symbol foo (test_recursive.F: 5)
0 inform, 0 warnings, 1 severes, 0 fatal for foo
% pgf90 -V
pgf90 7.2-4 64-bit target on x86-64 Linux -tp k8-64e

Note that I get a compilation error with or without the "recursive"
qualifier. I also have available the PathScale compilers:

% pathf90 -c test.F
% pathf90 -c test_recursive.F
% pathf90 -version
PathScale(TM) Compiler Suite: Version 3.2
GNU gcc version 3.3.1 (PathScale 3.2 driver)

Note that, even though the original code may not be legal Fortran, it
compiles fine. And lastly, with gfortran:

% gfortran -c test.F
% gfortran -c test_recursive.F
% gfortran -v
Using built-in specs.
Target: x86_64-suse-linux
Configured with: ../xt-gcc-4.2.0.quadcore/configure --prefix=/opt/gcc/
4.2.0.quadcore/snos --disable-nls --libdir=/opt/gcc/4.2.0.quadcore/
snos/lib --enable-languages=c,c++,fortran --with-gxx-include-dir=/opt/
gcc/4.2.0.quadcore/snos/include/g++ --with-slibdir=/opt/gcc/
4.2.0.quadcore/snos/lib --with-system-zlib --enable-shared --enable-
__cxa_atexit x86_64-suse-linux
Thread model: posix
gcc version 4.2.0 20070514 (quadcore:rpm:113)

Again, both versions are fine.
For comparison, I also tried it on an IBM Power5 cluster running AIX
5.3:

% xlf -c test.F
"test.F", line 5.18: 1516-009 (S) NAMELIST, ENTRY, PROGRAM,
SUBROUTINE, and statement function names are not permitted in this
context.
"test.F", 1513-004 (E) Subprogram name foo has been used in a context
which is not allowed.
** foo === End of Compilation 1 ===
1501-511 Compilation failed for file test.F.
% xlf -c test_recursive.F
** foo === End of Compilation 1 ===
1501-510 Compilation successful for file test_recursive.F.
% xlf -qversion
IBM XL Fortran Enterprise Edition for AIX, V11.1
Version: 11.01.0000.0001

and on an Opteron cluster running sles9 with PathScale compilers:

% pathf90 -c test.F
% pathf90 -c test_recursive.F
% pathf90 -version
PathScale(TM) Compiler Suite: Version 3.2
Built on: 2008-06-16 16:41:38 -0700
Thread model: posix
GNU gcc version 3.3.1 (PathScale 3.2 driver)

and on an SGI Altix (350?) running sles9 with Intel compilers:

% ifort -c test.F
fortcom: Error: test.F, line 5: A subroutine or function is calling
itself recursively. [FOO]
call bar(x,foo)
-----------------^
compilation aborted for test.F (code 1)
% ifort -c test_recursive.F
% ifort -v
Version 10.1


So, bottom line: the PGI compiler refuses to compile
test_recursive.F; is that a compiler bug?
Thanks! dt

Richard Maine

unread,
Oct 20, 2008, 8:35:34 PM10/20/08
to
<david....@comcast.net> wrote:
...

> % cat test_recursive.F
> recursive subroutine foo(x)
> implicit none
> real, intent(in) :: x
>
> call bar(x,foo)
>
> return
> end subroutine foo
...

> % pgf90 -c test_recursive.F
> PGF90-S-0084-Illegal use of symbol foo (test_recursive.F: 5)
> 0 inform, 0 warnings, 1 severes, 0 fatal for foo
> % pgf90 -V
> pgf90 7.2-4 64-bit target on x86-64 Linux -tp k8-64e
...

> So, bottom line: the PGI compiler refuses to compile
> test_recursive.F; is that a compiler bug?

I would formerly have thought so. I'm still at least somewhat inclined
in that direction, but Bob Corbett argues differently in other postings
to this thread. (I believe I'm correctly applying what I take to be his
argument). I'm not entirely convinced by Bob's arguments, but I'll grant
that they do have enough substance that I can't say he is provably wrong
either. So I'll go with "debatable" at the moment.

david....@comcast.net

unread,
Oct 22, 2008, 2:26:56 AM10/22/08
to
On Oct 20, 5:35 pm, nos...@see.signature (Richard Maine) wrote:

> <david.turn...@comcast.net> wrote:
>
> ...
>
>
>
> > % cat test_recursive.F
> >       recursive subroutine foo(x)
> >       implicit none
> >       real, intent(in) :: x
>
> >       call bar(x,foo)
>
> >       return
> >       end subroutine foo
> ...
> > % pgf90 -c test_recursive.F
> > PGF90-S-0084-Illegal use of symbol foo  (test_recursive.F: 5)
> >   0 inform,   0 warnings,   1 severes, 0 fatal for foo
> > % pgf90 -V
> > pgf90 7.2-4 64-bit target on x86-64 Linux -tp k8-64e
> ...
> > So, bottom line:  the PGI compiler refuses to compile
> > test_recursive.F; is that a compiler bug?
>
> I would formerly have thought so. I'm still at least somewhat inclined
> in that direction, but Bob Corbett argues differently in other postings
> to this thread. (I believe I'm correctly applying what I take to be his
> argument). I'm not entirely convinced by Bob's arguments, but I'll grant
> that they do have enough substance that I can't say he is provably wrong
> either. So I'll go with "debatable" at the moment.

I'm not real clear how the discussion of whether an "external"
attribute is duplicative applies, since neither of my two examples
includes an external statement. However, if I do include it:

% cat test_external_recursive.F


recursive subroutine foo(x)
implicit none
real, intent(in) :: x

external foo

call bar(x,foo)

return
end subroutine foo
% pgf90 -c test_external_recursive.F
%

So, adding the "external" statement allows the subroutine to be
compiled without error. And I know it is weird to have a subroutine
declare itself external; not something I would normally consider. And
oddly enough, it even compiles with "external" and _without_
"recursive". But I understand compiling doesn't mean it will actually
run correctly; I believe I need the "recursive" in this case.

So here is the rest of the story. This example is a simplified
version of a real code. The subroutine being called ("bar" in my
example) is written in C (a PETSc routine, for those who care). I
have intentionally left this fact out, because I'm just trying to
understand whether the Fortran compiler vendor has any culpability
here, or whether I should just keep looking for workarounds.

I think I'll probably send it to the vendor, and see what they say. I
appreciate all the comments here; thanks! dt

Richard Maine

unread,
Oct 22, 2008, 2:44:54 AM10/22/08
to
<david....@comcast.net> wrote:

> I'm not real clear how the discussion of whether an "external"
> attribute is duplicative applies, since neither of my two examples
> includes an external statement.

It applies very much. The external attribute is needed to pass the
procedure as an actual argument. If the procedure already has the
external attribute within itself, then all is fine (and declaring the
attribute explicitly would be duplicative). If the procedure does not
have the external attribute within itself, then it would need that
attribute declared, but that's disallowed, so you would be out of luck
(at least with a direct approach... see below).

Do note that you should be able to work around it by adding an extra
layer of indirection, doing a call foobar(x), where foobar has an
external statement for foo and then calls bar(x,foo)).

> So, adding the "external" statement allows the subroutine to be
> compiled without error. And I know it is weird to have a subroutine
> declare itself external; not something I would normally consider.

It is also explicitly disallowed by the standard. One can argue (as we
have done) about why it is disallowed, but the disallowance is
unambiguous. So if the compiler doesn't give at least a warning about
that, you have grounds to gripe; it certainly isn't a portable thing to
do.

Sounds to me like the safest thing is the indirect approach mentioned
above. Its a bit inelegant, but it should work ane be portable
regardless of the fine points of interpretation discussed in this
thread.

> The subroutine being called ("bar" in my
> example) is written in C (a PETSc routine, for those who care). I
> have intentionally left this fact out, because I'm just trying to
> understand whether the Fortran compiler vendor has any culpability
> here, or whether I should just keep looking for workarounds.

The called routine being written in C shouldn't matter.

James Van Buskirk

unread,
Oct 22, 2008, 3:05:50 AM10/22/08
to
"Richard Maine" <nos...@see.signature> wrote in message
news:1ip6pec.eg44ja14uvaiwN%nos...@see.signature...

> Sounds to me like the safest thing is the indirect approach mentioned
> above. Its a bit inelegant, but it should work ane be portable
> regardless of the fine points of interpretation discussed in this
> thread.

What's wrong with making foo a module procedure? Module procedures
of the same module can pass each other around as actual arguments
because they know through host association that the other module
procedures have the external attribute. It follows that a module
procedure must have an explicit interface to itself and know it has
the external attribute via host association as well. The only problem
I can envision is if foo is called from C (and not through the actual
argument it passed to bar() ) but the caller could in this instance use
the name mangling appropriate to module procedures or foo could be
given the BIND(C) attribute so that it could have an external name
that is obvious to the C compiler.

Richard Maine

unread,
Oct 22, 2008, 6:09:06 AM10/22/08
to
James Van Buskirk <not_...@comcast.net> wrote:

> It follows that a module
> procedure must have an explicit interface to itself and know it has
> the external attribute via host association as well.

That sounds like a good argument to me. Of course, perhaps I'm a bit
easy as I thought even an external recursive procedure had an explicit
interface within itself. Hmm... Hold it. I'm pretty sure of that... I
think. Maybe I better wait til I'm more awake. :-)

James Van Buskirk

unread,
Oct 22, 2008, 1:20:50 PM10/22/08
to
"Richard Maine" <nos...@see.signature> wrote in message
news:1ip6z41.jvv4vv1o8xczqN%nos...@see.signature...

> That sounds like a good argument to me. Of course, perhaps I'm a bit
> easy as I thought even an external recursive procedure had an explicit
> interface within itself. Hmm... Hold it. I'm pretty sure of that... I
> think. Maybe I better wait til I'm more awake. :-)

I'm pretty darned sure that external recursive procedures have
explicit interfaces to themselves, too, but I couldn't find the
passage in the standard that says this when I looked. Do you
remember where it is?

Richard Maine

unread,
Oct 22, 2008, 1:38:31 PM10/22/08
to
James Van Buskirk <not_...@comcast.net> wrote:

> "Richard Maine" <nos...@see.signature> wrote in message
> news:1ip6z41.jvv4vv1o8xczqN%nos...@see.signature...
>
> > That sounds like a good argument to me. Of course, perhaps I'm a bit
> > easy as I thought even an external recursive procedure had an explicit
> > interface within itself. Hmm... Hold it. I'm pretty sure of that... I
> > think. Maybe I better wait til I'm more awake. :-)
>
> I'm pretty darned sure that external recursive procedures have
> explicit interfaces to themselves, too, but I couldn't find the
> passage in the standard that says this when I looked. Do you
> remember where it is?

Afraid not. See the interchange between Bob Corbett and myself in the
other part of this thread. If I had managed to find somewhere that said
that, I'd probably have brought it up there. Admitedly, I was looking
for stuff about the external attribute instead of about explicit
interface. Still, if I managed to find that explicitly in the standard,
I might not have needed to do as much arm waving to argue my point.

Hmm. Probably needs another qualification in any case. Without actually
finding the stuff in the standard (if it is there)... but just thinking
on what would make sense... one would probably have to restrict it to
recursive procedures with a result clause. Without a result clause, the
procedure isn't directly accessible within itself by its name at all, so
I don't think it can possibly have an explicit interface within itself
(the name being part of an explicit interface).

Ron Shepard

unread,
Oct 22, 2008, 7:06:13 PM10/22/08
to
In article <1ip6pec.eg44ja14uvaiwN%nos...@see.signature>,
nos...@see.signature (Richard Maine) wrote:

> > The subroutine being called ("bar" in my
> > example) is written in C (a PETSc routine, for those who care). I
> > have intentionally left this fact out, because I'm just trying to
> > understand whether the Fortran compiler vendor has any culpability
> > here, or whether I should just keep looking for workarounds.
>
> The called routine being written in C shouldn't matter.

It should not matter as long as that routine can be called
recursively and in a consistent way as recursive fortran routines.
It does seem that this might cause problems if some effort was not
taken by the compiler writers to ensure the same kinds of
conventions are used by both compilers.

$.02 -Ron Shepard

Richard Maine

unread,
Oct 22, 2008, 8:18:09 PM10/22/08
to
Ron Shepard <ron-s...@NOSPAM.comcast.net> wrote:

Well, yes, but that's not going to affect whether the code compiles or
not, which seemed to be the main problem here. It could potentially
affect whether it runs correctly (and I suppose theoretically whether it
links correctly if there was some linkage difference for recursive
procedures).

Dick Hendrickson

unread,
Oct 22, 2008, 9:47:14 PM10/22/08
to
12.3.1 in F2003 (similar words in F2008) says
"The interface of a subroutine or a function with a separate result name
is explicit within the subprogram that defines it."
Which seems to say a (recursive) function with a result clause has an
explicit interface within itself.
(I'd say it's ambiguous about how you parse the "subroutine or
function", since subroutines don't have result variables, but that's
merely grammar.)

It goes on to say
"The interface of an external procedure or dummy procedure is explicit
in a scoping unit other than its own if an interface body (12.3.2.1) for
the procedure is supplied or accessible, and implicit otherwise."

Which I think says the interface is implicit within the external routine
itself.

If I hadn't just finished a Belgian beer, I'd say that's not very clear.

Dick Hendrickson

glen herrmannsfeldt

unread,
Oct 22, 2008, 11:00:59 PM10/22/08
to
Dick Hendrickson wrote:
(snip)

> 12.3.1 in F2003 (similar words in F2008) says
> "The interface of a subroutine or a function with a separate result name
> is explicit within the subprogram that defines it."
> Which seems to say a (recursive) function with a result clause has an
> explicit interface within itself.
> (I'd say it's ambiguous about how you parse the "subroutine or
> function", since subroutines don't have result variables, but that's
> merely grammar.)

Maybe it is:

The interface of a subroutine or (a function with a separate result name)


is explicit within the subprogram that defines it.

and not

The interface of a (subroutine or a function) with a separate result name


is explicit within the subprogram that defines it.

.OR. has low precedence.

-- glen

Dick Hendrickson

unread,
Oct 22, 2008, 10:37:31 PM10/22/08
to
How about
Would you like pancakes or bacon and eggs for breakfast?
versus
Would you like ham or bacon and eggs for breakfast?

Unfortunately, the precedence is context dependent.

Dick Hendrickson

Richard Maine

unread,
Oct 23, 2008, 12:17:53 AM10/23/08
to
glen herrmannsfeldt <g...@ugcs.caltech.edu> wrote:

I don't think it is the "or". I think it is the "a" in front of
"function" that makes the difference. If you wanted "with a separate
result name" to modify both, I'd write it as

"a subroutine or function with a separate result name"

All based purely on the English, of course. We all know what it means
because a result name for a subroutine amkes no sense, but using that
knowledge is "cheating".

Though I'll raise Dick's Belgian beer with the famous Dave's margharita
I just had. As Dick knows, I'm not a beer person, Belgian or otherwise.
You wouldn't think just one would do that. Glad my wife was along to
drive.

0 new messages