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

Mixing functions and subroutines in a combined generic interface

164 views
Skip to first unread message

Peter Klausler US

unread,
Nov 8, 2022, 12:16:33 PM11/8/22
to
Generic interfaces are constrained in some specific circumstances to contain all functions or all subroutines, but in general they can contain both. (There's language in the standard that pertains to the visibility of intrinsic procedures of the same name that depends on whether a generic interface contains a mixture or not, so it must be possible.)

While it's probably not the best practice to explicitly define an interface that has a mixture of functions and subroutines, it's possible for such an interface to be created -- perhaps inadvertently -- when an interface is defined in multiple locations and merged together. For example:

> module m1
> interface generic
> module procedure func
> end interface
> contains
> integer function func(n)
> integer, intent(in) :: n
> func = n
> end function
> end module
>
> module m2
> interface generic
> module procedure subr
> end interface
> contains
> subroutine subr
> print *, 'ok'
> end subroutine
> end module
>
> program main
> use m1
> use m2
> call generic
> end

Some compilers can handle this example, some can't, and complain that a mixed generic interface is not allowed. I think that those compilers are incorrect. If you disagree, please let me know why.

Amusingly, if you delete the function's dummy argument from that example, *no* compiler can deal with it, since they apparently don't take the function/subroutine distinction into account when comparing specific procedures for distinguishability, only their dummy arguments. So I think I'm going to get to add another item to f18's documentation section on features that it supports that are standard but might as well not be.

Arjen Markus

unread,
Nov 8, 2022, 3:30:56 PM11/8/22
to
If you take away the argument from the function, then its interface is not distinguishable from the subroutine according to ifort. With the argument, it emits a warning, but builds the program.
gfortran does not accept it on the grounds of it being a mixture, with or without the argument n.

I do not know which one is right, but the mixups (pun not entirely intended) you sketch are unfortunate and possible. Renaming would solve it, but that is besides the point.

Regards,

Arjen

Thomas Koenig

unread,
Nov 10, 2022, 4:42:11 PM11/10/22
to
Arjen Markus <arjen.m...@gmail.com> schrieb:
I actually ran aross this some time ago.

The key is 15.4.3.4.5 Restrictions on generic declarations, where there
is a constraint:

C1514 Within the scope of a generic name, each pair of procedures
identified by that name shall both be subroutines or both be
functions, and [...]

I think this makes the code illegal, and not diagnosing it is a bug.

Please feel free to disagree :-)

Peter Klausler US

unread,
Nov 10, 2022, 4:56:15 PM11/10/22
to
On Thursday, November 10, 2022 at 1:42:11 PM UTC-8, Thomas Koenig wrote:
> The key is 15.4.3.4.5 Restrictions on generic declarations, where there
> is a constraint:
>
> C1514 Within the scope of a generic name, each pair of procedures
> identified by that name shall both be subroutines or both be
> functions, and [...]
>
> I think this makes the code illegal, and not diagnosing it is a bug.
>
> Please feel free to disagree :-)

I think that in my example above the "scope of the generic name" is one module or the other, but in the main program the generic name is being accessed via USE association and the main program is technically not in a (or the) scope of the generic name.

FortranFan

unread,
Nov 10, 2022, 7:18:43 PM11/10/22
to
On Tuesday, November 8, 2022 at 12:16:33 PM UTC-5, Peter Klausler US wrote:

> Generic interfaces are constrained in some specific circumstances to contain all functions or all subroutines, but in general they can contain both. (There's language in the standard that pertains to the visibility of intrinsic procedures of the same name that depends on whether a generic interface contains a mixture or not, so it must be possible.)
>

Re: "but in general they can contain both," from what I can understand from 18-007r1 document toward Fortran 2018, I do *not* think the semantics of the standard is such that "in general they can contain both" Sure the standard has following carve out but that does suggest any generality, in fact the section on "Restrictions on generic declarations" indicates the opposite:
"Within the scope of a generic name that is the same as the generic name of an intrinsic procedure, the intrinsic procedure is not accessible by its generic name if the procedures in the interface and the intrinsic procedure are *not all functions or not all subroutines*. If a generic invocation is consistent with both a specific procedure from an interface and an accessible intrinsic procedure, it is the specific procedure from the interface that is referenced."
(emphasis with asterisk is mine)


> While it's probably not the best practice to explicitly define an interface that has a mixture of functions and subroutines, it's possible for such an interface to be created -- perhaps inadvertently -- when an interface is defined in multiple locations and merged together. For example:
>

I think the intended message by the OP with example is misleading. The example is *not* "explicitly define an interface that has a mixture of functions and subroutines, it's possible for such an interface to be created -- perhaps inadvertently -- when an interface is defined in multiple locations and merged together"

Rather the example shows two different ultimate entities, both of which are generic interfaces named 'generic'. One ultimate entity is that for functions (func being one specific procedure in it) and the other for subroutines (subr being one specific procedure in this interface).

I think the standard only permits the second of these two entities to be referenced in the scope containing the USE statement, meaning the following:

A) consume the generic as a function, here note the order of USE statements
program main
use m2
use m1
print *, generic(42)
end

