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

Having an interface block for a program unit accessible inside an internal procedure of that program unit

14 views
Skip to first unread message

Ian Harvey

unread,
Feb 7, 2012, 5:18:18 AM2/7/12
to
Is the following standard compliant?

MODULE a
INTERFACE
SUBROUTINE sub
END SUBROUTINE sub
END INTERFACE
END MODULE a

SUBROUTINE sub
CONTAINS
SUBROUTINE internal
USE a
! Did we just violate C1201?
END SUBROUTINE internal
END SUBROUTINE sub

Richard Maine

unread,
Feb 7, 2012, 12:16:30 PM2/7/12
to
Hmm. Tricky. I'm sure it is a bad idea. I think it is legal (but still a
bad idea).

C1201 is not relevant; that part I'm sure of. It is about "An interface
block in a subprogram...". The interface block here is not in the
subprogram. It is accessed via USE in the suprogram, but that is not the
same thing as being in the subprogram. Yes, the distinction is
important. A USE statement is not like INCLUDE in this regard.

I think the most important bit of the standard on this is in 16.4.1.3
(of f2003; I don't pay much attention to f2008 and am certainly not well
equipped to give interpretations of it, except insomuch as f2003
pertains.)

"If an entity that is accessed by use association has the same name as
a host entity, the host entity is inaccessible by that name."

So basically, the USE statement blocks the host association. Within
INTERNAL, the name SUB refers to what is accessed via the USE. One
slightly tricky part is that the names are the same in this case. I
think the wording of the standard is a little off in that the "by that
name" doesn't quite catch it. I think it is more accurately that the
host entity is not accessible via host association. That seems to me to
fit the intention better, but I'll admit that the literal words of the
standard do say "by that name", which reads like you can't access it by
that name via the USE association either.

If I take the literal reading there (which I don't think is the right
reading), then I think the code would still be legal, but only because
you never access the name in internal so it doesn't matter if it is
inaccessible.

If you actually call sub from within internal, you have invalid code
anyway because that would count as recursion and you haven't declared
SUB to be recursive. But something like

call some_other_subroutine(sub)

would count as accessing the name without being recursive. So I think
that's the only case where I see much question. I think that would be
legal, but a literal reading seems to imply otherwise.

Do note that the restriction in question is not a constraint, so
compilers aren't required to diagnose it anyway, even with the literal
reading. (Good thing because the literal reading makes it a strange
special case that I could well see as being unreasonable to diagnose
with separate compilation of the module.)

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

Ian Harvey

unread,
Feb 7, 2012, 7:38:56 PM2/7/12
to
On 2012-02-08 4:16 AM, Richard Maine wrote:
> Ian Harvey<ian_h...@bigpond.com> wrote:
>
>> Is the following standard compliant?
>>
>> MODULE a
>> INTERFACE
>> SUBROUTINE sub
>> END SUBROUTINE sub
>> END INTERFACE
>> END MODULE a
>>
>> SUBROUTINE sub
>> CONTAINS
>> SUBROUTINE internal
>> USE a
>> ! Did we just violate C1201?
>> END SUBROUTINE internal
>> END SUBROUTINE sub
>
> Hmm. Tricky. I'm sure it is a bad idea. I think it is legal (but still a
> bad idea).

Thanks for the considered response!

I had vague recollections that there was something more specific that
ruled out the above, but when quickly reading through I only noticed
C1201. Reading again I see F2003 (in 12.3.2.1, p260, line 1 in the
draft pdf I've got) has words "A procedure shall not have more than one
explicit specific interface in a given scoping unit, except that if the
interface is accessed by use association, there may be more than one
local name for the procedure."

I think my original example breaks this?

This arrangement exists in the real world code because of a need to
break module dependencies:

- module a defines an abstract type that is USE'd in a large number of
program units;

- those program units are then USE'd by subroutine sub;

- those program units also call sub;

- sub takes a allocatable polymorphic argument of that ubiquitous type
defined by module a (and hence requires an explicit interface);

- module a seemed like a dandy place to put said interface because any
program unit that calls sub must have USE'd a).

For now I block out the interface using an ONLY clause, but that's a
nuisance (and one day I'll forget why the only clause is there...).

In the real world sub is declared as being recursive, and is called
recursively, but via other program units.

How about:

MODULE a
PRIVATE
PUBLIC :: submarine
INTERFACE submarine
SUBROUTINE sub
END SUBROUTINE sub
END INTERFACE submarine
END MODULE a

RECURSIVE SUBROUTINE sub
USE a
! Elided code here that stops infinite recursion.
CALL submarine
END SUBROUTINE sub

Based on what you wrote around the accessibility of entities and names,
and the bit I've subsequently found from F2003 above, maybe this is ok?
Or do I sink because one of the explicit interfaces is not obtained
via use association?

(Note no RECURSIVE on the subroutine statement in the interface block -
I'm assuming this is ok since the recursive is not part of the
characteristics of the procedure?)

Richard Maine

unread,
Feb 7, 2012, 10:08:21 PM2/7/12
to
I considered that one and almost put it forward, but I concluded that it
didn't apply. My reasoning is that there is only one explicit specific
interface in the scoping unit - the one from the USE statement. That's
because the USE statement blocks the host association of the other one.
I'm not going to claim that's any kind of definitive "official" answer,
but I think that's my reading.

> This arrangement exists in the real world code because of a need to
> break module dependencies:
>
> - module a defines an abstract type that is USE'd in a large number of
> program units;
>
> - those program units are then USE'd by subroutine sub;
>
> - those program units also call sub;

So I suppose that's why sub is external? I generally don't like external
procedures. They bring a bunch of complications. I suppose that breaking
module circularity is one reason that can sometimes justify their use,
but that doesn't mean I like it.

Without having put much thought into this particular case, I might
suggest that I'd often find submodules to be a preferable path to
breaking such circularity. But I admit I didn't take the time to sit
down and go through how that might apply to this kind of case, so I
won't swear it fits.

Anyway, my conclusion is that your code is legal, and I accept that
you've given a plausibel reason why it might also be reasonable.

> How about:
>
> MODULE a
> PRIVATE
> PUBLIC :: submarine
> INTERFACE submarine
> SUBROUTINE sub
> END SUBROUTINE sub
> END INTERFACE submarine
> END MODULE a
>
> RECURSIVE SUBROUTINE sub
> USE a
> ! Elided code here that stops infinite recursion.
> CALL submarine
> END SUBROUTINE sub
>
> Based on what you wrote around the accessibility of entities and names,
> and the bit I've subsequently found from F2003 above, maybe this is ok?
> Or do I sink because one of the explicit interfaces is not obtained
> via use association?

Hmm. Also a bit tricky, but I think it is ok because of the PRIVATE.

I'd sure be happier if that interface block had a PROCEDURE statement
instead of an interface body, but then you'd need for sub to be in a
module and you'd have the module circular reference problem. I don't
think I have access to any compilers that implement submodules for me to
experiment with. Even if submodules can help, you'd have the problem of
restricting your code to compilers that did support them, which might
kill the idea.

> (Note no RECURSIVE on the subroutine statement in the interface block -
> I'm assuming this is ok since the recursive is not part of the
> characteristics of the procedure?)

That part sounds sensible, but I didn't go check. Feeling lazy tonight.
0 new messages