1 // RUN: %clang_cc1 -verify -fopenmp=libiomp5 -ferror-limit 100 %s
2 
3 int foo() {
4 L1:
5   foo();
6 #pragma omp atomic
7   // expected-error@+1 {{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   {
9     foo();
10     goto L1; // expected-error {{use of undeclared label 'L1'}}
11   }
12   goto L2; // expected-error {{use of undeclared label 'L2'}}
13 #pragma omp atomic
14   // expected-error@+1 {{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}}
15   {
16     foo();
17   L2:
18     foo();
19   }
20 
21   return 0;
22 }
23 
24 template <class T>
25 T read() {
26   T a, b = 0;
27 // Test for atomic read
28 #pragma omp atomic read
29   // expected-error@+1 {{the statement for 'atomic read' must be an expression statement of form 'v = x;', where v and x are both l-value expressions with scalar type}}
30   ;
31 // expected-error@+1 {{directive '#pragma omp atomic' cannot contain more than one 'read' clause}}
32 #pragma omp atomic read read
33   a = b;
34 
35   return T();
36 }
37 
38 int read() {
39   int a, b = 0;
40 // Test for atomic read
41 #pragma omp atomic read
42   // expected-error@+1 {{the statement for 'atomic read' must be an expression statement of form 'v = x;', where v and x are both l-value expressions with scalar type}}
43   ;
44 // expected-error@+1 {{directive '#pragma omp atomic' cannot contain more than one 'read' clause}}
45 #pragma omp atomic read read
46   a = b;
47 
48   return read<int>();
49 }
50 
51 template <class T>
52 T write() {
53   T a, b = 0;
54 // Test for atomic write
55 #pragma omp atomic write
56   // expected-error@+1 {{the statement for 'atomic write' must be an expression statement of form 'x = expr;', where x is an l-value expression with scalar type}}
57   ;
58 // expected-error@+1 {{directive '#pragma omp atomic' cannot contain more than one 'write' clause}}
59 #pragma omp atomic write write
60   a = b;
61 
62   return T();
63 }
64 
65 int write() {
66   int a, b = 0;
67 // Test for atomic write
68 #pragma omp atomic write
69   // expected-error@+1 {{the statement for 'atomic write' must be an expression statement of form 'x = expr;', where x is an l-value expression with scalar type}}
70   ;
71 // expected-error@+1 {{directive '#pragma omp atomic' cannot contain more than one 'write' clause}}
72 #pragma omp atomic write write
73   a = b;
74 
75   return write<int>();
76 }
77 
78 template <class T>
79 T update() {
80   T a, b = 0;
81 // Test for atomic update
82 #pragma omp atomic update
83   // expected-error@+1 {{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}}
84   ;
85 // expected-error@+1 {{directive '#pragma omp atomic' cannot contain more than one 'update' clause}}
86 #pragma omp atomic update update
87   a += b;
88 
89 #pragma omp atomic
90   // expected-error@+1 {{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}}
91   ;
92 
93   return T();
94 }
95 
96 int update() {
97   int a, b = 0;
98 // Test for atomic update
99 #pragma omp atomic update
100   // expected-error@+1 {{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}}
101   ;
102 // expected-error@+1 {{directive '#pragma omp atomic' cannot contain more than one 'update' clause}}
103 #pragma omp atomic update update
104   a += b;
105 
106 #pragma omp atomic
107   // expected-error@+1 {{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}}
108   ;
109 
110   return update<int>();
111 }
112 
113 template <class T>
114 T capture() {
115   T a, b = 0;
116 // Test for atomic capture
117 #pragma omp atomic capture
118   // expected-error@+1 {{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}}
119   ++a;
120 #pragma omp atomic capture
121   // expected-error@+1 {{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}}
122   ;
123 // expected-error@+1 {{directive '#pragma omp atomic' cannot contain more than one 'capture' clause}}
124 #pragma omp atomic capture capture
125   a = ++b;
126 
127   return T();
128 }
129 
130 int capture() {
131   int a, b = 0;
132 // Test for atomic capture
133 #pragma omp atomic capture
134   // expected-error@+1 {{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}}
135   ++a;
136 #pragma omp atomic capture
137   // expected-error@+1 {{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}}
138   ;
139 // expected-error@+1 {{directive '#pragma omp atomic' cannot contain more than one 'capture' clause}}
140 #pragma omp atomic capture capture
141   a = ++b;
142 
143   return capture<int>();
144 }
145 
146 template <class T>
147 T seq_cst() {
148   T a, b = 0;
149 // Test for atomic seq_cst
150 #pragma omp atomic seq_cst
151   // expected-error@+1 {{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}}
152   ;
153 // expected-error@+1 {{directive '#pragma omp atomic' cannot contain more than one 'seq_cst' clause}}
154 #pragma omp atomic seq_cst seq_cst
155   a += b;
156 
157 #pragma omp atomic update seq_cst
158   // expected-error@+1 {{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   ;
160 
161   return T();
162 }
163 
164 int seq_cst() {
165   int a, b = 0;
166 // Test for atomic seq_cst
167 #pragma omp atomic seq_cst
168   // expected-error@+1 {{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}}
169   ;
170 // expected-error@+1 {{directive '#pragma omp atomic' cannot contain more than one 'seq_cst' clause}}
171 #pragma omp atomic seq_cst seq_cst
172   a += b;
173 
174 #pragma omp atomic update seq_cst
175   // expected-error@+1 {{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   ;
177 
178  return seq_cst<int>();
179 }
180 
181 template <class T>
182 T mixed() {
183   T a, b = T();
184 // expected-error@+2 2 {{directive '#pragma omp atomic' cannot contain more than one 'read', 'write', 'update' or 'capture' clause}}
185 // expected-note@+1 2 {{'read' clause used here}}
186 #pragma omp atomic read write
187   a = b;
188 // expected-error@+2 2 {{directive '#pragma omp atomic' cannot contain more than one 'read', 'write', 'update' or 'capture' clause}}
189 // expected-note@+1 2 {{'write' clause used here}}
190 #pragma omp atomic write read
191   a = b;
192 // expected-error@+2 2 {{directive '#pragma omp atomic' cannot contain more than one 'read', 'write', 'update' or 'capture' clause}}
193 // expected-note@+1 2 {{'update' clause used here}}
194 #pragma omp atomic update read
195   a += b;
196 // expected-error@+2 2 {{directive '#pragma omp atomic' cannot contain more than one 'read', 'write', 'update' or 'capture' clause}}
197 // expected-note@+1 2 {{'capture' clause used here}}
198 #pragma omp atomic capture read
199   a = ++b;
200   return T();
201 }
202 
203 int mixed() {
204   int a, b = 0;
205 // expected-error@+2 {{directive '#pragma omp atomic' cannot contain more than one 'read', 'write', 'update' or 'capture' clause}}
206 // expected-note@+1 {{'read' clause used here}}
207 #pragma omp atomic read write
208   a = b;
209 // expected-error@+2 {{directive '#pragma omp atomic' cannot contain more than one 'read', 'write', 'update' or 'capture' clause}}
210 // expected-note@+1 {{'write' clause used here}}
211 #pragma omp atomic write read
212   a = b;
213 // expected-error@+2 {{directive '#pragma omp atomic' cannot contain more than one 'read', 'write', 'update' or 'capture' clause}}
214 // expected-note@+1 {{'write' clause used here}}
215 #pragma omp atomic write update
216   a = b;
217 // expected-error@+2 {{directive '#pragma omp atomic' cannot contain more than one 'read', 'write', 'update' or 'capture' clause}}
218 // expected-note@+1 {{'write' clause used here}}
219 #pragma omp atomic write capture
220   a = b;
221   // expected-note@+1 {{in instantiation of function template specialization 'mixed<int>' requested here}}
222   return mixed<int>();
223 }
224 
225