-
Notifications
You must be signed in to change notification settings - Fork 14.3k
[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
[flang][OpenMP] Clarify confusing error message #144707
Conversation
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
@llvm/pr-subscribers-flang-semantics @llvm/pr-subscribers-flang-openmp Author: Krzysztof Parzyszek (kparzysz) ChangesThe 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:
Fixes #144599 Full diff: https://github.com/llvm/llvm-project/pull/144707.diff 4 Files Affected:
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
|
There was a problem hiding this 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!
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:
Fixes #144599