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

Fortran 16 fails at "contains"

Laura_S_3
Beginner
3,314 Views

Bottom line: I'm having problems getting a program to compile under Intel 16 Fortran and I suspect it isn't the code being flagged but is something elsewhere or compiler options.

I'm having problems getting Intel Fortran 16 to compile a rather large, proprietary program, so I can't post more than small snippets of code.This program compiles at least back to Intel Fortran 11, and probably further. The problems don't make sense, so I am wondering if the error messages are red-herrings and there actually is a different issue.

First output error messages:

        ifort -c -qopenmp -fpp -O2 -traceback -g -shared-intel -heap-arrays -fpe3 -qopt-report0 -DMKL -DMKL -DMKL -DMKL -DTHREADEDINTELMKL -I/p/home/apps/intel/compilers/16/compilers_and_libraries_2016.4.258/linux/mkl/include/intel64/lp64 -i4 -r8 -qopenmp -I. -I.. -I.././<directory name> -I.././<directory name> <file name>.f90
<file name>.f90(1235): error #6681: This is either an invalid statement, a declaration statement that is ordered incorrectly, or a null procedure statement.
contains
^
<file name>.f90(1252): error #6681: This is either an invalid statement, a declaration statement that is ordered incorrectly, or a null procedure statement.
end subroutine
^

Like I said, this compiles fine under previous versions, so the error doesn't make sense. I inserted an "endif" or an "enddo" before the "contains" to see if somehow it thought there was an unterminated block, but both of those were correctly flagged by the compiler as unpaired.

Later error messages in the contained subroutines include messages flagging local variable names in the contained routines. In the example below, i is locally declared within the subroutine.

<file name>.f90(3264): error #6405: The same named entity from different modules and/or program units cannot be referenced.  
         do i = 1, size(<array name>,1)
------------^

Anyone have any ideas? I spent several hours reworking code in what that looked to correct to last fall, and never got through all of the issues. (The one above was solved by turning the contained subroutines into not-contained ones, but then there were further issues, including OpenMP related ones.)

 

 

 

0 Kudos
36 Replies
Laura_S_3
Beginner
1,081 Views

If I succeed in isolating a clear cause, I will try to get you a reproducer.

I'm trying to look at other clues now. We do get a few instances of the "warning #5462: Global name too long, shortened from: ..." message. From other forum discussion, that is still considered innocuous, correct?

I notice that the .mod files are now larger than they were for Intel Fortran 14. What sort of functionality changes lead to the change in size? Maybe the changes would give me a clue as to where to look for atypical coding that could cause compiler problems. Also, the two modules that seemed most associated with the issues are also the largest ,mod files (1.4M and just under 1M). Are their any known issues with too-large modules?

0 Kudos
Steven_L_Intel1
Employee
1,081 Views

The 5462 warning can be ignored.

We made changes in module file structure to accommodate the submodule feature of Fortran 2008. That might account for size differences. Not helpful in diagnosis. We have much larger modules that work without issue.

The error you're getting suggests a compiler bug, perhaps in creation of one of the modules. Don't try to look for "atypical coding" - just see if you can come up with a small set of files that show the problem.

0 Kudos
TimP
Honored Contributor III
1,081 Views

Browser jumped to wrong thread, sorry

0 Kudos
jimdempseyatthecove
Honored Contributor III
1,081 Views

Laura,

Since your build/make is using the Fortran preprocessor, can you try adding -fpp-name=PathAndNameOfOlderFpp

This is to verify if the issue is preprocessor related and not compiler related.

Jim Dempsey

0 Kudos
Laura_S_3
Beginner
1,081 Views

I found a system with Intel Fortran 17.0, and have confirmed that the problem persists in 17.0. I have a colleague who is trying to make a trimmed-down reproducer that we can provide.

I know this isn't enough information to debug with, but it is definitely associated with the contents of .mod files, and its manifestation varies between two systems with the same exact version of the compiler. (Different MPI modules are on the systems, and this may account for the different manifestation.) The symptoms from the first system can be replicated on the second system by using the .mod files produced on the first system.

Laura

0 Kudos
Steven_L_Intel1
Employee
1,081 Views

Thanks - we'll look forward to the complete reproducer. Be sure to include source files only, no .mod files.

