Skip to content

Commit b63bc81

Browse files
committed
PWR083: Add entry and code examples
1 parent 2a3f496 commit b63bc81

File tree

5 files changed

+210
-0
lines changed

5 files changed

+210
-0
lines changed

Checks/PWR083/README.md

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

Checks/PWR083/example.f90

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

Checks/PWR083/simulation.f90

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
! PWR083: Match dummy and actual argument types in procedure calls
2+
3+
pure subroutine updateSimulationTime(numberSteps, prevTime, newTime)
4+
use iso_fortran_env, only: real32
5+
implicit none
6+
7+
integer, intent(in) :: numberSteps
8+
real(kind=real32), intent(in) :: prevTime
9+
real(kind=real32), intent(out) :: newTime
10+
11+
! Each step is 0.1 seconds
12+
newTime = prevTime + numberSteps * 0.1_real32
13+
end subroutine updateSimulationTime

Checks/PWR083/solution.f90

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
! PWR083: Match dummy and actual argument types in procedure calls
2+
3+
! NOT-PWR068: External procedure used to demonstrate how compilers can't catch
4+
! the type 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) :: 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 correct_call

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,7 @@ designed to demonstrate:
9797
| [PWR079](Checks/PWR079/) | Avoid undefined behavior due to uninitialized variables | 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) | ✓ | ✓ | ✓ | |
9898
| [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) | ✓ | ✓ | ✓ | |
9999
| [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) | | | ✓ | | |
100+
| [PWR083](Checks/PWR083/) | Match dummy and actual argument types 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) | | | ✓ | | |
100101
| [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) | | ✓ | ✓ | ✓ | |
101102
| [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) | | ✓ | ✓ | ✓ | |
102103
| [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)