Intel® Fortran Compiler
Build applications that can scale for the future with optimized code designed for Intel® Xeon® and compatible processors.

ONLY : MYSELF to blame

jimdempseyatthecove
Honored Contributor III
3,677 Views

This isn't a bug as such, but perhaps a feature request.

I have some code that I am maintaining and enhancing, and in this instance I am annotating it for offload programming on the Xeon Phi. Wishing to keep as much of the annotations out of the source code as possible, I place the !DIR$ ATTRIBUTES OFFLOAD : mic :: foobar into an interface module. This works quite well provided you do not do something like the following:

subroutine FooBar(A,B,C)
use MyInterfaces, ONLY: SomeOtherRoutine

Well, this eliminates considering the interface for FooBar itself (assuming it is contained in the module, it was).

This was definitely my programming error, however, on the other hand, the compiler could implicitly (and conditionally) ONLY-fy interfaces to self. Or, note that self interface was inside the module and issue a warning to the potential for error.

I had a significant amount of issues in trying to figure this out because the code was inside a DLL called from a managed C# forms application. Error diagnostics (defining H_TRACE in this case), was not documented in the offload, and the fact that the app had no console, using it placed the error messaged into the bit bucket. This error was not detectible at compile or link time, rather it was a runtime error only inside the MIC offload. IOW the subroutine was not found in the dynamic load library generated.

Jim Dempsey

0 Kudos
33 Replies
andrew_4619
Honored Contributor III
2,471 Views

If I understand correctly a  "warn unused" would apply? There was a feature request for USE xxx, Only: yyyy  where yyyy is not actually used to generate a warning. This feature was added to 15.x but doesn't work  in many instances. I haven't seen that DPD closed as yet....

 

 

0 Kudos
Steven_L_Intel1
Employee
2,471 Views

Interface-to-self has been hotly debated amongst the standards committee members, but the majority opinion was not to go there. The suggestion of automatically excluding interface-to-self is interesting, but I don't see the committee going for that.

As for directives that apply to a routine implementation, our rule is that they have to appear in the routine itself so that the compiler can change its behavior accordingly (since interface-to-self is prohibited.)

The compiler DOES complain about interface-to-self if you ask for standards checking:

C:\Projects>ifort -c -stand t.f90
Intel(R) Visual Fortran Intel(R) 64 Compiler for applications running on Intel(R
) 64, Version 16.0.1.146 Build 20151021
Copyright (C) 1985-2015 Intel Corporation.  All rights reserved.

t.f90(9): warning #7925: An interface-block in a subprogram that contains an int
erface-body for a procedure defined by that subprogram is non-standard.   [FOO]
subroutine foo (arg)
-----------^

 

0 Kudos
jimdempseyatthecove
Honored Contributor III
2,471 Views

Hmm... then a module containing only interfaces cannot be uses in routines using the interface module to access other routines defined in the interface module.... without explicitly listing those routines with an ONLY clause to the USE statement. In this case an EXCLUDE would be handy to expressly exclude your own interface.

USE InterfaceModule, EXCLUDE: Myself ! *** EXCLUDE not valid

Note then, that you cannot then use the interface module to assure that the interface in the interface module is consistent with the interface of the actual routine. This goes against the intention of -warn:interfaces.

While one might argue that any well written module will have a CONTAINS section containing the actual routine, as opposed to a module containing just the interface, the reality (in practice) is you often have situations where modules A, B and C need to be aware of each other. Using a CONTAINS section then causes circular references (when editing routines), whereas using INTERFACE only modules does not.

Jim Dempsey

0 Kudos
nichols__john
Beginner
2,471 Views

reading this thread is both interesting and challenging

Merry Thanksgiving Day

0 Kudos
Steven_L_Intel1
Employee
2,471 Views

Actually, if you use /warn:interface we can (sometimes) detect an inconsistency and warn you. 

0 Kudos
jimdempseyatthecove
Honored Contributor III
2,471 Views

>>if you use /warn:interface we can (sometimes) detect an inconsistency and warn you.

But then by permitting self, you (always) detect inconsistencies.

Note 2

Assuming a well respected routine contains multiple USE of other vendors modules, which may contain USE of there modules containing interfaces... to your routine!!!. By permitting "self" you also enforce a consistency check of all such USE's and avoid interface conflicts.

Jim Dempsey

0 Kudos
FortranFan
Honored Contributor III
2,471 Views

jimdempseyatthecove wrote:

>>if you use /warn:interface we can (sometimes) detect an inconsistency and warn you.

But then by permitting self, you (always) detect inconsistencies.

Note 2

Assuming a well respected routine contains multiple USE of other vendors modules, which may contain USE of there modules containing interfaces... to your routine!!!. By permitting "self" you also enforce a consistency check of all such USE's and avoid interface conflicts.

Jim Dempsey

It'll help if such a discussion can be based on a concrete, workable example (and given Jim's experience, shouldn't take long to present an actual scenario, especially to avoid any misunderstanding among other readers of the issue at hand).

For I think the standard Fortran solution for Jim would be to use SUBMODULEs - given a concrete case in front of us, we would be able to try it out and illustrate it.

0 Kudos
jimdempseyatthecove
Honored Contributor III
2,471 Views

Use of sub-modules may resolve the circular reference issue... at the expense of a major overhaul of the code. This is not the subject of the discussion, but rather one such situation.

Providing self-reference with respect to interface modules is important to assure that the routine itself is consistent with the interface you provide.

It is not unreasonable for a software vendor to supply binary files only (.obj, .lib, .dll), together with a module that defines the interfaces to their code. What is the purpose of having a standard that inhibits verification that your interfaces are consistent with your actual code??

Jim Dempsey

0 Kudos
FortranFan
Honored Contributor III
2,471 Views

jimdempseyatthecove wrote:

Use of sub-modules may resolve the circular reference issue... at the expense of a major overhaul of the code. This is not the subject of the discussion, but rather one such situation.

Providing self-reference with respect to interface modules is important to assure that the routine itself is consistent with the interface you provide.

It is not unreasonable for a software vendor to supply binary files only (.obj, .lib, .dll), together with a module that defines the interfaces to their code. What is the purpose of having a standard that inhibits verification that your interfaces are consistent with your actual code??

Jim Dempsey

Jim,

I agree with you totally.  See this thread, especially Message #30.

https://software.intel.com/en-us/forums/intel-visual-fortran-compiler-for-windows/topic/507087

And there have been other threads too on this forum as well as others where I have tried to engage experts-that-may-be in discussion on changes in the Fortran standard that would provide an "interface to self" kind of feature.  But as Steve said, I get swatted away by the usual suspects.  It appears the standard body has pretty much settled on SUBMODULEs and that will be your path of least resistance if you're looking for a "standard Fortran" solution.  You may want to look into it, for chances are you will be able to figure out options (say using automated/semi-automated scripts, etc.) to achieve the code overhaul without much effort and pain:

module myinterfaces

   implicit none

   interface

      module subroutine foo()
      end subroutine foo

      module subroutine bar(i)
         integer, intent(in) :: i
      end subroutine bar

   end interface

end module myinterfaces
submodule(myinterfaces) sm1

contains

   module subroutine foo()

      call bar("Hello World!")

      return

   end subroutine foo

end submodule sm1
submodule(myinterfaces) sm2

contains

   module subroutine bar(i)

      integer, intent(in) :: i

      print *, " In bar: i = ", i

      return

   end subroutine bar

end submodule sm2

Upon compilation, the following error is raised in foo about the mismatch in interface with bar, thereby showing one of the benefits of SUBMODULEs:

------ Build started: Project: p, Configuration: Release|x64 ------

Compiling with Intel(R) Visual Fortran Compiler 16.0 [Intel(R) 64]...
m.f90
m.f90(24): error #6633: The type of the actual argument differs from the type of the dummy argument.   ['Hello World!']
compilation aborted for m.f90 (code 1)

 

0 Kudos
JVanB
Valued Contributor II
2,471 Views

Hey, interface to self has always been allowed and is useful for checking that a procedure matches its interface body.