0 Kudos
Laura_S_3
Beginner
1,081 Views

Here is a reproducer. It reproduces on Intel Fortran 17.0.0. Let me know what other details you may need.

I started with the big program and eliminated everything unnecessary to reproduce the bug. The resulting code has almost no executable statements and more than one totally empty module. It is extremely touchy - changing the order of "use" statements can make the compiler issue go away.

I would love to know what in particular is triggering this issue so I can refactor it in a non-triggering way. I need this code to compiie under many version of Intel Fortran.

Thank you!

Laura

0 Kudos
Steven_L_Intel1
Employee
1,081 Views

Thanks! Curiously, this reproduces with the 64-bit compiler but not the 32-bit compiler! We'll investigate.

0 Kudos
Steven_L_Intel1
Employee
1,081 Views

Escalated as issue DPD200415875. I have asked the developers to let me know if they can identify the source usage that triggers the problem.

Since, as you say, reordering some USE statements hides the problem, is that a workaround that works in your real application?

0 Kudos
Laura_S_3
Beginner
1,081 Views

I'm not sure if switching around the use statements will be a sufficient fix or not, since I don't know if the .mod files are always bad (but only sometimes causing overt symptoms) or not. Since it isn't time critical (yet) to have it compile under 16/17, I figured I'd wait and see what the finding are. I have a feeling that I am going to have to re-do those few modules at the bottom that actually have stuff in them still, but I have a vague recollection that they are written the way they are for syntactical reasons involving the way those functions are used (and passed around).

Laura

0 Kudos
FortranFan
Honored Contributor III
1,081 Views

Laura S. wrote:

.. It is extremely touchy - changing the order of "use" statements can make the compiler issue go away.  I would love to know what in particular is triggering this issue so I can refactor it in a non-triggering way. I need this code to compile under many version of Intel Fortran. ..

Given your statement, "I need this code to compile under many version of Intel Fortran" (and by this I assume versions going back to 15.0 and earlier), SUBMODULEs may not be an option, otherwise refactoring code using this Fortran 2008 feature is something you can consider.  See Steve's blog: https://software.intel.com/en-us/blogs/2015/07/07/doctor-fortran-in-we-all-live-in-a-yellow-submodule

Looking at your reproducer code, it is difficult to ascertain the true dependencies of various module contents and this is compounded by your use of default attribute of PUBLIC for module contents and your lack of use of ", ONLY : " while USE'ing modules.  In your actual code, will it be possible for you to switch to PRIVATE as the default attribute in each of your module and employ ', ONLY : ' in USE statements in order to only bring in those entities that are needed in each module.  This may make it a whole lot easier on the compiler.  Plus the code developers will themselves benefit from more expressive code that will be clearer in terms of showing what entities are coming from which module.  Also the PRIVATE will help foster 'encapsulation' (aka information hiding), a recommended practice in big projects.  These are just some suggestions toward refactoring since you asked.

 

 

0 Kudos
Laura_S_3
Beginner
1,081 Views

In the real code, the names tell you a lot about the relationships. (One thing this but is not sensitive to is renaming things, thank goodness, or I could not have submitted this reproducer without authorization.) Also, I took out every line of code I could find that did not impact the manifestation of the bug, so that is why you see only one "private" statement. Having said that, I haven't been using "only", but I'm not sure how much it would help the real code because of the way things are grouped into modules.

0 Kudos
FortranFan
Honored Contributor III
1,081 Views

Laura S. wrote:

.. I haven't been using "only", but I'm not sure how much it would help the real code because of the way things are grouped into modules.

Yes, no one can say for sure how much it would help.  But in Message #28, you used the word 'refactor' which is a big deal in my book.  See this: https://en.wikipedia.org/wiki/Code_refactoring and note the first paragraph where it says, "Code refactoring .. improves nonfunctional attributes of the software. Advantages include improved code readability and reduced complexity; these can improve source-code maintainability and create a more expressive internal architecture or object model to improve extensibility .."  If you really want to improve your use of modules, then I would strongly suggest that you consider PRIVATE as the default attribute of all your modules, employ ", ONLY : .." in all your USE statements (and of course, IMPLICIT NONE the most important statement in Fortran!).

