Skip to main content
GitHub

SAD02-F. Minimize imported module entities using the ONLY clause

Program units should use the only clause in the use statement to explicitly specify which entities are imported from a module.

By default, use imports all public entities from the module, which can obscure the origin of identifiers and increase the risk of name conflicts, particularly in large codebases.

Identifiers in mutually visible scopes must be unique to prevent confusion regarding which object or function is being referenced. In Fortran, if a scoping unit uses multiple modules without the only clause, and those modules contain entities with identical names, a local identifier conflict occurs. Consistently using the only option ensures that the source of each accessed entity is explicitly documented, reducing maintenance costs and improving code reliability.

Omitting only clause also creates a maintenance vulnerability: if a module later adds new public entities, they are automatically imported. With implicit typing and overlapping local variables, this can silently shadow existing identifiers, causing subtle and hard-to-diagnose logic errors.

Noncompliant Code Example

In this noncompliant example, the program imports two modules, Atmospheric_Models and Physical_Constants , without the only clause. It is not immediately clear to a reader which module provides sea_level_pressure , and if both modules were to define a public entity with that name, a compilation error would occur.

Non-compliant code
module Atmospheric_Models
  use iso_fortran_env, only: real64
  implicit none
  real(real64), parameter :: sea_level_pressure = 1013.25_real64
contains
  pure real(real64) function scale_height(temp)
    real(real64), intent(in) :: temp
    scale_height = (287.05_real64 * temp) / 9.89665_real64
  end function
end module Atmospheric_Models

program sensor_data__check
  use Atmospheric_Models    ! Noncompliant: Import all public entities
  use iso_fortran_env       ! Noncompliant
  implicit none

  real(real64) :: ambient_temp = 288.15_real64

  print *, 'Scale Height: ', scale_height(ambient_temp)
  print *, 'Reference Pressure: ', sea_level_pressure
end program

Compliant Solution

In this compliant solution, the only clause is used to explicitly list the required entities. This restricts the visibility of module members to only those mentioned, preventing namespace pollution.

Compliant code
program sensor_data__check
  ! Compliant: Explicitly state what is needed
  use Atmospheric_Models, only: scale_height, sea_level_pressure
  use iso_fortran_env, only: real64
  implicit none

  real(real64) :: ambient_temp = 288.15_real64

  print *, 'Scale Height: ', scale_height(ambient_temp)
  print *, 'Reference Pressure: ', sea_level_pressure
end program

Compliant Solution (Renaming)

If a name conflict arises, even when using only , or if a module entity's name is not descriptive enough, the renaming facility ( local_name => use_name ) should be used to maintain unique identifiers in the local scope.

Compliant code
program sensor_data__check
  ! Compliant: Resolving a potential conflict via renaming
  use Atmospheric_Models, only: scale_height, model_p_ref => sea_level_pressure
  use iso_fortran_env, only: real64
  implicit none

  real(real64) :: ambient_temp = 288.15_real64

  print *, 'Scale Height: ', scale_height(ambient_temp)
  print *, 'Reference Pressure: ', model_p_ref
end program

Risk Assessment

Importing entire modules pollutes the local namespace, making code difficult to audit for security and correctness. Namespace collisions can lead to the wrong function being invoked or variables being shadowed, potentially resulting in unintended information disclosure or abnormal program termination.

RecommendationSeverityLikelihoodDetectableRepairablePriorityLevel
SAD02-FHighUnlikelyYesYesP9L2

Attachments: