Skip to content

Commit 5d502ae

Browse files
authored
[flang][OpenMP] Clarify confusing error message (#144707)
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
1 parent 9da9d32 commit 5d502ae

File tree

4 files changed

+88
-64
lines changed

4 files changed

+88
-64
lines changed

flang/lib/Semantics/check-omp-structure.cpp

Lines changed: 38 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -3510,37 +3510,56 @@ void OmpStructureChecker::CheckAtomicUpdateAssignment(
35103510
operation::ToString(top.first));
35113511
return;
35123512
}
3513-
// Check if `atom` occurs exactly once in the argument list.
3513+
// Check how many times `atom` occurs as an argument, if it's a subexpression
3514+
// of an argument, and collect the non-atom arguments.
35143515
std::vector<SomeExpr> nonAtom;
3515-
auto unique{[&]() { // -> iterator
3516-
auto found{top.second.end()};
3517-
for (auto i{top.second.begin()}, e{top.second.end()}; i != e; ++i) {
3518-
if (IsSameOrConvertOf(*i, atom)) {
3519-
if (found != top.second.end()) {
3520-
return top.second.end();
3521-
}
3522-
found = i;
3516+
MaybeExpr subExpr;
3517+
auto atomCount{[&]() {
3518+
int count{0};
3519+
for (const SomeExpr &arg : top.second) {
3520+
if (IsSameOrConvertOf(arg, atom)) {
3521+
++count;
35233522
} else {
3524-
nonAtom.push_back(*i);
3523+
if (!subExpr && IsSubexpressionOf(atom, arg)) {
3524+
subExpr = arg;
3525+
}
3526+
nonAtom.push_back(arg);
35253527
}
35263528
}
3527-
return found;
3529+
return count;
35283530
}()};
35293531

3530-
if (unique == top.second.end()) {
3531-
if (top.first == operation::Operator::Identity) {
3532-
// This is "x = y".
3532+
bool hasError{false};
3533+
if (subExpr) {
3534+
context_.Say(rsrc,
3535+
"The atomic variable %s cannot be a proper subexpression of an argument (here: %s) in the update operation"_err_en_US,
3536+
atom.AsFortran(), subExpr->AsFortran());
3537+
hasError = true;
3538+
}
3539+
if (top.first == operation::Operator::Identity) {
3540+
// This is "x = y".
3541+
assert((atomCount == 0 || atomCount == 1) && "Unexpected count");
3542+
if (atomCount == 0) {
35333543
context_.Say(rsrc,
35343544
"The atomic variable %s should appear as an argument in the update operation"_err_en_US,
35353545
atom.AsFortran());
3536-
} else {
3537-
assert(top.first != operation::Operator::Identity &&
3538-
"Handle this separately");
3546+
hasError = true;
3547+
}
3548+
} else {
3549+
if (atomCount == 0) {
3550+
context_.Say(rsrc,
3551+
"The atomic variable %s should appear as an argument of the top-level %s operator"_err_en_US,
3552+
atom.AsFortran(), operation::ToString(top.first));
3553+
hasError = true;
3554+
} else if (atomCount > 1) {
35393555
context_.Say(rsrc,
3540-
"The atomic variable %s should occur exactly once among the arguments of the top-level %s operator"_err_en_US,
3556+
"The atomic variable %s should be exactly one of the arguments of the top-level %s operator"_err_en_US,
35413557
atom.AsFortran(), operation::ToString(top.first));
3558+
hasError = true;
35423559
}
3543-
} else {
3560+
}
3561+
3562+
if (!hasError) {
35443563
CheckStorageOverlap(atom, nonAtom, source);
35453564
}
35463565
}

flang/test/Semantics/OpenMP/atomic-update-only.f90

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,8 @@ subroutine f03
3030
integer :: x, y
3131

3232
!$omp atomic update
33-
!ERROR: The atomic variable x should occur exactly once among the arguments of the top-level + operator
33+
!ERROR: The atomic variable x cannot be a proper subexpression of an argument (here: (x+y)) in the update operation
34+
!ERROR: The atomic variable x should appear as an argument of the top-level + operator
3435
x = (x + y) + 1
3536
end
3637

flang/test/Semantics/OpenMP/atomic03.f90

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -25,19 +25,19 @@ program OmpAtomic
2525
y = MIN(y, 8)
2626

2727
!$omp atomic
28-
!ERROR: The atomic variable z should occur exactly once among the arguments of the top-level AND operator
28+
!ERROR: The atomic variable z should appear as an argument of the top-level AND operator
2929
z = IAND(y, 4)
3030
!$omp atomic
31-
!ERROR: The atomic variable z should occur exactly once among the arguments of the top-level OR operator
31+
!ERROR: The atomic variable z should appear as an argument of the top-level OR operator
3232
z = IOR(y, 5)
3333
!$omp atomic
34-
!ERROR: The atomic variable z should occur exactly once among the arguments of the top-level NEQV/EOR operator
34+
!ERROR: The atomic variable z should appear as an argument of the top-level NEQV/EOR operator
3535
z = IEOR(y, 6)
3636
!$omp atomic
37-
!ERROR: The atomic variable z should occur exactly once among the arguments of the top-level MAX operator
37+
!ERROR: The atomic variable z should appear as an argument of the top-level MAX operator
3838
z = MAX(y, 7, b, c)
3939
!$omp atomic
40-
!ERROR: The atomic variable z should occur exactly once among the arguments of the top-level MIN operator
40+
!ERROR: The atomic variable z should appear as an argument of the top-level MIN operator
4141
z = MIN(y, 8, a, d)
4242

4343
!$omp atomic
@@ -58,19 +58,19 @@ program OmpAtomic
5858
y = MIN(y, 8)
5959

6060
!$omp atomic update
61-
!ERROR: The atomic variable z should occur exactly once among the arguments of the top-level AND operator
61+
!ERROR: The atomic variable z should appear as an argument of the top-level AND operator
6262
z = IAND(y, 4)
6363
!$omp atomic update
64-
!ERROR: The atomic variable z should occur exactly once among the arguments of the top-level OR operator
64+
!ERROR: The atomic variable z should appear as an argument of the top-level OR operator
6565
z = IOR(y, 5)
6666
!$omp atomic update
67-
!ERROR: The atomic variable z should occur exactly once among the arguments of the top-level NEQV/EOR operator
67+
!ERROR: The atomic variable z should appear as an argument of the top-level NEQV/EOR operator
6868
z = IEOR(y, 6)
6969
!$omp atomic update
70-
!ERROR: The atomic variable z should occur exactly once among the arguments of the top-level MAX operator
70+
!ERROR: The atomic variable z should appear as an argument of the top-level MAX operator
7171
z = MAX(y, 7)
7272
!$omp atomic update
73-
!ERROR: The atomic variable z should occur exactly once among the arguments of the top-level MIN operator
73+
!ERROR: The atomic variable z should appear as an argument of the top-level MIN operator
7474
z = MIN(y, 8)
7575

7676
!$omp atomic update
@@ -90,7 +90,7 @@ subroutine conflicting_types()
9090
type(simple) ::s
9191
z = 1
9292
!$omp atomic
93-
!ERROR: The atomic variable z should occur exactly once among the arguments of the top-level AND operator
93+
!ERROR: The atomic variable z should appear as an argument of the top-level AND operator
9494
z = IAND(s%z, 4)
9595
end subroutine
9696

@@ -103,30 +103,30 @@ subroutine more_invalid_atomic_update_stmts()
103103
type(some_type) :: s
104104

105105
!$omp atomic update
106-
!ERROR: The atomic variable a should occur exactly once among the arguments of the top-level MIN operator
106+
!ERROR: The atomic variable a should be exactly one of the arguments of the top-level MIN operator
107107
a = min(a, a, b)
108108

109109
!$omp atomic
110-
!ERROR: The atomic variable a should occur exactly once among the arguments of the top-level MAX operator
110+
!ERROR: The atomic variable a should be exactly one of the arguments of the top-level MAX operator
111111
a = max(b, a, b, a)
112112

113113
!$omp atomic
114114
a = min(b, a, b)
115115

116116
!$omp atomic
117-
!ERROR: The atomic variable a should occur exactly once among the arguments of the top-level MAX operator
117+
!ERROR: The atomic variable a should be exactly one of the arguments of the top-level MAX operator
118118
a = max(b, a, b, a, b)
119119

120120
!$omp atomic update
121-
!ERROR: The atomic variable y should occur exactly once among the arguments of the top-level MIN operator
121+
!ERROR: The atomic variable y should appear as an argument of the top-level MIN operator
122122
y = min(z, x)
123123

124124
!$omp atomic
125125
z = max(z, y)
126126

127127
!$omp atomic update
128128
!ERROR: Atomic variable k should be a scalar
129-
!ERROR: The atomic variable k should occur exactly once among the arguments of the top-level MAX operator
129+
!ERROR: The atomic variable k should appear as an argument of the top-level MAX operator
130130
k = max(x, y)
131131

132132
!$omp atomic

flang/test/Semantics/OpenMP/atomic04.f90

Lines changed: 32 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -17,21 +17,21 @@ program OmpAtomic
1717
!$omp atomic
1818
x = 1 + x
1919
!$omp atomic
20-
!ERROR: The atomic variable x should occur exactly once among the arguments of the top-level + operator
20+
!ERROR: The atomic variable x should appear as an argument of the top-level + operator
2121
x = y + 1
2222
!$omp atomic
23-
!ERROR: The atomic variable x should occur exactly once among the arguments of the top-level + operator
23+
!ERROR: The atomic variable x should appear as an argument of the top-level + operator
2424
x = 1 + y
2525

2626
!$omp atomic
2727
x = x - 1
2828
!$omp atomic
2929
x = 1 - x
3030
!$omp atomic
31-
!ERROR: The atomic variable x should occur exactly once among the arguments of the top-level - operator
31+
!ERROR: The atomic variable x should appear as an argument of the top-level - operator
3232
x = y - 1
3333
!$omp atomic
34-
!ERROR: The atomic variable x should occur exactly once among the arguments of the top-level - operator
34+
!ERROR: The atomic variable x should appear as an argument of the top-level - operator
3535
x = 1 - y
3636

3737
!$omp atomic
@@ -50,64 +50,64 @@ program OmpAtomic
5050
!$omp atomic
5151
x = 1/x
5252
!$omp atomic
53-
!ERROR: The atomic variable x should occur exactly once among the arguments of the top-level / operator
53+
!ERROR: The atomic variable x should appear as an argument of the top-level / operator
5454
x = y/1
5555
!$omp atomic
56-
!ERROR: The atomic variable x should occur exactly once among the arguments of the top-level / operator
56+
!ERROR: The atomic variable x should appear as an argument of the top-level / operator
5757
x = 1/y
5858

5959
!$omp atomic
6060
m = m .AND. n
6161
!$omp atomic
6262
m = n .AND. m
6363
!$omp atomic
64-
!ERROR: The atomic variable m should occur exactly once among the arguments of the top-level AND operator
64+
!ERROR: The atomic variable m should appear as an argument of the top-level AND operator
6565
m = n .AND. l
6666

6767
!$omp atomic
6868
m = m .OR. n
6969
!$omp atomic
7070
m = n .OR. m
7171
!$omp atomic
72-
!ERROR: The atomic variable m should occur exactly once among the arguments of the top-level OR operator
72+
!ERROR: The atomic variable m should appear as an argument of the top-level OR operator
7373
m = n .OR. l
7474

7575
!$omp atomic
7676
m = m .EQV. n
7777
!$omp atomic
7878
m = n .EQV. m
7979
!$omp atomic
80-
!ERROR: The atomic variable m should occur exactly once among the arguments of the top-level EQV operator
80+
!ERROR: The atomic variable m should appear as an argument of the top-level EQV operator
8181
m = n .EQV. l
8282

8383
!$omp atomic
8484
m = m .NEQV. n
8585
!$omp atomic
8686
m = n .NEQV. m
8787
!$omp atomic
88-
!ERROR: The atomic variable m should occur exactly once among the arguments of the top-level NEQV/EOR operator
88+
!ERROR: The atomic variable m should appear as an argument of the top-level NEQV/EOR operator
8989
m = n .NEQV. l
9090

9191
!$omp atomic update
9292
x = x + 1
9393
!$omp atomic update
9494
x = 1 + x
9595
!$omp atomic update
96-
!ERROR: The atomic variable x should occur exactly once among the arguments of the top-level + operator
96+
!ERROR: The atomic variable x should appear as an argument of the top-level + operator
9797
x = y + 1
9898
!$omp atomic update
99-
!ERROR: The atomic variable x should occur exactly once among the arguments of the top-level + operator
99+
!ERROR: The atomic variable x should appear as an argument of the top-level + operator
100100
x = 1 + y
101101

102102
!$omp atomic update
103103
x = x - 1
104104
!$omp atomic update
105105
x = 1 - x
106106
!$omp atomic update
107-
!ERROR: The atomic variable x should occur exactly once among the arguments of the top-level - operator
107+
!ERROR: The atomic variable x should appear as an argument of the top-level - operator
108108
x = y - 1
109109
!$omp atomic update
110-
!ERROR: The atomic variable x should occur exactly once among the arguments of the top-level - operator
110+
!ERROR: The atomic variable x should appear as an argument of the top-level - operator
111111
x = 1 - y
112112

113113
!$omp atomic update
@@ -126,42 +126,42 @@ program OmpAtomic
126126
!$omp atomic update
127127
x = 1/x
128128
!$omp atomic update
129-
!ERROR: The atomic variable x should occur exactly once among the arguments of the top-level / operator
129+
!ERROR: The atomic variable x should appear as an argument of the top-level / operator
130130
x = y/1
131131
!$omp atomic update
132-
!ERROR: The atomic variable x should occur exactly once among the arguments of the top-level / operator
132+
!ERROR: The atomic variable x should appear as an argument of the top-level / operator
133133
x = 1/y
134134

135135
!$omp atomic update
136136
m = m .AND. n
137137
!$omp atomic update
138138
m = n .AND. m
139139
!$omp atomic update
140-
!ERROR: The atomic variable m should occur exactly once among the arguments of the top-level AND operator
140+
!ERROR: The atomic variable m should appear as an argument of the top-level AND operator
141141
m = n .AND. l
142142

143143
!$omp atomic update
144144
m = m .OR. n
145145
!$omp atomic update
146146
m = n .OR. m
147147
!$omp atomic update
148-
!ERROR: The atomic variable m should occur exactly once among the arguments of the top-level OR operator
148+
!ERROR: The atomic variable m should appear as an argument of the top-level OR operator
149149
m = n .OR. l
150150

151151
!$omp atomic update
152152
m = m .EQV. n
153153
!$omp atomic update
154154
m = n .EQV. m
155155
!$omp atomic update
156-
!ERROR: The atomic variable m should occur exactly once among the arguments of the top-level EQV operator
156+
!ERROR: The atomic variable m should appear as an argument of the top-level EQV operator
157157
m = n .EQV. l
158158

159159
!$omp atomic update
160160
m = m .NEQV. n
161161
!$omp atomic update
162162
m = n .NEQV. m
163163
!$omp atomic update
164-
!ERROR: The atomic variable m should occur exactly once among the arguments of the top-level NEQV/EOR operator
164+
!ERROR: The atomic variable m should appear as an argument of the top-level NEQV/EOR operator
165165
m = n .NEQV. l
166166

167167
end program OmpAtomic
@@ -184,27 +184,30 @@ subroutine more_invalid_atomic_update_stmts()
184184
x = 1
185185

186186
!$omp atomic update
187-
!ERROR: Within atomic operation a and a*b access the same storage
187+
!ERROR: The atomic variable a cannot be a proper subexpression of an argument (here: a*b) in the update operation
188188
a = a * b + a
189189

190190
!$omp atomic
191-
!ERROR: The atomic variable a should occur exactly once among the arguments of the top-level * operator
191+
!ERROR: The atomic variable a cannot be a proper subexpression of an argument (here: (a+9_4)) in the update operation
192+
!ERROR: The atomic variable a should appear as an argument of the top-level * operator
192193
a = b * (a + 9)
193194

194195
!$omp atomic update
195-
!ERROR: Within atomic operation a and (a+b) access the same storage
196+
!ERROR: The atomic variable a cannot be a proper subexpression of an argument (here: (a+b)) in the update operation
196197
a = a * (a + b)
197198

198199
!$omp atomic
199-
!ERROR: Within atomic operation a and (b+a) access the same storage
200+
!ERROR: The atomic variable a cannot be a proper subexpression of an argument (here: (b+a)) in the update operation
200201
a = (b + a) * a
201202

202203
!$omp atomic
203-
!ERROR: The atomic variable a should occur exactly once among the arguments of the top-level + operator
204+
!ERROR: The atomic variable a cannot be a proper subexpression of an argument (here: a*b) in the update operation
205+
!ERROR: The atomic variable a should appear as an argument of the top-level + operator
204206
a = a * b + c
205207

206208
!$omp atomic update
207-
!ERROR: The atomic variable a should occur exactly once among the arguments of the top-level + operator
209+
!ERROR: The atomic variable a cannot be a proper subexpression of an argument (here: a+b) in the update operation
210+
!ERROR: The atomic variable a should appear as an argument of the top-level + operator
208211
a = a + b + c
209212

210213
!$omp atomic
@@ -219,11 +222,12 @@ subroutine more_invalid_atomic_update_stmts()
219222

220223
!$omp atomic update
221224
!ERROR: No intrinsic or user-defined ASSIGNMENT(=) matches scalar REAL(4) and rank 1 array of REAL(4)
222-
!ERROR: The atomic variable x should occur exactly once among the arguments of the top-level / operator
225+
!ERROR: The atomic variable x cannot be a proper subexpression of an argument (here: x*y) in the update operation
226+
!ERROR: The atomic variable x should appear as an argument of the top-level / operator
223227
x = x * y / z
224228

225229
!$omp atomic
226-
!ERROR: The atomic variable p%m should occur exactly once among the arguments of the top-level + operator
230+
!ERROR: The atomic variable p%m should appear as an argument of the top-level + operator
227231
p%m = x + y
228232

229233
!$omp atomic update

0 commit comments

Comments
 (0)