ARR02-F. Declare array dummy arguments as assumed-shape
Array dummy arguments should be declared as assumed-shape arrays to let the compiler automatically infer dimensions and perform rank compatibility checks.
Legacy approaches such as explicit-shape and assumed-size arrays mimic C behavior by requiring programmers to manually pass and manage the sizes of array dimensions. This is error-prone, as mismatches between actual and dummy shapes are not checked by the compiler, potentially causing runtime errors, memory corruption, or silent logic errors.
Assumed-shape arrays mitigate these risks by inheriting the shape and size directly from the effective argument, enabling:
- Automatic dimension inference using intrinsic functions like
size()andshape(). - Compile-time rank checking to verify that the dummy array matches the actual argument.
- Safe handling of slices or strided accesses without creating temporary contiguous copies.
Beware that any procedure utilizing assumed-shape arrays must have an explicit interface at the point of call (e.g., by being encapsulated in a module or utilizing an interface block).
Noncompliant Code Example
In this noncompliant example, a subroutine is designed to calculate the average value of a vector. The array is passed as an explicit-shape array, requiring the dimension n to be passed manually. In the call to calculate_average() , the programmer mistakenly passes a constant 5 that is smaller than the actual array size 10. While this specific instance might only result in a partial calculation, a similar error passing a larger value (e.g., passing 100 for a 10-element array) would lead to an out-of-bounds read and undefined behavior.
program test_average
implicit none
real :: data_points(10) = [1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0]
real :: avg
! Noncompliant: Array size is passed manually, passing only 5 elements out of 10.
call calculate_average(data_points, 5, avg)
print *, "Average: ", avg
contains
subroutine calculate_average(v, n, result)
integer, intent(in) :: n
! Noncompliant: Explicit-shape array declared in terms of the dummy argument n
real, intent(in) :: v(n)
real, intent(out) :: result
result = sum(v) / real(n)
end subroutine calculate_average
end program test_average
Compliant Solution
In this compliant solution, the vector is declared as an assumed-shape array using a colon (:) . The dimension argument is removed, and the subroutine uses the intrinsic function size() to determine the bounds. The error is prevented because the subroutine automatically inherits the correct dimensions from the calling program, and the compiler enforces rank compatibility.
program test_average
implicit none
real :: data_points(10) = [1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0]
real :: avg
! Compliant: The array carries its own shape information.
call calculate_average(data_points, avg)
print *, "Average: ", avg
contains
subroutine calculate_average(v, result)
! Compliant: Assumed-shape inherits dimensions automatically, using the declaration syntax (:).
real, intent(in) :: v(:)
real, intent(out) :: result
result = sum(v) / real(size(v))
end subroutine calculate_average
end program test_average
Risk Assessment
Using explicit-shape or assumed-size arrays increases the programmer's cognitive load and prevents the compiler from automating safety checks. This leads to high-risk memory interpretation errors and buffer overflows that are difficult to detect through static analysis.
| Recommendation | Severity | Likelihood | Detectable | Repairable | Priority | Level |
| ARR02-F | Low | Probable | Yes | No | P4 | L3 |
Attachments:
button_arrow_left.png (image/png)
button_arrow_up.png (image/png)
button_arrow_right.png (image/png)


