1 // RUN: %clang_cc1 -verify -fopenmp -ferror-limit 100 %s
2 
foo()3 int foo() {
4 L1:
5   foo();
6 #pragma omp atomic
7   // expected-error@+2 {{the statement for 'atomic' must be an expression statement of form '++x;', '--x;', 'x++;', 'x--;', 'x binop= expr;', 'x = x binop expr' or 'x = expr binop x', where x is an l-value expression with scalar type}}
8   // expected-note@+1 {{expected an expression statement}}
9   {
10     foo();
11     goto L1; // expected-error {{use of undeclared label 'L1'}}
12   }
13   goto L2; // expected-error {{use of undeclared label 'L2'}}
14 #pragma omp atomic
15   // expected-error@+2 {{the statement for 'atomic' must be an expression statement of form '++x;', '--x;', 'x++;', 'x--;', 'x binop= expr;', 'x = x binop expr' or 'x = expr binop x', where x is an l-value expression with scalar type}}
16   // expected-note@+1 {{expected an expression statement}}
17   {
18     foo();
19   L2:
20     foo();
21   }
22 
23   return 0;
24 }
25 
26 struct S {
27   int a;
operator =S28   S &operator=(int v) {
29     a = v;
30     return *this;
31   }
operator +=S32   S &operator+=(const S &s) {
33     a += s.a;
34     return *this;
35   }
36 };
37 
38 template <class T>
read()39 T read() {
40   T a = T(), b = T();
41 // Test for atomic read
42 #pragma omp atomic read
43   // expected-error@+2 {{the statement for 'atomic read' must be an expression statement of form 'v = x;', where v and x are both lvalue expressions with scalar type}}
44   // expected-note@+1 {{expected an expression statement}}
45   ;
46 #pragma omp atomic read
47   // expected-error@+2 {{the statement for 'atomic read' must be an expression statement of form 'v = x;', where v and x are both lvalue expressions with scalar type}}
48   // expected-note@+1 {{expected built-in assignment operator}}
49   foo();
50 #pragma omp atomic read
51   // expected-error@+2 2 {{the statement for 'atomic read' must be an expression statement of form 'v = x;', where v and x are both lvalue expressions with scalar type}}
52   // expected-note@+1 2 {{expected built-in assignment operator}}
53   a += b;
54 #pragma omp atomic read
55   // expected-error@+2 {{the statement for 'atomic read' must be an expression statement of form 'v = x;', where v and x are both lvalue expressions with scalar type}}
56   // expected-note@+1 {{expected lvalue expression}}
57   a = 0;
58 #pragma omp atomic read
59   // expected-error@+2 {{the statement for 'atomic read' must be an expression statement of form 'v = x;', where v and x are both lvalue expressions with scalar type}}
60   // expected-note@+1 {{expected built-in assignment operator}}
61   a = b;
62   // expected-error@+1 {{directive '#pragma omp atomic' cannot contain more than one 'read' clause}}
63 #pragma omp atomic read read
64   // expected-error@+2 {{the statement for 'atomic read' must be an expression statement of form 'v = x;', where v and x are both lvalue expressions with scalar type}}
65   // expected-note@+1 {{expected built-in assignment operator}}
66   a = b;
67 
68   return a;
69 }
70 
read()71 int read() {
72   int a = 0, b = 0;
73 // Test for atomic read
74 #pragma omp atomic read
75   // expected-error@+2 {{the statement for 'atomic read' must be an expression statement of form 'v = x;', where v and x are both lvalue expressions with scalar type}}
76   // expected-note@+1 {{expected an expression statement}}
77   ;
78 #pragma omp atomic read
79   // expected-error@+2 {{the statement for 'atomic read' must be an expression statement of form 'v = x;', where v and x are both lvalue expressions with scalar type}}
80   // expected-note@+1 {{expected built-in assignment operator}}
81   foo();
82 #pragma omp atomic read
83   // expected-error@+2 {{the statement for 'atomic read' must be an expression statement of form 'v = x;', where v and x are both lvalue expressions with scalar type}}
84   // expected-note@+1 {{expected built-in assignment operator}}
85   a += b;
86 #pragma omp atomic read
87   // expected-error@+2 {{the statement for 'atomic read' must be an expression statement of form 'v = x;', where v and x are both lvalue expressions with scalar type}}
88   // expected-note@+1 {{expected lvalue expression}}
89   a = 0;
90 #pragma omp atomic read
91   a = b;
92   // expected-error@+1 {{directive '#pragma omp atomic' cannot contain more than one 'read' clause}}
93 #pragma omp atomic read read
94   a = b;
95 
96   // expected-note@+2 {{in instantiation of function template specialization 'read<S>' requested here}}
97   // expected-note@+1 {{in instantiation of function template specialization 'read<int>' requested here}}
98   return read<int>() + read<S>().a;
99 }
100 
101 template <class T>
write()102 T write() {
103   T a, b = 0;
104 // Test for atomic write
105 #pragma omp atomic write
106   // expected-error@+2 {{the statement for 'atomic write' must be an expression statement of form 'x = expr;', where x is a lvalue expression with scalar type}}
107   // expected-note@+1 {{expected an expression statement}}
108   ;
109 // expected-error@+1 {{directive '#pragma omp atomic' cannot contain more than one 'write' clause}}
110 #pragma omp atomic write write
111   a = b;
112 #pragma omp atomic write
113   // expected-error@+2 {{the statement for 'atomic write' must be an expression statement of form 'x = expr;', where x is a lvalue expression with scalar type}}
114   // expected-note@+1 {{expected built-in assignment operator}}
115   foo();
116 #pragma omp atomic write
117   // expected-error@+2 {{the statement for 'atomic write' must be an expression statement of form 'x = expr;', where x is a lvalue expression with scalar type}}
118   // expected-note@+1 {{expected built-in assignment operator}}
119   a += b;
120 #pragma omp atomic write
121   a = 0;
122 #pragma omp atomic write
123   a = b;
124 
125   return T();
126 }
127 
write()128 int write() {
129   int a, b = 0;
130 // Test for atomic write
131 #pragma omp atomic write
132   // expected-error@+2 {{the statement for 'atomic write' must be an expression statement of form 'x = expr;', where x is a lvalue expression with scalar type}}
133   // expected-note@+1 {{expected an expression statement}}
134   ;
135 // expected-error@+1 {{directive '#pragma omp atomic' cannot contain more than one 'write' clause}}
136 #pragma omp atomic write write
137   a = b;
138 #pragma omp atomic write
139   // expected-error@+2 {{the statement for 'atomic write' must be an expression statement of form 'x = expr;', where x is a lvalue expression with scalar type}}
140   // expected-note@+1 {{expected built-in assignment operator}}
141   foo();
142 #pragma omp atomic write
143   // expected-error@+2 {{the statement for 'atomic write' must be an expression statement of form 'x = expr;', where x is a lvalue expression with scalar type}}
144   // expected-note@+1 {{expected built-in assignment operator}}
145   a += b;
146 #pragma omp atomic write
147   a = 0;
148 #pragma omp atomic write
149   a = foo();
150 
151   // expected-note@+1 {{in instantiation of function template specialization 'write<int>' requested here}}
152   return write<int>();
153 }
154 
155 template <class T>
update()156 T update() {
157   T a = 0, b = 0, c = 0;
158 // Test for atomic update
159 #pragma omp atomic update
160   // expected-error@+2 {{the statement for 'atomic update' must be an expression statement of form '++x;', '--x;', 'x++;', 'x--;', 'x binop= expr;', 'x = x binop expr' or 'x = expr binop x', where x is an l-value expression with scalar type}}
161   // expected-note@+1 {{expected an expression statement}}
162   ;
163 // expected-error@+1 {{directive '#pragma omp atomic' cannot contain more than one 'update' clause}}
164 #pragma omp atomic update update
165   a += b;
166 #pragma omp atomic
167   // expected-error@+2 {{the statement for 'atomic' must be an expression statement of form '++x;', '--x;', 'x++;', 'x--;', 'x binop= expr;', 'x = x binop expr' or 'x = expr binop x', where x is an l-value expression with scalar type}}
168   // expected-note@+1 {{expected built-in binary operator}}
169   a = b;
170 #pragma omp atomic update
171   // expected-error@+2 {{the statement for 'atomic update' must be an expression statement of form '++x;', '--x;', 'x++;', 'x--;', 'x binop= expr;', 'x = x binop expr' or 'x = expr binop x', where x is an l-value expression with scalar type}}
172   // expected-note@+1 {{expected one of '+', '*', '-', '/', '&', '^', '|', '<<', or '>>' built-in operations}}
173   a = b || a;
174 #pragma omp atomic update
175   // expected-error@+2 {{the statement for 'atomic update' must be an expression statement of form '++x;', '--x;', 'x++;', 'x--;', 'x binop= expr;', 'x = x binop expr' or 'x = expr binop x', where x is an l-value expression with scalar type}}
176   // expected-note@+1 {{expected one of '+', '*', '-', '/', '&', '^', '|', '<<', or '>>' built-in operations}}
177   a = a && b;
178 #pragma omp atomic update
179   // expected-error@+2 {{the statement for 'atomic update' must be an expression statement of form '++x;', '--x;', 'x++;', 'x--;', 'x binop= expr;', 'x = x binop expr' or 'x = expr binop x', where x is an l-value expression with scalar type}}
180   // expected-note@+1 {{expected in right hand side of expression}}
181   a = float(a) + b;
182 #pragma omp atomic
183   // expected-error@+2 {{the statement for 'atomic' must be an expression statement of form '++x;', '--x;', 'x++;', 'x--;', 'x binop= expr;', 'x = x binop expr' or 'x = expr binop x', where x is an l-value expression with scalar type}}
184   // expected-note@+1 {{expected in right hand side of expression}}
185   a = 2 * b;
186 #pragma omp atomic
187   // expected-error@+2 {{the statement for 'atomic' must be an expression statement of form '++x;', '--x;', 'x++;', 'x--;', 'x binop= expr;', 'x = x binop expr' or 'x = expr binop x', where x is an l-value expression with scalar type}}
188   // expected-note@+1 {{expected in right hand side of expression}}
189   a = b + *&a;
190 #pragma omp atomic
191   *&a = b * *&a;
192 #pragma omp atomic update
193   a++;
194 #pragma omp atomic
195   ++a;
196 #pragma omp atomic update
197   a--;
198 #pragma omp atomic
199   --a;
200 #pragma omp atomic update
201   a += b;
202 #pragma omp atomic
203   a %= b;
204 #pragma omp atomic update
205   a *= b;
206 #pragma omp atomic
207   a -= b;
208 #pragma omp atomic update
209   a /= b;
210 #pragma omp atomic
211   a &= b;
212 #pragma omp atomic update
213   a ^= b;
214 #pragma omp atomic
215   a |= b;
216 #pragma omp atomic update
217   a <<= b;
218 #pragma omp atomic
219   a >>= b;
220 #pragma omp atomic update
221   a = b + a;
222 #pragma omp atomic
223   a = a * b;
224 #pragma omp atomic update
225   a = b - a;
226 #pragma omp atomic
227   a = a / b;
228 #pragma omp atomic update
229   a = b & a;
230 #pragma omp atomic
231   a = a ^ b;
232 #pragma omp atomic update
233   a = b | a;
234 #pragma omp atomic
235   a = a << b;
236 #pragma omp atomic
237   a = b >> a;
238 
239 #pragma omp atomic
240   // expected-error@+2 {{the statement for 'atomic' must be an expression statement of form '++x;', '--x;', 'x++;', 'x--;', 'x binop= expr;', 'x = x binop expr' or 'x = expr binop x', where x is an l-value expression with scalar type}}
241   // expected-note@+1 {{expected an expression statement}}
242   ;
243 
244   return T();
245 }
246 
update()247 int update() {
248   int a, b = 0;
249 // Test for atomic update
250 #pragma omp atomic update
251   // expected-error@+2 {{the statement for 'atomic update' must be an expression statement of form '++x;', '--x;', 'x++;', 'x--;', 'x binop= expr;', 'x = x binop expr' or 'x = expr binop x', where x is an l-value expression with scalar type}}
252   // expected-note@+1 {{expected an expression statement}}
253   ;
254 // expected-error@+1 {{directive '#pragma omp atomic' cannot contain more than one 'update' clause}}
255 #pragma omp atomic update update
256   a += b;
257 #pragma omp atomic
258   // expected-error@+2 {{the statement for 'atomic' must be an expression statement of form '++x;', '--x;', 'x++;', 'x--;', 'x binop= expr;', 'x = x binop expr' or 'x = expr binop x', where x is an l-value expression with scalar type}}
259   // expected-note@+1 {{expected built-in binary operator}}
260   a = b;
261 #pragma omp atomic update
262   // expected-error@+2 {{the statement for 'atomic update' must be an expression statement of form '++x;', '--x;', 'x++;', 'x--;', 'x binop= expr;', 'x = x binop expr' or 'x = expr binop x', where x is an l-value expression with scalar type}}
263   // expected-note@+1 {{expected one of '+', '*', '-', '/', '&', '^', '|', '<<', or '>>' built-in operations}}
264   a = b || a;
265 #pragma omp atomic update
266   // expected-error@+2 {{the statement for 'atomic update' must be an expression statement of form '++x;', '--x;', 'x++;', 'x--;', 'x binop= expr;', 'x = x binop expr' or 'x = expr binop x', where x is an l-value expression with scalar type}}
267   // expected-note@+1 {{expected one of '+', '*', '-', '/', '&', '^', '|', '<<', or '>>' built-in operations}}
268   a = a && b;
269 #pragma omp atomic update
270   // expected-error@+2 {{the statement for 'atomic update' must be an expression statement of form '++x;', '--x;', 'x++;', 'x--;', 'x binop= expr;', 'x = x binop expr' or 'x = expr binop x', where x is an l-value expression with scalar type}}
271   // expected-note@+1 {{expected in right hand side of expression}}
272   a = float(a) + b;
273 #pragma omp atomic
274   // expected-error@+2 {{the statement for 'atomic' must be an expression statement of form '++x;', '--x;', 'x++;', 'x--;', 'x binop= expr;', 'x = x binop expr' or 'x = expr binop x', where x is an l-value expression with scalar type}}
275   // expected-note@+1 {{expected in right hand side of expression}}
276   a = 2 * b;
277 #pragma omp atomic
278   // expected-error@+2 {{the statement for 'atomic' must be an expression statement of form '++x;', '--x;', 'x++;', 'x--;', 'x binop= expr;', 'x = x binop expr' or 'x = expr binop x', where x is an l-value expression with scalar type}}
279   // expected-note@+1 {{expected in right hand side of expression}}
280   a = b + *&a;
281 #pragma omp atomic update
282   a++;
283 #pragma omp atomic
284   ++a;
285 #pragma omp atomic update
286   a--;
287 #pragma omp atomic
288   --a;
289 #pragma omp atomic update
290   a += b;
291 #pragma omp atomic
292   a %= b;
293 #pragma omp atomic update
294   a *= b;
295 #pragma omp atomic
296   a -= b;
297 #pragma omp atomic update
298   a /= b;
299 #pragma omp atomic
300   a &= b;
301 #pragma omp atomic update
302   a ^= b;
303 #pragma omp atomic
304   a |= b;
305 #pragma omp atomic update
306   a <<= b;
307 #pragma omp atomic
308   a >>= b;
309 #pragma omp atomic update
310   a = b + a;
311 #pragma omp atomic
312   a = a * b;
313 #pragma omp atomic update
314   a = b - a;
315 #pragma omp atomic
316   a = a / b;
317 #pragma omp atomic update
318   a = b & a;
319 #pragma omp atomic
320   a = a ^ b;
321 #pragma omp atomic update
322   a = b | a;
323 #pragma omp atomic
324   a = a << b;
325 #pragma omp atomic
326   a = b >> a;
327 #pragma omp atomic
328   // expected-error@+2 {{the statement for 'atomic' must be an expression statement of form '++x;', '--x;', 'x++;', 'x--;', 'x binop= expr;', 'x = x binop expr' or 'x = expr binop x', where x is an l-value expression with scalar type}}
329   // expected-note@+1 {{expected an expression statement}}
330   ;
331 
332   return update<int>();
333 }
334 
335 template <class T>
capture()336 T capture() {
337   T a = 0, b = 0, c = 0;
338 // Test for atomic capture
339 #pragma omp atomic capture
340   // expected-error@+2 {{the statement for 'atomic capture' must be a compound statement of form '{v = x; x binop= expr;}', '{x binop= expr; v = x;}', '{v = x; x = x binop expr;}', '{v = x; x = expr binop x;}', '{x = x binop expr; v = x;}', '{x = expr binop x; v = x;}' or '{v = x; x = expr;}', '{v = x; x++;}', '{v = x; ++x;}', '{++x; v = x;}', '{x++; v = x;}', '{v = x; x--;}', '{v = x; --x;}', '{--x; v = x;}', '{x--; v = x;}' where x is an l-value expression with scalar type}}
341   // expected-note@+1 {{expected compound statement}}
342   ;
343 #pragma omp atomic capture
344   // expected-error@+2 {{the statement for 'atomic capture' must be an expression statement of form 'v = ++x;', 'v = --x;', 'v = x++;', 'v = x--;', 'v = x binop= expr;', 'v = x = x binop expr' or 'v = x = expr binop x', where x and v are both l-value expressions with scalar type}}
345   // expected-note@+1 {{expected assignment expression}}
346   foo();
347 #pragma omp atomic capture
348   // expected-error@+2 {{the statement for 'atomic capture' must be an expression statement of form 'v = ++x;', 'v = --x;', 'v = x++;', 'v = x--;', 'v = x binop= expr;', 'v = x = x binop expr' or 'v = x = expr binop x', where x and v are both l-value expressions with scalar type}}
349   // expected-note@+1 {{expected built-in binary or unary operator}}
350   a = b;
351 #pragma omp atomic capture
352   // expected-error@+2 {{the statement for 'atomic capture' must be an expression statement of form 'v = ++x;', 'v = --x;', 'v = x++;', 'v = x--;', 'v = x binop= expr;', 'v = x = x binop expr' or 'v = x = expr binop x', where x and v are both l-value expressions with scalar type}}
353   // expected-note@+1 {{expected assignment expression}}
354   a = b || a;
355 #pragma omp atomic capture
356   // expected-error@+2 {{the statement for 'atomic capture' must be an expression statement of form 'v = ++x;', 'v = --x;', 'v = x++;', 'v = x--;', 'v = x binop= expr;', 'v = x = x binop expr' or 'v = x = expr binop x', where x and v are both l-value expressions with scalar type}}
357   // expected-note@+1 {{expected one of '+', '*', '-', '/', '&', '^', '|', '<<', or '>>' built-in operations}}
358   b = a = a && b;
359 #pragma omp atomic capture
360   // expected-error@+2 {{the statement for 'atomic capture' must be an expression statement of form 'v = ++x;', 'v = --x;', 'v = x++;', 'v = x--;', 'v = x binop= expr;', 'v = x = x binop expr' or 'v = x = expr binop x', where x and v are both l-value expressions with scalar type}}
361   // expected-note@+1 {{expected assignment expression}}
362   a = (float)a + b;
363 #pragma omp atomic capture
364   // expected-error@+2 {{the statement for 'atomic capture' must be an expression statement of form 'v = ++x;', 'v = --x;', 'v = x++;', 'v = x--;', 'v = x binop= expr;', 'v = x = x binop expr' or 'v = x = expr binop x', where x and v are both l-value expressions with scalar type}}
365   // expected-note@+1 {{expected assignment expression}}
366   a = 2 * b;
367 #pragma omp atomic capture
368   // expected-error@+2 {{the statement for 'atomic capture' must be an expression statement of form 'v = ++x;', 'v = --x;', 'v = x++;', 'v = x--;', 'v = x binop= expr;', 'v = x = x binop expr' or 'v = x = expr binop x', where x and v are both l-value expressions with scalar type}}
369   // expected-note@+1 {{expected assignment expression}}
370   a = b + *&a;
371 #pragma omp atomic capture
372   // expected-error@+2 {{the statement for 'atomic capture' must be a compound statement of form '{v = x; x binop= expr;}', '{x binop= expr; v = x;}', '{v = x; x = x binop expr;}', '{v = x; x = expr binop x;}', '{x = x binop expr; v = x;}', '{x = expr binop x; v = x;}' or '{v = x; x = expr;}', '{v = x; x++;}', '{v = x; ++x;}', '{++x; v = x;}', '{x++; v = x;}', '{v = x; x--;}', '{v = x; --x;}', '{--x; v = x;}', '{x--; v = x;}' where x is an l-value expression with scalar type}}
373   // expected-note@+1 {{expected exactly two expression statements}}
374   { a = b; }
375 #pragma omp atomic capture
376   // expected-error@+2 {{the statement for 'atomic capture' must be a compound statement of form '{v = x; x binop= expr;}', '{x binop= expr; v = x;}', '{v = x; x = x binop expr;}', '{v = x; x = expr binop x;}', '{x = x binop expr; v = x;}', '{x = expr binop x; v = x;}' or '{v = x; x = expr;}', '{v = x; x++;}', '{v = x; ++x;}', '{++x; v = x;}', '{x++; v = x;}', '{v = x; x--;}', '{v = x; --x;}', '{--x; v = x;}', '{x--; v = x;}' where x is an l-value expression with scalar type}}
377   // expected-note@+1 {{expected exactly two expression statements}}
378   {}
379 #pragma omp atomic capture
380   // expected-error@+2 {{the statement for 'atomic capture' must be a compound statement of form '{v = x; x binop= expr;}', '{x binop= expr; v = x;}', '{v = x; x = x binop expr;}', '{v = x; x = expr binop x;}', '{x = x binop expr; v = x;}', '{x = expr binop x; v = x;}' or '{v = x; x = expr;}', '{v = x; x++;}', '{v = x; ++x;}', '{++x; v = x;}', '{x++; v = x;}', '{v = x; x--;}', '{v = x; --x;}', '{--x; v = x;}', '{x--; v = x;}' where x is an l-value expression with scalar type}}
381   // expected-note@+1 {{expected in right hand side of the first expression}}
382   {a = b;a = b;}
383 #pragma omp atomic capture
384   // expected-error@+2 {{the statement for 'atomic capture' must be a compound statement of form '{v = x; x binop= expr;}', '{x binop= expr; v = x;}', '{v = x; x = x binop expr;}', '{v = x; x = expr binop x;}', '{x = x binop expr; v = x;}', '{x = expr binop x; v = x;}' or '{v = x; x = expr;}', '{v = x; x++;}', '{v = x; ++x;}', '{++x; v = x;}', '{x++; v = x;}', '{v = x; x--;}', '{v = x; --x;}', '{--x; v = x;}', '{x--; v = x;}' where x is an l-value expression with scalar type}}
385   // expected-note@+1 {{expected in right hand side of the first expression}}
386   {a = b; a = b || a;}
387 #pragma omp atomic capture
388   {b = a; a = a && b;}
389 #pragma omp atomic capture
390   // expected-error@+2 {{the statement for 'atomic capture' must be an expression statement of form 'v = ++x;', 'v = --x;', 'v = x++;', 'v = x--;', 'v = x binop= expr;', 'v = x = x binop expr' or 'v = x = expr binop x', where x and v are both l-value expressions with scalar type}}
391   // expected-note@+1 {{expected in right hand side of expression}}
392   b = a = (float)a + b;
393 #pragma omp atomic capture
394   // expected-error@+2 {{the statement for 'atomic capture' must be an expression statement of form 'v = ++x;', 'v = --x;', 'v = x++;', 'v = x--;', 'v = x binop= expr;', 'v = x = x binop expr' or 'v = x = expr binop x', where x and v are both l-value expressions with scalar type}}
395   // expected-note@+1 {{expected in right hand side of expression}}
396   b = a = 2 * b;
397 #pragma omp atomic capture
398   // expected-error@+2 {{the statement for 'atomic capture' must be an expression statement of form 'v = ++x;', 'v = --x;', 'v = x++;', 'v = x--;', 'v = x binop= expr;', 'v = x = x binop expr' or 'v = x = expr binop x', where x and v are both l-value expressions with scalar type}}
399   // expected-note@+1 {{expected in right hand side of expression}}
400   b = a = b + *&a;
401 #pragma omp atomic capture
402   c = *&a = *&a +  2;
403 #pragma omp atomic capture
404   c = a++;
405 #pragma omp atomic capture
406   c = ++a;
407 #pragma omp atomic capture
408   c = a--;
409 #pragma omp atomic capture
410   c = --a;
411 #pragma omp atomic capture
412   c = a += b;
413 #pragma omp atomic capture
414   c = a %= b;
415 #pragma omp atomic capture
416   c = a *= b;
417 #pragma omp atomic capture
418   c = a -= b;
419 #pragma omp atomic capture
420   c = a /= b;
421 #pragma omp atomic capture
422   c = a &= b;
423 #pragma omp atomic capture
424   c = a ^= b;
425 #pragma omp atomic capture
426   c = a |= b;
427 #pragma omp atomic capture
428   c = a <<= b;
429 #pragma omp atomic capture
430   c = a >>= b;
431 #pragma omp atomic capture
432   c = a = b + a;
433 #pragma omp atomic capture
434   c = a = a * b;
435 #pragma omp atomic capture
436   c = a = b - a;
437 #pragma omp atomic capture
438   c = a = a / b;
439 #pragma omp atomic capture
440   c = a = b & a;
441 #pragma omp atomic capture
442   c = a = a ^ b;
443 #pragma omp atomic capture
444   c = a = b | a;
445 #pragma omp atomic capture
446   c = a = a << b;
447 #pragma omp atomic capture
448   c = a = b >> a;
449 #pragma omp atomic capture
450   { c = *&a; *&a = *&a +  2;}
451 #pragma omp atomic capture
452   { *&a = *&a +  2; c = *&a;}
453 #pragma omp atomic capture
454   {c = a; a++;}
455 #pragma omp atomic capture
456   {++a;c = a;}
457 #pragma omp atomic capture
458   {c = a;a--;}
459 #pragma omp atomic capture
460   {--a;c = a;}
461 #pragma omp atomic capture
462   {c = a; a += b;}
463 #pragma omp atomic capture
464   {a %= b; c = a;}
465 #pragma omp atomic capture
466   {c = a; a *= b;}
467 #pragma omp atomic capture
468   {a -= b;c = a;}
469 #pragma omp atomic capture
470   {c = a; a /= b;}
471 #pragma omp atomic capture
472   {a &= b; c = a;}
473 #pragma omp atomic capture
474   {c = a; a ^= b;}
475 #pragma omp atomic capture
476   {a |= b; c = a;}
477 #pragma omp atomic capture
478   {c = a; a <<= b;}
479 #pragma omp atomic capture
480   {a >>= b; c = a;}
481 #pragma omp atomic capture
482   {c = a; a = b + a;}
483 #pragma omp atomic capture
484   {a = a * b; c = a;}
485 #pragma omp atomic capture
486   {c = a; a = b - a;}
487 #pragma omp atomic capture
488   {a = a / b; c = a;}
489 #pragma omp atomic capture
490   {c = a; a = b & a;}
491 #pragma omp atomic capture
492   {a = a ^ b; c = a;}
493 #pragma omp atomic capture
494   {c = a; a = b | a;}
495 #pragma omp atomic capture
496   {a = a << b; c = a;}
497 #pragma omp atomic capture
498   {c = a; a = b >> a;}
499 #pragma omp atomic capture
500   {c = a; a = foo();}
501   // expected-error@+1 {{directive '#pragma omp atomic' cannot contain more than one 'capture' clause}}
502 #pragma omp atomic capture capture
503   b = a /= b;
504 
505   return T();
506 }
507 
capture()508 int capture() {
509   int a = 0, b = 0, c = 0;
510 // Test for atomic capture
511 #pragma omp atomic capture
512   // expected-error@+2 {{the statement for 'atomic capture' must be a compound statement of form '{v = x; x binop= expr;}', '{x binop= expr; v = x;}', '{v = x; x = x binop expr;}', '{v = x; x = expr binop x;}', '{x = x binop expr; v = x;}', '{x = expr binop x; v = x;}' or '{v = x; x = expr;}', '{v = x; x++;}', '{v = x; ++x;}', '{++x; v = x;}', '{x++; v = x;}', '{v = x; x--;}', '{v = x; --x;}', '{--x; v = x;}', '{x--; v = x;}' where x is an l-value expression with scalar type}}
513   // expected-note@+1 {{expected compound statement}}
514   ;
515 #pragma omp atomic capture
516   // expected-error@+2 {{the statement for 'atomic capture' must be an expression statement of form 'v = ++x;', 'v = --x;', 'v = x++;', 'v = x--;', 'v = x binop= expr;', 'v = x = x binop expr' or 'v = x = expr binop x', where x and v are both l-value expressions with scalar type}}
517   // expected-note@+1 {{expected assignment expression}}
518   foo();
519 #pragma omp atomic capture
520   // expected-error@+2 {{the statement for 'atomic capture' must be an expression statement of form 'v = ++x;', 'v = --x;', 'v = x++;', 'v = x--;', 'v = x binop= expr;', 'v = x = x binop expr' or 'v = x = expr binop x', where x and v are both l-value expressions with scalar type}}
521   // expected-note@+1 {{expected built-in binary or unary operator}}
522   a = b;
523 #pragma omp atomic capture
524   // expected-error@+2 {{the statement for 'atomic capture' must be an expression statement of form 'v = ++x;', 'v = --x;', 'v = x++;', 'v = x--;', 'v = x binop= expr;', 'v = x = x binop expr' or 'v = x = expr binop x', where x and v are both l-value expressions with scalar type}}
525   // expected-note@+1 {{expected assignment expression}}
526   a = b || a;
527 #pragma omp atomic capture
528   // expected-error@+2 {{the statement for 'atomic capture' must be an expression statement of form 'v = ++x;', 'v = --x;', 'v = x++;', 'v = x--;', 'v = x binop= expr;', 'v = x = x binop expr' or 'v = x = expr binop x', where x and v are both l-value expressions with scalar type}}
529   // expected-note@+1 {{expected one of '+', '*', '-', '/', '&', '^', '|', '<<', or '>>' built-in operations}}
530   b = a = a && b;
531 #pragma omp atomic capture
532   // expected-error@+2 {{the statement for 'atomic capture' must be an expression statement of form 'v = ++x;', 'v = --x;', 'v = x++;', 'v = x--;', 'v = x binop= expr;', 'v = x = x binop expr' or 'v = x = expr binop x', where x and v are both l-value expressions with scalar type}}
533   // expected-note@+1 {{expected assignment expression}}
534   a = (float)a + b;
535 #pragma omp atomic capture
536   // expected-error@+2 {{the statement for 'atomic capture' must be an expression statement of form 'v = ++x;', 'v = --x;', 'v = x++;', 'v = x--;', 'v = x binop= expr;', 'v = x = x binop expr' or 'v = x = expr binop x', where x and v are both l-value expressions with scalar type}}
537   // expected-note@+1 {{expected assignment expression}}
538   a = 2 * b;
539 #pragma omp atomic capture
540   // expected-error@+2 {{the statement for 'atomic capture' must be an expression statement of form 'v = ++x;', 'v = --x;', 'v = x++;', 'v = x--;', 'v = x binop= expr;', 'v = x = x binop expr' or 'v = x = expr binop x', where x and v are both l-value expressions with scalar type}}
541   // expected-note@+1 {{expected assignment expression}}
542   a = b + *&a;
543 #pragma omp atomic capture
544   // expected-error@+2 {{the statement for 'atomic capture' must be a compound statement of form '{v = x; x binop= expr;}', '{x binop= expr; v = x;}', '{v = x; x = x binop expr;}', '{v = x; x = expr binop x;}', '{x = x binop expr; v = x;}', '{x = expr binop x; v = x;}' or '{v = x; x = expr;}', '{v = x; x++;}', '{v = x; ++x;}', '{++x; v = x;}', '{x++; v = x;}', '{v = x; x--;}', '{v = x; --x;}', '{--x; v = x;}', '{x--; v = x;}' where x is an l-value expression with scalar type}}
545   // expected-note@+1 {{expected exactly two expression statements}}
546   { a = b; }
547 #pragma omp atomic capture
548   // expected-error@+2 {{the statement for 'atomic capture' must be a compound statement of form '{v = x; x binop= expr;}', '{x binop= expr; v = x;}', '{v = x; x = x binop expr;}', '{v = x; x = expr binop x;}', '{x = x binop expr; v = x;}', '{x = expr binop x; v = x;}' or '{v = x; x = expr;}', '{v = x; x++;}', '{v = x; ++x;}', '{++x; v = x;}', '{x++; v = x;}', '{v = x; x--;}', '{v = x; --x;}', '{--x; v = x;}', '{x--; v = x;}' where x is an l-value expression with scalar type}}
549   // expected-note@+1 {{expected exactly two expression statements}}
550   {}
551 #pragma omp atomic capture
552   // expected-error@+2 {{the statement for 'atomic capture' must be a compound statement of form '{v = x; x binop= expr;}', '{x binop= expr; v = x;}', '{v = x; x = x binop expr;}', '{v = x; x = expr binop x;}', '{x = x binop expr; v = x;}', '{x = expr binop x; v = x;}' or '{v = x; x = expr;}', '{v = x; x++;}', '{v = x; ++x;}', '{++x; v = x;}', '{x++; v = x;}', '{v = x; x--;}', '{v = x; --x;}', '{--x; v = x;}', '{x--; v = x;}' where x is an l-value expression with scalar type}}
553   // expected-note@+1 {{expected in right hand side of the first expression}}
554   {a = b;a = b;}
555 #pragma omp atomic capture
556   // expected-error@+2 {{the statement for 'atomic capture' must be a compound statement of form '{v = x; x binop= expr;}', '{x binop= expr; v = x;}', '{v = x; x = x binop expr;}', '{v = x; x = expr binop x;}', '{x = x binop expr; v = x;}', '{x = expr binop x; v = x;}' or '{v = x; x = expr;}', '{v = x; x++;}', '{v = x; ++x;}', '{++x; v = x;}', '{x++; v = x;}', '{v = x; x--;}', '{v = x; --x;}', '{--x; v = x;}', '{x--; v = x;}' where x is an l-value expression with scalar type}}
557   // expected-note@+1 {{expected in right hand side of the first expression}}
558   {a = b; a = b || a;}
559 #pragma omp atomic capture
560   {b = a; a = a && b;}
561 #pragma omp atomic capture
562   // expected-error@+2 {{the statement for 'atomic capture' must be an expression statement of form 'v = ++x;', 'v = --x;', 'v = x++;', 'v = x--;', 'v = x binop= expr;', 'v = x = x binop expr' or 'v = x = expr binop x', where x and v are both l-value expressions with scalar type}}
563   // expected-note@+1 {{expected in right hand side of expression}}
564   b = a = (float)a + b;
565 #pragma omp atomic capture
566   // expected-error@+2 {{the statement for 'atomic capture' must be an expression statement of form 'v = ++x;', 'v = --x;', 'v = x++;', 'v = x--;', 'v = x binop= expr;', 'v = x = x binop expr' or 'v = x = expr binop x', where x and v are both l-value expressions with scalar type}}
567   // expected-note@+1 {{expected in right hand side of expression}}
568   b = a = 2 * b;
569 #pragma omp atomic capture
570   // expected-error@+2 {{the statement for 'atomic capture' must be an expression statement of form 'v = ++x;', 'v = --x;', 'v = x++;', 'v = x--;', 'v = x binop= expr;', 'v = x = x binop expr' or 'v = x = expr binop x', where x and v are both l-value expressions with scalar type}}
571   // expected-note@+1 {{expected in right hand side of expression}}
572   b = a = b + *&a;
573 #pragma omp atomic capture
574   c = *&a = *&a +  2;
575 #pragma omp atomic capture
576   c = a++;
577 #pragma omp atomic capture
578   c = ++a;
579 #pragma omp atomic capture
580   c = a--;
581 #pragma omp atomic capture
582   c = --a;
583 #pragma omp atomic capture
584   c = a += b;
585 #pragma omp atomic capture
586   c = a %= b;
587 #pragma omp atomic capture
588   c = a *= b;
589 #pragma omp atomic capture
590   c = a -= b;
591 #pragma omp atomic capture
592   c = a /= b;
593 #pragma omp atomic capture
594   c = a &= b;
595 #pragma omp atomic capture
596   c = a ^= b;
597 #pragma omp atomic capture
598   c = a |= b;
599 #pragma omp atomic capture
600   c = a <<= b;
601 #pragma omp atomic capture
602   c = a >>= b;
603 #pragma omp atomic capture
604   c = a = b + a;
605 #pragma omp atomic capture
606   c = a = a * b;
607 #pragma omp atomic capture
608   c = a = b - a;
609 #pragma omp atomic capture
610   c = a = a / b;
611 #pragma omp atomic capture
612   c = a = b & a;
613 #pragma omp atomic capture
614   c = a = a ^ b;
615 #pragma omp atomic capture
616   c = a = b | a;
617 #pragma omp atomic capture
618   c = a = a << b;
619 #pragma omp atomic capture
620   c = a = b >> a;
621 #pragma omp atomic capture
622   { c = *&a; *&a = *&a +  2;}
623 #pragma omp atomic capture
624   { *&a = *&a +  2; c = *&a;}
625 #pragma omp atomic capture
626   {c = a; a++;}
627 #pragma omp atomic capture
628   {++a;c = a;}
629 #pragma omp atomic capture
630   {c = a;a--;}
631 #pragma omp atomic capture
632   {--a;c = a;}
633 #pragma omp atomic capture
634   {c = a; a += b;}
635 #pragma omp atomic capture
636   {a %= b; c = a;}
637 #pragma omp atomic capture
638   {c = a; a *= b;}
639 #pragma omp atomic capture
640   {a -= b;c = a;}
641 #pragma omp atomic capture
642   {c = a; a /= b;}
643 #pragma omp atomic capture
644   {a &= b; c = a;}
645 #pragma omp atomic capture
646   {c = a; a ^= b;}
647 #pragma omp atomic capture
648   {a |= b; c = a;}
649 #pragma omp atomic capture
650   {c = a; a <<= b;}
651 #pragma omp atomic capture
652   {a >>= b; c = a;}
653 #pragma omp atomic capture
654   {c = a; a = b + a;}
655 #pragma omp atomic capture
656   {a = a * b; c = a;}
657 #pragma omp atomic capture
658   {c = a; a = b - a;}
659 #pragma omp atomic capture
660   {a = a / b; c = a;}
661 #pragma omp atomic capture
662   {c = a; a = b & a;}
663 #pragma omp atomic capture
664   {a = a ^ b; c = a;}
665 #pragma omp atomic capture
666   {c = a; a = b | a;}
667 #pragma omp atomic capture
668   {a = a << b; c = a;}
669 #pragma omp atomic capture
670   {c = a; a = b >> a;}
671 #pragma omp atomic capture
672   {c = a; a = foo();}
673   // expected-error@+1 {{directive '#pragma omp atomic' cannot contain more than one 'capture' clause}}
674 #pragma omp atomic capture capture
675   b = a /= b;
676 
677   // expected-note@+1 {{in instantiation of function template specialization 'capture<int>' requested here}}
678   return capture<int>();
679 }
680 
681 template <class T>
seq_cst()682 T seq_cst() {
683   T a, b = 0;
684 // Test for atomic seq_cst
685 #pragma omp atomic seq_cst
686   // expected-error@+2 {{the statement for 'atomic' must be an expression statement of form '++x;', '--x;', 'x++;', 'x--;', 'x binop= expr;', 'x = x binop expr' or 'x = expr binop x', where x is an l-value expression with scalar type}}
687   // expected-note@+1 {{expected an expression statement}}
688   ;
689 // expected-error@+1 {{directive '#pragma omp atomic' cannot contain more than one 'seq_cst' clause}}
690 #pragma omp atomic seq_cst seq_cst
691   a += b;
692 
693 #pragma omp atomic update seq_cst
694   // expected-error@+2 {{the statement for 'atomic update' must be an expression statement of form '++x;', '--x;', 'x++;', 'x--;', 'x binop= expr;', 'x = x binop expr' or 'x = expr binop x', where x is an l-value expression with scalar type}}
695   // expected-note@+1 {{expected an expression statement}}
696   ;
697 
698   return T();
699 }
700 
seq_cst()701 int seq_cst() {
702   int a, b = 0;
703 // Test for atomic seq_cst
704 #pragma omp atomic seq_cst
705   // expected-error@+2 {{the statement for 'atomic' must be an expression statement of form '++x;', '--x;', 'x++;', 'x--;', 'x binop= expr;', 'x = x binop expr' or 'x = expr binop x', where x is an l-value expression with scalar type}}
706   // expected-note@+1 {{expected an expression statement}}
707   ;
708 // expected-error@+1 {{directive '#pragma omp atomic' cannot contain more than one 'seq_cst' clause}}
709 #pragma omp atomic seq_cst seq_cst
710   a += b;
711 
712 #pragma omp atomic update seq_cst
713   // expected-error@+2 {{the statement for 'atomic update' must be an expression statement of form '++x;', '--x;', 'x++;', 'x--;', 'x binop= expr;', 'x = x binop expr' or 'x = expr binop x', where x is an l-value expression with scalar type}}
714   // expected-note@+1 {{expected an expression statement}}
715   ;
716 
717  return seq_cst<int>();
718 }
719 
720 template <class T>
mixed()721 T mixed() {
722   T a, b = T();
723 // expected-error@+2 2 {{directive '#pragma omp atomic' cannot contain more than one 'read', 'write', 'update' or 'capture' clause}}
724 // expected-note@+1 2 {{'read' clause used here}}
725 #pragma omp atomic read write
726   a = b;
727 // expected-error@+2 2 {{directive '#pragma omp atomic' cannot contain more than one 'read', 'write', 'update' or 'capture' clause}}
728 // expected-note@+1 2 {{'write' clause used here}}
729 #pragma omp atomic write read
730   a = b;
731 // expected-error@+2 2 {{directive '#pragma omp atomic' cannot contain more than one 'read', 'write', 'update' or 'capture' clause}}
732 // expected-note@+1 2 {{'update' clause used here}}
733 #pragma omp atomic update read
734   a += b;
735 // expected-error@+2 2 {{directive '#pragma omp atomic' cannot contain more than one 'read', 'write', 'update' or 'capture' clause}}
736 // expected-note@+1 2 {{'capture' clause used here}}
737 #pragma omp atomic capture read
738   a = ++b;
739   return T();
740 }
741 
mixed()742 int mixed() {
743   int a, b = 0;
744 // expected-error@+2 {{directive '#pragma omp atomic' cannot contain more than one 'read', 'write', 'update' or 'capture' clause}}
745 // expected-note@+1 {{'read' clause used here}}
746 #pragma omp atomic read write
747   a = b;
748 // expected-error@+2 {{directive '#pragma omp atomic' cannot contain more than one 'read', 'write', 'update' or 'capture' clause}}
749 // expected-note@+1 {{'write' clause used here}}
750 #pragma omp atomic write read
751   a = b;
752 // expected-error@+2 {{directive '#pragma omp atomic' cannot contain more than one 'read', 'write', 'update' or 'capture' clause}}
753 // expected-note@+1 {{'write' clause used here}}
754 #pragma omp atomic write update
755   a = b;
756 // expected-error@+2 {{directive '#pragma omp atomic' cannot contain more than one 'read', 'write', 'update' or 'capture' clause}}
757 // expected-note@+1 {{'write' clause used here}}
758 #pragma omp atomic write capture
759   a = b;
760   // expected-note@+1 {{in instantiation of function template specialization 'mixed<int>' requested here}}
761   return mixed<int>();
762 }
763 
764