Skip to content

[flang][OpenMP] Clarify confusing error message #144707

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jun 18, 2025

Conversation

kparzysz
Copy link
Contributor

@kparzysz kparzysz commented Jun 18, 2025

The message "The atomic variable x should occur exactly once among the arguments of the top-level [...] operator" was intended to convey that (1) an atomic variable should be an argument, and (2) it should be exactly one of the arguments. However, the wording turned out to be sowing confusion instead.

Rework the corresponding check, and emit an individual error message for each problematic situation:

  • "atomic variable cannot be a proper subexpression of an argument",
  • "atomic variable should appear as an argument",
  • "atomic variable should be exactly one of the arguments".

Fixes #144599

The message "The atomic variable x should occur exactly once among the
arguments of the top-level [...] operator" was intended to convey that
(1) an atomic variable should be an argument, and (2) it should be
exactly one of the arguments. However, the wording turns out to be sowing
confusion instead.

Rework the corresponding check, and emit an individual error message
for each problematic situation:
- "atomic variable cannot be a proper subexpression of an argument",
- "atomic variable should appear as an argument",
- "atomic variable should be exactly one of the arguments".

Fixes llvm#144599
@kparzysz kparzysz requested review from tblah and eugeneepshteyn June 18, 2025 14:02
@llvmbot llvmbot added flang Flang issues not falling into any other category flang:openmp flang:semantics labels Jun 18, 2025
@llvmbot
Copy link
Member

llvmbot commented Jun 18, 2025

@llvm/pr-subscribers-flang-semantics

@llvm/pr-subscribers-flang-openmp

Author: Krzysztof Parzyszek (kparzysz)

Changes

The message "The atomic variable x should occur exactly once among the arguments of the top-level [...] operator" was intended to convey that (1) an atomic variable should be an argument, and (2) it should be exactly one of the arguments. However, the wording turned out to be sowing confusion instead.

Rework the corresponding check, and emit an individual error message for each problematic situation:

  • "atomic variable cannot be a proper subexpression of an argument",
  • "atomic variable should appear as an argument",
  • "atomic variable should be exactly one of the arguments".

Fixes #144599


Full diff: https://github.com/llvm/llvm-project/pull/144707.diff

4 Files Affected:

  • (modified) flang/lib/Semantics/check-omp-structure.cpp (+38-19)
  • (modified) flang/test/Semantics/OpenMP/atomic-update-only.f90 (+2-1)
  • (modified) flang/test/Semantics/OpenMP/atomic03.f90 (+16-16)
  • (modified) flang/test/Semantics/OpenMP/atomic04.f90 (+32-28)
diff --git a/flang/lib/Semantics/check-omp-structure.cpp b/flang/lib/Semantics/check-omp-structure.cpp
index 83f4d1edf3c4f..36d4bcb5d99fa 100644
--- a/flang/lib/Semantics/check-omp-structure.cpp
+++ b/flang/lib/Semantics/check-omp-structure.cpp
@@ -3510,37 +3510,56 @@ void OmpStructureChecker::CheckAtomicUpdateAssignment(
         operation::ToString(top.first));
     return;
   }
-  // Check if `atom` occurs exactly once in the argument list.
+  // Check how many times `atom` occurs as an argument, if it's a subexpression
+  // of an argument, and collect the non-atom arguments.
   std::vector<SomeExpr> nonAtom;