To put it another way, consider below the 'refactored' code of your problem reproducer.  You should find it compiles without errors, at least it does for me with Intel Fortran 17.0 compiler update 1 as well as gfortran (and with a slight change to ID_Type and BLOCK_ID_Type, all the way back in Compaq Fortran, the predecessor to Intel Fortran).  Can you try to 'break it', meaning create the error you get with your reproducer from Message #28, while retaining the PRIVATE attribute as well as USE'ing , ONLY  statements and only making those entities PUBLIC in modules that need to be?  My hunch is this approach will help you.  Please note this does not mean Intel should not resolve the problem incident created by Steve; this is just a possible workaround for you that will also bring other benefits.

module ModuleAC

   implicit none

   private

   type, public :: ID_Type
   end type ID_Type
   
   interface operator (==)
      module procedure ID_equal
   end interface

   interface operator (/=)
      module procedure ID_notequal
   end interface

   interface operator (<)
      module procedure ID_lessThan
   end interface

   interface operator (>)
      module procedure ID_greaterThan
   end interface

   interface operator (<=)
      module procedure ID_lessThanEqualTo
   end interface

   interface operator (>=)
      module procedure ID_greaterThanEqualTo
   end interface

contains

   pure function ID_equal(ID1, ID2)
      implicit none
      type (ID_Type), intent(In) :: ID1, ID2
      logical :: ID_equal
      integer :: i
   end function

   pure function ID_notequal(ID1, ID2)
      implicit none
      type (ID_Type), intent(In) :: ID1, ID2
      logical :: ID_notequal
   end function

   pure function ID_lessThan(ID1, ID2)
      implicit none
      type (ID_Type), intent(In) :: ID1, ID2
      logical :: ID_lessThan
   end function

   pure function ID_lessThanEqualTo(ID1, ID2)
      implicit none
      type (ID_Type), intent(in) ::ID1, ID2
      logical :: ID_lessThanEqualTo
   end function

   pure function ID_greaterThan(ID1, ID2)
      implicit none
      type (ID_Type), intent(In) :: ID1, ID2
      logical :: ID_greaterThan
   end function

   pure function ID_greaterThanEqualTo(ID1, ID2)
      implicit none
      type (ID_Type), intent(In) :: ID1, ID2
      logical :: ID_greaterThanEqualTo
   end function

end module ModuleAC

module ModuleAB

   use ModuleAC, only :

   implicit none

   private

   type, public :: BlockID_Type
   end type BlockID_Type

   interface operator (==)
      module procedure BlockID_equal
   end interface

   interface operator (/=)
      module procedure BlockID_notequal
   end interface

   interface operator (<)
      module procedure BlockID_lessThan
   end interface

   interface operator (>)
      module procedure BlockID_greaterThan
   end interface

   interface operator (<=)
      module procedure BlockID_lessThanEqualTo
   end interface

   interface operator (>=)
      module procedure BlockID_greaterThanEqualTo
   end interface

contains

   pure function BlockID_equal(ID1, ID2)
      implicit none
      type (BlockID_Type), intent(In) :: ID1, ID2
      logical :: BlockID_equal
   end function

   pure function BlockID_notequal(ID1, ID2)
      implicit none
      type (BlockID_Type), intent(In) :: ID1, ID2
      logical :: BlockID_notequal
   end function

   pure function BlockID_lessThan(ID1, ID2)
      implicit none
      type (BlockID_Type), intent(In) :: ID1, ID2
      logical :: BlockID_lessThan
   end function

   pure function BlockID_lessThanEqualTo(ID1, ID2)
      implicit none
      type (BlockID_Type), intent(in) ::ID1, ID2
      logical :: BlockID_lessThanEqualTo
   end function

   pure function BlockID_greaterThan(ID1, ID2)
      implicit none
      type (BlockID_Type), intent(In) :: ID1, ID2
      logical :: BlockID_greaterThan
   end function

   pure function BlockID_greaterThanEqualTo(ID1, ID2)
      implicit none
      type (BlockID_Type), intent(In) :: ID1, ID2
      logical :: BlockID_greaterThanEqualTo
   end function