module M
   implicit none
   interface
      subroutine S(x)
         implicit none
         real x
      end subroutine S
   end interface
end module M

program P
   use M
   implicit none
   real y
   call S(y)
   write(*,*) 'y = ', y
end program P

subroutine S(x)
   use M
   use M, only: T => S
   implicit none
   real x

   if(.FALSE.) then
      BLOCK
         procedure(T), pointer :: U => S
      END BLOCK
   end if
   x = 257
end subroutine S

BTW, has this bug been fixed in Update 1?

 

0 Kudos
IanH
Honored Contributor III
2,471 Views

In #11, there are two interfaces, from two separate definitions, for S accessible inside the scope of the subroutine S.  That's non-conforming. 

There is a distinction between the interface as a thing, and the identifier used to refer to that thing.  The use renaming just changes the latter.

0 Kudos
JVanB
Valued Contributor II
2,471 Views

No, there is no nonconformance. In module M, there are only instructions on how a user of the module is to invoke a specific procedure and how the linker is to search for the procedure that satisfies that interface. It's no problem that subroutine S uses that interface. What if we had named it subroutine R instead? Surely that would be OK. Then the *.DEF file makes subroutine R available to the linker under the name S. Still OK, right? What's the difference that we named the subroutine S directly?

 

0 Kudos
IanH
Honored Contributor III
2,471 Views

Discussion of linkers and DEF files gets into implementation details, beyond what the standard covers. 

The standard just says you cannot have more than one explicit specific interface for a procedure accessible in a scoping unit. 

