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 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 
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>
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 
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>
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 
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>
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   {c = a; (a)++;}
457 #pragma omp atomic capture
458   {++a;c = a;}
459 #pragma omp atomic capture
460   {c = a;a--;}
461 #pragma omp atomic capture
462   {--a;c = a;}
463 #pragma omp atomic capture
464   {c = a; a += b;}
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;}
483 #pragma omp atomic capture
484   {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   {a = a << b; c = a;}
501 #pragma omp atomic capture
502   {c = a; a = b >> a;}
503 #pragma omp atomic capture
504   {c = a; a = foo();}
505   // expected-error@+1 {{directive '#pragma omp atomic' cannot contain more than one 'capture' clause}}
506 #pragma omp atomic capture capture
507   b = a /= b;
508 
509   return T();
510 }
511 
512 int capture() {
513   int a = 0, b = 0, c = 0;
514 // Test for atomic capture
515 #pragma omp atomic capture
516   // 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}}
517   // expected-note@+1 {{expected compound statement}}
518   ;
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 assignment expression}}
522   foo();
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 built-in binary or unary operator}}
526   a = b;
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 assignment expression}}
530   a = b || a;
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 one of '+', '*', '-', '/', '&', '^', '|', '<<', or '>>' built-in operations}}
534   b = a = 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 = (float)a + 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 = 2 * b;
543 #pragma omp atomic capture
544   // 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}}
545   // expected-note@+1 {{expected assignment expression}}
546   a = b + *&a;
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   { a = b; }
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 exactly two expression statements}}
554   {}
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;}
559 #pragma omp atomic capture
560   // 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}}
561   // expected-note@+1 {{expected in right hand side of the first expression}}
562   {a = b; a = b || a;}
563 #pragma omp atomic capture
564   {b = a; a = 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 = (float)a + 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 = 2 * b;
573 #pragma omp atomic capture
574   // 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}}
575   // expected-note@+1 {{expected in right hand side of expression}}
576   b = a = b + *&a;
577 #pragma omp atomic capture
578   c = *&a = *&a +  2;
579 #pragma omp atomic capture
580   c = a++;
581 #pragma omp atomic capture
582   c = ++a;
583 #pragma omp atomic capture
584   c = a--;
585 #pragma omp atomic capture
586   c = --a;
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;
605 #pragma omp atomic capture
606   c = 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 << b;
623 #pragma omp atomic capture
624   c = a = b >> a;
625 #pragma omp atomic capture
626   { c = *&a; *&a = *&a +  2;}
627 #pragma omp atomic capture
628   { *&a = *&a +  2; 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--;}
635 #pragma omp atomic capture
636   {--a;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;}
655 #pragma omp atomic capture
656   {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   {a = a << b; c = a;}
673 #pragma omp atomic capture
674   {c = a; a = b >> a;}
675 #pragma omp atomic capture
676   {c = a; a = foo();}
677   // expected-error@+1 {{directive '#pragma omp atomic' cannot contain more than one 'capture' clause}}
678 #pragma omp atomic capture capture
679   b = a /= b;
680 
681   // expected-note@+1 {{in instantiation of function template specialization 'capture<int>' requested here}}
682   return capture<int>();
683 }
684 
685 template <class T>
686 T seq_cst() {
687   T a, b = 0;
688 // Test for atomic seq_cst
689 #pragma omp atomic seq_cst
690   // 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}}
691   // expected-note@+1 {{expected an expression statement}}
692   ;
693 // expected-error@+1 {{directive '#pragma omp atomic' cannot contain more than one 'seq_cst' clause}}
694 #pragma omp atomic seq_cst seq_cst
695   a += b;
696 
697 #pragma omp atomic update seq_cst
698   // 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}}
699   // expected-note@+1 {{expected an expression statement}}
700   ;
701 
702   return T();
703 }
704 
705 int seq_cst() {
706   int a, b = 0;
707 // Test for atomic seq_cst
708 #pragma omp atomic seq_cst
709   // 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}}
710   // expected-note@+1 {{expected an expression statement}}
711   ;
712 // expected-error@+1 {{directive '#pragma omp atomic' cannot contain more than one 'seq_cst' clause}}
713 #pragma omp atomic seq_cst seq_cst
714   a += b;
715 
716 #pragma omp atomic update seq_cst
717   // 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}}
718   // expected-note@+1 {{expected an expression statement}}
719   ;
720 
721  return seq_cst<int>();
722 }
723 
724 template <class T>
725 T mixed() {
726   T a, b = T();
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 {{'read' clause used here}}
729 #pragma omp atomic read write
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 {{'write' clause used here}}
733 #pragma omp atomic write 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 {{'update' clause used here}}
737 #pragma omp atomic update read
738   a += b;
739 // expected-error@+2 2 {{directive '#pragma omp atomic' cannot contain more than one 'read', 'write', 'update' or 'capture' clause}}
740 // expected-note@+1 2 {{'capture' clause used here}}
741 #pragma omp atomic capture read
742   a = ++b;
743   return T();
744 }
745 
746 int mixed() {
747   int a, b = 0;
748 // expected-error@+2 {{directive '#pragma omp atomic' cannot contain more than one 'read', 'write', 'update' or 'capture' clause}}
749 // expected-note@+1 {{'read' clause used here}}
750 #pragma omp atomic read write
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 read
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 update
759   a = b;
760 // expected-error@+2 {{directive '#pragma omp atomic' cannot contain more than one 'read', 'write', 'update' or 'capture' clause}}
761 // expected-note@+1 {{'write' clause used here}}
762 #pragma omp atomic write capture
763   a = b;
764   // expected-note@+1 {{in instantiation of function template specialization 'mixed<int>' requested here}}
765   return mixed<int>();
766 }
767 
768