Or

B) consume the generic as a subroutine, note the order of USE statements is opposite to that A)
program main
use m1
use m2
call generic
end

It will take me effort to decode the standardese and try to explain in plain English but I think this is tied to semantics with "An ultimate entity is a module entity that is not accessed by use association. An accessed entity shall not be associated with two or more ultimate entities unless its identifier is not used, or the ultimate entities are generic interfaces. Generic interfaces are handled as described in 15.4.3.4."

I think this is also tied to how the standard permits extension of generic interfaces via USE statements, as in the following example:
module m1
interface generic
module procedure func
end interface
contains
integer function func(n)
integer, intent(in) :: n
func = n
end function
end module

module m2
interface generic
module procedure func
end interface
contains
real function func(n)
real, intent(in) :: n
func = n
end function
end module

program main
use m1
use m2
print *, generic(42)
print *, generic(99.0)
end

>.. So I think I'm going to get to add another item to f18's documentation section on features that it supports that are standard but might as well not be.

Honestly I think the "f18 documentation" on "features that it supports that are standard but might as well not be" needs a thorough review by a subgroup in the J3 committee, say JoR or /DATA or the Editor. I think there are inaccuracies in that "f18 documentation", the above comments by OP in the original post on generic interfaces will be one such if that were to get included. Until the f18 team (is it all at Nvidia?) can get it thoroughly reviewed and all corrections applied, ideally it will only be in the publicly available online with clearly stated disclaimers.

FortranFan

