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

Legacy F77 code compiler errors in IVF: problems related to N-dimensional arrays declared as ARRAY(1)

avinashs
New Contributor I
480 Views

Background: This post has been created to illustrate a common problem with some legacy Fortran code that does not compile with IVF. It may be noted that the origins of these codes are the well known American Computing Machinery Transactions on Mathematical Software (ACM TOMS) archives. The underlying numerical methods are sound and the codes provided by the authors worked for them and users such as myself for several years up until CVF66C (1993-2007) with correct results. However, they do not compile with IVF.

Objective: What is the solution or workaround? Note: It is difficult to modify the code confidently and the code is extremely valuable to abandon.

Example: An array A is dimensioned A(15) (say) in the main program, which calls a subroutine TASK1 that takes A as an argument. A is dimensioned A(1) in TASK1. Then within TASK1, A is passed to another subroutine TASK2. A is dimensioned as A(3,1) in TASK2. N is passed as an argument to both TASK1 and TASK2. However, this generates a #7983 error with IVF at the point where TASK2 is called within TASK1. In my opinion, the legacy code is not good programming practice but it worked for several years. The question is whether a compiler setting can overcome this error without compromising the rest of the project.

      PROGRAM MAIN
      INTEGER N
      REAL S,A(15)
      INTEGER I
C     DEFINE LENGTH OF ARRAY AND ARRAY ELEMENTS
      N=5
      A(1)=1.0
      DO 2 I=2,N
         A(I)=A(I-1)+1.0
 2    CONTINUE
C     CALL ROUTINE THAT ACCEPTS AN ARRAY DEFINED AS A(1)
      CALL TASK1(N,A,S)
      END PROGRAM MAIN
      
      SUBROUTINE TASK1(N,Y,S)
      INTEGER N
      REAL S,Y(1)
C     THE FOLLOWING STATEMENT GENERATES A COMPILER ERROR
C     error #7983: The storage extent of the dummy argument exceeds that of the actual argument.   
      CALL TASK2(N,Y,S)
      RETURN
      END

      SUBROUTINE TASK2(N,X,S)
      INTEGER N
      REAL S,X(3,1)
      INTEGER I
C     STATEMENT BELOW IS AN EXAMPLE OF THE KIND OF CALCULATION INVOLVING X
      S = X(1,N) + X(2,N) + X(3,N)
      RETURN
      END

 

0 Kudos
6 Replies
IanH
Honored Contributor II
480 Views

The example code (which is broken under the standard) compiles at a command line with out any further options for me (i.e. ifort source.for).  How are you compiling the code?

Are you compiling with interface checking turned on?  If so, turn it off - /warn:nointerfaces at the command line, or within Visual Studio set Fortran > Diagnostics > Compile Time Diagnostics to Custom, and then set Check Routine Interfaces in the same category to No.  I would be as particular as possible about disabling  diagnostic options like this, to reduce the likelihood of missing serious errors.

0 Kudos
avinashs
New Contributor I
480 Views

ianh wrote:

The example code (which is broken under the standard) compiles at a command line with out any further options for me (i.e. ifort source.for).  How are you compiling the code?

Are you compiling with interface checking turned on?  If so, turn it off - /warn:nointerfaces at the command line, or within Visual Studio set Fortran > Diagnostics > Compile Time Diagnostics to Custom, and then set Check Routine Interfaces in the same category to No.  I would be as particular as possible about disabling  diagnostic options like this, to reduce the likelihood of missing serious errors.

@ianh: Thanks. I tested this option and it does work (no compiler error). Considering this code has worked historically, I will presume that the previous compiler error was more of a warning than an error because if I trace the allocation of workspace within the TOMS code, then the array is correctly sized as 3*N in the main program and "resized" for convenience in an internally-used subroutine as (3,1), which should be equivalent to (3,*) or (3,N). Also:

(1) was the default CVF setting /warn:nointerfaces?

(2) when I look at the BuildLog.htm file, the newly chosen option /warn:nointerfaces does not appear anywhere.

(3) in a large project, would it be acceptable to build certain files with the /warn:nointerfaces option and then link them with the rest of the files that were compiled with the default options?

0 Kudos
Steve_Lionel
Honored Contributor III
480 Views

CVF did not have this feature. Since it is off by default in the compiler (it is set as a project property in a Debug configuration in Visual Studio), there is no need for a /warn:nointerface option in the command line used.

/warn:interface affects diagnostics only - it has zero effects on generated code.

The compiler can only go on what you tell it. The use of (1) as a dimension is an old trick often used to say "I don't know the size". In Fortran 77, (*) serves that purpose, and if you replaced the (1) with (*) it should work ok. Otherwise the compiler takes you at your word that Y in TASK1 has only one element, and that is clearly smaller than 3 in TASK2.

0 Kudos
avinashs
New Contributor I
480 Views

Steve Lionel (Ret.) wrote:

CVF did not have this feature. Since it is off by default in the compiler (it is set as a project property in a Debug configuration in Visual Studio), there is no need for a /warn:nointerface option in the command line used.

/warn:interface affects diagnostics only - it has zero effects on generated code.

The compiler can only go on what you tell it. The use of (1) as a dimension is an old trick often used to say "I don't know the size". In Fortran 77, (*) serves that purpose, and if you replaced the (1) with (*) it should work ok. Otherwise the compiler takes you at your word that Y in TASK1 has only one element, and that is clearly smaller than 3 in TASK2.

Thanks. This is clear to me now. Also explained in the thread you posted on a previous question and contained in this article. https://software.intel.com/en-us/articles/migrating-from-compaq-visual-fortran

 

0 Kudos
LRaim
New Contributor I
480 Views

To use (1) as dimension, simply disable boundary check option.
The var(1) notation indicates to the compiler that the variable is a vector. 
I use this feature to have a base address and point to any other variable by using address displacement.
Regards

 

0 Kudos
FortranFan
Honored Contributor II
480 Views

avinashs wrote:

..

(3) in a large project, would it be acceptable to build certain files with the /warn:nointerfaces option and then link them with the rest of the files that were compiled with the default options?

 

An option to consider will be to manage code involving any "special" considerations, say because of their legacy nature, etc., in separate static (or dynamic e.g., DLL) library projects in Visual Studio; such projects can have their own project settings that include appropriate compiler options.

0 Kudos
Reply