[flang][OpenMP] Reduction identifier matching an intrinsic name but bound to a user procedure aborts lowering
- Dominant language
- LLVM
- Stars
- 40.5k
- Forks
- 18.7k
- PR merge metrics
- PR metrics pending
Description
### Summary
A `reduction(:)` clause whose reduction identifier is one of the intrinsic reduction names (`max`, `min`, `iand`, `ior`, `ieor`) but resolves to a user procedure (with no `declare reduction`) is accepted by semantics and then aborts lowering with a "not yet implemented" TODO.
### Reproducer
```fortran
program p
integer :: x, i
interface max
procedure mymax
end interface
x = 0
!$omp parallel do reduction(max:x)
do i = 1, 10
x = i
end do
print *, x
contains
integer function mymax(a, b)
integer, intent(in) :: a, b
mymax = merge(a, b, a > b)
end function
end program
```
```
$ flang -fopenmp -c repro.f90
error: loc(...): flang/lib/Lower/Support/ReductionProcessor.cpp: not yet implemented: Lowering unrecognised reduction type
LLVM ERROR: aborting
```
### Other compilers
flang is the only compiler that aborts. On the same program:
| Compiler | Result | Compiler Explorer |
|----------|--------|-------------------|
| flang (trunk) | ICE: `not yet implemented: Lowering unrecognised reduction type` | https://flang.godbolt.org/z/Gxe7fP49x |
| gfortran (trunk) | clean error: `!$OMP DECLARE REDUCTION max not found` | https://gfortran.godbolt.org/z/hqv93GWGv |
| ifx (latest) | accepts, exit 0 | https://fortran.godbolt.org/z/ohfh7d4MK |
| nvfortran | accepts, exit 0 | https://fortran.godbolt.org/z/j5TW54bxh |
| Cray Fortran (CCE 20.0.0) | accepts, exit 0 | (not on Compiler Explorer) |
flang's `-fsyntax-only` accepts the program (semantics); the abort is in lowering, shown on Compiler Explorer via `-emit-hlfir`. So flang neither accepts the program nor emits a diagnostic; it aborts.
### Root cause
Semantics (`CheckReductionOperator::visitDesignator`, `flang/lib/Semantics/check-omp-structure.cpp`) accepts a procedure-designator reduction identifier if its name is one of `{max, min, iand, ior, ieor}`, or if it carries `UserReductionDetails`. It accepts by name.
Lowering (`flang/lib/Lower/Support/ReductionProcessor.cpp`) decides the reduction by the INTRINSIC attribute (`supportedIntrinsicProcReduction`). When the name is shadowed by a user procedure, the symbol is neither `INTRINSIC` nor a user-defined reduction, so lowering falls through to the TODO and aborts.
The gap: semantics accepts by name, lowering checks by attribute.
### Suggested fix
One of:
1. Tighten the semantic check so a procedure-designator reduction identifier that resolves to a non-intrinsic symbol without a `declare reduction` is rejected with a proper diagnostic, rather than accepted and later aborted in lowering.
2. Handle the case in lowering.
This is distinct from the related issues in this area:
- #191927 (open): a `declare reduction` whose identifier is an intrinsic procedure name, plus an accessibility statement, emits an incorrect semantic error. That case has a `declare reduction` and fails in semantics; this one has no `declare reduction` and aborts in lowering.
- #205893 (fixed): a user `declare reduction` shadowing an intrinsic name, where a visible declaration takes precedence.
- #68654 (fixed): a reduction identifier that renames the actual intrinsic (`use m, ren => max`), which now lowers correctly.
Here there is no `declare reduction`, and the name resolves to an ordinary user procedure. Surfaced during review of #207493 / #207494.
Contributor guide
Assessment
This issue has not been assessed yet.