end module ModuleAB
module ModuleAA

   use ModuleAB, only :
   use ModuleAC, only : ID_Type

   implicit none

   ! This private appears to be necessary for the manifestaion of the bug
   private

   interface ToString
      module procedure Integer4ToString
      module procedure Integer8ToString
      module procedure IDToString
   end interface

   interface intlen
      module procedure intlen4
      module procedure intlen8
   end interface

contains

   function Integer8ToString(I)
      implicit none
      integer(8), intent(In) :: I
      character(intlen(I)) :: Integer8ToString
   end function

   function Integer4ToString(I)
      implicit none
      integer(4), intent(In) :: I
      character(intlen(I)) :: Integer4ToString
   end function

   function IDToString(ID)
      implicit none
      type(ID_Type), intent(In) :: ID
      character(IDStringLength(ID)) :: IDToString
   end function

   elemental function IDStringLength(ID)
      integer IDStringLength
      type(ID_Type), intent(In) :: ID
   end function

   elemental function intlen4(i)
      integer intlen4
      integer(4), intent(In) :: i
   end function

   elemental function intlen8(i)
      integer intlen8
      integer(8), intent(In) :: i
   end function

end module ModuleAA

module ModuleZ

   use ModuleAA, only :

   implicit none

   private

end module ModuleZ

module ModuleG

   use ModuleZ, only :
   use ModuleAB, only :

   implicit none

   private

end module ModuleG

module ModuleY

   use ModuleZ, only :

   implicit none

   private

end module ModuleY

module ModuleX

   use ModuleY, only :

   implicit none

   private

end module ModuleX

module ModuleW

   use ModuleY, only :
   use ModuleX, only :

   implicit none

   private

end module ModuleW

module ModuleV

   use ModuleW, only :

   implicit none

   private

end module ModuleV

module ModuleM

   use ModuleV, only :

   implicit none

   private

end module ModuleM

module ModuleL

   use ModuleY, only :
   use ModuleX, only :

   implicit none

   private

end module ModuleL

module ModuleK

   use ModuleY, only :
   use ModuleX, only :
   use ModuleM, only :
   use ModuleAA, only :
   use ModuleL, only :

   implicit none

   private

end module ModuleK

module ModuleI

   use ModuleY, only :
   use ModuleX, only :
   use ModuleK, only :
   use ModuleW, only :
   use ModuleV, only :

   implicit none

   private

end module ModuleI

module ModuleF

   use ModuleM, only :
   use ModuleX, only :
   use ModuleK, only :

   implicit none

   private

end module ModuleF

module ModuleE

   use ModuleG, only :
   use ModuleK, only :
   use ModuleF, only :
   use ModuleL, only :
   use ModuleI, only :

   implicit none

   private

end module ModuleE

module ModuleD

  use ModuleE, only :
  
  implicit none
  
  private

end module ModuleD

module ModuleC

   use ModuleD, only :
   use ModuleE, only :

   implicit none

   private

end module ModuleC

module ModuleB

   use ModuleC, only :

   implicit none

   private

end module ModuleB

module ModuleA

   use ModuleC, only : 
   
   implicit none
   
   private

end module ModuleA

module module_Top

   implicit none

   private

contains

   subroutine SubroutineC()
   
      use ModuleA, only :
      use ModuleB, only :
      use ModuleC, only :
      
   end subroutine SubroutineC

   subroutine SubroutineB()

      use ModuleC, only :

      integer :: VariableA

   contains

      subroutine SubroutineA()
         VariableA = 1
      end subroutine SubroutineA

   end subroutine SubroutineB

end module module_Top

 

0 Kudos
Steven_L_Intel1
Employee
1,081 Views

I expect this to be fixed in Update 2 to Parallel Studio XE 2017. All I can tell you about the bug is that it's related to importing modules in a contained procedure.

0 Kudos
Laura_S_3
Beginner
1,081 Views

Thank you for the update! :-) Are the developers able to give any info on if this affected object code? Specifically, if it compiles, can I assume that the object code is unaffected by this bug?

Laura

0 Kudos
Steven_L_Intel1
Employee
1,081 Views

Sorry, we can't be certain about that in general. It seems unlikely to me, for this sort of issue, that there would be a risk of bad code.

0 Kudos
Reply