Skip to content

Commit 45b87dd

Browse files
committed
PWR088: Add entry and code examples
1 parent e9bbbb1 commit 45b87dd

6 files changed

Lines changed: 202 additions & 0 deletions

File tree

Checks/PWR088/README.md

Lines changed: 148 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,148 @@
1+
# PWR088: Add missing arguments to procedure calls
2+
3+
### Issue
4+
5+
Calling a procedure while omitting one or more required arguments (i.e., dummy
6+
arguments that are not `optional`) can lead to compilation failures or, if not
7+
caught, undefined behavior at runtime.
8+
9+
### Actions
10+
11+
Ensure all arguments required by the procedure (i.e., not marked `optional`)
12+
are supplied at the call site. If a call with fewer arguments is actually
13+
needed, adapt the procedure accordingly; for example, by converting arguments
14+
to `optional` and handling the missing scenarios in the implementation.
15+
16+
### Relevance
17+
18+
When calling a Fortran procedure, the caller is expected to supply all
19+
mandatory arguments. If an explicit procedure interface is available at the
20+
call site, compilers can typically detect and report a mismatch in the number
21+
of supplied arguments during compilation.
22+
23+
However, Fortran also allows calling procedures without information about the
24+
expected arguments; in such cases, an _implicit interface_ is used. The caller
25+
effectively passes a list of memory addresses, which the called procedure
26+
interprets according to its dummy argument declarations. If the actual
27+
arguments are fewer than the dummy arguments, the result is undefined behavior
28+
and may manifest as incorrect results, "random" behavior, or even crashes.
29+
30+
> [!TIP]
31+
> To enhance code safety and reliability, ensure procedures provide
32+
> explicit interfaces to their callers. Check the [PWR068 entry](../PWR068/)
33+
> for more details!
34+
35+
### Code examples
36+
37+
The following example advances a simulation time by `numberSteps * dt`. The
38+
procedure expects three arguments, but the caller accidentally passes only two:
39+
40+
```fortran {7,11} showLineNumbers
41+
! simulation.f90
42+
pure subroutine updateSimulationTime(numberSteps, dt, prevTime, newTime)
43+
use iso_fortran_env, only: real32
44+
implicit none
45+
46+
integer, intent(in) :: numberSteps
47+
real(kind=real32), intent(in) :: dt
48+
real(kind=real32), intent(in) :: prevTime
49+
real(kind=real32), intent(out) :: newTime
50+
51+
newTime = prevTime + numberSteps * dt
52+
end subroutine updateSimulationTime
53+
```
54+
55+
```fortran {6,13} showLineNumbers
56+
! example.f90
57+
program call_with_missing_arguments
58+
use iso_fortran_env, only: real32
59+
implicit none
60+
61+
external :: updateSimulationTime
62+
integer :: numberSteps
63+
real(kind=real32) :: prevTime, newTime
64+
65+
numberSteps = 10
66+
prevTime = 0.0
67+
68+
call updateSimulationTime(numberSteps, prevTime, newTime)
69+
print *, "New time = ", newTime
70+
end program call_with_missing_arguments
71+
```
72+
73+
Because `updateSimulationTime()` is an `external` procedure, the call uses an
74+
implicit interface. Compilers will typically allow this program to compile
75+
despite the argument count mismatch, producing an incorrect result at runtime:
76+
77+
```txt
78+
$ gfortran --version
79+
GNU Fortran (Ubuntu 13.3.0-6ubuntu2~24.04) 13.3.0
80+
$ gfortran simulation.f90 example.f90
81+
$ ./a.out
82+
New time = -2.23126931E+24
83+
```
84+
85+
A simple solution is to pass the missing `dt` in the procedure call:
86+
87+
```fortran {8,11,14} showLineNumbers
88+
! solution.f90
89+
program correct_call
90+
use iso_fortran_env, only: real32
91+
implicit none
92+
93+
external :: updateSimulationTime
94+
integer :: numberSteps
95+
real(kind=real32) :: dt, prevTime, newTime
96+
97+
numberSteps = 10
98+
dt = 0.1
99+
prevTime = 0.0
100+
101+
call updateSimulationTime(numberSteps, dt, prevTime, newTime)
102+
print *, "New time = ", newTime
103+
end program correct_call
104+
```
105+
106+
Now, the program will produce the correct result:
107+
108+
```txt
109+
$ gfortran simulation.f90 solution.f90
110+
$ ./a.out
111+
New time = 1.00000000
112+
```
113+
114+
Ultimately, it is recommended to encapsulate all procedures within modules so
115+
that callers have explicit interfaces. This enables the compiler to verify the
116+
provided arguments against the actual dummy arguments, preventing
117+
difficult-to-diagnose runtime bugs.
118+
119+
> [!TIP]
120+
> Check the [PWR068 entry](../PWR068/) for more details on implicit and
121+
> explicit interfaces!
122+
123+
### Related resources
124+
125+
- [PWR088
126+
examples](https://github.com/codee-com/open-catalog/tree/main/Checks/PWR088/)
127+
128+
### References
129+
130+
- ["Implicit
131+
Interfaces"](https://people.cs.vt.edu/~asandu/Courses/MTU/CS2911/fortran_notes/node44.html),
132+
Adrian Sandu. [last checked February 2026]
133+
134+
- ["More on Implicit
135+
Interfaces"](https://people.cs.vt.edu/~asandu/Courses/MTU/CS2911/fortran_notes/node181.html),
136+
Adrian Sandu. [last checked February 2026]
137+
138+
- ["Explicit
139+
Interfaces"](https://people.cs.vt.edu/~asandu/Courses/MTU/CS2911/fortran_notes/node182.html),
140+
Adrian Sandu. [last checked February 2026]
141+
142+
- ["Doctor Fortran Gets
143+
Explicit!"](https://web.archive.org/web/20130803094211/http://software.intel.com/en-us/forums/topic/275071),
144+
Steve Lionel. [last checked February 2026]
145+
146+
- ["Doctor Fortran Gets Explicit - Again!
147+
"](https://web.archive.org/web/20130113070703/http://software.intel.com/en-us/blogs/2012/01/05/doctor-fortran-gets-explicit-again),
148+
Steve Lionel. [last checked February 2026]

Checks/PWR088/benchmark/README.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
Omitting required arguments leads to undefined behavior. Thus, performance
2+
benchmarking isn't meaningful since there isn't a correct baseline to measure
3+
against.

Checks/PWR088/example.f90

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
! PWR088: Add missing arguments to procedure calls
2+
3+
! NOT-PWR068: External procedure used to demonstrate how compilers can't catch
4+
! the argument count mismatch
5+
program call_with_missing_arguments
6+
use iso_fortran_env, only: real32
7+
implicit none
8+
9+
external :: updateSimulationTime
10+
integer :: numberSteps
11+
real(kind=real32) :: prevTime, newTime
12+
13+
numberSteps = 10
14+
prevTime = 0.0
15+
16+
call updateSimulationTime(numberSteps, prevTime, newTime)
17+
print *, "New time = ", newTime
18+
end program call_with_missing_arguments

Checks/PWR088/simulation.f90

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
! PWR088: Add missing arguments to procedure calls
2+
3+
pure subroutine updateSimulationTime(numberSteps, dt, prevTime, newTime)
4+
use iso_fortran_env, only: real32
5+
implicit none
6+
7+
integer, intent(in) :: numberSteps
8+
real(kind=real32), intent(in) :: dt
9+
real(kind=real32), intent(in) :: prevTime
10+
real(kind=real32), intent(out) :: newTime
11+
12+
newTime = prevTime + numberSteps * dt
13+
end subroutine updateSimulationTime

Checks/PWR088/solution.f90

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
! PWR088: Add missing arguments to procedure calls
2+
3+
! NOT-PWR068: External procedure used to demonstrate how compilers can't catch
4+
! the argument count mismatch
5+
program correct_call
6+
use iso_fortran_env, only: real32
7+
implicit none
8+
9+
external :: updateSimulationTime
10+
integer :: numberSteps
11+
real(kind=real32) :: dt, prevTime, newTime
12+
13+
numberSteps = 10
14+
dt = 0.1
15+
prevTime = 0.0
16+
17+
call updateSimulationTime(numberSteps, dt, prevTime, newTime)
18+
print *, "New time = ", newTime
19+
end program correct_call

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,7 @@ designed to demonstrate:
9696
| [PWR080](Checks/PWR080/) | Conditionally initialized variables can lead to undefined behavior | correctness, portability, security | [CWE-758](https://cwe.mitre.org/data/definitions/758.html), [CWE-908](https://cwe.mitre.org/data/definitions/908.html), [CWE-909](https://cwe.mitre.org/data/definitions/909.html) | [6.13](https://j3-fortran.org/doc/year/23/23-241.pdf), [6.22](https://j3-fortran.org/doc/year/23/23-241.pdf), [6.56](https://j3-fortran.org/doc/year/23/23-241.pdf) | [EXP33-C](https://wiki.sei.cmu.edu/confluence/display/c/EXP33-C.+Do+not+read+uninitialized+memory), [EXP34-C](https://wiki.sei.cmu.edu/confluence/display/c/EXP34-C.+Do+not+dereference+null+pointers), [MSC15-C](https://wiki.sei.cmu.edu/confluence/display/c/MSC15-C.+Do+not+depend+on+undefined+behavior) | [EXP53-CPP](https://wiki.sei.cmu.edu/confluence/spaces/cplusplus/pages/88046609/EXP53-CPP.+Do+not+read+uninitialized+memory) | ✓ | ✓ | ✓ | |
9797
| [PWR081](Checks/PWR081/) | Uninitialized output arguments can lead to undefined behavior | correctness, portability, security | [CWE-758](https://cwe.mitre.org/data/definitions/758.html), [CWE-908](https://cwe.mitre.org/data/definitions/908.html), [CWE-909](https://cwe.mitre.org/data/definitions/909.html) | [6.13](https://j3-fortran.org/doc/year/23/23-241.pdf), [6.22](https://j3-fortran.org/doc/year/23/23-241.pdf), [6.56](https://j3-fortran.org/doc/year/23/23-241.pdf) | [EXP33-C](https://wiki.sei.cmu.edu/confluence/display/c/EXP33-C.+Do+not+read+uninitialized+memory), [EXP34-C](https://wiki.sei.cmu.edu/confluence/display/c/EXP34-C.+Do+not+dereference+null+pointers), [MSC15-C](https://wiki.sei.cmu.edu/confluence/display/c/MSC15-C.+Do+not+depend+on+undefined+behavior) | | | ✓ | | |
9898
| [PWR083](Checks/PWR083/) | Match the types of dummy and actual arguments in procedure calls | correctness, security | [CWE-628](https://cwe.mitre.org/data/definitions/628.html) | [6.11](https://j3-fortran.org/doc/year/23/23-241.pdf), [6.32](https://j3-fortran.org/doc/year/23/23-241.pdf), [6.53](https://j3-fortran.org/doc/year/23/23-241.pdf) | [EXP37-C](https://wiki.sei.cmu.edu/confluence/display/c/EXP37-C.+Call+functions+with+the+correct+number+and+type+of+arguments) | | | ✓ | | |
99+
| [PWR088](Checks/PWR088/) | Add missing arguments to procedure calls | correctness, security | [CWE-628](https://cwe.mitre.org/data/definitions/628.html) | [6.32](https://j3-fortran.org/doc/year/23/23-241.pdf) | [EXP37-C](https://wiki.sei.cmu.edu/confluence/display/c/EXP37-C.+Call+functions+with+the+correct+number+and+type+of+arguments) | | | ✓ | | |
99100
| [PWD002](Checks/PWD002/) | Unprotected multithreading reduction operation | correctness, security | [CWE-366](https://cwe.mitre.org/data/definitions/366.html), [CWE-820](https://cwe.mitre.org/data/definitions/820.html) | [6.61](https://j3-fortran.org/doc/year/23/23-241.pdf) | [CON07-C](https://wiki.sei.cmu.edu/confluence/display/c/CON07-C.+Ensure+that+compound+operations+on+shared+variables+are+atomic), [CON43-C](https://wiki.sei.cmu.edu/confluence/display/c/CON43-C.+Do+not+allow+data+races+in+multithreaded+code) | | ✓ | ✓ | ✓ | |
100101
| [PWD003](Checks/PWD003/) | Missing array range in data copy to the GPU | correctness, security | [CWE-131](https://cwe.mitre.org/data/definitions/131.html), [CWE-758](https://cwe.mitre.org/data/definitions/758.html) | [6.56](https://j3-fortran.org/doc/year/23/23-241.pdf) | [MSC15-C](https://wiki.sei.cmu.edu/confluence/display/c/MSC15-C.+Do+not+depend+on+undefined+behavior) | | ✓ | ✓ | ✓ | |
101102
| [PWD004](Checks/PWD004/) | Out-of-memory-bounds array access | correctness, security | [CWE-125](https://cwe.mitre.org/data/definitions/125.html), [CWE-787](https://cwe.mitre.org/data/definitions/787.html) | [6.8](https://j3-fortran.org/doc/year/23/23-241.pdf), [6.9](https://j3-fortran.org/doc/year/23/23-241.pdf), [6.10](https://j3-fortran.org/doc/year/23/23-241.pdf) | [ARR30-C](https://wiki.sei.cmu.edu/confluence/display/c/ARR30-C.+Do+not+form+or+use+out-of-bounds+pointers+or+array+subscripts) | | ✓ | ✓ | ✓ | |

0 commit comments

Comments
 (0)