Errors in the Intent of Arguments

| SimCon Home | fpt Reference Manual Home |

What Are Intent Errors?

Fortran allows the arguments to sub-programs to be declared:

The intent is declared in INTENT statements or on an INTENT clause within a type declaration statement. The intent is not required to be declared, but declaration of intent improves the checking by compilers. Note that at least three other intents are possible and are recognised internally by fpt:

No provision is made to declare these intents explicitly.

The Fortran standard explicitly states that a declared intent may be used to guide code generation. Therefore, an INTENT(IN) object need not be exported on exit from a sub-program and an INTENT(OUT) object need not be imported when the sub-program is called. Therefore at least the following classes of intent error are possible:

  1. INTENT(IN): A formal argument is declared INTENT(IN) but is assigned a new value in the code.
  2. INTENT(OUT): A formal argument is declared INTENT(OUT) but the value is read before it is assigned.
  3. Access Violation: A formal argument is assigned in the code, and is therefore de facto INTENT(OUT) or INTENT(INOUT). The actual argument passed is a constant. This can occur whether the INTENT of the argument is declared or not.
  4. Write to Expression: A formal argument is assigned in the code, and is therefore de facto INTENT(OUT) or INTENT(INOUT). The actual argument passed is an expression. Again, this can occur whether the INTENT of the argument is declared or not.
  5. Sub-program: The intent of the formal argument is a sub-program and the actual argument passed is not, or vice versa.
  6. Label: The intent of the formal argument is a statement label and the actual argument is not assigned a label.

Do Compilers Trap These Errors?

These issues were tested on gfortran, ifort, Compaq Visual Fortran (CVF) and FTN95)

INTENT(IN): All compilers which we have tested trap INTENT(IN) errors when the argument is assigned across an equals sign in the code of the routine itself. Compilers do not detect this class of error when the argument is passed down into a secondary routine where it is assigned, unless the interface to the secondary routine is visible in the primary routine and the intent is declared in that interface. No error occurs at run-time. Therefore a large number of INTENT(IN) errors are found in code.

INTENT(OUT): None of the compilers we have tested detect INTENT(OUT) errors. An error may occur at run-time if the argument has never been initialised.

Access Violation: These errors are always trapped when the intent of the argument is explicitly declared and the interface is visble to the caller. The compilers tested do not detect this error if the intent is not declared. Run-time errors always occur.

Write to Expression: Again, these errors are always trapped when the intent of the argument is declared and the interface is visible. They are not detected when the intent is not declared. No run-time errors occur. This is a dangerous situation. Compilers generate a temporary variable to hold the value of the expression. This temporary is modified in the sub-program call. Optimising compilers may re-use it elsewhere.

Sub-program and Label: These errors were trapped by all compilers tested.

Detecting Intent Errors

fpt always reports errors in Access Violation and Write to Expression. No command is required to make these checks. Occurrences can be corrected automatically by the command:

CORRECT INCONSISTENT ARGUMENTS

The command to check for INTENT(IN) and INTENT(OUT) violations is

CHECK INTENT

The beginning of the report for WRFV3.6.1 is shown below:

Check of INTENT Declarations ============================ Arguments declared INTENT(IN) which are assigned ------------------------------------------------ Name Scope Use/COMMON Address Type Size Value/Bounds ---- ----- ---------- ------- ---- ---- ------------ comm wrf_ext_write_field Formal Input-Output Argument INTEGER *4 df comm wrf_ext_write_field_arr Formal Input-Output Argument INTEGER *4 df comm wrf_ext_read_field_arr Formal Input-Output Argument INTEGER *4 df config_flags med_initialdata_input Formal Input-Output Argument grid_config_rec_type *35164 df

The report ends with a summary:

Total number of arguments 60752 Declared INTENT(IN) 33126 Declared INTENT(OUT) 5309 Declared INTENT(INOUT) 7177 No INTENT declaration 15115 Sub-program formal arguments 25 INTENT(IN) Violations 138 0.4% INTENT(OUT) Violations 0 0.0% Additional possible INTENT(OUT) Violations 2044 38.5%

Note that there are no certain INTENT(OUT) violations, but that read accesses to a number of INTENT(OUT) arguments may be reachable before the argument is assigned.

Further Investigations

The large number of intent violations could cause problems if the declarations were used to guide code generation. Two additional fpt commands were developed to assess the risk:

REMOVE INTENT SPECIFICATIONS and ENFORCE INTENT IN AS DECLARED

The command REMOVE INTENT SPECIFICATIONS strips every non-mandatory INTENT specification from the code. The only INTENT specifications which remain are those for the arguments of pure and elemental sub-programs. In WRFV3.6.1 over 45,000 specifications are removed. Test runs of WRF showed no changes, the results were consistent to a single bit. We conclude that the compilers used, gfortran and ifort, do not use the INTENT specifications in code generation.

The command ENFORCE INTENT IN AS DECLARED modifies the code to prevent any possible violations. INTENT(IN) arguments are copied to temporaries if there is any possibility that they could be written to. Again, test runs of WRF showed no changes. The WRF code does not depend on the side effects of intent violations.

Copyright ©1995 to 2024 Software Validation Ltd. All rights reserved.