Skip to main content
GitHub

PRC03-F. Declare the intent for all dummy arguments

All dummy arguments in a procedure (function or subroutine) shall have their intent attribute explicitly declared.

The intent attribute specifies how a dummy argument is used within a procedure:

  • intent(in) : The argument is used only to pass data into the procedure and shall not be modified.
  • intent(out) : The argument is used to return data from the procedure; its initial value is undefined on entry.
  • intent(inout) : The argument is used to pass data in, modify it, and return the modified value.

If intent is not specified, a dummy argument is implicitly treated as modifiable. This weakens the compiler's ability to detect programming errors and prevents the enforcement of read-only semantics. Explicitly declaring intent improves correctness checking, documents procedure interfaces, and enables reliable data-flow analysis.

Noncompliant Code Example

In this noncompliant example, the intent of the dummy arguments is not declared. As a result, the input argument n is unintentionally modified. Because the compiler cannot determine whether the actual argument is definable, passing a constant or expression could lead to runtime errors or undefined behavior.

Non-compliant code
program test_square
  implicit none
  integer :: val = 5
  integer :: res

  call square(val, res)
  print *, "Val (expected 5): ", val

contains
  subroutine square(n, result)
    integer :: n ! Noncompliant: Implicit intent
    integer :: result ! Noncompliant: Implicit intent

    n = n * n
    result = n
  end subroutine square
end program test_square

Compliant Solution

By explicitly declaring intent , the compiler can enforce correct usage. Attempting to modify an intent(in) argument will result in a compile-time error, preventing accidental side effects.

Compliant code
program test_square
  implicit none
  integer :: val = 5
  integer :: res

  call square(val, res)
  print *, "Val (expected 5): ", val

contains
  subroutine square(n, result)
    integer, intent(in)  :: n
    integer, intent(out) :: result

    result = n * n
  end subroutine square
end program test_square

Noncompliant Code Example

Without explicit intent , the compiler must assume that all arguments may be modified. This obscures the procedure's contract and makes it unsafe to pass constants or expressions. If the procedure modifies such arguments, memory corruption or runtime failures may occur.

Non-compliant code
subroutine add_arrays(n, vec_a, vec_b)
  implicit none
  integer :: n
  real    :: vec_a(n) ! Noncompliant: Implicit INOUT
  real    :: vec_b(n) ! Noncompliant: Implicit INOUT

  vec_b = vec_a + 1.0
end subroutine add_arrays

Compliant Solution

Explicit intent declarations clearly define which arguments are read-only and which are outputs. This prevents accidental modification of inputs and allows the compiler to enforce interface correctness.

Compliant code
subroutine add_arrays(n, vec_a, vec_b)
  implicit none
  integer, intent(in)  :: n
  real,    intent(in)  :: vec_a(n)
  real,    intent(out) :: vec_b(n)

  vec_b = vec_a + 1.0
end subroutine add_arrays

Risk Assessment

Failing to declare intent obscures the intended data flow of procedures and allows accidental modification of input arguments. This can lead to subtle logic errors, unsafe argument passing (e.g., constants or expressions), and undefined behavior that is difficult to detect through testing alone.

RecommendationSeverityLikelihoodDetectableRepairablePriorityLevel
PRC03-FHighUnlikelyYesYesP9L2

Bibliography

[ Fortran 2023 Interpretation Document ]Section 8.5.10

Attachments: