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