(You are permitted to have multiple names for the one interface definition in the one scope, but there are two separate definitions in #11.)

I could come up with plenty of examples of where non-conforming code ends up "working", perhaps even relatively reliably, but that doesn't change the non-conforming nature of the code. 

0 Kudos
JVanB
Valued Contributor II
2,471 Views

You seem to be conflating the interface and the procedure itself. All the pieces are OK in themselves, it's just after they are all compiled, if the user chooses to link them together in a certain way, that the program might be claimed to be nonconforming. But the standard doesn't really go into choices at the linking stage of that sort -- does it even mention linking?

 

0 Kudos
JVanB
Valued Contributor II
2,471 Views

I couldn't find the passage in the standard where it says that you cannot have more than one explicit specific interface for a procedure accessible in a scoping unit. Can you point me to it so that it's possible to discuss what it means in the context of the present discussion?

 

0 Kudos
IanH
Honored Contributor III
2,471 Views

In the subprogram that defines the external procedure S, there is an explicit specific interface for the external procedure S, that is specified by the SUBROUTINE statement and the associated specification statements of the subprogram.  That is explicit specific interface #1.

The module has a public entity that is also an explicit interface for S, specified by the SUBROUTINE statement and specification part of the interface body.  That public entity is then made accessible inside the scope of the subprogram by a USE statement.  The rename facility of the USE statement changes the name by which the interface can be accessed, but it is still an explicit specific interface for S - as S is the name that appeared in the interface body.  That is explicit specific interface #2. 

"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.  If a procedure is accessed by use association, each access shall be to the same procedure declaration or definition."

One of the interfaces is not accessed by use association, and you have two definitions of the interface.  The source code is non-conforming.  How the user compiles or links things doesn't change that - it is a property of the source code comprising module M and subroutine subprogram S. 

Whether the restriction on interface to self is reasonable or not in the first place is also not relevant.  I haven't thought about this enough to come up with a view on its reasonableness, but I can understand why there would be some resistance to relaxing the restriction from a conceptual point of view - you would be permitting definition of the one entity from two completely separate sections of Fortran source, which I suspect would be a rather novel thing for the language (are there other examples?).

I have half finished (and fully buggy!) tools that do full program semantic analysis of Fortran source, one of the aims of which was to identify errors such as a mismatch between an external procedure definition and any interface bodies.  I know I am not the only one to head down this path, and ifort clearly already has material capability in this area.  I think the application of such tools to the problem that Jim describes (beyond the use of submodules, which do significantly reduce the requirement for external procedures) to be more efficacious than the implied alternative of modifying the language, all processors and all relevant Fortran source code.

0 Kudos
FortranFan
Honored Contributor III
2,471 Views

Repeat Offender wrote:

Hey, interface to self has always been allowed and is useful for checking that a procedure matches its interface body... 

Interesting idea, the following simplified version compiles fine with gfortran (GCC 6.0 development version) but Intel Fortran raises error #6592 and #6973 respectively.  Not sure if the code is standard-conforming.

module myinterfaces

   implicit none

   interface

      subroutine sub()
      end subroutine sub

   end interface

   public :: sub

end module myinterfaces

subroutine sub()

   use myinterfaces, only : Isub => sub

   procedure(Isub), pointer :: foo_ptr => sub

   return

end subroutine sub

Keeping in mind the goal here is to do interface checking, I suppose one would consider wrapping the procedure pointer line on 20 with some preprocessor/compiler directive to accomplish the check only until the interface is validated.

However, given the supposed constraints in the standard with procedure pointers (e.g., elemental procedures are not allowed), this approach has limitations, even if it were to be standard-conforming.

And to add, if an interface mismatch is introduced, gfortran flags it as shown below:

module myinterfaces

   implicit none

   interface

      subroutine sub()
      end subroutine sub

   end interface

   public :: sub

end module myinterfaces

subroutine sub(s)

   use myinterfaces, only : Isub => sub
   
   character(len=*), intent(in) :: s

   procedure(Isub), pointer :: foo_ptr => sub

   return

end subroutine sub
m.f90:22:45:
    procedure(Isub), pointer :: foo_ptr => sub
                                             1
Error: Interface mismatch in procedure pointer assignment at (1): 'sub' has the wrong number of arguments

 

0 Kudos
jimdempseyatthecove
Honored Contributor III
2,471 Views

ianh wrote:

In #11, there are two interfaces, from two separate definitions, for S accessible inside the scope of the subroutine S.  That's non-conforming. 

There is a distinction between the interface as a thing, and the identifier used to refer to that thing.  The use renaming just changes the latter.

Yes, IanH, there are two interfaces:

That inside the use, and
That of "self"

The whole point of this discussion is by permitting "self" in the USE'd module, the compiler can verify the USE's interface against "self". Consider this as an automated verification that you, or the next person touching your code, does not muck up anything else, by making a seemingly benign change.

Note, if you really do .NOT. want the interface checked (assuming you want the actual interface to differ from the USED interface) you have a means to do this using ONLY on the other parts of interest in the module.

I think the whole standards committee issue with permitting this that there compiler may have had issues with various attributes applied to the arguments. In earlier versions of IVF, where you could self reference, it would at times error out on some attribute combinations (even on a copy and paste of the actual code). My guess it they do not want to be required to fix this.

Jim Dempsey

0 Kudos
Steven_L_Intel1
Employee
2,471 Views

I think the code in #18 is conforming. The error message ifort gives is perplexing, to say the least. I will report this to the developers. Issue ID is DPD200379165.

0 Kudos
JVanB
Valued Contributor II
2,377 Views

OK, I see the section quoted in the standard. I still reserve my opinion on whether it wipes out my code in Quote #11. But I found another passage in the same section:

If an external procedure does not exist in the program, an interface body for it may be used to specify an explicit specific interface but the procedure shall not be used in any other way.

So I modified my program to something which, with the above qualification, I think you might find more agreeable.

module M
   implicit none
   interface
      subroutine S(x) bind(C,name='self1')
         implicit none
         real x
      end subroutine S
   end interface
end module M

program P
   use M
   implicit none
   interface
      subroutine R(x) bind(C,name='self2')
         implicit none
         real x
      end subroutine R
   end interface
   real y
   call R(y)
   write(*,*) 'y = ', y
end program P

subroutine S(x) bind(C,name='self2')
   use M
   use M, only: T => S
   implicit none
   real x

   if(.FALSE.) then
      BLOCK
         procedure(T), pointer :: U => S
      END BLOCK
   end if
   x = 257
end subroutine S

 

0 Kudos
Reply