-  auto unique{[&]() { // -> iterator
-    auto found{top.second.end()};
-    for (auto i{top.second.begin()}, e{top.second.end()}; i != e; ++i) {
-      if (IsSameOrConvertOf(*i, atom)) {
-        if (found != top.second.end()) {
-          return top.second.end();
-        }
-        found = i;
+  MaybeExpr subExpr;
+  auto atomCount{[&]() {
+    int count{0};
+    for (const SomeExpr &arg : top.second) {
+      if (IsSameOrConvertOf(arg, atom)) {
+        ++count;
       } else {
-        nonAtom.push_back(*i);
+        if (!subExpr && IsSubexpressionOf(atom, arg)) {
+          subExpr = arg;
+        }
+        nonAtom.push_back(arg);
       }
     }
-    return found;
+    return count;
   }()};
 
-  if (unique == top.second.end()) {
-    if (top.first == operation::Operator::Identity) {
-      // This is "x = y".
+  bool hasError{false};
+  if (subExpr) {
+    context_.Say(rsrc,
+        "The atomic variable %s cannot be a proper subexpression of an argument (here: %s) in the update operation"_err_en_US,
+        atom.AsFortran(), subExpr->AsFortran());
+    hasError = true;
+  }
+  if (top.first == operation::Operator::Identity) {
+    // This is "x = y".
+    assert((atomCount == 0 || atomCount == 1) && "Unexpected count");
+    if (atomCount == 0) {
       context_.Say(rsrc,
           "The atomic variable %s should appear as an argument in the update operation"_err_en_US,
           atom.AsFortran());
-    } else {
-      assert(top.first != operation::Operator::Identity &&
-          "Handle this separately");
+      hasError = true;
+    }
+  } else {
+    if (atomCount == 0) {
+      context_.Say(rsrc,
+          "The atomic variable %s should appear as an argument of the top-level %s operator"_err_en_US,
+          atom.AsFortran(), operation::ToString(top.first));
+      hasError = true;
+    } else if (atomCount > 1) {
       context_.Say(rsrc,
-          "The atomic variable %s should occur exactly once among the arguments of the top-level %s operator"_err_en_US,
+          "The atomic variable %s should be exactly one of the arguments of the top-level %s operator"_err_en_US,
           atom.AsFortran(), operation::ToString(top.first));
+      hasError = true;
     }
-  } else {
+  }
+
+  if (!hasError) {
     CheckStorageOverlap(atom, nonAtom, source);
   }
 }
diff --git a/flang/test/Semantics/OpenMP/atomic-update-only.f90 b/flang/test/Semantics/OpenMP/atomic-update-only.f90
index 28d0e264359cb..3c027924a1423 100644
--- a/flang/test/Semantics/OpenMP/atomic-update-only.f90
+++ b/flang/test/Semantics/OpenMP/atomic-update-only.f90
@@ -30,7 +30,8 @@ subroutine f03
   integer :: x, y
 
   !$omp atomic update
-  !ERROR: The atomic variable x should occur exactly once among the arguments of the top-level + operator
+  !ERROR: The atomic variable x cannot be a proper subexpression of an argument (here: (x+y)) in the update operation
+  !ERROR: The atomic variable x should appear as an argument of the top-level + operator
   x = (x + y) + 1
 end
 
diff --git a/flang/test/Semantics/OpenMP/atomic03.f90 b/flang/test/Semantics/OpenMP/atomic03.f90
index b3a3c0d5e7a14..691a483e6e801 100644
--- a/flang/test/Semantics/OpenMP/atomic03.f90
+++ b/flang/test/Semantics/OpenMP/atomic03.f90
@@ -25,19 +25,19 @@ program OmpAtomic
    y = MIN(y, 8)
 
 !$omp atomic
-   !ERROR: The atomic variable z should occur exactly once among the arguments of the top-level AND operator
+   !ERROR: The atomic variable z should appear as an argument of the top-level AND operator
    z = IAND(y, 4)
 !$omp atomic
-   !ERROR: The atomic variable z should occur exactly once among the arguments of the top-level OR operator
+   !ERROR: The atomic variable z should appear as an argument of the top-level OR operator
    z = IOR(y, 5)
 !$omp atomic
-   !ERROR: The atomic variable z should occur exactly once among the arguments of the top-level NEQV/EOR operator
+   !ERROR: The atomic variable z should appear as an argument of the top-level NEQV/EOR operator
    z = IEOR(y, 6)
 !$omp atomic
-   !ERROR: The atomic variable z should occur exactly once among the arguments of the top-level MAX operator
+   !ERROR: The atomic variable z should appear as an argument of the top-level MAX operator
    z = MAX(y, 7, b, c)
 !$omp atomic
-   !ERROR: The atomic variable z should occur exactly once among the arguments of the top-level MIN operator
+   !ERROR: The atomic variable z should appear as an argument of the top-level MIN operator
    z = MIN(y, 8, a, d)
 
 !$omp atomic
@@ -58,19 +58,19 @@ program OmpAtomic
    y = MIN(y, 8)
 
 !$omp atomic update
-   !ERROR: The atomic variable z should occur exactly once among the arguments of the top-level AND operator
+   !ERROR: The atomic variable z should appear as an argument of the top-level AND operator
    z = IAND(y, 4)
 !$omp atomic update 
-   !ERROR: The atomic variable z should occur exactly once among the arguments of the top-level OR operator
+   !ERROR: The atomic variable z should appear as an argument of the top-level OR operator
    z = IOR(y, 5)
 !$omp atomic update
-   !ERROR: The atomic variable z should occur exactly once among the arguments of the top-level NEQV/EOR operator
+   !ERROR: The atomic variable z should appear as an argument of the top-level NEQV/EOR operator
    z = IEOR(y, 6)
 !$omp atomic update
-   !ERROR: The atomic variable z should occur exactly once among the arguments of the top-level MAX operator
+   !ERROR: The atomic variable z should appear as an argument of the top-level MAX operator
    z = MAX(y, 7)
 !$omp atomic update
-   !ERROR: The atomic variable z should occur exactly once among the arguments of the top-level MIN operator
+   !ERROR: The atomic variable z should appear as an argument of the top-level MIN operator
    z = MIN(y, 8)
 
 !$omp atomic update
@@ -90,7 +90,7 @@ subroutine conflicting_types()
     type(simple) ::s
     z = 1
     !$omp atomic
-    !ERROR: The atomic variable z should occur exactly once among the arguments of the top-level AND operator
+    !ERROR: The atomic variable z should appear as an argument of the top-level AND operator
     z = IAND(s%z, 4)
 end subroutine
 
@@ -103,22 +103,22 @@ subroutine more_invalid_atomic_update_stmts()
     type(some_type) :: s
  
     !$omp atomic update
-    !ERROR: The atomic variable a should occur exactly once among the arguments of the top-level MIN operator
+    !ERROR: The atomic variable a should be exactly one of the arguments of the top-level MIN operator
         a = min(a, a, b)
      
     !$omp atomic
-    !ERROR: The atomic variable a should occur exactly once among the arguments of the top-level MAX operator
+    !ERROR: The atomic variable a should be exactly one of the arguments of the top-level MAX operator
         a = max(b, a, b, a)
 
     !$omp atomic
         a = min(b, a, b)
 
     !$omp atomic
-    !ERROR: The atomic variable a should occur exactly once among the arguments of the top-level MAX operator
+    !ERROR: The atomic variable a should be exactly one of the arguments of the top-level MAX operator
         a = max(b, a, b, a, b)
     
     !$omp atomic update
-    !ERROR: The atomic variable y should occur exactly once among the arguments of the top-level MIN operator
+    !ERROR: The atomic variable y should appear as an argument of the top-level MIN operator
         y = min(z, x)
      
     !$omp atomic
@@ -126,7 +126,7 @@ subroutine more_invalid_atomic_update_stmts()
 
     !$omp atomic update
     !ERROR: Atomic variable k should be a scalar
-    !ERROR: The atomic variable k should occur exactly once among the arguments of the top-level MAX operator
+    !ERROR: The atomic variable k should appear as an argument of the top-level MAX operator
         k = max(x, y)
 
     !$omp atomic
diff --git a/flang/test/Semantics/OpenMP/atomic04.f90 b/flang/test/Semantics/OpenMP/atomic04.f90
index 0f69befed1414..fb87ca5186612 100644
--- a/flang/test/Semantics/OpenMP/atomic04.f90
+++ b/flang/test/Semantics/OpenMP/atomic04.f90
@@ -17,10 +17,10 @@ program OmpAtomic
 !$omp atomic
    x = 1 + x
 !$omp atomic
-   !ERROR: The atomic variable x should occur exactly once among the arguments of the top-level + operator
+   !ERROR: The atomic variable x should appear as an argument of the top-level + operator
    x = y + 1
 !$omp atomic
-   !ERROR: The atomic variable x should occur exactly once among the arguments of the top-level + operator
+   !ERROR: The atomic variable x should appear as an argument of the top-level + operator
    x = 1 + y
 
 !$omp atomic
@@ -28,10 +28,10 @@ program OmpAtomic
 !$omp atomic
    x = 1 - x
 !$omp atomic
-   !ERROR: The atomic variable x should occur exactly once among the arguments of the top-level - operator
+   !ERROR: The atomic variable x should appear as an argument of the top-level - operator
    x = y - 1
 !$omp atomic
-   !ERROR: The atomic variable x should occur exactly once among the arguments of the top-level - operator
+   !ERROR: The atomic variable x should appear as an argument of the top-level - operator
    x = 1 - y
 
 !$omp atomic
@@ -50,10 +50,10 @@ program OmpAtomic
 !$omp atomic
    x = 1/x
 !$omp atomic
-   !ERROR: The atomic variable x should occur exactly once among the arguments of the top-level / operator
+   !ERROR: The atomic variable x should appear as an argument of the top-level / operator
    x = y/1
 !$omp atomic
-   !ERROR: The atomic variable x should occur exactly once among the arguments of the top-level / operator
+   !ERROR: The atomic variable x should appear as an argument of the top-level / operator
    x = 1/y
 
 !$omp atomic
@@ -61,7 +61,7 @@ program OmpAtomic
 !$omp atomic
    m = n .AND. m
 !$omp atomic 
-   !ERROR: The atomic variable m should occur exactly once among the arguments of the top-level AND operator
+   !ERROR: The atomic variable m should appear as an argument of the top-level AND operator
    m = n .AND. l
 
 !$omp atomic
@@ -69,7 +69,7 @@ program OmpAtomic
 !$omp atomic
    m = n .OR. m
 !$omp atomic 
-   !ERROR: The atomic variable m should occur exactly once among the arguments of the top-level OR operator
+   !ERROR: The atomic variable m should appear as an argument of the top-level OR operator
    m = n .OR. l
 
 !$omp atomic
@@ -77,7 +77,7 @@ program OmpAtomic
 !$omp atomic
    m = n .EQV. m
 !$omp atomic
-   !ERROR: The atomic variable m should occur exactly once among the arguments of the top-level EQV operator
+   !ERROR: The atomic variable m should appear as an argument of the top-level EQV operator
    m = n .EQV. l
 
 !$omp atomic
@@ -85,7 +85,7 @@ program OmpAtomic
 !$omp atomic
    m = n .NEQV. m
 !$omp atomic
-   !ERROR: The atomic variable m should occur exactly once among the arguments of the top-level NEQV/EOR operator
+   !ERROR: The atomic variable m should appear as an argument of the top-level NEQV/EOR operator
    m = n .NEQV. l
 
 !$omp atomic update
@@ -93,10 +93,10 @@ program OmpAtomic
 !$omp atomic update
    x = 1 + x
 !$omp atomic update
-   !ERROR: The atomic variable x should occur exactly once among the arguments of the top-level + operator
+   !ERROR: The atomic variable x should appear as an argument of the top-level + operator
    x = y + 1
 !$omp atomic update
-   !ERROR: The atomic variable x should occur exactly once among the arguments of the top-level + operator
+   !ERROR: The atomic variable x should appear as an argument of the top-level + operator
    x = 1 + y
 
 !$omp atomic update
@@ -104,10 +104,10 @@ program OmpAtomic
 !$omp atomic update
    x = 1 - x
 !$omp atomic update
-   !ERROR: The atomic variable x should occur exactly once among the arguments of the top-level - operator
+   !ERROR: The atomic variable x should appear as an argument of the top-level - operator
    x = y - 1
 !$omp atomic update
-   !ERROR: The atomic variable x should occur exactly once among the arguments of the top-level - operator
+   !ERROR: The atomic variable x should appear as an argument of the top-level - operator
    x = 1 - y
 
 !$omp atomic update
@@ -126,10 +126,10 @@ program OmpAtomic
 !$omp atomic update
    x = 1/x
 !$omp atomic update
-   !ERROR: The atomic variable x should occur exactly once among the arguments of the top-level / operator
+   !ERROR: The atomic variable x should appear as an argument of the top-level / operator
    x = y/1
 !$omp atomic update
-   !ERROR: The atomic variable x should occur exactly once among the arguments of the top-level / operator
+   !ERROR: The atomic variable x should appear as an argument of the top-level / operator
    x = 1/y
 
 !$omp atomic update
@@ -137,7 +137,7 @@ program OmpAtomic
 !$omp atomic update
    m = n .AND. m
 !$omp atomic update
-   !ERROR: The atomic variable m should occur exactly once among the arguments of the top-level AND operator
+   !ERROR: The atomic variable m should appear as an argument of the top-level AND operator
    m = n .AND. l
 
 !$omp atomic update
@@ -145,7 +145,7 @@ program OmpAtomic
 !$omp atomic update
    m = n .OR. m
 !$omp atomic update
-   !ERROR: The atomic variable m should occur exactly once among the arguments of the top-level OR operator
+   !ERROR: The atomic variable m should appear as an argument of the top-level OR operator
    m = n .OR. l
 
 !$omp atomic update
@@ -153,7 +153,7 @@ program OmpAtomic
 !$omp atomic update
    m = n .EQV. m
 !$omp atomic update
-   !ERROR: The atomic variable m should occur exactly once among the arguments of the top-level EQV operator
+   !ERROR: The atomic variable m should appear as an argument of the top-level EQV operator
    m = n .EQV. l
 
 !$omp atomic update
@@ -161,7 +161,7 @@ program OmpAtomic
 !$omp atomic update
    m = n .NEQV. m
 !$omp atomic update
-   !ERROR: The atomic variable m should occur exactly once among the arguments of the top-level NEQV/EOR operator
+   !ERROR: The atomic variable m should appear as an argument of the top-level NEQV/EOR operator
    m = n .NEQV. l
 
 end program OmpAtomic
@@ -184,27 +184,30 @@ subroutine more_invalid_atomic_update_stmts()
         x = 1    
 
     !$omp atomic update
-    !ERROR: Within atomic operation a and a*b access the same storage
+    !ERROR: The atomic variable a cannot be a proper subexpression of an argument (here: a*b) in the update operation
         a = a * b + a
 
     !$omp atomic
-    !ERROR: The atomic variable a should occur exactly once among the arguments of the top-level * operator
+    !ERROR: The atomic variable a cannot be a proper subexpression of an argument (here: (a+9_4)) in the update operation
+    !ERROR: The atomic variable a should appear as an argument of the top-level * operator
         a = b * (a + 9)
 
     !$omp atomic update
-    !ERROR: Within atomic operation a and (a+b) access the same storage
+    !ERROR: The atomic variable a cannot be a proper subexpression of an argument (here: (a+b)) in the update operation
         a = a * (a + b)
 
     !$omp atomic
-    !ERROR: Within atomic operation a and (b+a) access the same storage
+    !ERROR: The atomic variable a cannot be a proper subexpression of an argument (here: (b+a)) in the update operation
         a = (b + a) * a
 
     !$omp atomic
-    !ERROR: The atomic variable a should occur exactly once among the arguments of the top-level + operator
+    !ERROR: The atomic variable a cannot be a proper subexpression of an argument (here: a*b) in the update operation
+    !ERROR: The atomic variable a should appear as an argument of the top-level + operator
         a = a * b + c
 
     !$omp atomic update
-    !ERROR: The atomic variable a should occur exactly once among the arguments of the top-level + operator
+    !ERROR: The atomic variable a cannot be a proper subexpression of an argument (here: a+b) in the update operation
+    !ERROR: The atomic variable a should appear as an argument of the top-level + operator
         a = a + b + c
 
     !$omp atomic
@@ -219,11 +222,12 @@ subroutine more_invalid_atomic_update_stmts()
 
     !$omp atomic update
     !ERROR: No intrinsic or user-defined ASSIGNMENT(=) matches scalar REAL(4) and rank 1 array of REAL(4)
-    !ERROR: The atomic variable x should occur exactly once among the arguments of the top-level / operator
+    !ERROR: The atomic variable x cannot be a proper subexpression of an argument (here: x*y) in the update operation
+    !ERROR: The atomic variable x should appear as an argument of the top-level / operator
         x = x * y / z
 
     !$omp atomic
-    !ERROR: The atomic variable p%m should occur exactly once among the arguments of the top-level + operator
+    !ERROR: The atomic variable p%m should appear as an argument of the top-level + operator
         p%m = x + y
 
     !$omp atomic update

@kparzysz kparzysz requested a review from Stylie777 June 18, 2025 14:08
Copy link
Contributor

@tblah tblah left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM. Thank you for reworking this!

@kparzysz kparzysz merged commit 5d502ae into llvm:main Jun 18, 2025
11 checks passed
@kparzysz kparzysz deleted the users/kparzysz/improve-atomic-message branch June 18, 2025 15:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
flang:openmp flang:semantics flang Flang issues not falling into any other category
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[flang][OpenMP] Wrong or unclear error message for Fujitsu test 0481_0038
4 participants
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy