[Flang] Missing error for recursive invocation of NON_RECURSIVE procedures
- Dominant language
- LLVM
- Stars
- 40.5k
- Forks
- 18.7k
- PR merge metrics
- PR metrics pending
Description
## Summary
According to the Fortran 2023 standard, NON_RECURSIVE procedures are prohibited from invoking the procedures themselves. However, when such procedures are involved in defined assignment/operation, Flang seems to overlook this restriction.
* 15.6.2.1 General
> The NON_RECURSIVE prefix-spec shall not appear if any procedure defined by the subprogram directly or indirectly invokes itself or any other procedure defined by the subprogram.
### Reproducer
* test.f90
```fortran
program main
type t
integer :: i
end type
interface assignment(=)
procedure::prc
end interface
type(t):: v1,v2
v1%i = 1
v2 = v1
print *, v2
contains
non_recursive subroutine prc(x,y)
class(t),intent(out)::x
class(t),intent(in)::y
print *,'prc'
x = y ! call prc recursively
end subroutine prc
end program main
```
* commands
```console
$ flang --version
flang version 23.0.0git (https://github.com/llvm/llvm-project.git 349542f7e122b8fda1d60f0b37c8f92ad65635d6)
Target: aarch64-unknown-linux-gnu
Thread model: posix
InstalledDir: /path/to/llvm/build/bin
Build config: +assertions
$ flang test.f90 && ./a.out
prc
prc
prc
:
prc
prc
prc
Segmentation fault (core dumped)
```
In addition, this issue also occurs with the following programs:
```fortran
module mod
type t
integer:: t1v
contains
procedure:: prc
generic:: assignment(=) => prc
end type
contains
non_recursive subroutine prc(x,y)
class(t),intent(out)::x
class(t),intent(in)::y
print *,'prc'
x = y ! call prc recursively
end subroutine prc
end module
program main
use mod
type(t):: v1,v2
v1%t1v = 1
v2 = v1
print *, v2
end program main
```
```fortran
module mod
type t
integer:: t1v
end type
interface operator(.op.)
procedure::prc
end interface
contains
non_recursive function prc(x,y) result(n)
type (t),intent(in)::x
type (t),intent(in)::y
print *,'prc'
n = x.op.y ! call prc recursively
n=0
end function prc
end module
program main
use mod
type(t):: v
v%t1v=1
n= prc(v,v)
print *,v,n
end program main
```
## Non-problematic Conditions
The issue does not occur under the following conditions:
* Using a generic interface for an explicit procedure call instead of defined assignment:
```diff
@@ -2,18 +2,18 @@
type t
integer :: i
end type
- interface assignment(=)
+ interface asn
procedure::prc
end interface
type(t):: v1,v2
v1%i = 1
- v2 = v1
+ call asn(v2,v1)
print *, v2
contains
non_recursive subroutine prc(x,y)
class(t),intent(out)::x
class(t),intent(in)::y
print *,'prc'
- x = y ! call prc recursively
+ call prc(x,y) ! call prc recursively
end subroutine prc
end program main
```
## Other Compilers
* GFortran
```console
$ gfortran --version
GNU Fortran (GCC) 15.2.0
Copyright (C) 2025 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
$ gfortran test.f90 && ./a.out
test.f90:13:3:
13 | non_recursive subroutine prc(x,y)
| 1
Error: Unclassifiable statement at (1)
test.f90:14:27:
14 | class(t),intent(out)::x
| 1
Error: Unexpected data declaration statement in CONTAINS section at (1)
test.f90:15:26:
15 | class(t),intent(in)::y
| 1
Error: Unexpected data declaration statement in CONTAINS section at (1)
test.f90:16:17:
16 | print *,'prc'
| 1
Error: Unexpected WRITE statement in CONTAINS section at (1)
test.f90:17:32:
17 | x = y ! call prc recursively
| 1
Error: Unexpected assignment statement in CONTAINS section at (1)
test.f90:18:5:
18 | end subroutine prc
| 1
Error: Expecting END PROGRAM statement at (1)
test.f90:6:18:
6 | procedure::prc
| 1
Error: Procedure 'prc' in intrinsic assignment operator at (1) is neither function nor subroutine
```
* Intel Fortran
```console
$ ifx --version
ifx (IFX) 2025.3.2 20260112
Copyright (C) 1985-2026 Intel Corporation. All rights reserved.
$ ifx -O0 test.f90 && ./a.out
test.f90(17): error #6437: A subroutine or function is calling itself recursively. [PRC]
x = y ! call prc recursively
----^
compilation aborted for test.f90 (code 1)
```
Contributor guide
Research direction
Start by compiling the reproducer in test.f90 with Flang and compare its behavior with the diagnostic shown from Intel Fortran. Trace Flang's semantic handling of defined assignment and defined operator invocations inside NON_RECURSIVE procedures. Done means the reproducer is rejected with a recursion diagnostic instead of compiling into recursive execution and a segmentation fault.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- fortran
- Domain
- compilers
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 55/100