1 // RUN: %clang_cc1 -verify -fopenmp -ferror-limit 100 %s
2 
3 // RUN: %clang_cc1 -verify -fopenmp-simd -ferror-limit 100 %s
4 
5 int foo() {
6 L1:
7   foo();
8 #pragma omp atomic
9   // 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}}
10   // expected-note@+1 {{expected an expression statement}}
11   {
12     foo();
13     goto L1; // expected-error {{use of undeclared label 'L1'}}
14   }
15   goto L2; // expected-error {{use of undeclared label 'L2'}}
16 #pragma omp atomic
17   // 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}}
18   // expected-note@+1 {{expected an expression statement}}
19   {
20     foo();
21   L2:
22     foo();
23   }
24 
25   return 0;
26 }
27 
28 struct S {
29   int a;
30   S &operator=(int v) {
31     a = v;
32     return *this;
33   }
34   S &operator+=(const S &s) {
35     a += s.a;
36     return *this;
37   }
38 };
39 
40 template <class T>
41 T read() {
42   T a = T(), b = T();
43 // Test for atomic read
44 #pragma omp atomic read
45   // 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}}
46   // expected-note@+1 {{expected an expression statement}}
47   ;
48 #pragma omp atomic read
49   // 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}}
50   // expected-note@+1 {{expected built-in assignment operator}}
51   foo();
52 #pragma omp atomic read
53   // 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}}
54   // expected-note@+1 2 {{expected built-in assignment operator}}
55   a += b;
56 #pragma omp atomic read
57   // 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}}
58   // expected-note@+1 {{expected lvalue expression}}
59   a = 0;
60 #pragma omp atomic read
61   // 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}}
62   // expected-note@+1 {{expected built-in assignment operator}}
63   a = b;
64   // expected-error@+1 {{directive '#pragma omp atomic' cannot contain more than one 'read' clause}}
65 #pragma omp atomic read read
66   // 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}}
67   // expected-note@+1 {{expected built-in assignment operator}}
68   a = b;
69 
70   return a;
71 }
72 
73 int read() {
74   int a = 0, b = 0;
75 // Test for atomic read
76 #pragma omp atomic read
77   // 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}}
78   // expected-note@+1 {{expected an expression statement}}
79   ;
80 #pragma omp atomic read
81   // 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}}
82   // expected-note@+1 {{expected built-in assignment operator}}
83   foo();
84 #pragma omp atomic read
85   // 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}}
86   // expected-note@+1 {{expected built-in assignment operator}}
87   a += b;
88 #pragma omp atomic read
89   // 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}}
90   // expected-note@+1 {{expected lvalue expression}}
91   a = 0;
92 #pragma omp atomic read
93   a = b;
94   // expected-error@+1 {{directive '#pragma omp atomic' cannot contain more than one 'read' clause}}
95 #pragma omp atomic read read
96   a = b;
97 
98   // expected-note@+2 {{in instantiation of function template specialization 'read<S>' requested here}}
99   // expected-note@+1 {{in instantiation of function template specialization 'read<int>' requested here}}
100   return read<int>() + read<S>().a;
101 }
102 
103 template <class T>
104 T write() {
105   T a, b = 0;
106 // Test for atomic write
107 #pragma omp atomic write
108   // 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}}
109   // expected-note@+1 {{expected an expression statement}}
110   ;
111 // expected-error@+1 {{directive '#pragma omp atomic' cannot contain more than one 'write' clause}}
112 #pragma omp atomic write write
113   a = b;
114 #pragma omp atomic write
115   // 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}}
116   // expected-note@+1 {{expected built-in assignment operator}}
117   foo();
118 #pragma omp atomic write
119   // 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}}
120   // expected-note@+1 {{expected built-in assignment operator}}
121   a += b;
122 #pragma omp atomic write
123   a = 0;
124 #pragma omp atomic write
125   a = b;
126 
127   return T();
128 }
129 
130 int write() {
131   int a, b = 0;
132 // Test for atomic write
133 #pragma omp atomic write
134   // 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}}
135   // expected-note@+1 {{expected an expression statement}}
136   ;
137 // expected-error@+1 {{directive '#pragma omp atomic' cannot contain more than one 'write' clause}}
138 #pragma omp atomic write write
139   a = b;
140 #pragma omp atomic write
141   // 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}}
142   // expected-note@+1 {{expected built-in assignment operator}}
143   foo();
144 #pragma omp atomic write
145   // 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}}
146   // expected-note@+1 {{expected built-in assignment operator}}
147   a += b;
148 #pragma omp atomic write
149   a = 0;
150 #pragma omp atomic write
151   a = foo();
152 
153   // expected-note@+1 {{in instantiation of function template specialization 'write<int>' requested here}}
154   return write<int>();
155 }
156 
157 template <class T>
158 T update() {
159   T a = 0, b = 0, c = 0;
160 // Test for atomic update
161 #pragma omp atomic update
162   // 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}}
163   // expected-note@+1 {{expected an expression statement}}
164   ;
165 // expected-error@+1 {{directive '#pragma omp atomic' cannot contain more than one 'update' clause}}
166 #pragma omp atomic update update
167   a += b;
168 #pragma omp atomic
169   // 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}}
170   // expected-note@+1 {{expected built-in binary operator}}
171   a = b;
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 = b || a;
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 one of '+', '*', '-', '/', '&', '^', '|', '<<', or '>>' built-in operations}}
179   a = a && b;
180 #pragma omp atomic update
181   // 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}}
182   // expected-note@+1 {{expected in right hand side of expression}}
183   a = float(a) + 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 = 2 * b;
188 #pragma omp atomic
189   // 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}}
190   // expected-note@+1 {{expected in right hand side of expression}}
191   a = b + *&a;
192 #pragma omp atomic
193   *&a = b * *&a;
194 #pragma omp atomic update
195   a++;
196 #pragma omp atomic
197   ++a;
198 #pragma omp atomic update
199   a--;
200 #pragma omp atomic
201   --a;
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;
220 #pragma omp atomic
221   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 update
235   a = b | a;
236 #pragma omp atomic
237   a = a << b;
238 #pragma omp atomic
239   a = b >> a;
240 
241 #pragma omp atomic
242   // 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}}
243   // expected-note@+1 {{expected an expression statement}}
244   ;
245 
246   return T();
247 }
248 
249 int update() {
250   int a, b = 0;
251 // Test for atomic update
252 #pragma omp atomic update
253   // 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}}
254   // expected-note@+1 {{expected an expression statement}}
255   ;
256 // expected-error@+1 {{directive '#pragma omp atomic' cannot contain more than one 'update' clause}}
257 #pragma omp atomic update update
258   a += b;
259 #pragma omp atomic
260   // 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}}
261   // expected-note@+1 {{expected built-in binary operator}}
262   a = b;
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 = b || a;
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 one of '+', '*', '-', '/', '&', '^', '|', '<<', or '>>' built-in operations}}
270   a = a && b;
271 #pragma omp atomic update
272   // 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}}
273   // expected-note@+1 {{expected in right hand side of expression}}
274   a = float(a) + 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 = 2 * b;
279 #pragma omp atomic
280   // 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}}
281   // expected-note@+1 {{expected in right hand side of expression}}
282   a = b + *&a;
283 #pragma omp atomic update
284   a++;
285 #pragma omp atomic
286   ++a;
287 #pragma omp atomic update
288   a--;
289 #pragma omp atomic
290   --a;
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;
309 #pragma omp atomic
310   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 update
324   a = b | a;
325 #pragma omp atomic
326   a = a << b;
327 #pragma omp atomic
328   a = b >> a;
329 #pragma omp atomic
330   // 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}}
331   // expected-note@+1 {{expected an expression statement}}
332   ;
333 
334   return update<int>();
335 }
336 
337 template <class T>
338 T capture() {
339   T a = 0, b = 0, c = 0;
340 // Test for atomic capture
341 #pragma omp atomic capture
342   // 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}}
343   // expected-note@+1 {{expected compound statement}}
344   ;
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 assignment expression}}
348   foo();
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 built-in binary or unary operator}}
352   a = b;
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 assignment expression}}
356   a = b || a;
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 one of '+', '*', '-', '/', '&', '^', '|', '<<', or '>>' built-in operations}}
360   b = a = 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 = (float)a + 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 = 2 * b;
369 #pragma omp atomic capture
370   // 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}}
371   // expected-note@+1 {{expected assignment expression}}
372   a = b + *&a;
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   { a = b; }
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 exactly two expression statements}}
380   {}
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;}
385 #pragma omp atomic capture
386   // 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}}
387   // expected-note@+1 {{expected in right hand side of the first expression}}
388   {a = b; a = b || a;}
389 #pragma omp atomic capture
390   {b = a; a = 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 = (float)a + 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 = 2 * b;
399 #pragma omp atomic capture
400   // 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}}
401   // expected-note@+1 {{expected in right hand side of expression}}
402   b = a = b + *&a;
403 #pragma omp atomic capture
404   c = *&a = *&a +  2;
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;
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;
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 << b;
449 #pragma omp atomic capture
450   c = a = b >> a;
451 #pragma omp atomic capture
452   { c = *&a; *&a = *&a +  2;}
453 #pragma omp atomic capture
454   { *&a = *&a +  2; c = *&a;}
455 #pragma omp atomic capture
456   {c = a; 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--;}
463 #pragma omp atomic capture
464   {--a;c = a;}
465 #pragma omp atomic capture
466   {c = a; a += b;}
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;}
481 #pragma omp atomic capture
482   {a |= b; c = a;}
483 #pragma omp atomic capture
484   {c = a; a <<= b;}
485 #pragma omp atomic capture
486   {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   {a = a ^ b; c = a;}
499 #pragma omp atomic capture
500   {c = a; a = b | a;}
501 #pragma omp atomic capture
502   {a = a << b; c = a;}
503 #pragma omp atomic capture
504   {c = a; a = b >> a;}
505 #pragma omp atomic capture
506   {c = a; a = foo();}
507   // expected-error@+1 {{directive '#pragma omp atomic' cannot contain more than one 'capture' clause}}
508 #pragma omp atomic capture capture
509   b = a /= b;
510 
511   return T();
512 }
513 
514 int capture() {
515   int a = 0, b = 0, c = 0;
516 // Test for atomic capture
517 #pragma omp atomic capture
518   // 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}}
519   // expected-note@+1 {{expected compound statement}}
520   ;
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   foo();
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 built-in binary or unary operator}}
528   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 = b || a;
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 one of '+', '*', '-', '/', '&', '^', '|', '<<', or '>>' built-in operations}}
536   b = a = a && 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 = (float)a + b;
541 #pragma omp atomic capture
542   // 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}}
543   // expected-note@+1 {{expected assignment expression}}
544   a = 2 * b;
545 #pragma omp atomic capture
546   // 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}}
547   // expected-note@+1 {{expected assignment expression}}
548   a = b + *&a;
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 exactly two expression statements}}
552   { 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 exactly two expression statements}}
556   {}
557 #pragma omp atomic capture
558   // 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}}
559   // expected-note@+1 {{expected in right hand side of the first expression}}
560   {a = b;a = b;}
561 #pragma omp atomic capture
562   // 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}}
563   // expected-note@+1 {{expected in right hand side of the first expression}}
564   {a = b; a = b || a;}
565 #pragma omp atomic capture
566   {b = a; a = a && 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 = (float)a + b;
571 #pragma omp atomic capture
572   // 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}}
573   // expected-note@+1 {{expected in right hand side of expression}}
574   b = a = 2 * b;
575 #pragma omp atomic capture
576   // 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}}
577   // expected-note@+1 {{expected in right hand side of expression}}
578   b = a = b + *&a;
579 #pragma omp atomic capture
580   c = *&a = *&a +  2;
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;
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;
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 ^ b;
621 #pragma omp atomic capture
622   c = a = b | a;
623 #pragma omp atomic capture
624   c = a = a << b;
625 #pragma omp atomic capture
626   c = a = b >> a;
627 #pragma omp atomic capture
628   { c = *&a; *&a = *&a +  2;}
629 #pragma omp atomic capture
630   { *&a = *&a +  2; c = *&a;}
631 #pragma omp atomic capture
632   {c = a; a++;}
633 #pragma omp atomic capture
634   {++a;c = a;}
635 #pragma omp atomic capture
636   {c = a;a--;}
637 #pragma omp atomic capture
638   {--a;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;}
653 #pragma omp atomic capture
654   {a |= b; c = a;}
655 #pragma omp atomic capture
656   {c = a; a <<= b;}
657 #pragma omp atomic capture
658   {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   {a = a ^ b; c = a;}
671 #pragma omp atomic capture
672   {c = a; a = b | a;}
673 #pragma omp atomic capture
674   {a = a << b; c = a;}
675 #pragma omp atomic capture
676   {c = a; a = b >> a;}
677 #pragma omp atomic capture
678   {c = a; a = foo();}
679   // expected-error@+1 {{directive '#pragma omp atomic' cannot contain more than one 'capture' clause}}
680 #pragma omp atomic capture capture
681   b = a /= b;
682 
683   // expected-note@+1 {{in instantiation of function template specialization 'capture<int>' requested here}}
684   return capture<int>();
685 }
686 
687 template <class T>
688 T seq_cst() {
689   T a, b = 0;
690 // Test for atomic seq_cst
691 #pragma omp atomic seq_cst
692   // 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}}
693   // expected-note@+1 {{expected an expression statement}}
694   ;
695 // expected-error@+1 {{directive '#pragma omp atomic' cannot contain more than one 'seq_cst' clause}}
696 #pragma omp atomic seq_cst seq_cst
697   a += b;
698 
699 #pragma omp atomic update seq_cst
700   // 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}}
701   // expected-note@+1 {{expected an expression statement}}
702   ;
703 
704   return T();
705 }
706 
707 int seq_cst() {
708   int a, b = 0;
709 // Test for atomic seq_cst
710 #pragma omp atomic seq_cst
711   // 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}}
712   // expected-note@+1 {{expected an expression statement}}
713   ;
714 // expected-error@+1 {{directive '#pragma omp atomic' cannot contain more than one 'seq_cst' clause}}
715 #pragma omp atomic seq_cst seq_cst
716   a += b;
717 
718 #pragma omp atomic update seq_cst
719   // 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}}
720   // expected-note@+1 {{expected an expression statement}}
721   ;
722 
723  return seq_cst<int>();
724 }
725 
726 template <class T>
727 T mixed() {
728   T a, b = T();
729 // expected-error@+2 2 {{directive '#pragma omp atomic' cannot contain more than one 'read', 'write', 'update' or 'capture' clause}}
730 // expected-note@+1 2 {{'read' clause used here}}
731 #pragma omp atomic read write
732   a = b;
733 // expected-error@+2 2 {{directive '#pragma omp atomic' cannot contain more than one 'read', 'write', 'update' or 'capture' clause}}
734 // expected-note@+1 2 {{'write' clause used here}}
735 #pragma omp atomic write read
736   a = b;
737 // expected-error@+2 2 {{directive '#pragma omp atomic' cannot contain more than one 'read', 'write', 'update' or 'capture' clause}}
738 // expected-note@+1 2 {{'update' clause used here}}
739 #pragma omp atomic update read
740   a += b;
741 // expected-error@+2 2 {{directive '#pragma omp atomic' cannot contain more than one 'read', 'write', 'update' or 'capture' clause}}
742 // expected-note@+1 2 {{'capture' clause used here}}
743 #pragma omp atomic capture read
744   a = ++b;
745   return T();
746 }
747 
748 int mixed() {
749   int a, b = 0;
750 // expected-error@+2 {{directive '#pragma omp atomic' cannot contain more than one 'read', 'write', 'update' or 'capture' clause}}
751 // expected-note@+1 {{'read' clause used here}}
752 #pragma omp atomic read write
753   a = b;
754 // expected-error@+2 {{directive '#pragma omp atomic' cannot contain more than one 'read', 'write', 'update' or 'capture' clause}}
755 // expected-note@+1 {{'write' clause used here}}
756 #pragma omp atomic write read
757   a = b;
758 // expected-error@+2 {{directive '#pragma omp atomic' cannot contain more than one 'read', 'write', 'update' or 'capture' clause}}
759 // expected-note@+1 {{'write' clause used here}}
760 #pragma omp atomic write update
761   a = b;
762 // expected-error@+2 {{directive '#pragma omp atomic' cannot contain more than one 'read', 'write', 'update' or 'capture' clause}}
763 // expected-note@+1 {{'write' clause used here}}
764 #pragma omp atomic write capture
765   a = b;
766   // expected-note@+1 {{in instantiation of function template specialization 'mixed<int>' requested here}}
767   return mixed<int>();
768 }
769 
770