Automatic Error Correction
The automated error corrections made by fpt include:
Inconsistent Numeric Arguments
Inconsistent numeric arguments are detected as errors by compilers when the sub-programs called are internal or module routines. Inconsistent arguments are most common when the called routines are in a library.
Where the inconsistent argument is a literal value fpt rewrites the actual argument passed to the routine to match the type and kind of the formal argument.
for example, the limiter function:
FUNCTION bound( low, input, high ) REAL(4)) low,input,high bound = min ( high, max ( low, input ) ) END
is invoked:
alpha = acos ( bound ( 0, hdot / v, 1 ) )
The upper and lower bounds are written as integers. The lower bound, 0 is unlikely to cause a problem. The bit pattern for integer 0 will usually produce real 0.0 on most systems. The integer 1 will cause a problem.
fpt rewrites the invocation:
alpha = acos ( bound ( 0.0E0, hdot / v, 1.0E0 ) )
If the mis-matched argument is a variable fpt inserts the appropriate intrinsic function to make the change. Thus:
a = bound( i_low, val, i_high )
where i_low and i_high are integers, is rewritten:
a = bound ( REAL(i_low), val, REAL(i_high) )
These changes are controlled by the command CORRECT INCONSISTENT ARGUMENTS. No change is made by default.
Inconsistent Character Arguments
This is much more exciting!
Problems arise because most modern compilers pass arguments of type character to a calling routine by placing two values on the stack: the address of the character argument and its length. For the simple subroutine:
SUBROUTINE report(lab,ival) CHARACTER(LEN=*) :: lab INTEGER(4) :: ival) WRITE (*,'("Value ",A16,I8)') lab, ival END SUBROUTINE report
There are (at least) 3 ways this can be called with inconsistent arguments:
1. Pass a numeric value instead of a string:
CALL report (0, n)
The string will have the address of the constant 0 which may cause a problem. More importantly, the caller will only stack one value, the address of the argument, and not the length. This will cause a stack violation which will probably crash the program somewhere, but not necessarily anywhere near the current subroutine call.
2. Elide the string:
CALL report (, n)
Marking unused arguments with empty commas is explicitly forbidden in the Fortran Standard. But it was common practice before Fortran 90, and users will encounter this in migrating code. The caller will usually stack a single null value and again a stack violation will occur.
3. Pass an Hollerith
CALL report (7Hn_terms, n)
Yes yes, holleriths have long been illegal, but it still happens and many compilers still accept them. The problem is that holleriths are passed by reference - only the address goes onto the stack, and again a stack violation occurs.
The Corrections
fpt corrects the second two cases. In the first case it is not clear what the user intended and the occurrence is marked as an error. Holleriths are converted to strings and elided arguments are changed to empty strings where the length is specified by fpt commands and may be zero. Please see CORRECT INCONSISTENT ARGUMENTS in the fpt reference manual.
Correcting Missing Arguments
In moderm Fortran sub-program arguments may be declared to be optional. fpt makes no change to the code when optional arguments are not present.
Missing arguments may be marked by empty commas or may simply be omitted at the end of the sub-program call. fpt can supply them. The command to do this is CORRECT MISSING ARGUMENTS. The correction may be made:
The non-standard constructs work on most systems. It would be useful if a null pointer argument construct were to be added to the Fortran standard.
Enforcing INTENT(IN) as Declared
The authors have a very large library of Fortran codes, many of which conform to Fortran 2008 or later. Analysis of these codes reveals that about 2% of all variables (including arrays) declared as INTENT(IN) are actually written to. Compilers do not detect this if the violation occurs when the INTENT(IN) argument is passed down into an external routine.
fpt can correct this issue by copying the INTENT(IN) argument to a temporary in the caller, and passing the temporary. This is exactly equivalent to the modern sub-program attribute VALUE. The change could have been made by adding this attribute to the argument declaration. This was not done for two reasons:
The command to make this change is: ENFORCE INTENT IN AS DECLARED.
Correction of I/O Argument Kinds
Most I/O calls, e.g. OPEN, WRITE and INQUIRE have one or more arguments which are required to be of the default integer kind. Errors may occur if the supplied arguments are not, and compilers do not always trap these cases.
The command CORRECT I/O STATEMENT ARGUMENTS corrects all inconsistent arguments in the same way as the sub-program argument corrections described above.
Correction of Integers Used as Logicals
A common practice, particularly in legacy codes, is to accept an integer status return from a sub-program or I/O statement and then to use the integer to control an IF statement. For example:
READ (inlun,'(I4,3F12.4)', IOSTAT=istat) n,coords(1:3,n) IF (istat) GOTO 9990
This works on many systems but is not portable. The difficulty is that the Fortran standard does not specify how .TRUE. and .FALSE. are to be represented as integers. The possible options are (at least):
fpt can correct the IF statements. The command is CORRECT USE OF INTEGER FOR LOGICAL. The choice of the definition of .TRUE. and .FALSE. is made by the command REPRESENT TRUE BY. For example, if .TRUE. is represented by the least significant bit (the most common case) fpt would write:
READ (inlun,'(I4,3F12.4)', IOSTAT=istat) n,coords(1:3,n) IF (IAND(istat,1) /= 0) GOTO 9990
Correcting the Precision of REAL Numbers
A common error is to write a default kind real number in a context where the precision is intended to be higher. For example:
REAL(8),PARAMETER :: kappa = 4.7473229
The problem here is that 4.7473229 has no kind tag or exponent character and is therefore a default real, typically with 4-byte precision. Its value is 4.74732304. The last few decimal places fall outside the REAL(KIND=4) range.
Situations like this may be corrected by fpt. The command is CORRECT PRECISON OF REAL NUMBERS. The code then becomes:
REAL(8),PARAMETER ::kappa=4.7473229D0 !-------------------------------^------------------------------------------- !!! FPT - 3743 Real literal precision increased with a small change in value !---------------------------------------------------------------------------
The value is corrected by adding the exponent letter D. The value resulting is: 4.7473230361938477 which is as close as 8-byte real precision can get to the specified value.
Note that fpt marks the change with a note. There is also an overall report of the number of changes made, e.g.
Promotion of Literal REAL Numbers ================================= Count Percent REAL literal numbers: 103 With KIND tags: 18 17.48% Promoted to higher precision: 7 6.80% Promoted with change in value: 5 4.85% Not promoted: 2 1.94%
Copyright ©1995 to 2025 Software Validation Ltd. All rights reserved.