[flang-commits] [flang] [Flang][OpenMP] Diagnose invalid op sequence in atomic capture (no crash) (PR #162884)
via flang-commits
flang-commits at lists.llvm.org
Fri Oct 10 10:00:03 PDT 2025
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-flang-openmp
Author: Krish Gupta (KrxGu)
<details>
<summary>Changes</summary>
### Problem:
The Flang frontend's semantic analysis can produce invalid operation sequences for OpenMP atomic capture constructs. Specifically, it may generate a WRITE→READ sequence instead of the valid READ→UPDATE or UPDATE→WRITE sequences required by the OpenMP specification. When this invalid sequence reaches the MLIR lowering stage, verification fails with a cryptic error message and the compiler crashes.
Example that triggers the bug:
```fortran
type :: t
integer :: a(10)
end type
type(t) :: x, y
!$omp atomic capture
x%a(i) = y%a(i)
v = y%a(i)
!$omp end atomic capture
```
**Solution:**
Added validation in lowerAtomic() to check the operation sequence for atomic capture constructs before generating FIR/MLIR operations. If an invalid sequence is detected, the compiler now emits a clear diagnostic message:
This prevents the crash and provides actionable feedback to users or downstream bug reporters.
**Changes:**
[Atomic.cpp](vscode-file://vscode-app/Applications/Visual%20Studio%20Code.app/Contents/Resources/app/out/vs/code/electron-browser/workbench/workbench.html): Added validation check using typed enum constants for operation types
[atomic-capture-derived-array-diag.f90](vscode-file://vscode-app/Applications/Visual%20Studio%20Code.app/Contents/Resources/app/out/vs/code/electron-browser/workbench/workbench.html): Negative test case verifying the diagnostic is emitted
[atomic-capture-same-element.f90](vscode-file://vscode-app/Applications/Visual%20Studio%20Code.app/Contents/Resources/app/out/vs/code/electron-browser/workbench/workbench.html): Positive control test ensuring valid atomic capture constructs still work
Both tests pass, confirming the diagnostic is emitted for invalid sequences while valid constructs compile successfully.
<img width="1192" height="142" alt="image" src="https://github.com/user-attachments/assets/391aebaa-f211-4540-982b-39978147cb48" />
<img width="1192" height="142" alt="image" src="https://github.com/user-attachments/assets/def96bc5-8989-45e7-84f0-ee0ec3de63b1" />
**Notes:**
The root cause lies in the semantic analysis phase, which should be addressed in a future PR
This is a defensive fix to prevent crashes until the semantic analysis bug is resolved
The diagnostic message is intentionally generic to cover all invalid sequences, not just derived-type cases
---
Full diff: https://github.com/llvm/llvm-project/pull/162884.diff
3 Files Affected:
- (modified) flang/lib/Lower/OpenMP/Atomic.cpp (+18)
- (added) flang/test/Lower/OpenMP/atomic-capture-derived-array-diag.f90 (+24)
- (added) flang/test/Lower/OpenMP/atomic-capture-same-element.f90 (+21)
``````````diff
diff --git a/flang/lib/Lower/OpenMP/Atomic.cpp b/flang/lib/Lower/OpenMP/Atomic.cpp
index ff82a36951bfa..48016b5c21ab8 100644
--- a/flang/lib/Lower/OpenMP/Atomic.cpp
+++ b/flang/lib/Lower/OpenMP/Atomic.cpp
@@ -19,6 +19,7 @@
#include "flang/Lower/SymbolMap.h"
#include "flang/Optimizer/Builder/FIRBuilder.h"
#include "flang/Optimizer/Builder/Todo.h"
+#include "flang/Optimizer/Dialect/FIRType.h"
#include "flang/Parser/parse-tree.h"
#include "flang/Semantics/semantics.h"
#include "flang/Semantics/type.h"
@@ -459,6 +460,23 @@ void Fortran::lower::omp::lowerAtomic(
} else {
int action0 = analysis.op0.what & analysis.Action;
int action1 = analysis.op1.what & analysis.Action;
+
+ // Check for invalid atomic capture sequence.
+ // Valid sequences: (READ, UPDATE) or (UPDATE, WRITE)
+ if (construct.IsCapture()) {
+ using Action = parser::OpenMPAtomicConstruct::Analysis;
+ const bool validSequence =
+ (action0 == Action::Read && action1 == Action::Update) ||
+ (action0 == Action::Update && action1 == Action::Write);
+
+ if (!validSequence) {
+ mlir::emitError(loc,
+ "OpenMP atomic capture produced an invalid operation "
+ "sequence (expected read+update or update+write)");
+ return;
+ }
+ }
+
mlir::Operation *captureOp = nullptr;
fir::FirOpBuilder::InsertPoint preAt = builder.saveInsertionPoint();
fir::FirOpBuilder::InsertPoint atomicAt, postAt;
diff --git a/flang/test/Lower/OpenMP/atomic-capture-derived-array-diag.f90 b/flang/test/Lower/OpenMP/atomic-capture-derived-array-diag.f90
new file mode 100644
index 0000000000000..d22126c04005d
--- /dev/null
+++ b/flang/test/Lower/OpenMP/atomic-capture-derived-array-diag.f90
@@ -0,0 +1,24 @@
+! Test diagnostic for atomic capture with invalid operation sequence
+! RUN: not %flang_fc1 -emit-fir -fopenmp %s 2>&1 | FileCheck %s
+
+! This test verifies that a clear diagnostic is emitted when atomic capture
+! produces an invalid operation sequence. This can occur with derived-type
+! component array elements where different indices are used.
+
+program test_atomic_capture_invalid_sequence
+ type t1
+ integer :: i(1)
+ end type
+ type(t1) :: t2
+ integer :: j
+
+ t2%i = 0
+ j = 1
+
+ ! CHECK: error: OpenMP atomic capture produced an invalid operation sequence
+ !$omp atomic capture
+ t2%i(j*1) = t2%i(1) + 1
+ t2%i(1) = t2%i(j*1)
+ !$omp end atomic
+
+end program test_atomic_capture_invalid_sequence
diff --git a/flang/test/Lower/OpenMP/atomic-capture-same-element.f90 b/flang/test/Lower/OpenMP/atomic-capture-same-element.f90
new file mode 100644
index 0000000000000..208a2db362369
--- /dev/null
+++ b/flang/test/Lower/OpenMP/atomic-capture-same-element.f90
@@ -0,0 +1,21 @@
+! Test that atomic capture works correctly with same element (positive control)
+! RUN: %flang_fc1 -emit-fir -fopenmp %s -o - | FileCheck %s
+
+! This test verifies that atomic capture with the same array element in both
+! statements works correctly and doesn't trigger the invalid sequence diagnostic.
+
+! CHECK-LABEL: func @_QQmain
+program test_atomic_capture_same_element
+ integer :: a(10)
+ integer :: v
+
+ a = 0
+
+ ! This should work - same element a(1) in both statements
+ ! CHECK: omp.atomic.capture
+ !$omp atomic capture
+ v = a(1)
+ a(1) = a(1) + 1
+ !$omp end atomic
+
+end program test_atomic_capture_same_element
``````````
</details>
https://github.com/llvm/llvm-project/pull/162884
More information about the flang-commits
mailing list