unread,
Nov 10, 2022, 7:20:23 PM11/10/22
to
On Thursday, November 10, 2022 at 7:18:43 PM UTC-5, FortranFan wrote:
> On Tuesday, November 8, 2022 at 12:16:33 PM UTC-5, Peter Klausler US wrote:
>
> > Generic interfaces are constrained in some specific circumstances to contain all functions or all subroutines, but in general they can contain both. (There's language in the standard that pertains to the visibility of intrinsic procedures of the same name that depends on whether a generic interface contains a mixture or not, so it must be possible.)
> >
> Re: "but in general they can contain both," from what I can understand from 18-007r1 document toward Fortran 2018, I do *not* think the semantics of the standard is such that "in general they can contain both" Sure the standard has following carve out but that does suggest any generality

Oops, omitted a key word: I meant "that does not suggest any generality"

Thomas Koenig

unread,
Nov 11, 2022, 5:21:37 PM11/11/22
to
Peter Klausler US <pkla...@nvidia.com> schrieb:
I disagree there. Both interfacs are accessed by use association
in the main program, and thus are in its scope.

At least this is how I interpret use association and 14.2.2.

Peter Klausler US

unread,
Nov 11, 2022, 9:02:39 PM11/11/22
to
On Friday, November 11, 2022 at 2:21:37 PM UTC-8, Thomas Koenig wrote:
> I disagree there. Both interfacs are accessed by use association
> in the main program, and thus are in its scope.
>
> At least this is how I interpret use association and 14.2.2.

Thanks for the response. You're probably right. But since at least four compilers support this combination, so must I, and it's just a matter of determining how it should be documented.

gah4

unread,
Nov 11, 2022, 9:19:43 PM11/11/22
to
On Friday, November 11, 2022 at 6:02:39 PM UTC-8, Peter Klausler US wrote:

(snip)

> Thanks for the response. You're probably right. But since at least four
> compilers support this combination, so must I, and it's just a matter
> of determining how it should be documented.

Since compilers are allowed to support extensions, the fact that compilers
support it doesn't tell you much.

gah4

unread,
Nov 11, 2022, 10:06:00 PM11/11/22
to
On Tuesday, November 8, 2022 at 9:16:33 AM UTC-8, Peter Klausler US wrote:
> Generic interfaces are constrained in some specific circumstances to contain
> all functions or all subroutines, but in general they can contain both.
> (There's language in the standard that pertains to the visibility of intrinsic
> procedures of the same name that depends on whether a generic
> interface contains a mixture or not, so it must be possible.)

I tried something like this some years ago, about Fortran 95 days:

real x
external sub, fun
x=3
call sf(sub,1,x)
call sf(fun, 2,x)
print *,x
end
subroutine sf(fs, i, x)
integer i
real x
external fs
if(i.eq.1) call fs(x)
if(i.eq.2) x=fs(3.0)
end
subroutine sub(y)
y=y+2
end
function fun(z)
fun = z*z
end

This shows some of the surprising ways Fortran considers functions and subroutines.

It won't compile this way, but will if you comment out either if statement.

Note also that it never calls a function as a subroutine or subroutine as a function.

It makes me suspect that Fortran also won't like mixing them as generics.

Thomas Koenig

unread,
Nov 12, 2022, 2:35:23 AM11/12/22
to
Peter Klausler US <pkla...@nvidia.com> schrieb:
It's a violation of a numbered constraint, and not diagnosing it
is a bug in the compiler. See 4.2, conformance, clause 2:

# A processor conforms to this document if:
[...]

# (3) it contains the capability to detect and report the use within
# a submitted program unit of a form or relationship that is not
# permitted by the numbered syntax rules or constraints, including
# the deleted features described in Annex B;

So, you can support it, and you can even hide the check behind
some options, but unless you want a bug in the compiler, you need
to be able to issue a diagnostic.

As a matter of policy, I think all constraint violations should
be errors by default, and if needed, options should be used
to downgrade the error to a warning (which is still a diagnostic)
or to quieten it entirely.

Peter Klausler US

unread,
Nov 12, 2022, 2:02:38 PM11/12/22
to
On Friday, November 11, 2022 at 11:35:23 PM UTC-8, Thomas Koenig wrote:
> So, you can support it, and you can even hide the check behind
> some options, but unless you want a bug in the compiler, you need
> to be able to issue a diagnostic.
>
> As a matter of policy, I think all constraint violations should
> be errors by default, and if needed, options should be used
> to downgrade the error to a warning (which is still a diagnostic)
> or to quieten it entirely.

Thanks for the advice. I think a portability warning (optionally fatal but not by default) is sufficient in this case and in the best interest of users trying to port code to a new compiler. The extension is benign, unambiguous, useful, and well supported elsewhere. Were it dangerous, ambiguous, easy to avoid, or peculiar to a single compiler, things would be otherwise.

FortranFan

unread,
Nov 12, 2022, 3:17:33 PM11/12/22
to
On Friday, November 11, 2022 at 9:02:39 PM UTC-5, Peter Klausler US wrote:

> On Friday, November 11, 2022 at 2:21:37 PM UTC-8, Thomas Koenig wrote:
> > I disagree there. Both interfacs are accessed by use association
> > in the main program, and thus are in its scope.
> >
> > At least this is how I interpret use association and 14.2.2.
..
> Thanks for the response. You're probably right. But since at least four compilers support this combination, so must I, and it's just a matter of determining how it should be documented.

Re: ".. at least four compilers support this combination ..", I seriously doubt it.

The code in the original post is not generic enough to fully illustrate the issue. With the modification below, both Intel Fortran (IFORT, IFX) and gfortran appear to conform to the standard and detect and report the issue of a generic interface in a scope where the procedures are not all functions nor all subroutines:

module m1
interface generic
module procedure func
end interface
contains
integer function func(n)
integer, intent(in) :: n
func = n
end function
end module

module m2
interface generic
module procedure subr
end interface
contains
subroutine subr
print *, 'ok'
end subroutine
end module

program main
use m1
use m2
call generic
print *, generic(42)
end

C:\temp>ifort /c /standard-semantics p.f90
Intel(R) Fortran Intel(R) 64 Compiler Classic for applications running on Intel(R) 64, Version 2021.7.0 Build 20220726_000000
Copyright (C) 1985-2022 Intel Corporation. All rights reserved.

p.f90(24): warning #6706: There is a mixture of specific functions and specific subroutines for one generic-spec. [SUBR]
use m2
-------^

C:\temp>ifx /c /standard-semantics p.f90
Intel(R) Fortran Compiler for applications running on Intel(R) 64, Version 2022.2.0 Build 20220730
Copyright (C) 1985-2022 Intel Corporation. All rights reserved.

p.f90(24): warning #6706: There is a mixture of specific functions and specific subroutines for one generic-spec. [SUBR]
use m2
-------^

C:\temp>gfortran -c p.f90
p.f90:24:7:

24 | use m2
| 1
Error: In generic interface 'generic' at (1) procedures must be either all SUBROUTINEs or all FUNCTIONs
0 new messages