From: Bill on
Is the following program Fortran 95 conforming?

module mod1
contains
subroutine sub(x)
real x
end subroutine sub
end module mod1

module mod2
use mod1
interface sub
module procedure sub, sub_int
end interface sub
contains
subroutine sub_int(i)
integer i
end subroutine sub_int
end module mod2

program prog
use mod1
use mod2
call sub(1)
end program prog

mod1 is an existing module that cannot be changed. mod2 is attempting
to extend the name sub from mod1 to accept an integer argument. I
have 4 compilers that reject this program, and 5 that accept it. Some
that reject it will accept it with seemingly minor changes (e.g.
reverse the order of the USE statements in prog, omit USE mod1 in
prog, ...). Error messages from the objecting compilers are:
1) Illegal attempt to redefine symbol sub
2) Symbol SUB found both in module MOD1 and in MOD2 detected at
CALL(a)SUB
3) "SUB" has been use associated from module "MOD1" and at least one
more module. It must not be referenced.
4) call sub(1)
1
Error: Type mismatch in argument 'x' at (1); passed INTEGER(4) to REAL
(4)


It seems to me that the following constraint on the definition of an
interface block:

Constraint: The MODULE PROCEDURE specification is allowed only if the
interface-block has a generic-spec and has a host that is a module or
accesses a module by use association; each procedure-name must be the
name of a module procedure that is accessible in the host

indicates that sub can be used in the generic interface since it is a
module procedure and is accessible in mod2. But maybe there is
something somewhere else in the standard that I'm missing.

Thanks,
Bill
From: Paul van Delst on
What if you make the changes I made below:

Bill wrote:
> Is the following program Fortran 95 conforming?
>
> module mod1
> contains
> subroutine sub(x)
> real x
> end subroutine sub
> end module mod1
>
> module mod2
use mod1, sub_real=>sub
private
public :: sub
> interface sub
module procedure sub_real, sub_int
> end interface sub
> contains
> subroutine sub_int(i)
> integer i
> end subroutine sub_int
> end module mod2
>
> program prog
! use mod1 ! no longer needed here
> use mod2
> call sub(1)
> end program prog

?

I can't recall if there is a constraint in the standard that says you can't name a
procedure and an interface the same (I assume there is one), but, regardless, I find it
confusing even if it was allowed. By using the rename capability,
use mod1, sub_real=>sub
in mod2 you bypass any conformance issues, and general confused-user issues too. :o)

And you only have to USE one module, mod2, in the main program.

cheers,

paulv
From: Richard Maine on
Paul van Delst <paul.vandelst(a)noaa.gov> wrote:

> I can't recall if there is a constraint in the standard that says you
> can't name a procedure and an interface the same (I assume there is one),

No, there isn't. Quite the opposite, there is language specifically
allowing it.... except that you have the terminology wrong above. Yes, I
know that you declare a generic procedure using a construct that starts
with the keyword INTERFACE. I wouldn't have done the syntax that way,
but it is about 2 decades too late for that. In spite of that syntax,
what you are declaring is not an interface. You are declaring a generic
procedure.

Declaring an interface is something completely different. It is, in my
view, unfortunate and confusing that you might in some cases end up
declaring both ageneric procedure and also some interfaces in the same
"interface block", which starts with the keyword "interface".

I particularly mention this because there are completely diferent issues
with declaring an interface for a procedure. No, you can't declare an
interface for a module procedure because it already has one. But you can
put the module procedure name in an interface block to give it a generic
name, and yes, that generic name can be the same as the module procedure
name.

> but, regardless, I find it
> confusing even if it was allowed.

I agree with that part. I think there is evidence that some compilers
also get confused. It counts as a compiler bug, but such things have
been known to exist.

By having the module procedure and the generic block in different
modules, you have given the compilers extra ways to get it wrong. Sounds
like several of them do get it wrong. That doesn't horribly surprise me,
as it is a tricky bit, and one which probably doesn't come up a lot.
"Normally", you can't USE the same name from two different modules. This
is an exception, and a tricky enough one that I can easily see compilers
missing it. (One of the two that I tried missed it).

Anyway, to directly answer the question, yes, the code appears to be
standard conforming as far as I can see.

As to workarounds, well, I assume you can figure those out (and Paul
mentioned one), but that's not the question I heard being asked.

--
Richard Maine | Good judgment comes from experience;
email: last name at domain . net | experience comes from bad judgment.
domain: summertriangle | -- Mark Twain
From: Bill on
Thank you to both Paul, for his suggestion of renaming sub to sub_real
in mod2, and Richard, for his ever trustworthy judgement on standard
conformance. That's what I wanted to hear before I file a bug report
with the 4 vendors whose compilers failed.

As to Paul's comment that USE mod1 is no longer needed in prog, it
never was needed to get sub -- that comes from the generic interface
in mod2. The USE mod1 statement is there because prog uses other
things from mod1 (well, not in this bug report program, but in the
real program). But instead of omitting it, I can replace it with USE
mod1, nada=>sub. This seems to remove the confusion about sub coming
from two modules, and for 3 of the 4 failing compilers, that is all
that is needed. The 4th one still complains about sub being redefined
in mod2, unless I also add Paul's suggestion of renaming sub to
sub_real on the USE mod1 statement in mod2 (which also includes
changing sub to sub_real in the MODULE PROCEDURE statement, of
course). With just those changes the program works with all 7
compilers that I have available, so I guess that's my best workaround.

As for it being confusing to use a generic name that is the same as a
module procedure name, with that procedure in a different module, I
was thinking of it as being essentially the same as extending the
generic interface of intrinsic procedures to have an argument of a
user defined type. I have an existing procedure in mod1 which I want
to extend to accept a different kind of argument by defining a generic
interface. The only difference is that you wouldn't list the
intrinsic procedure on the MODULE PROCEDURE statement, and the
procedure in mod1 doesn't already have a generic interface like an
intrinsic procedure.

Bill